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.factory;
28  
29  import com.rapiddweller.benerator.Generator;
30  import com.rapiddweller.benerator.GeneratorProvider;
31  import com.rapiddweller.benerator.NonNullGenerator;
32  import com.rapiddweller.benerator.distribution.Distribution;
33  import com.rapiddweller.benerator.distribution.SequenceManager;
34  import com.rapiddweller.benerator.primitive.EquivalenceStringGenerator;
35  import com.rapiddweller.benerator.sample.OneShotGenerator;
36  import com.rapiddweller.benerator.sample.SequenceGenerator;
37  import com.rapiddweller.benerator.wrapper.CompositeStringGenerator;
38  import com.rapiddweller.benerator.wrapper.GeneratorChain;
39  import com.rapiddweller.benerator.wrapper.SimpleMultiSourceArrayGenerator;
40  import com.rapiddweller.benerator.wrapper.WrapperFactory;
41  import com.rapiddweller.common.Assert;
42  import com.rapiddweller.common.CollectionUtil;
43  import com.rapiddweller.common.Converter;
44  import com.rapiddweller.common.NumberUtil;
45  import com.rapiddweller.common.converter.AnyConverter;
46  import com.rapiddweller.common.converter.ConverterManager;
47  import com.rapiddweller.model.data.Uniqueness;
48  import com.rapiddweller.script.DatabeneScriptParser;
49  import com.rapiddweller.script.WeightedSample;
50  
51  import java.util.Collection;
52  import java.util.Date;
53  import java.util.List;
54  import java.util.Locale;
55  import java.util.Set;
56  import java.util.TreeSet;
57  
58  /**
59   * {@link GeneratorFactory} implementation which provides
60   * serial value generation and parallel combinations.<br/>
61   * <br/>
62   * Created: 22.07.2011 10:14:36
63   *
64   * @author Volker Bergmann
65   * @since 0.7.0
66   */
67  public class SerialGeneratorFactory extends GeneratorFactory {
68  
69    /**
70     * Instantiates a new Serial generator factory.
71     */
72    public SerialGeneratorFactory() {
73      super(new MeanDefaultsProvider());
74    }
75  
76    @Override
77    public <T> Generator<T> createAlternativeGenerator(
78        Class<T> targetType, Generator<T>[] sources, Uniqueness uniqueness) {
79      return new GeneratorChain<>(targetType, uniqueness.isUnique(), sources);
80    }
81  
82    @Override
83    public <T> Generator<T[]> createCompositeArrayGenerator(
84        Class<T> componentType, Generator<T>[] sources, Uniqueness uniqueness) {
85      return new SimpleMultiSourceArrayGenerator<>(componentType, sources);
86    }
87  
88    @Override
89    public <T> Generator<T> createSampleGenerator(Collection<T> values, Class<T> generatedType, boolean unique) {
90      return new SequenceGenerator<>(generatedType, values);
91    }
92  
93    @Override
94    @SuppressWarnings({"unchecked", "rawtypes"})
95    public <T> Generator<T> createFromWeightedLiteralList(String valueSpec, Class<T> targetType,
96                                                          Distribution distribution, boolean unique) {
97      List<WeightedSample<?>> samples = CollectionUtil.toList(DatabeneScriptParser.parseWeightedLiteralList(valueSpec));
98      List<?> values = FactoryUtil.extractValues((List) samples);
99      Converter<?, T> typeConverter = new AnyConverter<>(targetType);
100     Collection<T> convertedValues = ConverterManager.convertAll((List) values, typeConverter);
101     return createSampleGenerator(convertedValues, targetType, true);
102   }
103 
104   @Override
105   public <T> Generator<T> createWeightedSampleGenerator(Collection<WeightedSample<T>> samples, Class<T> targetType) {
106     List<T> values = FactoryUtil.extractValues(samples);
107     return createSampleGenerator(values, targetType, true);
108   }
109 
110   @Override
111   public Generator<Date> createDateGenerator(
112       Date min, Date max, long granularity, Distribution distribution) {
113     if (distribution == null) {
114       distribution = SequenceManager.STEP_SEQUENCE;
115     }
116     return super.createDateGenerator(min, max, granularity, distribution);
117   }
118 
119   @Override
120   public <T extends Number> NonNullGenerator<T> createNumberGenerator(
121       Class<T> numberType, T min, Boolean minInclusive, T max, Boolean maxInclusive,
122       T granularity, Distribution distribution, Uniqueness uniqueness) {
123     Assert.notNull(numberType, "numberType");
124     if (distribution == null) {
125       distribution = SequenceManager.STEP_SEQUENCE;
126     }
127     if (min == null) {
128       min = (NumberUtil.isLimited(numberType) ? NumberUtil.minValue(numberType) : defaultsProvider.defaultMin(numberType));
129     }
130     if (max == null) {
131       max = (NumberUtil.isLimited(numberType) ? NumberUtil.maxValue(numberType) : defaultsProvider.defaultMax(numberType));
132     }
133     if (granularity == null) {
134       granularity = defaultsProvider.defaultGranularity(numberType);
135     }
136     return super.createNumberGenerator(numberType, min, minInclusive, max, maxInclusive,
137         granularity, distribution, uniqueness);
138   }
139 
140   @Override
141   public NonNullGenerator<String> createStringGenerator(Set<Character> chars,
142                                                         Integer minLength, Integer maxLength, int lengthGranularity, Distribution lengthDistribution,
143                                                         Uniqueness uniqueness) {
144     Generator<Character> charGenerator = createCharacterGenerator(chars);
145     Set<Integer> counts = defaultCounts(minLength, maxLength, lengthGranularity);
146     NonNullGenerator<Integer> lengthGenerator = WrapperFactory.asNonNullGenerator(
147         new SequenceGenerator<>(Integer.class, counts));
148     return new EquivalenceStringGenerator<>(charGenerator, lengthGenerator);
149   }
150 
151   @SuppressWarnings("unchecked")
152   @Override
153   public NonNullGenerator<String> createCompositeStringGenerator(
154       GeneratorProvider<?> partGeneratorProvider, int minParts, int maxParts, Uniqueness uniqueness) {
155     GeneratorChain<String> result = new GeneratorChain<>(String.class, true);
156     Set<Integer> partCounts = defaultCounts(minParts, maxParts, 1);
157     for (int partCount : partCounts) {
158       Generator<String>[] sources = new Generator[partCount];
159       for (int i = 0; i < partCount; i++) {
160         sources[i] = WrapperFactory.asStringGenerator(partGeneratorProvider.create());
161       }
162       result.addSource(new CompositeStringGenerator(true, sources));
163     }
164     return WrapperFactory.asNonNullGenerator(result);
165   }
166 
167   @Override
168   public Generator<Character> createCharacterGenerator(String pattern, Locale locale, boolean unique) {
169     return super.createCharacterGenerator(pattern, locale, true);
170   }
171 
172   @Override
173   public NonNullGenerator<Character> createCharacterGenerator(Set<Character> characters) {
174     return WrapperFactory.asNonNullGenerator(
175         new SequenceGenerator<>(Character.class, characters));
176   }
177 
178   /**
179    * Default counts set.
180    *
181    * @param minCount       the min count
182    * @param maxCount       the max count
183    * @param countPrecision the count precision
184    * @return the set
185    */
186   protected Set<Integer> defaultCounts(int minCount, int maxCount, int countPrecision) {
187     Set<Integer> result = new TreeSet<>();
188     for (int i = minCount; i <= maxCount; i += countPrecision) {
189       result.add(i);
190     }
191     return result;
192   }
193 
194   @Override
195   public <T> Generator<T> createSingleValueGenerator(T value, boolean unique) {
196     return new OneShotGenerator<>(value);
197   }
198 
199   @Override
200   public <T> Generator<T> createNullGenerator(Class<T> generatedType) {
201     return new OneShotGenerator<>(null, generatedType);
202   }
203 
204   @Override
205   public Set<Character> defaultSubSet(Set<Character> characters) {
206     return characters;
207   }
208 
209   // defaults --------------------------------------------------------------------------------------------------------
210 
211   @Override
212   public Generator<?> applyNullSettings(Generator<?> source, Boolean nullable, Double nullQuota) {
213     if (nullable == null || nullable || (nullQuota != null && nullQuota > 0)) {
214       return WrapperFactory.prependNull(source);
215     } else {
216       return source;
217     }
218   }
219 
220   @Override
221   protected Distribution defaultLengthDistribution(Uniqueness uniqueness, boolean required) {
222     return (required ? SequenceManager.STEP_SEQUENCE : null);
223   }
224 
225   @Override
226   public Distribution defaultDistribution(Uniqueness uniqueness) {
227     return SequenceManager.STEP_SEQUENCE;
228   }
229 
230   @Override
231   protected double defaultTrueQuota() {
232     return 0.5;
233   }
234 
235   @Override
236   protected boolean defaultUnique() {
237     return true;
238   }
239 
240 }