1
2
3
4
5
6
7 package org.asyrinx.joey.gen.command.rdb2java.standard;
8
9 import java.util.HashMap;
10 import java.util.Iterator;
11 import java.util.Map;
12
13 import org.apache.commons.lang.StringUtils;
14 import org.apache.commons.logging.Log;
15 import org.apache.commons.logging.LogFactory;
16 import org.asyrinx.joey.gen.command.java.JavaCommand;
17 import org.asyrinx.joey.gen.command.rdb.RdbCommand;
18 import org.asyrinx.joey.gen.command.rdb.StandardCommands;
19 import org.asyrinx.joey.gen.model.Element;
20 import org.asyrinx.joey.gen.model.EnumerationEntry;
21 import org.asyrinx.joey.gen.model.command.Command;
22 import org.asyrinx.joey.gen.model.java.AppDomain;
23 import org.asyrinx.joey.gen.model.java.Entity;
24 import org.asyrinx.joey.gen.model.java.EntityKey;
25 import org.asyrinx.joey.gen.model.java.EntityKeyEntry;
26 import org.asyrinx.joey.gen.model.java.JavaEnumeration;
27 import org.asyrinx.joey.gen.model.java.Property;
28 import org.asyrinx.joey.gen.model.java.Reference;
29 import org.asyrinx.joey.gen.model.java.ReferenceEntry;
30 import org.asyrinx.joey.gen.model.java.ReferenceType;
31 import org.asyrinx.joey.gen.model.java.Type;
32 import org.asyrinx.joey.gen.model.java.classes.EmbeddedClassUtils;
33 import org.asyrinx.joey.gen.model.rdb.Column;
34 import org.asyrinx.joey.gen.model.rdb.Databases;
35 import org.asyrinx.joey.gen.model.rdb.ForeignKey;
36 import org.asyrinx.joey.gen.model.rdb.ForeignKeyEntry;
37 import org.asyrinx.joey.gen.model.rdb.ForeignKeyType;
38 import org.asyrinx.joey.gen.model.rdb.RdbEnumeration;
39 import org.asyrinx.joey.gen.model.rdb.Table;
40 import org.asyrinx.joey.gen.model.rdb.visitor.RdbTopDownVisitor;
41 import org.asyrinx.joey.gen.model.rdb.visitor.RdbVisitorMock;
42
43 /***
44 * @author akima
45 */
46 public class BasicBuilder implements Rdb2JavaBuilder {
47
48 /***
49 *
50 */
51 public BasicBuilder() {
52 super();
53 }
54
55 private final JavaElementBuilder elementBuilder = new JavaElementBuilder();
56
57 private final JavaTypeResolver resolver = new JavaTypeResolver();
58
59 private final JavaReferenceBuilder referenceBuilder = new JavaReferenceBuilder();
60
61 private final JavaPrimaryKeyBuilder pkBuilder = new JavaPrimaryKeyBuilder();
62
63 public AppDomain execute(Databases dbs) {
64 AppDomain result = new AppDomain();
65
66 final Command dbCommand = new StandardCommands();
67 dbCommand.execute(dbs);
68
69 elementBuilder.execute(dbs, result, this.resolver);
70
71 new PackagePreparer().execute(result, getPackaging());
72
73 pkBuilder.execute(dbs, elementBuilder.getRdb2java());
74
75 resolver.execute(result);
76
77 new DefaultValueBuilder().execute(result);
78
79 new EnumPropertyBuilder().execute(dbs, elementBuilder.getRdb2java(), this.getNaming());
80
81 new ExtendsResolver().execute(dbs, elementBuilder.getRdb2java());
82
83 referenceBuilder.execute(dbs, elementBuilder.getRdb2java());
84
85 new ImportBuilder().execute(result);
86 return result;
87 }
88
89 /***
90 * @return
91 */
92 public NamingStrategy getNaming() {
93 return elementBuilder.getNaming();
94 }
95
96 /***
97 * @return
98 */
99 public PackagingStrategy getPackaging() {
100 return elementBuilder.getPackaging();
101 }
102
103 /***
104 * @return
105 */
106 public TypeMappingStrategy getTypeMapping() {
107 return elementBuilder.getTypeMapping();
108 }
109
110 /***
111 * @param naming
112 */
113 public void setNaming(NamingStrategy naming) {
114 elementBuilder.setNaming(naming);
115 }
116
117 /***
118 * @param packaging
119 */
120 public void setPackaging(PackagingStrategy packaging) {
121 elementBuilder.setPackaging(packaging);
122 }
123
124 /***
125 * @param typeMapping
126 */
127 public void setTypeMapping(TypeMappingStrategy typeMapping) {
128 elementBuilder.setTypeMapping(typeMapping);
129 }
130
131 public Map getRdb2Java() {
132 return elementBuilder.getRdb2java();
133 }
134
135 /***
136 * @return
137 */
138 public Map getJava2rdb() {
139 return elementBuilder.getJava2rdb();
140 }
141 }
142
143 class JavaElementBuilder extends RdbVisitorMock {
144 private AppDomain appDomain = null;
145
146 private JavaTypeResolver resolver = null;
147
148 final Log log = LogFactory.getLog(this.getClass());
149
150 final Map java2rdb = new HashMap() {
151 public Object put(Object key, Object value) {
152 if (this.containsKey(key))
153 log.warn("java2rdb: key'" + key + "' was overriden.");
154 return super.put(key, value);
155 }
156 };
157
158 private final Map rdb2java = new HashMap() {
159 private String toName(Object obj) {
160 if (obj instanceof Element)
161 return ((Element) obj).getFullName();
162 else
163 return String.valueOf(obj);
164 }
165
166
167
168
169
170
171 public Object remove(Object key) {
172 final Object value = super.remove(key);
173 if (value != null)
174 JavaElementBuilder.this.java2rdb.remove(value);
175 return value;
176 }
177
178 public Object put(Object key, Object value) {
179 if (key == null)
180 log.warn("rdb2java: key was null. value =" + toName(value));
181 if (value == null)
182 log.warn("rdb2java: value was null. key =" + toName(key));
183 if (this.containsKey(key))
184 log.warn("rdb2java: key'" + key + "' was overriden.");
185 JavaElementBuilder.this.java2rdb.put(value, key);
186 return super.put(key, value);
187 }
188
189 };
190
191 private NamingStrategy naming = new BasicNaming();
192
193 private PackagingStrategy packaging = new BasicPackaging();
194
195 private TypeMappingStrategy typeMapping = new BasicTypeMapping();
196
197 public void execute(Databases databases, AppDomain domain, JavaTypeResolver typeResolver) {
198 this.appDomain = domain;
199 this.resolver = typeResolver;
200 final RdbTopDownVisitor topDownVisitor = new RdbTopDownVisitor(this);
201 topDownVisitor.visit(databases);
202 }
203
204
205
206
207
208
209 public void visit(RdbEnumeration enum) {
210 final JavaEnumeration result = new JavaEnumeration(this.appDomain, enum.getName(), enum.getValueType());
211 result.setOriginal(enum);
212
213 result.setLabel(enum.getLabel());
214
215 result.setPackageName(packaging.toPackageName(enum));
216 result.setDescription(enum.getDescription());
217 result.setValueTypeObj(typeMapping.toJavaType(enum.getValueType()));
218 result.getOptions().putAll(enum.getOptions());
219
220 for (Iterator i = enum.iterator(); i.hasNext();) {
221 final EnumerationEntry entry = (EnumerationEntry) i.next();
222 try {
223 result.add((EnumerationEntry) entry.clone());
224 } catch (CloneNotSupportedException e) {
225 e.printStackTrace();
226 throw new UnsupportedOperationException(e.getMessage());
227 }
228 }
229 rdb2java.put(enum, result);
230 resolver.addType(result.getFullName(), result);
231 }
232
233
234
235
236
237
238 public void visit(Table table) {
239 final Entity result = new Entity(this.appDomain);
240 result.setOriginal(table);
241
242 result.setName(naming.toClassName(table));
243 result.setPackageTemplate(packaging.toPackageName(table));
244 result.setDescription(table.getDescription());
245 result.setLabel(table.getLabel());
246 result.getOptions().putAll(table.getOptions());
247
248 rdb2java.put(table, result);
249 resolver.addType(result.getFullName(), result);
250 }
251
252
253
254
255
256
257 public void visit(Column column) {
258 final Entity owner = (Entity) rdb2java.get(column.getParent());
259 final Property result = new Property(owner);
260 result.setOriginal(column);
261
262 result.setName(naming.toPropertyName(column));
263 result.setType(typeMapping.toJavaType(column));
264 result.setPrimaryKey(column.isPrimaryKey());
265 if (result.getType() == null) {
266 JavaEnumeration enumeration = appDomain.getEnumerations().getEnumeration(column.getType());
267 if (enumeration != null)
268 result.setType(enumeration);
269 }
270 result.setDefaultValue(column.getDefaultValue());
271 result.setDescription(column.getDescription());
272 result.setLabel(column.getLabel());
273 result.setRequired(column.isRequired());
274 result.setMaxLength(column.getSizeAsInt());
275 result.setExtended(column.isExtended());
276 result.getOptions().putAll(column.getOptions());
277
278 rdb2java.put(column, result);
279 }
280
281 /***
282 * @return Returns the naming.
283 */
284 public NamingStrategy getNaming() {
285 return naming;
286 }
287
288 /***
289 * @param naming
290 * The naming to set.
291 */
292 public void setNaming(NamingStrategy naming) {
293 this.naming = naming;
294 }
295
296 /***
297 * @return Returns the packaging.
298 */
299 public PackagingStrategy getPackaging() {
300 return packaging;
301 }
302
303 /***
304 * @param packaging
305 * The packaging to set.
306 */
307 public void setPackaging(PackagingStrategy packaging) {
308 this.packaging = packaging;
309 }
310
311 /***
312 * @return Returns the typeMapping.
313 */
314 public TypeMappingStrategy getTypeMapping() {
315 return typeMapping;
316 }
317
318 /***
319 * @param typeMapping
320 * The typeMapping to set.
321 */
322 public void setTypeMapping(TypeMappingStrategy typeMapping) {
323 this.typeMapping = typeMapping;
324 }
325
326 /***
327 * @return Returns the rdb2java.
328 */
329 public Map getRdb2java() {
330 return rdb2java;
331 }
332
333 /***
334 * @return Returns the java2rdb.
335 */
336 public Map getJava2rdb() {
337 return java2rdb;
338 }
339 }
340
341 class JavaTypeResolver extends JavaCommand {
342 private final Map javaName2Type = new HashMap();
343
344 public void addType(String typeName, Type type) {
345 this.javaName2Type.put(typeName, type);
346 }
347
348 public Type getType(String typeName) {
349 final Type result = (Type) this.javaName2Type.get(typeName);
350 return (result != null) ? result : EmbeddedClassUtils.get(typeName);
351 }
352
353
354
355
356
357
358 public void visit(JavaEnumeration enum) {
359 if (enum.getValueTypeObj() != null)
360 return;
361 final Type type = getType(enum.getValueType());
362 if (type == null) {
363 addError(enum, "type[" + enum.getValueType() + "] is not found.");
364 return;
365 }
366 enum.setValueTypeObj(type);
367 }
368
369
370
371
372
373
374 public void visit(Property property) {
375 if (property.getType() != null)
376 return;
377 final Type type = getType(property.getTypeName());
378 if (type == null) {
379 addError(property, "type[" + property.getTypeName() + "] is not found.");
380 return;
381 }
382 property.setType(type);
383 }
384 }
385
386 class JavaPrimaryKeyBuilder extends RdbVisitorMock {
387 private Map rdb2java = null;
388
389 public void execute(Databases databases, Map rdb2javaMap) {
390 this.rdb2java = rdb2javaMap;
391 new RdbTopDownVisitor(this).visit(databases);
392 }
393
394
395
396
397
398
399 public void visit(Table table) {
400 final Entity ownerClass = (Entity) rdb2java.get(table);
401 if (table.getExtendsTable() != null)
402 return;
403 final EntityKey pk = new EntityKey(ownerClass, "pk");
404 pk.setPrimaryKey(true);
405 for (Iterator i = table.getColumns().iterator(); i.hasNext();) {
406 final Column column = (Column) i.next();
407 if (column.isPrimaryKey()) {
408 final Property property = (Property) rdb2java.get(column);
409 new EntityKeyEntry(pk, property);
410 }
411 }
412 }
413 }
414
415 class JavaReferenceBuilder extends RdbCommand {
416 private Map rdb2java = null;
417
418 public void execute(Databases databases, Map rdb2javaMap) {
419 this.rdb2java = rdb2javaMap;
420 super.execute(databases);
421 }
422
423 public void visit(ForeignKey foreignKey) {
424 if (foreignKey.getType() == ForeignKeyType.EXTENDS) {
425 rdb2java.remove(foreignKey);
426 return;
427 }
428 final Table localTable = foreignKey.getParent();
429 final Table foreignTable = foreignKey.getForeignTable();
430 final Entity ownerClass = (Entity) rdb2java.get(localTable);
431 final Entity referenceClass = (Entity) rdb2java.get(foreignTable);
432 final Reference result = new Reference(ownerClass);
433 result.setOriginal(foreignKey);
434 result.setType(ReferenceType.get(foreignKey.getType().getName()));
435 result.setReferenceClass(referenceClass);
436 if (result.getOption(Reference.HIBERNATE_DIRECTION) == null) {
437
438 result.getOptions().put(Reference.HIBERNATE_DIRECTION, Reference.DIRECTION_BIDIRECTIONAL);
439 }
440 for (Iterator i = foreignKey.iterator(); i.hasNext();) {
441 final ForeignKeyEntry entry = (ForeignKeyEntry) i.next();
442 final Property local = (Property) rdb2java.get(entry.getLocalColumn());
443 final Property foreign = (Property) rdb2java.get(entry.getForeignColumn());
444 if (local == null) {
445 addError(foreignKey, "property for column '" + entry.getLocal() + "'" + entry.getLocalColumn()
446 + " not found.");
447 }
448 if (foreign == null)
449 addError(foreignKey, "column '" + entry.getForeign() + "' not found.");
450 new ReferenceEntry(result, local, foreign);
451 }
452 rdb2java.put(foreignKey, result);
453 }
454
455 }
456
457 class DefaultValueBuilder extends JavaCommand {
458 public void visit(Property property) {
459 if (property.getDefaultValue() != null)
460 return;
461 if (property.getType() == null) {
462 addError(property, "type [" + property.getTypeName() + "] is not found", false);
463 return;
464 }
465 property.setDefaultValue(property.getType().getCategory().getDefaultValue());
466 }
467 }
468
469 class EnumPropertyBuilder extends RdbCommand {
470 private Map rdb2java = null;
471
472 private NamingStrategy naming = null;
473
474 public void execute(Databases databases, Map rdb2javaMap, NamingStrategy namingStrategy) {
475 this.rdb2java = rdb2javaMap;
476 this.naming = namingStrategy;
477 new RdbTopDownVisitor(this).visit(databases);
478 }
479
480 public void visit(Column column) {
481 final Property property = (Property) rdb2java.get(column);
482 if (StringUtils.isEmpty(column.getEnum()))
483 return;
484 property.setEnumPropertyName(naming.toEnumPropertyName(property.getName()));
485 property.setEnumType(findEnum(column));
486 }
487
488 protected JavaEnumeration findEnum(Column column) {
489 final RdbEnumeration rdbENum = column.getParent().getParent().getEnumerations()
490 .getEnumeration(column.getEnum());
491 if (rdbENum == null) {
492 addError(column, "enum [" + column.getEnum() + "] is not found.");
493 return null;
494 }
495 final Object javaEnum = rdb2java.get(rdbENum);
496 if (javaEnum == null) {
497 addError(column, "rdbENum [" + rdbENum.getFullName() + "] has no mapped java class.");
498 return null;
499 }
500 if (javaEnum instanceof JavaEnumeration) {
501 return (JavaEnumeration) javaEnum;
502 } else {
503 addError(column, "enum [" + column.getEnum() + "] is not found.");
504 return null;
505 }
506 }
507 }
508
509 class PackagePreparer extends JavaCommand {
510
511 private PackagingStrategy packaging = null;
512
513 public void execute(AppDomain appDomain, PackagingStrategy packagingStrategy) {
514 this.packaging = packagingStrategy;
515 execute(appDomain);
516 }
517
518
519
520
521
522
523 public void visit(Entity entity) {
524 packaging.preparePackageNames(entity);
525 }
526
527
528
529
530
531
532 public void visit(JavaEnumeration enum) {
533 packaging.preparePackageName(enum);
534 }
535
536 }
537
538 class ImportBuilder extends JavaCommand {
539
540
541
542
543
544 public void visit(Entity entity) {
545 addImport(entity, entity.getSuperClass());
546 for (Iterator i = entity.getProperties().iterator(); i.hasNext();) {
547 final Property property = (Property) i.next();
548 addImport(entity, property.getEnumType());
549 }
550 for (Iterator i = entity.getReferences().iterator(); i.hasNext();) {
551 final Reference reference = (Reference) i.next();
552 addImport(entity, reference.getReferenceClass());
553 }
554 for (Iterator i = entity.getReferreds().iterator(); i.hasNext();) {
555 final Reference reference = (Reference) i.next();
556 addImport(entity, reference.getParent());
557 }
558 }
559
560 /***
561 * @param entity
562 * @param type
563 */
564 private void addImport(Entity entity, final Type type) {
565 if (type == null)
566 return;
567 if (!type.getPackage().equals(entity.getPackage()))
568 entity.getImports().add(type.getFqn());
569 }
570 }
571
572 class ExtendsResolver extends RdbCommand {
573
574 private Map rdb2java = null;
575
576 public void execute(Databases databases, Map rdb2javaMap) {
577 this.rdb2java = rdb2javaMap;
578 new RdbTopDownVisitor(this).visit(databases);
579 }
580
581
582
583
584
585
586 public void visit(Table table) {
587 if (table.getExtendsTable() == null)
588 return;
589 final Entity subclass = (Entity) rdb2java.get(table);
590 final Entity superclass = (Entity) rdb2java.get(table.getExtendsTable());
591 subclass.setSuperClass(superclass);
592 }
593
594 }