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.NonNullGenerator;
31 import com.rapiddweller.benerator.StorageSystem;
32 import com.rapiddweller.benerator.composite.AlternativeComponentBuilder;
33 import com.rapiddweller.benerator.composite.ArrayElementBuilder;
34 import com.rapiddweller.benerator.composite.ComponentBuilder;
35 import com.rapiddweller.benerator.composite.ConditionalComponentBuilder;
36 import com.rapiddweller.benerator.composite.PlainEntityComponentBuilder;
37 import com.rapiddweller.benerator.composite.SimplifyingSingleSourceArrayGenerator;
38 import com.rapiddweller.benerator.distribution.DistributingGenerator;
39 import com.rapiddweller.benerator.distribution.Distribution;
40 import com.rapiddweller.benerator.distribution.SequenceManager;
41 import com.rapiddweller.benerator.distribution.sequence.ExpandSequence;
42 import com.rapiddweller.benerator.engine.BeneratorContext;
43 import com.rapiddweller.benerator.engine.expression.ScriptExpression;
44 import com.rapiddweller.benerator.primitive.ScriptGenerator;
45 import com.rapiddweller.benerator.wrapper.AsIntegerGeneratorWrapper;
46 import com.rapiddweller.benerator.wrapper.DataSourceGenerator;
47 import com.rapiddweller.benerator.wrapper.SingleSourceArrayGenerator;
48 import com.rapiddweller.benerator.wrapper.SingleSourceCollectionGenerator;
49 import com.rapiddweller.benerator.wrapper.WrapperFactory;
50 import com.rapiddweller.common.ConfigurationError;
51 import com.rapiddweller.common.StringUtil;
52 import com.rapiddweller.common.SyntaxError;
53 import com.rapiddweller.format.script.Script;
54 import com.rapiddweller.format.script.ScriptUtil;
55 import com.rapiddweller.model.data.AlternativeGroupDescriptor;
56 import com.rapiddweller.model.data.ArrayElementDescriptor;
57 import com.rapiddweller.model.data.ComplexTypeDescriptor;
58 import com.rapiddweller.model.data.ComponentDescriptor;
59 import com.rapiddweller.model.data.IdDescriptor;
60 import com.rapiddweller.model.data.PartDescriptor;
61 import com.rapiddweller.model.data.ReferenceDescriptor;
62 import com.rapiddweller.model.data.SimpleTypeDescriptor;
63 import com.rapiddweller.model.data.TypeDescriptor;
64 import com.rapiddweller.model.data.Uniqueness;
65 import com.rapiddweller.script.Expression;
66 import org.apache.logging.log4j.LogManager;
67 import org.apache.logging.log4j.Logger;
68
69 import java.io.IOException;
70 import java.io.StreamTokenizer;
71 import java.io.StringReader;
72 import java.util.ArrayList;
73 import java.util.Collection;
74 import java.util.HashSet;
75
76
77
78
79
80
81
82 public class ComponentBuilderFactory extends InstanceGeneratorFactory {
83
84
85
86
87 protected ComponentBuilderFactory() {
88 }
89
90 private static final Logger LOGGER = LogManager.getLogger(ComponentBuilderFactory.class);
91
92
93
94
95
96
97
98
99
100
101
102 public static ComponentBuilder<?> createComponentBuilder(
103 ComponentDescriptor descriptor, Uniqueness ownerUniqueness, BeneratorContext context) {
104 LOGGER.debug("createComponentBuilder({})", descriptor.getName());
105
106 ComponentBuilder<?> result = null;
107 if (descriptor instanceof ArrayElementDescriptor) {
108 result = createPartBuilder(descriptor, ownerUniqueness, context);
109 } else if (descriptor instanceof PartDescriptor) {
110 TypeDescriptor type = descriptor.getTypeDescriptor();
111 if (type instanceof AlternativeGroupDescriptor) {
112 result = createAlternativeGroupBuilder((AlternativeGroupDescriptor) type, ownerUniqueness, context);
113 } else {
114 result = createPartBuilder(descriptor, ownerUniqueness, context);
115 }
116 } else if (descriptor instanceof ReferenceDescriptor) {
117 result = createReferenceBuilder((ReferenceDescriptor) descriptor, context);
118 } else if (descriptor instanceof IdDescriptor) {
119 result = createIdBuilder((IdDescriptor) descriptor, ownerUniqueness, context);
120 } else {
121 throw new ConfigurationError("Not a supported element: " + descriptor.getClass());
122 }
123 result = wrapWithCondition(descriptor, result);
124 return result;
125 }
126
127
128
129
130
131
132
133
134 protected static ComponentBuilder<?> createScriptBuilder(ComponentDescriptor component, BeneratorContext context) {
135 TypeDescriptor type = component.getTypeDescriptor();
136 if (type == null) {
137 return null;
138 }
139 String scriptText = type.getScript();
140 if (scriptText == null) {
141 return null;
142 }
143 Script script = ScriptUtil.parseScriptText(scriptText);
144 Generator<?> generator = new ScriptGenerator(script);
145 generator = DescriptorUtil.createConvertingGenerator(component.getTypeDescriptor(), generator, context);
146 return builderFromGenerator(generator, component, context);
147
148 }
149
150 @SuppressWarnings({"unchecked", "rawtypes"})
151 private static ComponentBuilder<?> createAlternativeGroupBuilder(
152 AlternativeGroupDescriptor type, Uniqueness ownerUniqueness, BeneratorContext context) {
153 int i = 0;
154 Collection<ComponentDescriptor> components = type.getComponents();
155 ComponentBuilder<?>[] builders = new ComponentBuilder[components.size()];
156 for (ComponentDescriptor component : components) {
157 builders[i++] = createComponentBuilder(component, ownerUniqueness, context);
158 }
159 return new AlternativeComponentBuilder(builders, type.getScope());
160 }
161
162 private static ComponentBuilder<?> createPartBuilder(
163 ComponentDescriptor part, Uniqueness ownerUniqueness, BeneratorContext context) {
164 Generator<?> generator = createSingleInstanceGenerator(part, ownerUniqueness, context);
165 generator = createMultiplicityWrapper(part, generator, context);
166 LOGGER.debug("Created {}", generator);
167 return builderFromGenerator(generator, part, context);
168 }
169
170
171
172
173
174
175
176
177 @SuppressWarnings({"unchecked", "rawtypes"})
178 static ComponentBuilder<?> createReferenceBuilder(ReferenceDescriptor descriptor, BeneratorContext context) {
179 SimpleTypeDescriptorweller/model/data/SimpleTypeDescriptor.html#SimpleTypeDescriptor">SimpleTypeDescriptor typeDescriptor = (SimpleTypeDescriptor) descriptor.getTypeDescriptor();
180
181
182 boolean unique = DescriptorUtil.isUnique(descriptor, context);
183 Uniqueness uniqueness = (unique ? Uniqueness.SIMPLE : Uniqueness.NONE);
184
185
186 if (DescriptorUtil.isNullable(descriptor, context) && DescriptorUtil.shouldNullifyEachNullable(descriptor, context)) {
187 return builderFromGenerator(createNullGenerator(descriptor, context), descriptor, context);
188 }
189
190
191 Generator<?> generator = null;
192 generator = DescriptorUtil.getGeneratorByName(typeDescriptor, context);
193 if (generator == null) {
194 generator = SimpleTypeGeneratorFactory.createScriptGenerator(typeDescriptor);
195 }
196 if (generator == null) {
197 generator = SimpleTypeGeneratorFactory.createConstantGenerator(typeDescriptor, context);
198 }
199 if (generator == null) {
200 generator = SimpleTypeGeneratorFactory.createValuesGenerator(typeDescriptor, uniqueness, context);
201 }
202
203
204 Distribution distribution = FactoryUtil.getDistribution(
205 typeDescriptor.getDistribution(), descriptor.getUniqueness(), false, context);
206
207
208 if (generator == null) {
209
210 String targetTypeName = descriptor.getTargetType();
211 ComplexTypeDescriptoriddweller/model/data/ComplexTypeDescriptor.html#ComplexTypeDescriptor">ComplexTypeDescriptor targetType = (ComplexTypeDescriptor) context.getDataModel().getTypeDescriptor(targetTypeName);
212 if (targetType == null) {
213 throw new ConfigurationError("Type not defined: " + targetTypeName);
214 }
215
216
217 String targetComponent = descriptor.getTargetComponent();
218
219
220 String sourceName = typeDescriptor.getSource();
221 if (sourceName == null) {
222 throw new ConfigurationError("'source' is not set for " + descriptor);
223 }
224 Object sourceObject = context.get(sourceName);
225 if (sourceObject instanceof StorageSystem) {
226 StorageSystemom/rapiddweller/benerator/StorageSystem.html#StorageSystem">StorageSystem sourceSystem = (StorageSystem) sourceObject;
227 String selector = typeDescriptor.getSelector();
228 String subSelector = typeDescriptor.getSubSelector();
229 boolean subSelect = !StringUtil.isEmpty(subSelector);
230 String selectorToUse = (subSelect ? subSelector : selector);
231 if (isIndividualSelector(selectorToUse)) {
232 generator = new DataSourceGenerator(sourceSystem.query(selectorToUse, true, context));
233 } else {
234 generator = new DataSourceGenerator(sourceSystem.queryEntityIds(
235 targetTypeName, selectorToUse, context));
236 if (selectorToUse == null && distribution == null) {
237 if (context.isDefaultOneToOne()) {
238 distribution = new ExpandSequence();
239 } else {
240 distribution = SequenceManager.RANDOM_SEQUENCE;
241 }
242 }
243 }
244 if (subSelect) {
245 generator = WrapperFactory.applyHeadCycler(generator);
246 }
247 } else {
248 throw new ConfigurationError("Not a supported source type: " + sourceName);
249 }
250 }
251
252
253
254 if (distribution != null) {
255 generator = new DistributingGenerator(generator, distribution, unique);
256 }
257
258
259 generator = ComponentBuilderFactory.createMultiplicityWrapper(descriptor, generator, context);
260 if (LOGGER.isDebugEnabled()) {
261 LOGGER.debug("Created " + generator);
262 }
263
264
265 generator = DescriptorUtil.wrapWithProxy(generator, typeDescriptor);
266 return builderFromGenerator(generator, descriptor, context);
267 }
268
269
270
271
272
273
274
275
276 protected static boolean isIndividualSelector(String selector) {
277 if (selector == null) {
278 return false;
279 }
280 StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(selector));
281 tokenizer.ordinaryChar('\'');
282 tokenizer.ordinaryChar('"');
283 int token;
284 try {
285 while ((token = tokenizer.nextToken()) != StreamTokenizer.TT_EOF) {
286 if (token == StreamTokenizer.TT_WORD) {
287 return StringUtil.startsWithIgnoreCase(tokenizer.sval.trim(), "select");
288 }
289 }
290 } catch (IOException e) {
291 throw new RuntimeException("Unexpected error", e);
292 }
293 return false;
294 }
295
296
297
298
299
300
301
302
303
304
305 @SuppressWarnings({"unchecked", "rawtypes"})
306 static ComponentBuilder<?> wrapWithCondition(ComponentDescriptor descriptor, ComponentBuilder<?> builder) {
307 if (builder == null) {
308 return null;
309 }
310 TypeDescriptor typeDescriptor = descriptor.getTypeDescriptor();
311 if (typeDescriptor == null) {
312 return builder;
313 }
314 String conditionText = typeDescriptor.getCondition();
315 if (!StringUtil.isEmpty(conditionText)) {
316 Expression<Boolean> condition = new ScriptExpression<>(conditionText);
317 return new ConditionalComponentBuilder(builder, condition);
318 } else {
319 return builder;
320 }
321 }
322
323
324
325
326
327
328
329
330
331 static ComponentBuilder<?> createIdBuilder(IdDescriptor id, Uniqueness ownerUniqueness, BeneratorContext context) {
332 Generator<?> generator = createSingleInstanceGenerator(id, Uniqueness.ORDERED, context);
333 if (generator != null) {
334 LOGGER.debug("Created {}", generator);
335 }
336 return builderFromGenerator(generator, id, context);
337 }
338
339 private static ComponentBuilder<?> builderFromGenerator(
340 Generator<?> source, ComponentDescriptor descriptor, BeneratorContext context) {
341 if (source == null) {
342 return null;
343 }
344 boolean nullability = DescriptorUtil.isNullable(descriptor, context);
345 Double nullQuota = descriptor.getNullQuota();
346 if (nullQuota != null && nullQuota != 0) {
347 source = context.getGeneratorFactory().applyNullSettings(source, nullability, nullQuota);
348 }
349 TypeDescriptor typeDescriptor = descriptor.getTypeDescriptor();
350 String scope = (typeDescriptor != null ? typeDescriptor.getScope() : null);
351 if (descriptor instanceof ArrayElementDescriptor) {
352 int index = ((ArrayElementDescriptor) descriptor).getIndex();
353 return new ArrayElementBuilder(index, source, scope);
354 } else {
355 return new PlainEntityComponentBuilder(descriptor.getName(), source, scope);
356 }
357 }
358
359
360
361
362
363
364
365
366
367 @SuppressWarnings({"unchecked", "rawtypes"})
368 static Generator<Object> createMultiplicityWrapper(
369 ComponentDescriptor instance, Generator<?> generator, BeneratorContext context) {
370 if (generator == null) {
371 return null;
372 }
373 String container = instance.getContainer();
374 if (container == null) {
375 Generator<Long> longCountGenerator = DescriptorUtil.createDynamicCountGenerator(instance, 1L, 1L, true, context);
376 NonNullGenerator<Integer> countGenerator = WrapperFactory.asNonNullGenerator(
377 new AsIntegerGeneratorWrapper<Number>((Generator) longCountGenerator));
378 return new SimplifyingSingleSourceArrayGenerator(generator, countGenerator);
379 }
380
381 Generator<Long> longCountGenerator;
382 if (instance.getLocalType().getSource() != null) {
383 longCountGenerator = DescriptorUtil.createDynamicCountGenerator(instance, null, null, true, context);
384 } else {
385 longCountGenerator = DescriptorUtil.createDynamicCountGenerator(instance, 1L, 1L, true, context);
386 }
387 NonNullGenerator<Integer> countGenerator = WrapperFactory.asNonNullGenerator(
388 new AsIntegerGeneratorWrapper<Number>((Generator) longCountGenerator));
389 switch (container) {
390 case "array":
391 return new SingleSourceArrayGenerator(generator, generator.getGeneratedType(), countGenerator);
392 case "list":
393 return new SingleSourceCollectionGenerator(generator, ArrayList.class, countGenerator);
394 case "set":
395 return new SingleSourceCollectionGenerator(generator, HashSet.class, countGenerator);
396 default:
397 throw new SyntaxError("Not a supported container", container);
398 }
399 }
400
401 }