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.BeneratorFactory;
30 import com.rapiddweller.benerator.Generator;
31 import com.rapiddweller.benerator.distribution.Distribution;
32 import com.rapiddweller.benerator.engine.BeneratorContext;
33 import com.rapiddweller.benerator.parser.ModelParser;
34 import com.rapiddweller.benerator.primitive.DynamicCountGenerator;
35 import com.rapiddweller.benerator.sample.ConstantGenerator;
36 import com.rapiddweller.benerator.util.ExpressionBasedGenerator;
37 import com.rapiddweller.benerator.wrapper.WrapperFactory;
38 import com.rapiddweller.common.BeanUtil;
39 import com.rapiddweller.common.ConfigurationError;
40 import com.rapiddweller.common.Context;
41 import com.rapiddweller.common.ConversionException;
42 import com.rapiddweller.common.Converter;
43 import com.rapiddweller.common.NullSafeComparator;
44 import com.rapiddweller.common.ParseException;
45 import com.rapiddweller.common.StringUtil;
46 import com.rapiddweller.common.TimeUtil;
47 import com.rapiddweller.common.Validator;
48 import com.rapiddweller.common.converter.AnyConverter;
49 import com.rapiddweller.common.converter.ConverterChain;
50 import com.rapiddweller.common.converter.FormatFormatConverter;
51 import com.rapiddweller.common.converter.String2NumberConverter;
52 import com.rapiddweller.common.converter.ToStringConverter;
53 import com.rapiddweller.common.validator.AndValidator;
54 import com.rapiddweller.common.validator.bean.BeanConstraintValidator;
55 import com.rapiddweller.common.xml.XMLUtil;
56 import com.rapiddweller.format.script.ScriptConverterForStrings;
57 import com.rapiddweller.model.data.ArrayTypeDescriptor;
58 import com.rapiddweller.model.data.ComplexTypeDescriptor;
59 import com.rapiddweller.model.data.ComponentDescriptor;
60 import com.rapiddweller.model.data.IdDescriptor;
61 import com.rapiddweller.model.data.InstanceDescriptor;
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.model.data.VariableHolder;
66 import com.rapiddweller.script.BeanSpec;
67 import com.rapiddweller.script.DatabeneScriptParser;
68 import com.rapiddweller.script.Expression;
69 import com.rapiddweller.script.PrimitiveType;
70 import com.rapiddweller.script.expression.ConstantExpression;
71 import com.rapiddweller.script.expression.ExpressionUtil;
72 import com.rapiddweller.script.expression.MinExpression;
73 import org.w3c.dom.Element;
74
75 import javax.validation.ConstraintValidator;
76 import java.text.DateFormat;
77 import java.text.SimpleDateFormat;
78 import java.util.List;
79
80 import static com.rapiddweller.benerator.engine.DescriptorConstants.COMPONENT_TYPES;
81 import static com.rapiddweller.benerator.engine.DescriptorConstants.EL_VALUE;
82 import static com.rapiddweller.benerator.engine.DescriptorConstants.EL_VARIABLE;
83 import static com.rapiddweller.model.data.SimpleTypeDescriptor.MAX_LENGTH;
84 import static com.rapiddweller.model.data.SimpleTypeDescriptor.PATTERN;
85
86
87
88
89
90
91
92
93
94 public class DescriptorUtil {
95
96 private DescriptorUtil() {
97 }
98
99
100
101
102
103
104
105
106 public static Object convertType(Object sourceValue, SimpleTypeDescriptor targetType) {
107 if (sourceValue == null) {
108 return null;
109 }
110 PrimitiveType primitive = targetType.getPrimitiveType();
111 if (primitive == null) {
112 primitive = PrimitiveType.STRING;
113 }
114 Class<?> javaType = primitive.getJavaType();
115 return AnyConverter.convert(sourceValue, javaType);
116 }
117
118
119
120
121
122
123
124 public static boolean isWrappedSimpleType(ComplexTypeDescriptor complexType) {
125 List<ComponentDescriptor> components = complexType.getComponents();
126 return (components.size() == 1
127 && ComplexTypeDescriptor.__SIMPLE_CONTENT.equals(components.get(0).getName()));
128 }
129
130
131
132
133
134
135
136
137
138 @SuppressWarnings({"unchecked", "rawtypes"})
139 public static Generator<?> createConvertingGenerator(TypeDescriptor descriptor,
140 Generator<?> generator, BeneratorContext context) {
141 Converter<?, ?> converter = DescriptorUtil.getConverter(descriptor.getConverter(), context);
142 if (converter != null) {
143 if (descriptor.getPattern() != null && BeanUtil.hasProperty(converter.getClass(), PATTERN)) {
144 BeanUtil.setPropertyValue(converter, PATTERN, descriptor.getPattern(), false);
145 }
146 return WrapperFactory.applyConverter((Generator) generator, converter);
147 }
148 return generator;
149 }
150
151
152
153
154
155
156
157
158 public static Generator<?> getGeneratorByName(TypeDescriptor descriptor, BeneratorContext context) {
159 try {
160 Generator<?> generator = null;
161 String generatorSpec = descriptor.getGenerator();
162 if (generatorSpec != null) {
163 if (generatorSpec.startsWith("{") && generatorSpec.endsWith("}")) {
164 generatorSpec = generatorSpec.substring(1, generatorSpec.length() - 1);
165 }
166 BeanSpec generatorBeanSpec = DatabeneScriptParser.resolveBeanSpec(generatorSpec, context);
167 generator = (Generator<?>) generatorBeanSpec.getBean();
168 FactoryUtil.mapDetailsToBeanProperties(descriptor, generator, context);
169 if (generatorBeanSpec.isReference()) {
170 generator = WrapperFactory.preventClosing(generator);
171 }
172 }
173 return generator;
174 } catch (ParseException e) {
175 throw new ConfigurationError("Error in generator spec", e);
176 }
177 }
178
179
180
181
182
183
184
185
186 @SuppressWarnings({"unchecked", "rawtypes"})
187 public static Validator getValidator(String validatorSpec, BeneratorContext context) {
188 try {
189 if (StringUtil.isEmpty(validatorSpec)) {
190 return null;
191 }
192
193 Validator result = null;
194 Expression[] beanExpressions = DatabeneScriptParser.parseBeanSpecList(validatorSpec);
195 Object[] beans = ExpressionUtil.evaluateAll(beanExpressions, context);
196 for (Object bean : beans) {
197
198 Validator validator;
199 if (bean instanceof Validator) {
200 validator = (Validator<?>) bean;
201 } else if (bean instanceof ConstraintValidator) {
202 validator = new BeanConstraintValidator((ConstraintValidator) bean);
203 } else {
204 throw new ConfigurationError("Unknown validator type: " + BeanUtil.simpleClassName(bean));
205 }
206
207
208 if (result == null) {
209
210 result = validator;
211 } else if (result instanceof AndValidator) {
212
213 ((AndValidator) result).add(validator);
214 } else {
215 result = new AndValidator(result, validator);
216 }
217 }
218 result = BeneratorFactory.getInstance().configureValidator(result, context);
219 return result;
220 } catch (ParseException e) {
221 throw new ConfigurationError("Invalid validator definition", e);
222 }
223 }
224
225
226
227
228
229
230
231
232 @SuppressWarnings({"unchecked", "rawtypes"})
233 public static Converter getConverter(String converterSpec, BeneratorContext context) {
234 try {
235 if (StringUtil.isEmpty(converterSpec)) {
236 return null;
237 }
238
239 Converter result = null;
240 Expression[] beanExpressions = DatabeneScriptParser.parseBeanSpecList(converterSpec);
241 Object[] beans = ExpressionUtil.evaluateAll(beanExpressions, context);
242 for (Object bean : beans) {
243 Converter converter;
244 if (bean instanceof java.text.Format) {
245 converter = new FormatFormatConverter(Object.class, (java.text.Format) bean, false);
246 } else if (bean instanceof Converter) {
247 converter = (Converter) bean;
248 } else {
249 throw new ConfigurationError(bean + " is not an instance of " + Converter.class);
250 }
251 converter = BeneratorFactory.getInstance().configureConverter(converter, context);
252
253 if (result == null) {
254 result = converter;
255 } else if (result instanceof ConverterChain) {
256 ((ConverterChain) result).addComponent(converter);
257 } else {
258 result = new ConverterChain(result, converter);
259 }
260 }
261 return result;
262 } catch (ParseException e) {
263 throw new ConfigurationError("Error parsing converter spec: " + converterSpec, e);
264 }
265 }
266
267
268
269
270
271
272
273 public static DateFormat getPatternAsDateFormat(TypeDescriptor descriptor) {
274 String pattern = descriptor.getPattern();
275 if (pattern != null) {
276 return new SimpleDateFormat(pattern);
277 } else {
278 return TimeUtil.createDefaultDateFormat();
279 }
280 }
281
282
283
284
285
286
287
288
289 public static Uniqueness getUniqueness(InstanceDescriptor descriptor, BeneratorContext context) {
290 if (descriptor instanceof IdDescriptor) {
291 return Uniqueness.ORDERED;
292 } else if (isUnique(descriptor, context)) {
293 return Uniqueness.SIMPLE;
294 } else {
295 return Uniqueness.NONE;
296 }
297 }
298
299
300
301
302
303
304
305
306 public static boolean isUnique(InstanceDescriptor descriptor, BeneratorContext context) {
307 Boolean unique = descriptor.isUnique();
308 if (unique == null) {
309 unique = context.getGeneratorFactory().defaultUnique();
310 }
311 return unique;
312 }
313
314
315
316
317
318
319
320
321 public static char getSeparator(TypeDescriptor descriptor, BeneratorContext context) {
322 char separator = (context != null ? context.getDefaultSeparator() : ',');
323 if (!StringUtil.isEmpty(descriptor.getSeparator())) {
324 if (descriptor.getSeparator().length() > 1) {
325 throw new ConfigurationError("A CSV separator must be one character, but was: " + descriptor.getSeparator());
326 }
327 separator = descriptor.getSeparator().charAt(0);
328 }
329 return separator;
330 }
331
332
333
334
335
336
337
338
339 @SuppressWarnings("unchecked")
340 public static Expression<Long> getCount(InstanceDescriptor descriptor) {
341 Expression<Long> result = descriptor.getCount();
342 if (result != null) {
343 Expression<Long> globalMaxCount = getGlobalMaxCount();
344 if (globalMaxCount != null) {
345 result = new MinExpression<>(result, globalMaxCount);
346 }
347 }
348 return result;
349 }
350
351
352
353
354
355
356
357 public static Expression<Long> getMinCount(InstanceDescriptor descriptor) {
358 return getMinCount(descriptor, 1L);
359 }
360
361
362
363
364
365
366
367
368 @SuppressWarnings("unchecked")
369 public static Expression<Long> getMinCount(InstanceDescriptor descriptor, Long defaultMin) {
370 Expression<Long> result = null;
371 if (descriptor.getCount() != null) {
372 result = descriptor.getCount();
373 } else if (descriptor.getMinCount() != null) {
374 result = descriptor.getMinCount();
375 } else if (defaultMin != null) {
376 result = new ConstantExpression<>(defaultMin);
377 } else {
378 return new ConstantExpression<>(null);
379 }
380 Expression<Long> globalMaxCount = getGlobalMaxCount();
381 if (!ExpressionUtil.isNull(globalMaxCount)) {
382 result = new MinExpression<>(result, globalMaxCount);
383 }
384 return result;
385 }
386
387
388
389
390
391
392
393
394 @SuppressWarnings("unchecked")
395 public static Expression<Long> getMaxCount(InstanceDescriptor descriptor, Long defaultMax) {
396 Expression<Long> result = null;
397 if (descriptor.getCount() != null) {
398 result = descriptor.getCount();
399 } else if (descriptor.getMaxCount() != null) {
400 result = descriptor.getMaxCount();
401 } else if (descriptor instanceof ComponentDescriptor && defaultMax != null) {
402 result = new ConstantExpression<>(defaultMax);
403 } else {
404 return getGlobalMaxCount();
405 }
406 Expression<Long> globalMaxCount = getGlobalMaxCount();
407 if (!ExpressionUtil.isNull(globalMaxCount)) {
408 result = new MinExpression<>(result, globalMaxCount);
409 }
410 return result;
411 }
412
413 private static Expression<Long> getGlobalMaxCount() {
414 return new GlobalMaxCountExpression();
415 }
416
417
418
419
420
421
422
423 public static Expression<Long> getCountGranularity(InstanceDescriptor descriptor) {
424 return (descriptor.getCountGranularity() != null ?
425 descriptor.getCountGranularity() :
426 new ConstantExpression<>(1L));
427 }
428
429
430
431
432
433
434
435 public static Converter<String, String> createStringScriptConverter(BeneratorContext context) {
436 return new ConverterChain<>(
437 new ScriptConverterForStrings(context),
438 new ToStringConverter(null)
439 );
440 }
441
442
443
444
445
446
447
448
449
450
451
452 public static Generator<Long> createDynamicCountGenerator(final InstanceDescriptor descriptor,
453 Long defaultMin, Long defaultMax, boolean resetToMin, BeneratorContext context) {
454 Expression<Long> count = DescriptorUtil.getCount(descriptor);
455 if (count != null) {
456 return new ExpressionBasedGenerator<>(count, Long.class);
457 } else {
458 final Expression<Long> minCount = DescriptorUtil.getMinCount(descriptor, defaultMin);
459 final Expression<Long> maxCount = DescriptorUtil.getMaxCount(descriptor, defaultMax);
460 final Expression<Long> countGranularity = DescriptorUtil.getCountGranularity(descriptor);
461 if (minCount.isConstant()) {
462 if (maxCount.isConstant() && descriptor.getCountDistribution() == null) {
463
464
465 Long minCountValue = minCount.evaluate(context);
466 Long maxCountValue = maxCount.evaluate(context);
467 if (NullSafeComparator.equals(minCountValue, maxCountValue)) {
468 return new ConstantGenerator<>(minCountValue);
469 }
470 } else {
471
472
473 return new ExpressionBasedGenerator<>(maxCount, Long.class);
474 }
475 }
476
477 final Expression<Distribution> countDistribution =
478 FactoryUtil.getDistributionExpression(descriptor.getCountDistribution(), Uniqueness.NONE, true);
479 return new DynamicCountGenerator(minCount, maxCount, countGranularity, countDistribution,
480 ExpressionUtil.constant(false), resetToMin);
481 }
482 }
483
484
485
486
487
488
489
490
491
492
493 public static <T extends Number> T getNumberDetail(SimpleTypeDescriptor descriptor, String detailName, Class<T> targetType) {
494 try {
495 String detailValue = (String) descriptor.getDetailValue(detailName);
496 return (detailValue != null ? new String2NumberConverter<>(targetType).convert(detailValue) : null);
497 } catch (ConversionException e) {
498 throw new ConfigurationError(e);
499 }
500 }
501
502
503
504
505
506
507
508
509 public static void parseComponentConfig(Element element, TypeDescriptor type, BeneratorContext context) {
510
511 ModelParser/ModelParser.html#ModelParser">ModelParser parser = new ModelParser(context);
512 int valueCount = 0;
513 for (Element child : XMLUtil.getChildElements(element)) {
514 String childType = XMLUtil.localName(child);
515 if (EL_VARIABLE.equals(childType)) {
516 parser.parseVariable(child, (VariableHolder) type);
517 } else if (COMPONENT_TYPES.contains(childType)) {
518 parser.parseComponent(child, (ComplexTypeDescriptor) type);
519 } else if (EL_VALUE.equals(childType)) {
520 parser.parseSimpleTypeArrayElement(child, (ArrayTypeDescriptor) type, valueCount++);
521 }
522 }
523 }
524
525
526
527
528
529
530
531
532 public static boolean isNullable(InstanceDescriptor descriptor, BeneratorContext context) {
533 Boolean nullable = descriptor.isNullable();
534 if (nullable != null) {
535 return nullable;
536 }
537 Double nullQuota = descriptor.getNullQuota();
538 if (nullQuota != null && nullQuota > 0) {
539 return true;
540 }
541 TypeDescriptor typeDescriptor = descriptor.getTypeDescriptor();
542 if (descriptor.getNullQuota() == null && typeDescriptor != null) {
543
544 if (typeDescriptor.getSource() != null || typeDescriptor.getGenerator() != null) {
545 return false;
546 }
547 }
548 return context.getDefaultsProvider().defaultNullable();
549 }
550
551
552
553
554
555
556
557
558 public static boolean shouldNullifyEachNullable(
559 InstanceDescriptor descriptor, BeneratorContext context) {
560
561 Double nullQuota = descriptor.getNullQuota();
562 if (nullQuota != null && nullQuota == 1.) {
563 return true;
564 }
565
566 Boolean nullable = descriptor.isNullable();
567 if (nullable != null && !nullable) {
568
569 return false;
570 }
571 if (context.getDefaultsProvider().defaultNullQuota() < 1) {
572 return false;
573 }
574 return (!descriptor.overwritesParent() && context.isDefaultNull());
575 }
576
577
578
579
580
581
582
583
584
585
586
587 protected static <T> Generator<T> wrapWithProxy(Generator<T> generator, TypeDescriptor descriptor) {
588 generator = processOffset(generator, descriptor);
589 generator = processCyclic(generator, descriptor);
590 return generator;
591 }
592
593
594
595
596
597
598
599
600
601 public static <T> Generator<T> processCyclic(Generator<T> generator,
602 TypeDescriptor descriptor) {
603 boolean cyclic = descriptor.isCyclic() != null && descriptor.isCyclic();
604 if (cyclic) {
605 generator = WrapperFactory.applyCycler(generator);
606 }
607 return generator;
608 }
609
610
611
612
613
614
615
616
617
618 public static <T> Generator<T> processOffset(Generator<T> generator, TypeDescriptor descriptor) {
619 int offset = getOffset(descriptor);
620 if (offset > 0) {
621 generator = WrapperFactory.applyOffset(generator, offset);
622 }
623 return generator;
624 }
625
626
627
628
629
630
631
632 protected static int getOffset(TypeDescriptor descriptor) {
633 Integer offset = descriptor.getOffset();
634 return (offset != null ? offset : 0);
635 }
636
637
638
639
640
641
642
643 protected static Integer getMinLength(SimpleTypeDescriptor descriptor) {
644 Integer minLength = descriptor.getMinLength();
645 if (minLength == null) {
646 minLength = 0;
647 }
648 return minLength;
649 }
650
651
652
653
654
655
656
657
658 protected static Integer getMaxLength(SimpleTypeDescriptor descriptor, DefaultsProvider defaultsProvider) {
659
660 Integer maxLength = (Integer) descriptor.getDeclaredDetailValue(MAX_LENGTH);
661 if (maxLength == null) {
662
663 maxLength = descriptor.getMaxLength();
664 if (maxLength == null) {
665 maxLength = defaultsProvider.defaultMaxLength();
666 }
667 }
668 return maxLength;
669 }
670
671
672
673
674
675
676
677
678 public static Generator<?> createNullQuotaOneGenerator(InstanceDescriptor descriptor, BeneratorContext context) {
679
680 Double nullQuota = descriptor.getNullQuota();
681 if (nullQuota != null && nullQuota == 1.) {
682 return MetaGeneratorFactory.createNullGenerator(descriptor.getTypeDescriptor(), context);
683 } else {
684 return null;
685 }
686 }
687
688
689
690
691
692
693
694
695 public static TypeDescriptorweller/model/data/TypeDescriptor.html#TypeDescriptor">TypeDescriptor deriveType(String name, TypeDescriptor parentType) {
696 if (parentType instanceof SimpleTypeDescriptor) {
697 return new SimpleTypeDescriptorta/SimpleTypeDescriptor.html#SimpleTypeDescriptor">SimpleTypeDescriptor(name, parentType.getProvider(), (SimpleTypeDescriptor) parentType);
698 } else if (parentType instanceof ComplexTypeDescriptor) {
699 return new ComplexTypeDescriptora/ComplexTypeDescriptor.html#ComplexTypeDescriptor">ComplexTypeDescriptor(name, parentType.getProvider(), (ComplexTypeDescriptor) parentType);
700 } else if (parentType instanceof ArrayTypeDescriptor) {
701 return new ArrayTypeDescriptorata/ArrayTypeDescriptor.html#ArrayTypeDescriptor">ArrayTypeDescriptor(name, parentType.getProvider(), (ArrayTypeDescriptor) parentType);
702 } else {
703 throw new UnsupportedOperationException("Cannot derive child type from " + parentType.getClass());
704 }
705 }
706
707
708
709
710 static class GlobalMaxCountExpression implements Expression<Long> {
711 @Override
712 public boolean isConstant() {
713 return true;
714 }
715
716 @Override
717 public Long evaluate(Context context) {
718 return ((BeneratorContext) context).getMaxCount();
719 }
720 }
721
722 }