001 /* 002 * The MIT License 003 * 004 * Copyright (c) 2013, Ninja Squad 005 * 006 * Permission is hereby granted, free of charge, to any person obtaining a copy 007 * of this software and associated documentation files (the "Software"), to deal 008 * in the Software without restriction, including without limitation the rights 009 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 010 * copies of the Software, and to permit persons to whom the Software is 011 * furnished to do so, subject to the following conditions: 012 * 013 * The above copyright notice and this permission notice shall be included in 014 * all copies or substantial portions of the Software. 015 * 016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 018 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 019 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 020 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 021 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 022 * THE SOFTWARE. 023 */ 024 025 package com.ninja_squad.dbsetup.generator; 026 027 import com.ninja_squad.dbsetup.util.Preconditions; 028 029 import javax.annotation.Nonnull; 030 import java.sql.Timestamp; 031 import java.util.Calendar; 032 import java.util.Date; 033 import java.util.TimeZone; 034 035 /** 036 * A {@link ValueGenerator} that returns a sequence of dates, starting at a given date and incremented by a given 037 * time, specified as an increment and a calendar field. 038 * @author JB 039 */ 040 public final class DateSequenceValueGenerator implements ValueGenerator<Date> { 041 042 // the number of chars in yyyy-mm-dd hh:mm:ss 043 private static final int MIN_NUMBER_OF_CHARS_FOR_TIMESTAMP = 19; 044 045 /** 046 * The available units for the increment of this sequence 047 */ 048 public enum CalendarField { 049 YEAR(Calendar.YEAR), 050 MONTH(Calendar.MONTH), 051 DAY(Calendar.DATE), 052 HOUR(Calendar.HOUR), 053 MINUTE(Calendar.MINUTE), 054 SECOND(Calendar.SECOND), 055 MILLISECOND(Calendar.MILLISECOND); 056 057 private int field; 058 059 CalendarField(int field) { 060 this.field = field; 061 } 062 063 private int getField() { 064 return field; 065 } 066 } 067 068 private Calendar next; 069 private int increment; 070 private CalendarField unit; 071 072 DateSequenceValueGenerator() { 073 this(today(), 1, CalendarField.DAY); 074 } 075 076 private DateSequenceValueGenerator(Calendar next, int increment, CalendarField unit) { 077 this.next = next; 078 this.increment = increment; 079 this.unit = unit; 080 } 081 082 private static Calendar today() { 083 Calendar result = Calendar.getInstance(); 084 result.set(Calendar.HOUR_OF_DAY, 0); 085 result.set(Calendar.MINUTE, 0); 086 result.set(Calendar.SECOND, 0); 087 result.set(Calendar.MILLISECOND, 0); 088 return result; 089 } 090 091 /** 092 * Restarts the sequence at the given date, in the given time zone 093 * @return this instance, for chaining 094 */ 095 public DateSequenceValueGenerator startingAt(@Nonnull Date startDate, @Nonnull TimeZone timeZone) { 096 Preconditions.checkNotNull(startDate, "startDate may not be null"); 097 Preconditions.checkNotNull(timeZone, "timeZone may not be null"); 098 next = Calendar.getInstance(timeZone); 099 next.setTime(startDate); 100 return this; 101 } 102 103 /** 104 * Restarts the sequence at the given date, in the default time zone 105 * @return this instance, for chaining 106 */ 107 public DateSequenceValueGenerator startingAt(@Nonnull Date startDate) { 108 return startingAt(startDate, TimeZone.getDefault()); 109 } 110 111 /** 112 * Restarts the sequence at the given date 113 * @return this instance, for chaining 114 */ 115 public DateSequenceValueGenerator startingAt(@Nonnull Calendar startDate) { 116 Preconditions.checkNotNull(startDate, "startDate may not be null"); 117 next = (Calendar) startDate.clone(); 118 return this; 119 } 120 121 /** 122 * Restarts the sequence at the given date, in the default time zone 123 * @param startDate the starting date, as a String. The supported formats are the same as the ones supported by 124 * {@link com.ninja_squad.dbsetup.bind.Binders#timestampBinder()}, i.e. the formats supported by 125 * <code>java.sql.Timestamp.valueOf()</code> and <code>java.sql.Date.valueOf()</code> 126 * @return this instance, for chaining 127 */ 128 public DateSequenceValueGenerator startingAt(@Nonnull String startDate) { 129 Preconditions.checkNotNull(startDate, "startDate may not be null"); 130 if (startDate.length() >= MIN_NUMBER_OF_CHARS_FOR_TIMESTAMP) { 131 return startingAt(Timestamp.valueOf(startDate)); 132 } 133 else { 134 return startingAt(java.sql.Date.valueOf(startDate)); 135 } 136 } 137 138 /** 139 * Increments the date by the given increment of the given unit. 140 * @return this instance, for chaining 141 */ 142 public DateSequenceValueGenerator incrementingBy(int increment, @Nonnull CalendarField unit) { 143 Preconditions.checkNotNull(unit, "unit may not be null"); 144 this.increment = increment; 145 this.unit = unit; 146 return this; 147 } 148 149 @Override 150 public Date nextValue() { 151 Date result = next.getTime(); 152 next.add(unit.getField(), increment); 153 return result; 154 } 155 156 @Override 157 public String toString() { 158 return "DateSequenceValueGenerator[" 159 + "next=" + next 160 + ", increment=" + increment 161 + ", unit=" + unit 162 + "]"; 163 } 164 }