1 19 20 package org.netbeans.modules.j2ee.persistence.wizard.fromdb; 21 22 import com.sun.source.tree.*; 23 import java.util.HashMap ; 24 import org.netbeans.api.progress.ProgressHandle; 25 import org.netbeans.modules.j2ee.persistence.api.metadata.orm.Entity; 26 import org.netbeans.modules.j2ee.persistence.api.metadata.orm.Table; 27 import org.openide.filesystems.FileObject; 28 import java.io.IOException ; 29 import java.util.ArrayList ; 30 import java.util.Collections ; 31 import java.util.EnumSet ; 32 import java.util.HashSet ; 33 import java.util.Iterator ; 34 import java.util.List ; 35 import java.util.Map ; 36 import java.util.Set ; 37 import java.util.logging.Level ; 38 import java.util.logging.Logger ; 39 import javax.lang.model.element.*; 40 import javax.lang.model.type.*; 41 import org.netbeans.api.java.classpath.ClassPath; 42 import org.netbeans.api.java.source.JavaSource; 43 import org.netbeans.api.java.source.TreeMaker; 44 import org.netbeans.api.java.source.WorkingCopy; 45 import org.netbeans.api.project.FileOwnerQuery; 46 import org.netbeans.api.project.Project; 47 import org.netbeans.modules.j2ee.persistence.util.AbstractTask; 48 import org.netbeans.modules.j2ee.persistence.util.GenerationUtils; 49 import org.netbeans.modules.j2ee.persistence.dd.persistence.model_1_0.PersistenceUnit; 50 import org.netbeans.modules.j2ee.persistence.entitygenerator.CMPMappingModel; 51 import org.netbeans.modules.j2ee.persistence.entitygenerator.EntityClass; 52 import org.netbeans.modules.j2ee.persistence.entitygenerator.EntityMember; 53 import org.netbeans.modules.j2ee.persistence.entitygenerator.RelationshipRole; 54 import org.netbeans.modules.j2ee.persistence.provider.InvalidPersistenceXmlException; 55 import org.netbeans.modules.j2ee.persistence.provider.ProviderUtil; 56 import org.netbeans.modules.j2ee.persistence.unit.PUDataObject; 57 import org.netbeans.modules.j2ee.persistence.util.JPAClassPathHelper; 58 import org.netbeans.modules.j2ee.persistence.wizard.Util; 59 import org.openide.WizardDescriptor; 60 import org.openide.filesystems.FileUtil; 61 import org.openide.util.NbBundle; 62 63 68 public class JavaPersistenceGenerator implements PersistenceGenerator { 69 70 74 79 private final Map <String , String > entityName2TableName = new HashMap <String , String >(); 80 81 private static boolean fieldAccess = true; 84 private static boolean genNamedParams = true; 86 private static boolean genSerializableEntities = true; 88 89 public JavaPersistenceGenerator() { 90 } 91 92 public void generateBeans(final ProgressPanel progressPanel, 93 final RelatedCMPHelper helper, 94 final FileObject dbSchemaFile, 95 final ProgressHandle handle, 96 boolean justTesting) throws IOException { 97 new Generator(helper, handle, progressPanel).run(); 98 } 99 100 public void init(WizardDescriptor wiz) { 101 } 110 111 private void processEntities(Set <Entity> entityClasses) { 112 for (Entity entity : entityClasses) { 113 Table entityTable = entity.getTable(); 114 if (entityTable != null) { 115 entityName2TableName.put(entityTable.getName(), entity.getClass2()); 116 } 117 } 118 } 119 120 public void uninit() { 121 } 122 123 public String getFQClassName(String tableName) { 124 return entityName2TableName.get(tableName); 125 } 126 127 public String generateEntityName(String name) { 128 return name; 129 } 130 131 public Set createdObjects() { 132 return Collections.EMPTY_SET; 133 } 134 135 138 private static final class Generator { 139 140 private final RelatedCMPHelper helper; 141 private final ProgressHandle handle; 142 private final ProgressPanel progressPanel; 143 private final Map <String , EntityClass> beanMap = new HashMap <String , EntityClass>(); 144 145 public Generator(RelatedCMPHelper helper, ProgressHandle handle, ProgressPanel progressPanel) { 146 this.helper = helper; 147 this.handle = handle; 148 this.progressPanel = progressPanel; 149 } 150 151 public void run() throws IOException { 152 EntityClass[] genBeans = helper.getBeans(); 153 154 int progressMax = genBeans.length * 2; 155 handle.switchToDeterminate(progressMax); 156 157 162 beanMap.clear(); 163 Set <FileObject> generationPackageFOs = new HashSet <FileObject>(); 164 Set <String > generatedEntityClasses = new HashSet <String >(); 165 for (int i = 0; i < genBeans.length; i++) { 166 final EntityClass entityClass = genBeans[i]; 167 String entityClassName = entityClass.getClassName(); 168 FileObject packageFileObject = genBeans[i].getPackageFileObject(); 169 beanMap.put(entityClassName, entityClass); 170 171 if (packageFileObject.getFileObject(entityClassName, "java") != null) { handle.progress(i); 173 continue; 174 } 175 String progressMsg = NbBundle.getMessage(JavaPersistenceGenerator.class, "TXT_GeneratingClass", entityClassName); 176 handle.progress(progressMsg, i); 177 progressPanel.setText(progressMsg); 178 179 generationPackageFOs.add(packageFileObject); 180 generatedEntityClasses.add(entityClassName); 181 182 GenerationUtils.createClass(packageFileObject, entityClassName, NbBundle.getMessage(JavaPersistenceGenerator.class, "MSG_Javadoc_Class")); 184 if (!genBeans[i].isUsePkField()) { 185 String pkClassName = createPKClassName(entityClassName); 186 GenerationUtils.createClass(packageFileObject, pkClassName, NbBundle.getMessage(JavaPersistenceGenerator.class, "MSG_Javadoc_PKClass", pkClassName, entityClassName)); 187 } 188 } 189 190 193 194 for (int i = 0; i < genBeans.length; i++) { 195 final EntityClass entityClass = genBeans[i]; 196 String entityClassName = entityClass.getClassName(); 197 198 if (!generatedEntityClasses.contains(entityClassName)) { 199 handle.progress(genBeans.length + i); 201 continue; 202 } 203 String progressMsg = NbBundle.getMessage(JavaPersistenceGenerator.class, "TXT_GeneratingClass", entityClassName); 204 handle.progress(progressMsg, genBeans.length + i); 205 progressPanel.setText(progressMsg); 206 207 FileObject entityClassPackageFO = entityClass.getPackageFileObject(); 208 final FileObject entityClassFO = entityClassPackageFO.getFileObject(entityClassName, "java"); final FileObject pkClassFO = entityClassPackageFO.getFileObject(createPKClassName(entityClassName), "java"); try { 211 212 Set <ClassPath> bootCPs = getAllClassPaths(generationPackageFOs, ClassPath.BOOT); 213 Set <ClassPath> compileCPs = getAllClassPaths(generationPackageFOs, ClassPath.COMPILE); 214 Set <ClassPath> sourceCPs = getAllClassPaths(generationPackageFOs, ClassPath.SOURCE); 215 216 JPAClassPathHelper cpHelper = new JPAClassPathHelper(bootCPs, compileCPs, sourceCPs); 217 218 JavaSource javaSource = (pkClassFO != null) ? 219 JavaSource.create(cpHelper.createClasspathInfo(), entityClassFO, pkClassFO) : 220 JavaSource.create(cpHelper.createClasspathInfo(), entityClassFO); 221 javaSource.runModificationTask(new AbstractTask<WorkingCopy>() { 222 public void run(WorkingCopy copy) throws IOException { 223 if (copy.getFileObject().equals(entityClassFO)) { 224 new EntityClassGenerator(helper, copy, entityClass).run(); 225 } else { 226 new PKClassGenerator(helper, copy, entityClass).run(); 227 } 228 } 229 }).commit(); 230 } catch (IOException e) { 231 String message = e.getMessage(); 232 String newMessage = ((message == null) ? 233 NbBundle.getMessage(JavaPersistenceGenerator.class, "ERR_GeneratingClass_NoExceptionMessage", entityClassName) : 234 NbBundle.getMessage(JavaPersistenceGenerator.class, "ERR_GeneratingClass", entityClassName, message)); 235 IOException wrappedException = new IOException (newMessage); 236 wrappedException.initCause(e); 237 throw wrappedException; 238 } 239 240 Project project = FileOwnerQuery.getOwner(entityClassFO); 241 if (!Util.isSupportedJavaEEVersion(project) && ProviderUtil.getDDFile(project) != null) { 242 try { 243 PUDataObject pudo = ProviderUtil.getPUDataObject(project); 244 PersistenceUnit pu[] = pudo.getPersistence().getPersistenceUnit(); 245 if (pu.length == 1) { 247 pudo.addClass(pu[0], entityClassName); 248 } 249 } catch (InvalidPersistenceXmlException ipx){ 250 Logger.getLogger(JavaPersistenceGenerator.class.getName()).log(Level.FINE, "Invalid persistence.xml: " + ipx.getPath(), ipx); } 254 } 255 } 256 257 handle.progress(progressMax); 258 } 259 260 private static String createPKClassName(String entityClassName) { 261 return entityClassName + "PK"; } 263 264 private static Set <ClassPath> getAllClassPaths(Set <FileObject> fileObjects, String id) { 265 Set <ClassPath> classPaths = new HashSet <ClassPath>(); 266 for (FileObject fileObject : fileObjects) { 267 classPaths.add(ClassPath.getClassPath(fileObject, id)); 268 } 269 return classPaths; 270 } 271 272 273 278 private abstract class ClassGenerator { 279 280 protected final RelatedCMPHelper helper; 281 protected final WorkingCopy copy; 282 protected final GenerationUtils genUtils; 283 284 protected final EntityClass entityClass; 286 protected final CMPMappingModel dbMappings; 288 protected final boolean needsPKClass; 290 protected final String pkClassName; 292 protected final String pkFQClassName; 294 295 protected final List <Property> properties = new ArrayList <Property>(); 297 protected final List <MethodTree> methods = new ArrayList <MethodTree>(); 299 protected final List <MethodTree> constructors = new ArrayList <MethodTree>(); 301 302 protected ClassTree classTree; 304 305 public ClassGenerator(RelatedCMPHelper helper, WorkingCopy copy, EntityClass entityClass) throws IOException { 306 this.helper = helper; 307 this.copy = copy; 308 309 this.entityClass = entityClass; 310 dbMappings = entityClass.getCMPMapping(); 311 needsPKClass = !entityClass.isUsePkField(); 312 pkClassName = needsPKClass ? createPKClassName(entityClass.getClassName()) : null; 313 pkFQClassName = entityClass.getPackage() + "." + pkClassName; 315 genUtils = GenerationUtils.newInstance(copy); 316 if (genUtils == null) { 317 throw new IllegalStateException ("Cannot find a public top-level class named " + entityClass.getClassName() + " in " + FileUtil.getFileDisplayName(copy.getFileObject())); } 320 classTree = genUtils.getClassTree(); 321 } 322 323 protected String createFieldName(String capitalizedFieldName) { 324 return createFieldNameImpl(capitalizedFieldName, false); 325 } 326 327 protected String createCapitalizedFieldName(String fieldName) { 328 return createFieldNameImpl(fieldName, true); 329 } 330 331 private String createFieldNameImpl(String fieldName, boolean capitalized) { 332 StringBuffer sb = new StringBuffer (fieldName); 333 char firstChar = sb.charAt(0); 334 sb.setCharAt(0, capitalized ? Character.toUpperCase(firstChar) : Character.toLowerCase(firstChar)); 335 return sb.toString(); 336 } 337 338 342 protected Property createProperty(EntityMember m) throws IOException { 343 boolean isPKMember = m.isPrimaryKey(); 344 List <AnnotationTree> annotations = new ArrayList <AnnotationTree>(); 345 346 if (isPKMember && !needsPKClass) { 348 annotations.add(genUtils.createAnnotation("javax.persistence.Id")); } 350 351 boolean isLobType = m.isLobType(); 352 if (isLobType) { 353 annotations.add(genUtils.createAnnotation("javax.persistence.Lob")); } 355 356 List <ExpressionTree> columnAnnArguments = new ArrayList (); 357 String memberName = m.getMemberName(); 358 359 String columnName = (String ) dbMappings.getCMPFieldMapping().get(memberName); 360 columnAnnArguments.add(genUtils.createAnnotationArgument("name", columnName)); if (!m.isNullable()) { 362 columnAnnArguments.add(genUtils.createAnnotationArgument("nullable", false)); } 364 annotations.add(genUtils.createAnnotation("javax.persistence.Column", columnAnnArguments)); 366 String temporalType = getMemberTemporalType(m); 367 if (temporalType != null) { 368 ExpressionTree temporalAnnValueArgument = genUtils.createAnnotationArgument(null, "javax.persistence.TemporalType", temporalType); annotations.add(genUtils.createAnnotation("javax.persistence.Temporal", Collections.singletonList(temporalAnnValueArgument))); 370 } 371 372 return new Property(Modifier.PRIVATE, annotations, getMemberType(m), memberName); 373 } 374 375 380 protected VariableTree createVariable(EntityMember m) { 381 return genUtils.createVariable(m.getMemberName(), getMemberType(m)); 382 } 383 384 private String getMemberType(EntityMember m) { 385 String memberType = m.getMemberType(); 386 if ("java.sql.Date".equals(memberType)) { memberType = "java.util.Date"; 388 } else if ("java.sql.Time".equals(memberType)) { memberType = "java.util.Date"; 390 } else if ("java.sql.Timestamp".equals(memberType)) { memberType = "java.util.Date"; 392 } 393 return memberType; 394 } 395 396 private String getMemberTemporalType(EntityMember m) { 397 String memberType = m.getMemberType(); 398 String temporalType = null; 399 if ("java.sql.Date".equals(memberType)) { temporalType = "DATE"; 401 } else if ("java.sql.Time".equals(memberType)) { temporalType = "TIME"; 403 } else if ("java.sql.Timestamp".equals(memberType)) { temporalType = "TIMESTAMP"; 405 } 406 return temporalType; 407 } 408 409 protected MethodTree createHashCodeMethod(List <VariableTree> fields) { 410 StringBuilder body = new StringBuilder (20 + fields.size() * 30); 411 body.append("{"); body.append("int hash = 0;"); for (VariableTree field : fields) { 414 body.append(createHashCodeLineForField(field)); 415 } 416 body.append("return hash;"); body.append("}"); TreeMaker make = copy.getTreeMaker(); 419 return make.Method( 421 make.Modifiers(EnumSet.of(Modifier.PUBLIC), Collections.singletonList(genUtils.createAnnotation("java.lang.Override"))), 422 "hashCode", make.PrimitiveType(TypeKind.INT), 424 Collections.<TypeParameterTree>emptyList(), 425 Collections.<VariableTree>emptyList(), 426 Collections.<ExpressionTree>emptyList(), 427 body.toString(), 428 null); 429 } 430 431 private String createHashCodeLineForField(VariableTree field) { 432 Name fieldName = field.getName(); 433 Tree fieldType = field.getType(); 434 if (fieldType.getKind() == Tree.Kind.PRIMITIVE_TYPE) { 435 if (((PrimitiveTypeTree)fieldType).getPrimitiveTypeKind() == TypeKind.BOOLEAN) { 436 return "hash += (" + fieldName + " ? 1 : 0"; } 438 return "hash += (int)" + fieldName + ";"; } 440 return "hash += (" + fieldName + " != null ? " + fieldName + ".hashCode() : 0);"; } 442 443 protected MethodTree createEqualsMethod(String simpleClassName, List <VariableTree> fields) { 444 StringBuilder body = new StringBuilder (50 + fields.size() * 30); 445 body.append("{"); body.append("// TODO: Warning - this method won't work in the case the id fields are not set\n"); body.append("if (!(object instanceof "); body.append(simpleClassName + ")) {return false;}"); body.append(simpleClassName + " other = (" + simpleClassName + ")object;"); for (VariableTree field : fields) { 451 body.append(createEqualsLineForField(field)); 452 } 453 body.append("return true;"); body.append("}"); TreeMaker make = copy.getTreeMaker(); 456 return make.Method( 458 make.Modifiers(EnumSet.of(Modifier.PUBLIC), Collections.singletonList(genUtils.createAnnotation("java.lang.Override"))), "equals", make.PrimitiveType(TypeKind.BOOLEAN), 461 Collections.<TypeParameterTree>emptyList(), 462 Collections.singletonList(genUtils.createVariable("object", "java.lang.Object")), Collections.<ExpressionTree>emptyList(), 464 body.toString(), 465 null); 466 } 467 468 private String createEqualsLineForField(VariableTree field){ 469 Name fieldName = field.getName(); 470 Tree fieldType = field.getType(); 471 if (fieldType.getKind() == Tree.Kind.PRIMITIVE_TYPE) { 472 return "if (this." + fieldName + " != other." + fieldName + ") return false;"; } 474 return "if (this." + fieldName + " != other." + fieldName + " && (this." + fieldName + " == null || !this." + fieldName + ".equals(other." + fieldName + "))) return false;"; } 478 479 protected MethodTree createToStringMethod(String simpleClassName, List <VariableTree> fields) { 480 StringBuilder body = new StringBuilder (30 + fields.size() * 30); 481 body.append("{"); body.append("return \"" + simpleClassName + "["); for (Iterator <VariableTree> i = fields.iterator(); i.hasNext();) { 484 String fieldName = i.next().getName().toString(); 485 body.append(fieldName + "=\" + " + fieldName + " + \""); body.append(i.hasNext() ? ", " : "]\";"); } 488 body.append("}"); TreeMaker make = copy.getTreeMaker(); 490 return make.Method( 492 make.Modifiers(EnumSet.of(Modifier.PUBLIC), Collections.singletonList(genUtils.createAnnotation("java.lang.Override"))), 493 "toString", genUtils.createType("java.lang.String"), Collections.<TypeParameterTree>emptyList(), 496 Collections.<VariableTree>emptyList(), 497 Collections.<ExpressionTree>emptyList(), 498 body.toString(), 499 null); 500 } 501 502 public void run() throws IOException { 503 initialize(); 504 for (Object object : entityClass.getFields()) { 505 generateMember((EntityMember)object); 506 } 507 afterMembersGenerated(); 508 for (Object object : entityClass.getRoles()) { 509 generateRelationship((RelationshipRole)object); 510 } 511 finish(); 512 513 TreeMaker make = copy.getTreeMaker(); 515 int position = 0; 516 for (Property property : properties) { 517 classTree = make.insertClassMember(classTree, position, property.getField()); 518 position++; 519 } 520 for (MethodTree constructor : constructors) { 521 classTree = make.addClassMember(classTree, constructor); 522 } 523 for (Property property : properties) { 524 classTree = make.addClassMember(classTree, property.getGetter()); 525 classTree = make.addClassMember(classTree, property.getSetter()); 526 } 527 for (MethodTree method : methods) { 528 classTree = make.addClassMember(classTree, method); 529 } 530 copy.rewrite(genUtils.getClassTree(), classTree); 531 } 532 533 536 protected abstract void initialize() throws IOException ; 537 538 541 protected abstract void generateMember(EntityMember m) throws IOException ; 542 543 546 protected abstract void afterMembersGenerated() throws IOException ; 547 548 551 protected abstract void generateRelationship(RelationshipRole role) throws IOException ; 552 553 556 protected abstract void finish() throws IOException ; 557 558 562 protected final class Property { 563 564 private final VariableTree field; 565 private final MethodTree getter; 566 private final MethodTree setter; 567 568 public Property(Modifier modifier, List <AnnotationTree> annotations, String type, String name) throws IOException { 569 this(modifier, annotations, genUtils.createType(type), name); 570 } 571 572 public Property(Modifier modifier, List <AnnotationTree> annotations, TypeMirror type, String name) throws IOException { 573 this(modifier, annotations, copy.getTreeMaker().Type(type), name); 574 } 575 576 private Property(Modifier modifier, List <AnnotationTree> annotations, Tree typeTree, String name) throws IOException { 577 TreeMaker make = copy.getTreeMaker(); 578 field = make.Variable( 579 make.Modifiers(EnumSet.of(modifier), fieldAccess ? annotations : Collections.<AnnotationTree>emptyList()), 580 name, 581 typeTree, 582 null); 583 getter = genUtils.createPropertyGetterMethod( 584 make.Modifiers(EnumSet.of(Modifier.PUBLIC), fieldAccess ? Collections.<AnnotationTree>emptyList() : annotations), 585 name, 586 typeTree); 587 setter = genUtils.createPropertySetterMethod( 588 genUtils.createModifiers(Modifier.PUBLIC), 589 name, 590 typeTree); 591 } 592 593 public VariableTree getField() { 594 return field; 595 } 596 597 public MethodTree getGetter() { 598 return getter; 599 } 600 601 public MethodTree getSetter() { 602 return setter; 603 } 604 } 605 } 606 607 610 private final class EntityClassGenerator extends ClassGenerator { 611 612 private final String entityClassName; 614 private final String entityFQClassName; 616 private final List <Property> nonNullableProps = new ArrayList <Property>(); 618 private final List <String > pkColumnNames = new ArrayList <String >(); 620 private final List <VariableTree> pkClassVariables = new ArrayList <VariableTree>(); 622 private final List <ExpressionTree> namedQueryAnnotations = new ArrayList <ExpressionTree>(); 624 625 private Property pkProperty; 627 private String namedQueryPrefix; 629 630 public EntityClassGenerator(RelatedCMPHelper helper, WorkingCopy copy, EntityClass entityClass) throws IOException { 631 super(helper, copy, entityClass); 632 entityClassName = entityClass.getClassName(); 633 assert genUtils.getTypeElement().getSimpleName().contentEquals(entityClassName); 634 entityFQClassName = entityClass.getPackage() + "." + entityClassName; 635 } 636 637 protected void initialize() throws IOException { 638 classTree = genUtils.ensureNoArgConstructor(classTree); 639 if (genSerializableEntities) { 640 classTree = genUtils.addImplementsClause(classTree, "java.io.Serializable"); } 642 classTree = genUtils.addAnnotation(classTree, genUtils.createAnnotation("javax.persistence.Entity")); ExpressionTree tableNameArgument = genUtils.createAnnotationArgument("name", dbMappings.getTableName()); classTree = genUtils.addAnnotation(classTree, genUtils.createAnnotation("javax.persistence.Table", Collections.singletonList(tableNameArgument))); 645 646 if (needsPKClass) { 647 String pkFieldName = createFieldName(pkClassName); 648 pkProperty = new Property( 649 Modifier.PROTECTED, 650 Collections.singletonList(genUtils.createAnnotation("javax.persistence.EmbeddedId")), 651 pkFQClassName, 652 pkFieldName); 653 properties.add(pkProperty); 654 } 655 656 } 660 661 protected void generateMember(EntityMember m) throws IOException { 662 String memberName = m.getMemberName(); 663 boolean isPKMember = m.isPrimaryKey(); 664 Property property = null; 665 if (isPKMember) { 666 if (needsPKClass) { 667 pkClassVariables.add(createVariable(m)); 668 } else { 669 pkProperty = property = createProperty(m); 670 } 671 String pkColumnName = (String )dbMappings.getCMPFieldMapping().get(memberName); 672 pkColumnNames.add(pkColumnName); 673 } else { 674 property = createProperty(m); 675 if (!m.isNullable()) { 676 nonNullableProps.add(property); 677 } 678 } 679 assert (property != null) || (property == null && isPKMember && needsPKClass); 682 if (property != null) { 683 properties.add(property); 684 } 685 686 if (helper.isGenerateFinderMethods() && !m.isLobType()) { 688 List <ExpressionTree> namedQueryAnnArguments = new ArrayList <ExpressionTree>(); 689 namedQueryAnnArguments.add(genUtils.createAnnotationArgument("name", entityClassName + ".findBy" + createCapitalizedFieldName(memberName))); 691 if (namedQueryPrefix == null) { 692 char firstLetter = entityClassName.toLowerCase().charAt(0); 693 namedQueryPrefix = "SELECT " + firstLetter + " FROM " + entityClassName + " " + firstLetter + " WHERE " + firstLetter + "."; } 695 String memberAccessString = ((needsPKClass && isPKMember) ? (pkProperty.getField().getName().toString() + "." + memberName) : memberName); namedQueryAnnArguments.add(genUtils.createAnnotationArgument( 698 "query", namedQueryPrefix + memberAccessString + ((genNamedParams) ? (" = :" + memberName) : "= ?1"))); namedQueryAnnotations.add(genUtils.createAnnotation("javax.persistence.NamedQuery", namedQueryAnnArguments)); } 702 } 703 704 protected void afterMembersGenerated() { 705 classTree = genUtils.addAnnotation(classTree, genUtils.createAnnotation("javax.persistence.NamedQueries", Collections.singletonList(genUtils.createAnnotationArgument(null, namedQueryAnnotations)))); 707 } 708 709 protected void generateRelationship(RelationshipRole role) throws IOException { 710 String memberName = role.getFieldName(); 711 712 String typeName = getRelationshipFieldType(role, entityClass.getPackage()); 715 TypeMirror fieldType = copy.getElements().getTypeElement(typeName).asType(); 716 if (role.isToMany()) { 717 TypeElement collectionType = copy.getElements().getTypeElement("java.util.Collection"); fieldType = copy.getTypes().getDeclaredType(collectionType, fieldType); 720 } 721 722 List <AnnotationTree> annotations = new ArrayList <AnnotationTree>(); 723 List <ExpressionTree> annArguments = new ArrayList <ExpressionTree>(); 724 if (role.isCascade()) { 725 annArguments.add(genUtils.createAnnotationArgument("cascade", "javax.persistence.CascadeType", "ALL")); } 727 if (role.equals(role.getParent().getRoleB())) { 728 annArguments.add(genUtils.createAnnotationArgument("mappedBy", role.getParent().getRoleA().getFieldName())); } else { 730 if (role.isMany() && role.isToMany()) { 731 List <ExpressionTree> joinTableAnnArguments = new ArrayList <ExpressionTree>(); 732 joinTableAnnArguments.add(genUtils.createAnnotationArgument("name", (String ) dbMappings.getJoinTableMapping().get(role.getFieldName()))); 734 CMPMappingModel.JoinTableColumnMapping joinColumnMap = dbMappings.getJoinTableColumnMppings().get(role.getFieldName()); 735 736 List <AnnotationTree> joinCols = new ArrayList <AnnotationTree>(); 737 String [] colNames = joinColumnMap.getColumns(); 738 String [] refColNames = joinColumnMap.getReferencedColumns(); 739 for(int colIndex = 0; colIndex < colNames.length; colIndex++) { 740 List <ExpressionTree> attrs = new ArrayList <ExpressionTree>(); 741 attrs.add(genUtils.createAnnotationArgument("name", colNames[colIndex])); attrs.add(genUtils.createAnnotationArgument("referencedColumnName", refColNames[colIndex])); joinCols.add(genUtils.createAnnotation("javax.persistence.JoinColumn", attrs)); } 745 joinTableAnnArguments.add(genUtils.createAnnotationArgument("joinColumns", joinCols)); 747 List <AnnotationTree> inverseCols = new ArrayList <AnnotationTree>(); 748 String [] invColNames = joinColumnMap.getInverseColumns(); 749 String [] refInvColNames = joinColumnMap.getReferencedInverseColumns(); 750 for(int colIndex = 0; colIndex < invColNames.length; colIndex++) { 751 List <ExpressionTree> attrs = new ArrayList <ExpressionTree>(); 752 attrs.add(genUtils.createAnnotationArgument("name", invColNames[colIndex])); attrs.add(genUtils.createAnnotationArgument("referencedColumnName", refInvColNames[colIndex])); inverseCols.add(genUtils.createAnnotation("javax.persistence.JoinColumn", attrs)); } 756 joinTableAnnArguments.add(genUtils.createAnnotationArgument("inverseJoinColumns", inverseCols)); 758 annotations.add(genUtils.createAnnotation("javax.persistence.JoinTable", joinTableAnnArguments)); } else { 760 String [] colNames = (String []) dbMappings.getCmrFieldMapping().get(role.getFieldName()); 761 CMPMappingModel relatedMappings = beanMap.get(role.getParent().getRoleB().getEntityName()).getCMPMapping(); 762 String [] invColNames = (String []) relatedMappings.getCmrFieldMapping().get(role.getParent().getRoleB().getFieldName()); 763 if (colNames.length == 1) { 764 List <ExpressionTree> attrs = new ArrayList <ExpressionTree>(); 765 attrs.add(genUtils.createAnnotationArgument("name", colNames[0])); attrs.add(genUtils.createAnnotationArgument("referencedColumnName", invColNames[0])); makeReadOnlyIfNecessary(pkColumnNames, colNames[0], attrs); 768 annotations.add(genUtils.createAnnotation("javax.persistence.JoinColumn", attrs)); } else { 770 List <AnnotationTree> joinCols = new ArrayList <AnnotationTree>(); 771 for(int colIndex = 0; colIndex < colNames.length; colIndex++) { 772 List <ExpressionTree> attrs = new ArrayList <ExpressionTree>(); 773 attrs.add(genUtils.createAnnotationArgument("name", colNames[colIndex])); attrs.add(genUtils.createAnnotationArgument("referencedColumnName", invColNames[colIndex])); makeReadOnlyIfNecessary(pkColumnNames, colNames[colIndex], attrs); 776 joinCols.add(genUtils.createAnnotation("javax.persistence.JoinColumn", attrs)); } 778 ExpressionTree joinColumnsNameAttrValue = genUtils.createAnnotationArgument(null, joinCols); 779 AnnotationTree joinColumnsAnnotation = genUtils.createAnnotation("javax.persistence.JoinColumns", Collections.singletonList(joinColumnsNameAttrValue)); annotations.add(joinColumnsAnnotation); 781 } 782 } 783 } 784 String relationAnn; 785 if (role.isMany() && role.isToMany()) { 786 relationAnn = "ManyToMany"; } else if (role.isMany()) { 788 relationAnn = "ManyToOne"; } else if (role.isToMany()) { 790 relationAnn = "OneToMany"; } else { 792 relationAnn = "OneToOne"; } 794 annotations.add(genUtils.createAnnotation("javax.persistence." + relationAnn, annArguments)); 796 properties.add(new Property(Modifier.PRIVATE, annotations, fieldType, memberName)); 797 } 798 799 protected void finish() { 800 VariableTree pkFieldParam = genUtils.removeModifiers(pkProperty.getField()); 802 List <VariableTree> pkFieldParams = Collections.singletonList(pkFieldParam); 803 constructors.add(genUtils.createAssignmentConstructor(genUtils.createModifiers(Modifier.PUBLIC), entityClassName, pkFieldParams)); 804 805 if (nonNullableProps.size() > 0) { 808 List <VariableTree> nonNullableParams = new ArrayList <VariableTree>(nonNullableProps.size() + 1); 809 nonNullableParams.add(pkFieldParam); 810 for (Property property : nonNullableProps) { 811 nonNullableParams.add(genUtils.removeModifiers(property.getField())); 812 } 813 constructors.add(genUtils.createAssignmentConstructor(genUtils.createModifiers(Modifier.PUBLIC), entityClassName, nonNullableParams)); 814 } 815 816 if (pkClassVariables.size() > 0) { 818 StringBuilder body = new StringBuilder (30 + 30 * pkClassVariables.size()); 819 body.append("{"); body.append("this." + pkProperty.getField().getName() + " = new " + pkClassName + "("); for (Iterator <VariableTree> i = pkClassVariables.iterator(); i.hasNext();) { 822 body.append(i.next().getName()); 823 body.append(i.hasNext() ? ", " : ");"); } 825 body.append("}"); TreeMaker make = copy.getTreeMaker(); 827 constructors.add(make.Constructor( 828 make.Modifiers(EnumSet.of(Modifier.PUBLIC), Collections.<AnnotationTree>emptyList()), 829 Collections.<TypeParameterTree>emptyList(), 830 pkClassVariables, 831 Collections.<ExpressionTree>emptyList(), 832 body.toString())); 833 } 834 835 methods.add(createHashCodeMethod(pkFieldParams)); 837 methods.add(createEqualsMethod(entityClassName, pkFieldParams)); 838 methods.add(createToStringMethod(entityFQClassName, pkFieldParams)); 839 } 840 841 private String getRelationshipFieldType(RelationshipRole role, String pkg) { 842 RelationshipRole rA = role.getParent().getRoleA(); 843 RelationshipRole rB = role.getParent().getRoleB(); 844 RelationshipRole otherRole = role.equals(rA) ? rB : rA; 845 return pkg + "." + otherRole.getEntityName(); } 847 848 private void makeReadOnlyIfNecessary(List <String > pkColumnNames, String testColumnName, List <ExpressionTree> attrs) { 849 if (pkColumnNames.contains(testColumnName)) { 851 attrs.add(genUtils.createAnnotationArgument("insertable", false)); attrs.add(genUtils.createAnnotationArgument("updatable", false)); } 854 } 855 } 856 857 861 private final class PKClassGenerator extends ClassGenerator { 862 863 public PKClassGenerator(RelatedCMPHelper helper, WorkingCopy copy, EntityClass entityClass) throws IOException { 864 super(helper, copy, entityClass); 865 } 866 867 protected void initialize() throws IOException { 868 classTree = genUtils.ensureNoArgConstructor(classTree); 869 classTree = genUtils.addImplementsClause(classTree, "java.io.Serializable"); classTree = genUtils.addAnnotation(classTree, genUtils.createAnnotation("javax.persistence.Embeddable")); } 873 874 protected void generateMember(EntityMember m) throws IOException { 875 if (!m.isPrimaryKey()) { 876 return; 877 } 878 Property property = createProperty(m); 879 properties.add(property); 880 } 881 882 protected void afterMembersGenerated() { 883 } 884 885 protected void generateRelationship(RelationshipRole relationship) { 886 } 887 888 protected void finish() { 889 List <VariableTree> parameters = new ArrayList <VariableTree>(properties.size()); 891 for (Property property : properties) { 892 parameters.add(genUtils.removeModifiers(property.getField())); 893 } 894 constructors.add(genUtils.createAssignmentConstructor(genUtils.createModifiers(Modifier.PUBLIC), pkClassName, parameters)); 895 896 methods.add(createHashCodeMethod(parameters)); 898 methods.add(createEqualsMethod(pkClassName, parameters)); 899 methods.add(createToStringMethod(pkFQClassName, parameters)); 900 } 901 } 902 } 903 } 904 | Popular Tags |