1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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.BooleanGenerator;
35 import com.rapiddweller.benerator.primitive.IncrementalStringGenerator;
36 import com.rapiddweller.benerator.primitive.RandomVarLengthStringGenerator;
37 import com.rapiddweller.benerator.primitive.UniqueScrambledStringGenerator;
38 import com.rapiddweller.benerator.sample.AttachedWeightSampleGenerator;
39 import com.rapiddweller.benerator.sample.ConstantGenerator;
40 import com.rapiddweller.benerator.sample.OneShotGenerator;
41 import com.rapiddweller.benerator.sample.SampleGenerator;
42 import com.rapiddweller.benerator.wrapper.AlternativeGenerator;
43 import com.rapiddweller.benerator.wrapper.CompositeStringGenerator;
44 import com.rapiddweller.benerator.wrapper.GeneratorChain;
45 import com.rapiddweller.benerator.wrapper.IteratingGenerator;
46 import com.rapiddweller.benerator.wrapper.SimpleMultiSourceArrayGenerator;
47 import com.rapiddweller.benerator.wrapper.UniqueMultiSourceArrayGenerator;
48 import com.rapiddweller.benerator.wrapper.WrapperFactory;
49 import com.rapiddweller.common.ConfigurationError;
50 import com.rapiddweller.common.converter.ConverterManager;
51 import com.rapiddweller.common.converter.ToStringConverter;
52 import com.rapiddweller.common.iterator.ArrayIterable;
53 import com.rapiddweller.model.data.Uniqueness;
54 import com.rapiddweller.script.DatabeneScriptParser;
55 import com.rapiddweller.script.WeightedSample;
56
57 import java.util.Collection;
58 import java.util.Set;
59
60
61
62
63
64
65
66
67
68
69
70 public class StochasticGeneratorFactory extends GeneratorFactory {
71
72
73
74
75 public StochasticGeneratorFactory() {
76 super(new GentleDefaultsProvider());
77 }
78
79 @Override
80 public <T> Generator<T> createAlternativeGenerator(Class<T> targetType, Generator<T>[] sources,
81 Uniqueness uniqueness) {
82 if (uniqueness == Uniqueness.ORDERED) {
83 return new GeneratorChain<>(targetType, uniqueness.isUnique(), sources);
84 } else {
85 return new AlternativeGenerator<>(targetType, sources);
86 }
87 }
88
89 @Override
90 public <T> Generator<T[]> createCompositeArrayGenerator(
91 Class<T> componentType, Generator<T>[] sources, Uniqueness uniqueness) {
92 if (uniqueness.isUnique()) {
93 return new UniqueMultiSourceArrayGenerator<>(componentType, sources);
94 } else {
95 return new SimpleMultiSourceArrayGenerator<>(componentType, sources);
96 }
97 }
98
99 @Override
100 public <T> Generator<T> createSampleGenerator(Collection<T> values,
101 Class<T> generatedType, boolean unique) {
102 SampleGenerator<T> generator = new SampleGenerator<>(generatedType, values);
103 generator.setUnique(unique);
104 return generator;
105 }
106
107 @Override
108 @SuppressWarnings("unchecked")
109 public <T> Generator<T> createFromWeightedLiteralList(String valueSpec, Class<T> targetType,
110 Distribution distribution, boolean unique) {
111 WeightedSample<T>[] samples = (WeightedSample<T>[]) DatabeneScriptParser.parseWeightedLiteralList(valueSpec);
112 if (distribution == null && !unique && weightsUsed(samples)) {
113 AttachedWeightSampleGenerator<T> generator = new AttachedWeightSampleGenerator<>(targetType);
114 for (WeightedSample<T> sample : samples) {
115 if (sample.getValue() == null) {
116 throw new ConfigurationError("null is not supported in values='...', drop it from the list and " +
117 "use a nullQuota instead");
118 }
119 generator.addSample(sample.getValue(), sample.getWeight());
120 }
121 return generator;
122 } else {
123 String[] values = new String[samples.length];
124 for (int i = 0; i < samples.length; i++) {
125 T rawValue = samples[i].getValue();
126 String value = ToStringConverter.convert(rawValue, null);
127 values[i] = value;
128 }
129 IteratingGenerator<String> source = new IteratingGenerator<>(
130 new ArrayIterable<>(values, String.class));
131 if (distribution == null) {
132 distribution = SequenceManager.RANDOM_SEQUENCE;
133 }
134 Generator<T> gen = WrapperFactory.applyConverter(source, ConverterManager.getInstance().createConverter(
135 String.class, targetType));
136 return distribution.applyTo(gen, unique);
137 }
138 }
139
140 @Override
141 public Generator<Boolean> createBooleanGenerator(Double trueQuota) {
142 return new BooleanGenerator(trueQuota != null ? trueQuota : 0.5);
143 }
144
145 private static boolean weightsUsed(WeightedSample<?>[] samples) {
146 for (WeightedSample<?> sample : samples) {
147 if (sample.getWeight() != 1) {
148 return true;
149 }
150 }
151 return false;
152 }
153
154 @Override
155 public NonNullGenerator<String> createStringGenerator(Set<Character> chars,
156 Integer minLength, Integer maxLength, int lengthGranularity, Distribution lengthDistribution,
157 Uniqueness uniqueness) {
158 if (uniqueness == Uniqueness.ORDERED) {
159 return new IncrementalStringGenerator(chars, minLength, maxLength, lengthGranularity);
160 } else if (uniqueness.isUnique()) {
161 return new UniqueScrambledStringGenerator(chars, minLength, maxLength);
162 } else {
163 return new RandomVarLengthStringGenerator(
164 chars, minLength, maxLength, lengthGranularity, lengthDistribution);
165 }
166 }
167
168 @Override
169 public Generator<?> applyNullSettings(Generator<?> source, Boolean nullable, Double nullQuota) {
170 if (nullQuota == null) {
171 if (nullable == null) {
172 nullable = defaultsProvider.defaultNullable();
173 }
174 nullQuota = (nullable ? (defaultsProvider.defaultNullQuota() != 1 ? defaultsProvider.defaultNullQuota() : 0) : 0);
175 }
176 return WrapperFactory.injectNulls(source, nullQuota);
177 }
178
179 @Override
180 public <T> Generator<T> createSingleValueGenerator(T value, boolean unique) {
181 if (unique) {
182 return new OneShotGenerator<>(value);
183 } else {
184 return new ConstantGenerator<>(value);
185 }
186 }
187
188 @Override
189 protected double defaultTrueQuota() {
190 return 0.5;
191 }
192
193 @Override
194 protected Distribution defaultLengthDistribution(Uniqueness uniqueness, boolean required) {
195 switch (uniqueness) {
196 case ORDERED:
197 return SequenceManager.STEP_SEQUENCE;
198 case SIMPLE:
199 return SequenceManager.EXPAND_SEQUENCE;
200 default:
201 if (required) {
202 return SequenceManager.RANDOM_SEQUENCE;
203 } else {
204 return null;
205 }
206 }
207 }
208
209 @Override
210 public Distribution defaultDistribution(Uniqueness uniqueness) {
211 if (uniqueness == null) {
212 return SequenceManager.STEP_SEQUENCE;
213 }
214 switch (uniqueness) {
215 case ORDERED:
216 return SequenceManager.STEP_SEQUENCE;
217 case SIMPLE:
218 return SequenceManager.EXPAND_SEQUENCE;
219 default:
220 return SequenceManager.RANDOM_SEQUENCE;
221 }
222 }
223
224 @Override
225 protected boolean defaultUnique() {
226 return false;
227 }
228
229 @Override
230 public <T> Generator<T> createNullGenerator(Class<T> generatedType) {
231 return new ConstantGenerator<>(null, generatedType);
232 }
233
234 @SuppressWarnings("unchecked")
235 @Override
236 public NonNullGenerator<String> createCompositeStringGenerator(
237 GeneratorProvider<?> partGeneratorProvider, int minParts, int maxParts, Uniqueness uniqueness) {
238 AlternativeGenerator<String> result = new AlternativeGenerator<>(String.class);
239 for (int partCount = minParts; partCount <= maxParts; partCount++) {
240 Generator<String>[] sources = new Generator[partCount];
241 for (int i = 0; i < partCount; i++) {
242 sources[i] = WrapperFactory.asStringGenerator(partGeneratorProvider.create());
243 }
244 result.addSource(new CompositeStringGenerator(uniqueness.isUnique(), sources));
245 }
246 return WrapperFactory.asNonNullGenerator(result);
247 }
248
249 }