View Javadoc
1   /*
2    * (c) Copyright 2006-2020 by rapiddweller GmbH & Volker Bergmann. All rights reserved.
3    *
4    * Redistribution and use in source and binary forms, with or without
5    * modification, is permitted under the terms of the
6    * GNU General Public License.
7    *
8    * For redistributing this software or a derivative work under a license other
9    * than the GPL-compatible Free Software License as defined by the Free
10   * Software Foundation or approved by OSI, you must first obtain a commercial
11   * license to this software product from rapiddweller GmbH & Volker Bergmann.
12   *
13   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14   * WITHOUT A WARRANTY OF ANY KIND. ALL EXPRESS OR IMPLIED CONDITIONS,
15   * REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF
16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE
17   * HEREBY EXCLUDED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24   * POSSIBILITY OF SUCH DAMAGE.
25   */
26  
27  package com.rapiddweller.benerator.primitive.datetime;
28  
29  import com.rapiddweller.benerator.GeneratorContext;
30  import com.rapiddweller.benerator.distribution.Distribution;
31  import com.rapiddweller.benerator.distribution.SequenceManager;
32  import com.rapiddweller.benerator.wrapper.NonNullGeneratorWrapper;
33  import com.rapiddweller.benerator.wrapper.ProductWrapper;
34  import com.rapiddweller.common.Period;
35  import com.rapiddweller.common.TimeUtil;
36  import com.rapiddweller.common.converter.DateString2DurationConverter;
37  
38  import java.util.Date;
39  import java.util.GregorianCalendar;
40  
41  /**
42   * creates date values by a LongGenerator.
43   * <br/>
44   * Created: 07.06.2006 22:54:28
45   *
46   * @author Volker Bergmann
47   * @since 0.1
48   */
49  public class DateGenerator extends NonNullGeneratorWrapper<Long, Date> {
50  
51    private final DateString2DurationConverter dateConverter = new DateString2DurationConverter();
52  
53    private long min;
54    private long max;
55    private long granularity;
56    private Distribution distribution;
57    private final boolean unique;
58  
59    // constructors ----------------------------------------------------------------------------------------------------
60  
61    /**
62     * Initializes the generator to create days within about the last 80 years with a one-day resolution
63     */
64    public DateGenerator() {
65      this(defaultStartDate(), currentDay(), Period.DAY.getMillis());
66    }
67  
68    /**
69     * Initializes the generator to create dates with a uniform distribution
70     *
71     * @param min         the min
72     * @param max         the max
73     * @param granularity the granularity
74     */
75    public DateGenerator(Date min, Date max, long granularity) {
76      this(min, max, granularity, SequenceManager.RANDOM_SEQUENCE);
77    }
78  
79    /**
80     * Initializes the generator to create dates of a Sequence or WeightFunction
81     *
82     * @param min          the min
83     * @param max          the max
84     * @param granularity  the granularity
85     * @param distribution the distribution
86     */
87    public DateGenerator(Date min, Date max, long granularity, Distribution distribution) {
88      this(min, max, granularity, distribution, false);
89    }
90  
91    /**
92     * Initializes the generator to create dates of a Sequence or WeightFunction
93     *
94     * @param min          the min
95     * @param max          the max
96     * @param granularity  the granularity
97     * @param distribution the distribution
98     * @param unique       the unique
99     */
100   public DateGenerator(Date min, Date max, long granularity, Distribution distribution, boolean unique) {
101     super(null);
102     this.distribution = distribution;
103     this.min = (min != null ? min.getTime() : Long.MIN_VALUE);
104     this.max = (max != null ? max.getTime() : TimeUtil.date(TimeUtil.currentYear() + 10, 11, 31).getTime());
105     this.granularity = granularity;
106     this.unique = unique;
107     setSource(distribution.createNumberGenerator(Long.class, this.min, this.max, this.granularity, this.unique));
108   }
109 
110   // config properties -----------------------------------------------------------------------------------------------
111 
112   /**
113    * Sets the earliest date to generate
114    *
115    * @param min the min
116    */
117   public void setMin(Date min) {
118     this.min = min.getTime();
119   }
120 
121   /**
122    * Sets the latest date to generate
123    *
124    * @param max the max
125    */
126   public void setMax(Date max) {
127     this.max = max.getTime();
128   }
129 
130   /**
131    * Sets the date granularity in milliseconds
132    *
133    * @param granularity the granularity
134    */
135   public void setGranularity(String granularity) {
136     this.granularity = dateConverter.convert(granularity);
137   }
138 
139   /**
140    * Sets the distribution to use
141    *
142    * @param distribution the distribution
143    */
144   public void setDistribution(Distribution distribution) {
145     this.distribution = distribution;
146   }
147 
148   // source interface ---------------------------------------------------------------------------------------------
149 
150   @Override
151   public Class<Date> getGeneratedType() {
152     return Date.class;
153   }
154 
155   @Override
156   public void init(GeneratorContext context) {
157     assertNotInitialized();
158     setSource(distribution.createNumberGenerator(Long.class, min, max, granularity, unique));
159     super.init(context);
160   }
161 
162   /**
163    * Generates a Date by creating a millisecond value from the source generator and wrapping it into a Date
164    */
165   @Override
166   public Date generate() {
167     assertInitialized();
168     ProductWrapper<Long> tmp = generateFromSource();
169     if (tmp == null) {
170       return null;
171     }
172     Long millis = tmp.unwrap();
173     return new Date(millis);
174   }
175 
176   @Override
177   public boolean isThreadSafe() {
178     return super.isThreadSafe() && dateConverter.isThreadSafe();
179   }
180 
181   @Override
182   public boolean isParallelizable() {
183     return super.isParallelizable() && dateConverter.isParallelizable();
184   }
185 
186   // implementation --------------------------------------------------------------------------------------------------
187 
188   /**
189    * Returns the default start date as 80 years ago
190    */
191   private static Date defaultStartDate() {
192     return new Date(currentDay().getTime() - 80L * 365 * Period.DAY.getMillis());
193   }
194 
195   /**
196    * Returns the current day as Date value rounded to midnight
197    */
198   private static Date currentDay() {
199     GregorianCalendar calendar = new GregorianCalendar();
200     calendar.set(
201         calendar.get(GregorianCalendar.YEAR),
202         calendar.get(GregorianCalendar.MONTH),
203         calendar.get(GregorianCalendar.DAY_OF_MONTH),
204         0,
205         0,
206         0);
207     calendar.set(GregorianCalendar.MILLISECOND, 0);
208     return calendar.getTime();
209   }
210 
211   @Override
212   public String toString() {
213     return getClass().getSimpleName() + '[' + getSource() + ']';
214   }
215 
216 }