1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.nuiton.topia.generator;
25
26 import org.apache.commons.lang3.RandomStringUtils;
27 import org.apache.commons.lang3.StringUtils;
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.codehaus.plexus.component.annotations.Component;
31 import org.nuiton.eugene.GeneratorUtil;
32 import org.nuiton.eugene.Template;
33 import org.nuiton.eugene.java.JavaBuilder;
34 import org.nuiton.eugene.java.ObjectModelTransformerToJava;
35 import org.nuiton.eugene.models.object.ObjectModel;
36 import org.nuiton.eugene.models.object.ObjectModelAssociationClass;
37 import org.nuiton.eugene.models.object.ObjectModelAttribute;
38 import org.nuiton.eugene.models.object.ObjectModelClass;
39 import org.nuiton.eugene.models.object.ObjectModelClassifier;
40 import org.nuiton.eugene.models.object.ObjectModelJavaModifier;
41 import org.nuiton.eugene.models.object.ObjectModelModifier;
42 import org.nuiton.eugene.models.object.ObjectModelOperation;
43 import org.nuiton.eugene.models.object.ObjectModelType;
44 import org.nuiton.topia.framework.TopiaQuery;
45 import org.nuiton.topia.persistence.TopiaEntity;
46
47 import java.util.HashMap;
48 import java.util.Map;
49
50
51
52
53
54
55
56
57 @Component(role = Template.class, hint = "org.nuiton.topia.generator.QueryHelperTransformer")
58 public class QueryHelperTransformer extends ObjectModelTransformerToJava {
59
60 private static final Log log = LogFactory.getLog(QueryHelperTransformer.class);
61
62 protected ObjectModelClass helperClass;
63
64 protected ObjectModelClass abstractEntityPropertyClass;
65
66 protected static final String ENTITY_PROPERTY_CLASS_NAME = "EntityProperty";
67
68 protected static final String ENTITY_PROPERTY_SUFFIX = "Property";
69
70 protected static final String ENTITY_PROPERTY_GENERIC_TYPE = "<E>";
71
72 protected String mainException;
73
74 protected Map<String, String> aliases;
75
76 public static final String CONSTANT_PREFIX = "ALIAS_";
77
78
79
80 @Override
81 public void transformFromModel(ObjectModel model) {
82
83 aliases = new HashMap<String, String>();
84
85 String modelName = StringUtils.capitalize(model.getName());
86 String packageName = getDefaultPackageName();
87 helperClass = createClass(modelName + "QueryHelper", packageName);
88
89 addImport(helperClass, TopiaQuery.class);
90 addImport(helperClass, TopiaEntity.class);
91
92 String exception = TopiaGeneratorUtil.getExceptionClassTagValue(model);
93 if (exception != null) {
94 addImport(helperClass, exception);
95 mainException = TopiaGeneratorUtil.getSimpleName(exception);
96 }
97
98 initConstantPrefixFromModel();
99
100 createInnerAbstractEntityPropertyClass();
101 createUtilOperations();
102 }
103
104 protected void createInnerAbstractEntityPropertyClass() {
105
106 abstractEntityPropertyClass = (ObjectModelClass)addInnerClassifier(helperClass,
107 ObjectModelType.OBJECT_MODEL_CLASS,
108 ENTITY_PROPERTY_CLASS_NAME + ENTITY_PROPERTY_GENERIC_TYPE,
109 ObjectModelJavaModifier.ABSTRACT,
110 ObjectModelJavaModifier.STATIC);
111
112 addImport(helperClass, HashMap.class);
113 addImport(helperClass, Map.class);
114
115 addAttribute(abstractEntityPropertyClass, "alias",
116 String.class, null,
117 ObjectModelJavaModifier.PROTECTED);
118
119 addAttribute(abstractEntityPropertyClass, "propertiesCache",
120 "Map<String, String>", null,
121 ObjectModelJavaModifier.PROTECTED);
122
123
124
125
126
127 ObjectModelOperation constructor =
128 builder.addOperation(abstractEntityPropertyClass, ENTITY_PROPERTY_CLASS_NAME, null, ObjectModelJavaModifier.PUBLIC);
129
130 setOperationBody(constructor, ""
131
132
133
134 );
135
136
137 ObjectModelOperation setAlias =
138 addOperation(abstractEntityPropertyClass, "setAlias", "void",
139 ObjectModelJavaModifier.PROTECTED);
140 addParameter(setAlias, String.class, "alias");
141
142
143 setOperationBody(setAlias, ""
144
145
146
147 );
148
149 ObjectModelOperation getAlias =
150 addOperation(abstractEntityPropertyClass, "$alias", String.class,
151 ObjectModelJavaModifier.PUBLIC);
152
153
154 setOperationBody(getAlias, ""
155
156
157
158 );
159
160
161 ObjectModelOperation getProperty =
162 addOperation(abstractEntityPropertyClass, "$property", String.class,
163 ObjectModelJavaModifier.PUBLIC);
164 addParameter(getProperty, String.class, "propertyName");
165
166
167 setOperationBody(getProperty, ""
168
169
170
171
172
173
174
175
176 );
177
178 ObjectModelOperation topiaCreateDate =
179 addOperation(abstractEntityPropertyClass, "topiaCreateDate", String.class,
180 ObjectModelJavaModifier.PUBLIC);
181
182 setOperationBody(topiaCreateDate, ""
183
184
185
186 );
187
188 ObjectModelOperation topiaId =
189 addOperation(abstractEntityPropertyClass, "topiaId", String.class,
190 ObjectModelJavaModifier.PUBLIC);
191
192 setOperationBody(topiaId, ""
193
194
195
196 );
197
198 ObjectModelOperation topiaVersion =
199 addOperation(abstractEntityPropertyClass, "topiaVersion", String.class,
200 ObjectModelJavaModifier.PUBLIC);
201
202 setOperationBody(topiaVersion, ""
203
204
205
206 );
207
208
209 addOperation(abstractEntityPropertyClass, "getEntityClass",
210 "Class" + ENTITY_PROPERTY_GENERIC_TYPE,
211 ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.ABSTRACT);
212
213 addOperation(abstractEntityPropertyClass, "defaultAlias", String.class,
214 ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.ABSTRACT);
215 }
216
217 protected void createUtilOperations() {
218
219
220 ObjectModelOperation createQuery =
221 addOperation(helperClass, "createQuery", TopiaQuery.class,
222 ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC);
223 addParameter(createQuery, ENTITY_PROPERTY_CLASS_NAME, "property");
224
225 setOperationBody(createQuery, ""
226
227
228
229 );
230
231
232 ObjectModelOperation format =
233 addOperation(helperClass, "format", String.class,
234 ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC);
235 addParameter(format, String.class, "statement");
236 addParameter(format, "String...", "propertyNames");
237
238 setOperationBody(format, ""
239
240
241
242
243
244
245 );
246
247
248 String genericType = "<P extends " + ENTITY_PROPERTY_CLASS_NAME + "> P";
249 ObjectModelOperation newEntityProperty1 =
250 addOperation(helperClass, "newEntityProperty", genericType,
251 ObjectModelJavaModifier.PRIVATE, ObjectModelJavaModifier.STATIC);
252 addParameter(newEntityProperty1, "Class<P>", "propertyClass");
253
254 setOperationBody(newEntityProperty1, ""
255
256
257
258 );
259 ObjectModelOperation newEntityProperty2 =
260 addOperation(helperClass, "newEntityProperty", genericType,
261 ObjectModelJavaModifier.PRIVATE, ObjectModelJavaModifier.STATIC);
262 addParameter(newEntityProperty2, "Class<P>", "propertyClass");
263 addParameter(newEntityProperty2, String.class, "alias");
264
265 StringBuilder buffer = new StringBuilder(""
266
267
268
269
270
271
272
273
274
275
276 );
277
278 if (mainException != null) {
279 addException(newEntityProperty1, mainException);
280 addException(newEntityProperty2, mainException);
281 buffer.append(""
282
283
284
285 );
286 } else {
287 buffer.append(""
288
289
290
291 );
292 }
293 buffer.append(""
294
295
296
297 );
298
299 setOperationBody(newEntityProperty2, buffer.toString());
300 }
301
302
303
304 @Override
305
306 public void transformFromClassifier(ObjectModelClassifier clazz) {
307 if (!TopiaGeneratorUtil.hasEntityStereotype(clazz)) {
308 return;
309 }
310
311
312 String aliasConstant = createAliasConstant(clazz.getName());
313
314
315 ObjectModelClass entityPropertyClass = createInnerClass(clazz, aliasConstant);
316
317
318 createNewOperations(entityPropertyClass);
319
320 addExtraForSubEntity(clazz);
321 }
322
323 protected String createAliasConstant(String entityName) {
324
325 String constantName =
326 TopiaGeneratorUtil.convertVariableNameToConstantName(entityName);
327
328 String[] words = constantName.split("_");
329 String alias = "";
330
331 for (String word : words) {
332 alias += word.substring(0, 1);
333 }
334
335
336 String lastWord = words[words.length - 1];
337 while(aliases.containsKey(alias)) {
338
339 lastWord = lastWord.substring(1, lastWord.length());
340 if (!lastWord.isEmpty()) {
341
342 alias += lastWord.charAt(0);
343 } else {
344
345 alias += StringUtils.upperCase(RandomStringUtils.randomAlphabetic(1));
346 }
347 }
348
349 String aliasPropertyName = CONSTANT_PREFIX + constantName;
350
351 if (log.isDebugEnabled()) {
352 log.debug("Add alias '" + alias + "' named " + aliasPropertyName);
353 }
354
355 aliases.put(alias, aliasPropertyName);
356
357 addAttribute(helperClass, aliasPropertyName, String.class, "\"" + alias + "\"",
358 ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC, ObjectModelJavaModifier.FINAL);
359
360 return aliasPropertyName;
361 }
362
363 protected ObjectModelClass createInnerClass(ObjectModelClassifier input, String aliasConstant) {
364 String className = getPropertyClassName(input);
365
366 ObjectModelClass propertyClass = (ObjectModelClass)
367 addInnerClassifier(helperClass,
368 ObjectModelType.OBJECT_MODEL_CLASS,
369 className,
370 ObjectModelJavaModifier.STATIC);
371
372 if (log.isDebugEnabled()) {
373 log.debug("Generate for entity : " + input.getQualifiedName());
374 }
375
376
377 addImport(helperClass, input.getQualifiedName());
378
379
380 String superClassQualifiedName = abstractEntityPropertyClass.getQualifiedName().
381 replace(ENTITY_PROPERTY_GENERIC_TYPE, "<" + input.getName() + ">");
382
383 setSuperClass(propertyClass, superClassQualifiedName);
384
385 ObjectModelOperation constructor =
386 addConstructor(propertyClass, ObjectModelJavaModifier.PROTECTED);
387
388 setOperationBody(constructor, ""
389
390
391 );
392
393 ObjectModelOperation getEntityClass =
394 addOperation(propertyClass, "getEntityClass", "Class<" + input.getName() + ">",
395 ObjectModelJavaModifier.PUBLIC);
396
397 addAnnotation(propertyClass, getEntityClass, "Override");
398
399 setOperationBody(getEntityClass, ""
400
401
402
403 );
404
405 ObjectModelOperation defaultAlias =
406 addOperation(propertyClass, "defaultAlias", String.class,
407 ObjectModelJavaModifier.PUBLIC);
408
409 addAnnotation(propertyClass, defaultAlias, "Override");
410
411 setOperationBody(defaultAlias, ""
412
413
414
415 );
416
417 createGetterOperations(input, propertyClass);
418
419 return propertyClass;
420 }
421
422 protected void createGetterOperations(ObjectModelClassifier input, ObjectModelClass propertyClass) {
423
424
425 for (ObjectModelAttribute attr : input.getAttributes()) {
426
427
428 if (!attr.isNavigable()) {
429 continue;
430 }
431
432 String attrName = getReferenceAttributeName(attr);
433
434 if (log.isDebugEnabled()) {
435 log.debug("Entity property : name=" + attrName +
436 " _ navigable=" + attr.isNavigable() +
437 " _ maxMultiplicity=" + attr.getMaxMultiplicity() +
438 " _ associationClass=" + attr.hasAssociationClass() +
439 " _ referenceClassifier=" + attr.referenceClassifier());
440 }
441
442 ObjectModelOperation propertyNameOperation =
443 createGetPropertyNameOperation(propertyClass, attrName, input.getName());
444
445 createGetPropertyObjectOperation(propertyClass, attr, propertyNameOperation);
446 }
447
448
449 if (input instanceof ObjectModelAssociationClass) {
450
451 ObjectModelAssociationClass assoc = (ObjectModelAssociationClass)input;
452
453 for (ObjectModelAttribute attr : assoc.getParticipantsAttributes()) {
454 ObjectModelOperation propertyNameOperation =
455 createGetPropertyNameOperation(propertyClass, attr.getName(), input.getName());
456
457 createGetPropertyObjectOperation(propertyClass, attr, propertyNameOperation);
458 }
459 }
460 }
461
462 protected ObjectModelOperation createGetPropertyNameOperation(ObjectModelClass output, String attrName, String entityClassName) {
463 ObjectModelOperation result =
464 addOperation(output, attrName, String.class, ObjectModelJavaModifier.PUBLIC);
465
466 String constantName =
467 entityClassName + "." + getConstantName(attrName);
468
469 if (log.isDebugEnabled()) {
470 log.debug("Add getter for property : " + attrName +
471 " _ constantName = " + constantName +
472 " _ constantPrefix = " + getConstantPrefix());
473 }
474
475 setOperationBody(result, ""
476
477
478
479 );
480
481 return result;
482 }
483
484 protected ObjectModelOperation createGetPropertyObjectOperation(ObjectModelClass output,
485 ObjectModelAttribute attrReference,
486 ObjectModelOperation propertyNameOperation) {
487
488 ObjectModelClassifier referenceClass = getReferenceAttributeClassifier(attrReference);
489
490
491
492 if (referenceClass == null || referenceClass.isEnum()) {
493 return null;
494 }
495
496 String operationName = getReferenceAttributeName(attrReference) +
497 ENTITY_PROPERTY_SUFFIX;
498
499 String referencePropertyClassName = getPropertyClassName(referenceClass);
500
501 ObjectModelOperation result =
502 addOperation(output, operationName, referencePropertyClassName);
503
504 if (log.isDebugEnabled()) {
505 log.debug("Extra operation : " + operationName +
506 " _ className = " + referencePropertyClassName);
507 }
508
509 setOperationBody(result, ""
510
511
512
513 );
514
515 return result;
516 }
517
518 protected void createNewOperations(ObjectModelClass entityProperty) {
519
520 String className = entityProperty.getName();
521
522 String methodName = "new" + className;
523
524 ObjectModelOperation newEntityProperty1 =
525 addOperation(helperClass, "new" + className, className,
526 ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC);
527
528 setOperationBody(newEntityProperty1, ""
529
530
531
532 );
533
534 ObjectModelOperation newEntityProperty2 =
535 addOperation(helperClass, "new" + className, className,
536 ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC);
537 addParameter(newEntityProperty2, String.class, "alias");
538
539 setOperationBody(newEntityProperty2, ""
540
541
542
543 );
544 }
545
546 protected void addExtraForSubEntity(ObjectModelClassifier entityClass) {
547 for (ObjectModelAttribute attr : entityClass.getAttributes()) {
548
549 if (attr.isNavigable() && attr.referenceClassifier() &&
550 attr.getClassifier().getName().equals(entityClass.getName())) {
551
552
553 String propertyClassName = getPropertyClassName(entityClass);
554
555 String subEntityName = entityClass.getName() + StringUtils.capitalize(attr.getName());
556 String aliasConstant = createAliasConstant(subEntityName);
557
558 ObjectModelOperation newEntityProperty =
559 addOperation(helperClass, "new" + subEntityName + "Property", propertyClassName,
560 ObjectModelJavaModifier.PUBLIC, ObjectModelJavaModifier.STATIC);
561
562 String callMethodName = "new" + propertyClassName;
563
564 setOperationBody(newEntityProperty, ""
565
566
567
568 );
569
570 }
571 }
572 }
573
574
575 protected String getPropertyClassName(ObjectModelClassifier entityClass) {
576 return entityClass.getName() + ENTITY_PROPERTY_SUFFIX;
577 }
578
579 protected String getReferenceAttributeName(ObjectModelAttribute attrReference) {
580 String attrName = attrReference.getName();
581 if(attrReference.hasAssociationClass()) {
582 attrName = GeneratorUtil.getAssocAttrName(attrReference);
583 }
584 return attrName;
585 }
586
587 protected ObjectModelClassifier getReferenceAttributeClassifier(ObjectModelAttribute attrReference) {
588 ObjectModelClassifier referenceClass = null;
589
590 if (attrReference.referenceClassifier() && attrReference.getMaxMultiplicity() == 1) {
591 referenceClass = attrReference.getClassifier();
592
593 } else if (attrReference.hasAssociationClass()) {
594 referenceClass = attrReference.getAssociationClass();
595 }
596 return referenceClass;
597 }
598
599
600 protected void setBuilder(JavaBuilder builder) {
601 this.builder = builder;
602 }
603 }