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.anno;
28
29 import com.rapiddweller.benerator.Generator;
30 import com.rapiddweller.benerator.engine.BeneratorContext;
31 import com.rapiddweller.benerator.engine.DescriptorBasedGenerator;
32 import com.rapiddweller.benerator.factory.ArrayTypeGeneratorFactory;
33 import com.rapiddweller.benerator.factory.CoverageGeneratorFactory;
34 import com.rapiddweller.benerator.factory.DescriptorUtil;
35 import com.rapiddweller.benerator.factory.EquivalenceGeneratorFactory;
36 import com.rapiddweller.benerator.factory.GeneratorFactory;
37 import com.rapiddweller.benerator.factory.GentleDefaultsProvider;
38 import com.rapiddweller.benerator.factory.InstanceGeneratorFactory;
39 import com.rapiddweller.benerator.factory.MeanDefaultsProvider;
40 import com.rapiddweller.benerator.factory.SerialGeneratorFactory;
41 import com.rapiddweller.benerator.factory.StochasticGeneratorFactory;
42 import com.rapiddweller.benerator.wrapper.LastFlagGenerator;
43 import com.rapiddweller.benerator.wrapper.NShotGeneratorProxy;
44 import com.rapiddweller.benerator.wrapper.WrapperFactory;
45 import com.rapiddweller.common.BeanUtil;
46 import com.rapiddweller.common.CollectionUtil;
47 import com.rapiddweller.common.ConfigurationError;
48 import com.rapiddweller.common.ParseException;
49 import com.rapiddweller.common.ProgrammerError;
50 import com.rapiddweller.common.StringUtil;
51 import com.rapiddweller.common.TimeUtil;
52 import com.rapiddweller.common.context.ContextAware;
53 import com.rapiddweller.format.script.ScriptUtil;
54 import com.rapiddweller.format.util.DataFileUtil;
55 import com.rapiddweller.model.data.ArrayElementDescriptor;
56 import com.rapiddweller.model.data.ArrayTypeDescriptor;
57 import com.rapiddweller.model.data.ComplexTypeDescriptor;
58 import com.rapiddweller.model.data.DataModel;
59 import com.rapiddweller.model.data.DefaultDescriptorProvider;
60 import com.rapiddweller.model.data.InstanceDescriptor;
61 import com.rapiddweller.model.data.Mode;
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.platform.db.DBSystem;
66 import com.rapiddweller.platform.db.DefaultDBSystem;
67 import com.rapiddweller.platform.java.BeanDescriptorProvider;
68 import com.rapiddweller.platform.java.Entity2JavaConverter;
69 import com.rapiddweller.script.DatabeneScriptParser;
70 import org.apache.logging.log4j.LogManager;
71 import org.apache.logging.log4j.Logger;
72
73 import javax.validation.constraints.AssertFalse;
74 import javax.validation.constraints.AssertTrue;
75 import javax.validation.constraints.DecimalMax;
76 import javax.validation.constraints.DecimalMin;
77 import javax.validation.constraints.Digits;
78 import javax.validation.constraints.Future;
79 import javax.validation.constraints.Max;
80 import javax.validation.constraints.Min;
81 import javax.validation.constraints.NotNull;
82 import javax.validation.constraints.Null;
83 import javax.validation.constraints.Past;
84 import javax.validation.constraints.Pattern;
85 import javax.validation.constraints.Size;
86 import java.io.File;
87 import java.io.IOException;
88 import java.lang.annotation.Annotation;
89 import java.lang.reflect.Array;
90 import java.lang.reflect.Field;
91 import java.lang.reflect.Method;
92 import java.text.SimpleDateFormat;
93 import java.util.HashSet;
94 import java.util.Set;
95
96
97
98
99
100
101
102
103 public class AnnotationMapper extends DefaultDescriptorProvider {
104
105 private static final Logger LOGGER = LogManager.getLogger(AnnotationMapper.class);
106
107 private static final Set<String> STANDARD_METHODS;
108
109 private static final Package BENERATOR_ANNO_PACKAGE = Unique.class.getPackage();
110 private static final Package BEANVAL_ANNO_PACKAGE = Max.class.getPackage();
111
112 private static final Set<Class<? extends Annotation>> EXPLICITLY_MAPPED_ANNOTATIONS = CollectionUtil.toSet(
113 Bean.class,
114 Database.class,
115 Descriptor.class,
116 InvocationCount.class,
117 Factory.class, Equivalence.class, Coverage.class, Serial.class,
118 Defaults.class, Gentle.class, Mean.class,
119 ThreadPoolSize.class);
120
121 static {
122 STANDARD_METHODS = new HashSet<>();
123 for (Method method : Annotation.class.getMethods()) {
124 STANDARD_METHODS.add(method.getName());
125 }
126 }
127
128 private final DataModel dataModel;
129 private final PathResolver pathResolver;
130
131 private final ArrayTypeGeneratorFactory arrayTypeGeneratorFactory;
132
133
134
135
136
137
138
139 public AnnotationMapper(DataModel dataModel, PathResolver pathResolver) {
140 super("anno", dataModel);
141 this.dataModel = dataModel;
142 this.dataModel.addDescriptorProvider(this);
143 this.arrayTypeGeneratorFactory = new ArrayTypeGeneratorFactory();
144 this.pathResolver = pathResolver;
145 }
146
147
148
149 private static boolean containsConfig(Annotation[] annotations) {
150 for (Annotation annotation : annotations) {
151 Package annoPkg = annotation.annotationType().getPackage();
152 if ((annoPkg == BENERATOR_ANNO_PACKAGE || annoPkg == BEANVAL_ANNO_PACKAGE) &&
153 explicitlyMappedAnnotation(annotation)) {
154 return true;
155 }
156 }
157 return false;
158 }
159
160
161
162
163
164
165
166 protected static boolean explicitlyMappedAnnotation(Annotation annotation) {
167 return !EXPLICITLY_MAPPED_ANNOTATIONS
168 .contains(annotation.annotationType());
169 }
170
171 private static boolean applyDefaultsProvider(Annotation[] annotations, BeneratorContext context) {
172 for (Annotation annotation : annotations) {
173 if (annotation instanceof Defaults) {
174 context.setDefaultsProvider(BeanUtil.newInstance(((Defaults) annotation).value()));
175 return true;
176 } else if (annotation instanceof Gentle) {
177 context.setDefaultsProvider(new GentleDefaultsProvider());
178 return true;
179 } else if (annotation instanceof Mean) {
180 context.setDefaultsProvider(new MeanDefaultsProvider());
181 return true;
182 }
183 }
184 return false;
185 }
186
187 private static int indexOfLast(MethodDescriptor testMethod) {
188 Annotation[][] paramsAnnotations = testMethod.getParameterAnnotations();
189 for (int i = 0; i < paramsAnnotations.length; i++) {
190 for (Annotation paramAnnotation : paramsAnnotations[i]) {
191 if (paramAnnotation.annotationType() == Last.class) {
192 return i;
193 }
194 }
195 }
196 return -1;
197 }
198
199
200
201 @SuppressWarnings({"unchecked", "rawtypes"})
202 private static Generator<Object[]> createDescriptorBasedGenerator(Descriptor annotation, MethodDescriptor testMethod, BeneratorContext context) {
203 String filename = null;
204 try {
205 if (annotation.file().length() > 0) {
206 filename = annotation.file();
207 } else {
208 filename = testMethod.getDeclaringClass().getName().replace('.', File.separatorChar) + ".ben.xml";
209 }
210 String testName;
211 if (annotation.name().length() > 0) {
212 testName = annotation.name();
213 } else {
214 testName = testMethod.getName();
215 }
216 return (Generator) new DescriptorBasedGenerator(filename, testName, context);
217 } catch (IOException e) {
218 throw new RuntimeException("Error opening file " + filename, e);
219 }
220 }
221
222 private static void parseDatabase(Database annotation, BeneratorContext context) {
223 DBSystem db;
224 if (!StringUtil.isEmpty(annotation.environment())) {
225 db = new DefaultDBSystem(annotation.id(), annotation.environment(), context.getDataModel());
226 } else {
227 db = new DefaultDBSystem(annotation.id(), annotation.url(), annotation.driver(),
228 annotation.user(), annotation.password(), context.getDataModel());
229 }
230 if (!StringUtil.isEmpty(annotation.catalog())) {
231 db.setCatalog(annotation.catalog());
232 }
233 if (!StringUtil.isEmpty(annotation.schema())) {
234 db.setSchema(annotation.schema());
235 }
236 db.setLazy(true);
237 context.setGlobal(db.getId(), db);
238 }
239
240 private static void parseBean(Bean annotation, BeneratorContext context) {
241 Object bean = instantiateBean(annotation, context);
242 applyProperties(annotation.properties(), bean, context);
243 context.setGlobal(annotation.id(), bean);
244 if (bean instanceof ContextAware) {
245 ((ContextAware) bean).setContext(context);
246 }
247 }
248
249 private static Object instantiateBean(Bean beanAnno, BeneratorContext context) {
250 String beanSpec = beanAnno.spec();
251 Class<?> beanClass = beanAnno.type();
252 if (!StringUtil.isEmpty(beanSpec)) {
253 try {
254 if (beanClass != Object.class) {
255 throw new ConfigurationError("'type' and 'spec' exclude each other in a @Bean");
256 }
257 return DatabeneScriptParser.parseBeanSpec(beanSpec).evaluate(context);
258 } catch (ParseException e) {
259 throw new ConfigurationError("Error parsing bean spec: " + beanSpec, e);
260 }
261 } else if (beanClass != Object.class) {
262 return BeanUtil.newInstance(beanClass);
263 } else {
264 throw new ConfigurationError("@Bean is missing 'type' or 'spec' attribute");
265 }
266 }
267
268 private static void applyProperties(Property[] properties, Object bean, BeneratorContext context) {
269 for (Property property : properties) {
270 Object value = resolveProperty(property, bean, context);
271 BeanUtil.setPropertyValue(bean, property.name(), value, true, true);
272 }
273 }
274
275 private static Object resolveProperty(Property property, Object bean, BeneratorContext context) {
276 if (!StringUtil.isEmpty(property.value())) {
277 if (!StringUtil.isEmpty(property.ref())) {
278 throw new ConfigurationError("'value' and 'ref' exclude each other in a @Property");
279 }
280 Object value = ScriptUtil.evaluate(property.value(), context);
281 if (value instanceof String) {
282 value = StringUtil.unescape((String) value);
283 }
284 return value;
285 } else if (!StringUtil.isEmpty(property.ref())) {
286 return context.get(property.ref());
287 } else {
288 throw new ConfigurationError("@Property is missing 'value' or 'ref' attribute");
289 }
290 }
291
292 private static void mapSizeAnnotation(Size size, InstanceDescriptor instanceDescriptor) {
293 setDetail("minLength", size.min(), instanceDescriptor);
294 setDetail("maxLength", size.max(), instanceDescriptor);
295 }
296
297 private static void mapPatternAnnotation(Pattern pattern, InstanceDescriptor instanceDescriptor) {
298 if (!StringUtil.isEmpty(pattern.regexp())) {
299 setDetail("pattern", pattern.regexp(), instanceDescriptor);
300 }
301 }
302
303 private static void mapSourceSetting(String value, String detailName, InstanceDescriptor instanceDescriptor) {
304 if (!StringUtil.isEmpty(value)) {
305 setDetail(detailName, value, instanceDescriptor);
306 }
307 }
308
309 private static void mapFormatted(Source source, InstanceDescriptor instanceDescriptor) {
310 switch (source.format()) {
311 case formatted:
312 case raw:
313 setDetail("format", source.format().name(), instanceDescriptor);
314 break;
315 case globalDefault:
316 break;
317 default:
318 throw new UnsupportedOperationException("Not a supported Format: " + source.format());
319 }
320 }
321
322 private static void mapValuesAnnotation(Values annotation, InstanceDescriptor instanceDescriptor) throws Exception {
323 Method method = annotation.annotationType().getMethod("value");
324 String[] values = (String[]) method.invoke(annotation);
325 StringBuilder builder = new StringBuilder();
326 for (int i = 0; i < values.length; i++) {
327 if (i > 0) {
328 builder.append(',');
329 }
330 builder.append("'").append(values[i].replace("'", "\\'")).append("'");
331 }
332 ((SimpleTypeDescriptor) instanceDescriptor.getLocalType(false)).setValues(builder.toString());
333 }
334
335 private static void mapOffsetAnnotation(Offset annotation, InstanceDescriptor instanceDescriptor) {
336 if (annotation.value() != 0) {
337 instanceDescriptor.getLocalType().setOffset(annotation.value());
338 }
339 }
340
341 private static void mapMinDateAnnotation(MinDate annotation, InstanceDescriptor instanceDescriptor) {
342 TypeDescriptor localType = instanceDescriptor.getLocalType();
343 if (!(localType instanceof SimpleTypeDescriptor)) {
344 throw new ConfigurationError("@MinDate can only be applied to Date types");
345 }
346 ((SimpleTypeDescriptor) localType).setMin(annotation.value());
347 }
348
349 private static void mapMaxDateAnnotation(MaxDate annotation, InstanceDescriptor instanceDescriptor) {
350 TypeDescriptor localType = instanceDescriptor.getLocalType();
351 if (!(localType instanceof SimpleTypeDescriptor)) {
352 throw new ConfigurationError("@MaxDate can only be applied to Date types");
353 }
354 ((SimpleTypeDescriptor) localType).setMax(annotation.value());
355 }
356
357 private static void mapAnyValueTypeAnnotation(Annotation annotation, InstanceDescriptor instanceDescriptor) throws Exception {
358 Method method = annotation.annotationType().getMethod("value");
359 Object value = normalize(method.invoke(annotation));
360 String detailName = StringUtil.uncapitalize(annotation.annotationType().getSimpleName());
361 setDetail(detailName, value, instanceDescriptor);
362 }
363
364 private static void mapBeanValidationParameter(Annotation annotation, InstanceDescriptor element) {
365 SimpleTypeDescriptorweller/model/data/SimpleTypeDescriptor.html#SimpleTypeDescriptor">SimpleTypeDescriptor typeDescriptor = (SimpleTypeDescriptor) element.getLocalType(false);
366 if (annotation instanceof AssertFalse) {
367 typeDescriptor.setTrueQuota(0.);
368 } else if (annotation instanceof AssertTrue) {
369 typeDescriptor.setTrueQuota(1.);
370 } else if (annotation instanceof DecimalMax) {
371 typeDescriptor.setMax(String.valueOf(DescriptorUtil.convertType(((DecimalMax) annotation).value(), typeDescriptor)));
372 } else if (annotation instanceof DecimalMin) {
373 typeDescriptor.setMin(String.valueOf(DescriptorUtil.convertType(((DecimalMin) annotation).value(), typeDescriptor)));
374 } else if (annotation instanceof Digits) {
375 Digits digits = (Digits) annotation;
376 typeDescriptor.setGranularity(String.valueOf(Math.pow(10, -digits.fraction())));
377 } else if (annotation instanceof Future) {
378 typeDescriptor.setMin(new SimpleDateFormat("yyyy-MM-dd").format(TimeUtil.tomorrow()));
379 } else if (annotation instanceof Max) {
380 typeDescriptor.setMax(String.valueOf(((Max) annotation).value()));
381 } else if (annotation instanceof Min) {
382 typeDescriptor.setMin(String.valueOf(((Min) annotation).value()));
383 } else if (annotation instanceof NotNull) {
384 element.setNullable(false);
385 element.setNullQuota(0.);
386 } else if (annotation instanceof Null) {
387 element.setNullable(true);
388 element.setNullQuota(1.);
389 } else if (annotation instanceof Past) {
390 typeDescriptor.setMax(new SimpleDateFormat("yyyy-MM-dd").format(TimeUtil.yesterday()));
391 } else if (annotation instanceof Pattern) {
392 typeDescriptor.setPattern(((Pattern) annotation).regexp());
393 } else if (annotation instanceof Size) {
394 Size size = (Size) annotation;
395 typeDescriptor.setMinLength(size.min());
396 typeDescriptor.setMaxLength(size.max());
397 }
398 }
399
400 private static void setDetail(String detailName, Object detailValue, InstanceDescriptor instanceDescriptor) {
401 if (instanceDescriptor.supportsDetail(detailName)) {
402 instanceDescriptor.setDetailValue(detailName, detailValue);
403 } else {
404 instanceDescriptor.getLocalType().setDetailValue(detailName, detailValue);
405 }
406 }
407
408 private static Object normalize(Object value) {
409 if (value == null) {
410 return null;
411 }
412 if (value instanceof String && ((String) value).length() == 0) {
413 return null;
414 }
415 if (value.getClass().isArray() && Array.getLength(value) == 0) {
416 return null;
417 }
418 return value;
419 }
420
421
422
423
424
425
426
427
428 public void parseClassAnnotations(Annotation[] annotations, BeneratorContext context) {
429 for (Annotation annotation : annotations) {
430 if (annotation instanceof Database) {
431 parseDatabase((Database) annotation, context);
432 } else if (annotation instanceof Bean) {
433 parseBean((Bean) annotation, context);
434 }
435 }
436 }
437
438
439
440
441
442
443
444
445
446 public Generator<?> createAndInitAttributeGenerator(Field attribute, BeneratorContext context) {
447 Source sourceAnno = attribute.getAnnotation(Source.class);
448 if (sourceAnno != null) {
449 return createAndInitAttributeSourceGenerator(sourceAnno, attribute, context);
450 } else {
451 return null;
452 }
453 }
454
455
456
457
458
459
460
461
462 public Generator<Object[]> createAndInitMethodParamsGenerator(Method testMethod, BeneratorContext context) {
463 return createAndInitMethodParamsGenerator(new MethodDescriptor(testMethod), context);
464 }
465
466
467
468
469
470
471
472
473 public Generator<Object[]> createAndInitMethodParamsGenerator(MethodDescriptor testMethod, BeneratorContext context) {
474 applyMethodGeneratorFactory(testMethod, context);
475
476
477 if (testMethod.getAnnotation(Bean.class) != null) {
478 parseBean(testMethod.getAnnotation(Bean.class), context);
479 }
480 if (testMethod.getAnnotation(Database.class) != null) {
481 parseDatabase(testMethod.getAnnotation(Database.class), context);
482 }
483
484
485 ArrayTypeDescriptor type = createMethodParamsType(testMethod);
486 InstanceDescriptor instance = createMethodParamsInstanceDescriptor(testMethod, type);
487 Uniqueness uniqueness = (instance.isUnique() != null && instance.isUnique() ? Uniqueness.ORDERED : Uniqueness.NONE);
488
489
490 Generator<Object[]> generator = createGenerator(type, testMethod, uniqueness, context);
491 generator.init(context);
492 return generator;
493 }
494
495
496
497
498
499
500
501 protected ArrayTypeDescriptor createMethodParamsType(MethodDescriptor testMethod) {
502 ArrayTypeDescriptor nativeType = createNativeParamsDescriptor(testMethod);
503 return createConfiguredParamsDescriptor(testMethod, nativeType);
504 }
505
506
507
508
509
510
511
512
513 protected InstanceDescriptor createMethodParamsInstanceDescriptor(
514 MethodDescriptor testMethod, ArrayTypeDescriptor type) {
515 InstanceDescriptorptor.html#InstanceDescriptor">InstanceDescriptor instance = new InstanceDescriptor(testMethod.getName(), this, type);
516 for (Annotation annotation : testMethod.getAnnotations()) {
517 mapParamAnnotation(annotation, instance, testMethod.getDeclaringClass());
518 }
519 return instance;
520 }
521
522
523
524
525
526
527
528 protected ArrayTypeDescriptor createNativeParamsDescriptor(MethodDescriptor testMethod) {
529 ArrayTypeDescriptorl#ArrayTypeDescriptor">ArrayTypeDescriptor nativeDescriptor = new ArrayTypeDescriptor(testMethod.getName() + "_native", this);
530 Class<?>[] paramTypes = testMethod.getParameterTypes();
531 for (int i = 0; i < paramTypes.length; i++) {
532 TypeDescriptor elementType = dataModel.getTypeDescriptor(paramTypes[i].getName());
533 BeanDescriptorProvider beanDescriptorProvider = dataModel.getBeanDescriptorProvider();
534 ArrayElementDescriptor#ArrayElementDescriptor">ArrayElementDescriptor elementDescriptor = new ArrayElementDescriptor(i, beanDescriptorProvider, elementType);
535 if (elementDescriptor.isNullable() == null) {
536 if (BeanUtil.isPrimitiveType(paramTypes[i].getName())) {
537 elementDescriptor.setNullable(false);
538 } else {
539 elementDescriptor.setNullable(
540 elementDescriptor.getNullQuota() == null ||
541 ((Double) elementDescriptor
542 .getDeclaredDetailValue("nullQuota")) !=
543 0.);
544 }
545 }
546 nativeDescriptor.addElement(elementDescriptor);
547 }
548 return nativeDescriptor;
549 }
550
551 private ArrayTypeDescriptor createConfiguredParamsDescriptor(
552 MethodDescriptor testMethod, ArrayTypeDescriptor nativeDescriptor) {
553 ArrayTypeDescriptorscriptor.html#ArrayTypeDescriptor">ArrayTypeDescriptor type = new ArrayTypeDescriptor(
554 testMethod.getName() + "_configured", this, nativeDescriptor);
555 Class<?>[] parameterTypes = testMethod.getParameterTypes();
556 Annotation[][] paramAnnos = testMethod.getParameterAnnotations();
557 for (int i = 0; i < parameterTypes.length; i++) {
558 ArrayElementDescriptor parentElement = nativeDescriptor.getElement(i);
559 if (containsConfig(paramAnnos[i])) {
560 TypeDescriptor parentElementType = parentElement.getTypeDescriptor();
561 TypeDescriptor elementType = DescriptorUtil.deriveType(
562 parentElementType.getName(), parentElementType);
563 ArrayElementDescriptoriptor.html#ArrayElementDescriptor">ArrayElementDescriptor element = new ArrayElementDescriptor(i, this, elementType);
564 element.setParent(parentElement);
565 for (Annotation annotation : paramAnnos[i]) {
566 mapParamAnnotation(annotation, element, testMethod.getDeclaringClass());
567 }
568 type.addElement(element);
569 }
570 }
571 return type;
572 }
573
574
575
576
577
578
579
580 protected void applyMethodGeneratorFactory(MethodDescriptor testMethod, BeneratorContext context) {
581 boolean configured = applyGeneratorFactory(testMethod.getAnnotations(), context);
582 if (!configured) {
583 applyClassGeneratorFactory(testMethod.getDeclaringClass().getAnnotations(), context);
584 }
585 applyMethodDefaultsProvider(testMethod, context);
586 }
587
588 private void applyClassGeneratorFactory(Annotation[] annotations, BeneratorContext context) {
589 boolean configured = applyGeneratorFactory(annotations, context);
590 if (!configured) {
591 context.setGeneratorFactory(context.getGeneratorFactory());
592 }
593 }
594
595
596
597
598
599
600
601
602 protected boolean applyGeneratorFactory(Annotation[] annotations, BeneratorContext context) {
603 boolean configured = false;
604 for (Annotation annotation : annotations) {
605 if (annotation instanceof Factory) {
606 GeneratorFactory factory = BeanUtil.newInstance(((Factory) annotation).value());
607 factory.setDefaultsProvider(context.getDefaultsProvider());
608 context.setGeneratorFactory(factory);
609 return true;
610 } else if (annotation instanceof Equivalence) {
611 context.setGeneratorFactory(new EquivalenceGeneratorFactory());
612 return true;
613 } else if (annotation instanceof Coverage) {
614 context.setGeneratorFactory(new CoverageGeneratorFactory());
615 return true;
616 } else if (annotation instanceof Stochastic) {
617 context.setGeneratorFactory(new StochasticGeneratorFactory());
618 return true;
619 } else if (annotation instanceof Serial) {
620 context.setGeneratorFactory(new SerialGeneratorFactory());
621 return true;
622 }
623 }
624 return configured;
625 }
626
627
628
629
630
631
632
633 protected void applyMethodDefaultsProvider(MethodDescriptor testMethod, BeneratorContext context) {
634
635 boolean configured = applyDefaultsProvider(testMethod.getAnnotations(), context);
636
637 if (!configured) {
638 applyDefaultsProvider(testMethod.getDeclaringClass().getAnnotations(), context);
639 }
640
641 }
642
643
644
645
646
647
648
649
650
651
652 @SuppressWarnings({"unchecked", "rawtypes"})
653 private Generator<?> createAndInitAttributeSourceGenerator(
654 Source source, Field attribute, BeneratorContext context) {
655 String attName = attribute.getName();
656 TypeDescriptor typeDescriptor = createTypeDescriptor(attribute.getType());
657 InstanceDescriptoror.html#InstanceDescriptor">InstanceDescriptor descriptor = new InstanceDescriptor(attName, this, typeDescriptor);
658 Class<?> testClass = attribute.getDeclaringClass();
659 mapParamAnnotation(source, descriptor, testClass);
660 Offset offset = attribute.getAnnotation(Offset.class);
661 if (offset != null) {
662 mapParamAnnotation(offset, descriptor, testClass);
663 }
664 Generator generator = InstanceGeneratorFactory.createSingleInstanceGenerator(
665 descriptor, Uniqueness.NONE, context);
666 generator = WrapperFactory.applyConverter(generator, new Entity2JavaConverter());
667 generator.init(context);
668 return generator;
669 }
670
671
672
673
674
675
676
677
678
679
680 @SuppressWarnings("unchecked")
681 protected Generator<Object[]> createGenerator(ArrayTypeDescriptor type,
682 MethodDescriptor testMethod, Uniqueness uniqueness, BeneratorContext context) {
683 Generator<Object[]> generator;
684
685 Descriptor descriptorBasedAnno = testMethod.getAnnotation(Descriptor.class);
686 if (descriptorBasedAnno != null) {
687 context.setGeneratorFactory(new StochasticGeneratorFactory());
688 generator = createDescriptorBasedGenerator(descriptorBasedAnno, testMethod, context);
689 } else {
690 generator = (Generator<Object[]>) arrayTypeGeneratorFactory.createGenerator(
691 type, testMethod.getName(), false, uniqueness, context);
692 }
693 Class<?> generatedType = generator.getGeneratedType();
694 if (generatedType != Object[].class && generatedType != Object.class) {
695 throw new ProgrammerError("Expected Generator<Object[]> or Generator<Object>, but found Generator<" +
696 generatedType.getClass().getSimpleName() + '>');
697 }
698
699
700 InvocationCount testCount = testMethod.getAnnotation(InvocationCount.class);
701 if (testCount != null) {
702 generator = new NShotGeneratorProxy<>(generator, testCount.value());
703 }
704
705
706 generator = WrapperFactory.applyLastProductDetector(generator);
707
708 int indexOfLast = indexOfLast(testMethod);
709 if (indexOfLast >= 0) {
710 generator = new LastFlagGenerator(generator, indexOfLast);
711 }
712 return generator;
713 }
714
715
716
717
718
719
720
721
722
723
724 private <T> void mapParamAnnotation(Annotation annotation, InstanceDescriptor descriptor, Class<?> testClass) {
725 Package annoPackage = annotation.annotationType().getPackage();
726 if (BENERATOR_ANNO_PACKAGE.equals(annoPackage)) {
727 mapBeneratorParamAnnotation(annotation, descriptor, testClass);
728 } else if (BEANVAL_ANNO_PACKAGE.equals(annoPackage)) {
729 mapBeanValidationParameter(annotation, descriptor);
730 }
731 }
732
733 private void mapBeneratorParamAnnotation(Annotation annotation, InstanceDescriptor instanceDescriptor, Class<?> testClass) {
734 if (LOGGER.isDebugEnabled()) {
735 LOGGER.debug("mapDetails(" + annotation + ", " + instanceDescriptor + ")");
736 }
737 try {
738 Class<?> annotationType = annotation.annotationType();
739 if (annotationType == Unique.class) {
740 instanceDescriptor.setDetailValue("unique", true);
741 } else if (annotationType == Granularity.class) {
742 instanceDescriptor.getLocalType(false).setDetailValue("granularity", String
743 .valueOf(DescriptorUtil.convertType(((Granularity) annotation).value(), (SimpleTypeDescriptor) instanceDescriptor.getLocalType(false))));
744 } else if (annotationType == DecimalGranularity.class) {
745 instanceDescriptor.getLocalType(false).setDetailValue("granularity", String.valueOf(
746 DescriptorUtil.convertType(((DecimalGranularity) annotation).value(), (SimpleTypeDescriptor) instanceDescriptor.getLocalType(false))));
747 } else if (annotationType == SizeDistribution.class) {
748 instanceDescriptor.getLocalType(false).setDetailValue("lengthDistribution", ((SizeDistribution) annotation).value());
749 } else if (annotationType == Pattern.class) {
750 mapPatternAnnotation((Pattern) annotation, instanceDescriptor);
751 } else if (annotationType == Size.class) {
752 mapSizeAnnotation((Size) annotation, instanceDescriptor);
753 } else if (annotationType == Source.class) {
754 mapSourceAnnotation((Source) annotation, instanceDescriptor, testClass);
755 } else if (annotationType == Values.class) {
756 mapValuesAnnotation((Values) annotation, instanceDescriptor);
757 } else if (annotationType == Offset.class) {
758 mapOffsetAnnotation((Offset) annotation, instanceDescriptor);
759 } else if (annotationType == MinDate.class) {
760 mapMinDateAnnotation((MinDate) annotation, instanceDescriptor);
761 } else if (annotationType == MaxDate.class) {
762 mapMaxDateAnnotation((MaxDate) annotation, instanceDescriptor);
763 } else if (annotationType == Last.class) {
764 instanceDescriptor.setMode(Mode.ignored);
765 } else if (explicitlyMappedAnnotation(annotation)) {
766 mapAnyValueTypeAnnotation(annotation, instanceDescriptor);
767 }
768 } catch (Exception e) {
769 throw new ConfigurationError("Error mapping annotation settings", e);
770 }
771 }
772
773 private void mapSourceAnnotation(Source source, InstanceDescriptor instanceDescriptor, Class<?> testClass) {
774 mapSourceUriOrValue(source.value(), instanceDescriptor, testClass);
775 mapSourceUriOrValue(source.uri(), instanceDescriptor, testClass);
776 mapSourceSetting(source.segment(), "segment", instanceDescriptor);
777 mapSourceSetting(source.id(), "source", instanceDescriptor);
778 mapSourceSetting(source.dataset(), "dataset", instanceDescriptor);
779 mapSourceSetting(source.nesting(), "nesting", instanceDescriptor);
780 mapSourceSetting(source.encoding(), "encoding", instanceDescriptor);
781 mapSourceSetting(source.filter(), "filter", instanceDescriptor);
782 mapSourceSetting(source.selector(), "selector", instanceDescriptor);
783 mapSourceSetting(source.separator(), "separator", instanceDescriptor);
784 mapSourceSetting(source.emptyMarker(), "emptyMarker", instanceDescriptor);
785 mapSourceSetting(source.nullMarker(), "nullMarker", instanceDescriptor);
786 mapFormatted(source, instanceDescriptor);
787 setDetail("rowBased", source.rowBased(), instanceDescriptor);
788 }
789
790 private void mapSourceUriOrValue(String value, InstanceDescriptor instanceDescriptor, Class<?> testClass) {
791 if (DataFileUtil.isExcelOrCsvDocument(value)) {
792 value = pathResolver.getPathFor(value, testClass);
793 }
794 mapSourceSetting(value, "source", instanceDescriptor);
795 }
796
797
798
799
800
801
802
803 protected TypeDescriptor createTypeDescriptor(Class<?> type) {
804 String abstractType = dataModel.getBeanDescriptorProvider().abstractType(type);
805 TypeDescriptor baseTypeDescriptor = dataModel.getTypeDescriptor(abstractType);
806 TypeDescriptor typeDescriptor;
807 if (baseTypeDescriptor instanceof SimpleTypeDescriptor) {
808 typeDescriptor = new SimpleTypeDescriptorl#SimpleTypeDescriptor">SimpleTypeDescriptor(type.getName(), this, (SimpleTypeDescriptor) baseTypeDescriptor);
809 } else if (baseTypeDescriptor instanceof ComplexTypeDescriptor) {
810 typeDescriptor = new ComplexTypeDescriptorl#ComplexTypeDescriptor">ComplexTypeDescriptor(type.getName(), this, (ComplexTypeDescriptor) baseTypeDescriptor);
811 } else {
812 throw new ConfigurationError("Cannot handle descriptor: " + baseTypeDescriptor);
813 }
814 return typeDescriptor;
815 }
816
817 }