| /******************************************************************************* |
| * Copyright (c) 2006, 2007 Oracle. All rights reserved. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v1.0, which accompanies this distribution |
| * and is available at http://www.eclipse.org/legal/epl-v10.html. |
| * |
| * Contributors: |
| * Oracle - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.jpt.gen.internal; |
| |
| import java.io.PrintWriter; |
| import java.io.Serializable; |
| import java.io.StringWriter; |
| import java.lang.reflect.Modifier; |
| import java.text.Collator; |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.TreeSet; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.jdt.core.IJavaModelStatusConstants; |
| import org.eclipse.jdt.core.IPackageFragment; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jpt.core.internal.content.java.mappings.JPA; |
| import org.eclipse.jpt.db.internal.Column; |
| import org.eclipse.jpt.db.internal.ForeignKey; |
| import org.eclipse.jpt.db.internal.Table; |
| import org.eclipse.jpt.utility.internal.IndentingPrintWriter; |
| import org.eclipse.jpt.utility.internal.JavaType; |
| import org.eclipse.jpt.utility.internal.StringTools; |
| import org.eclipse.jpt.utility.internal.iterators.FilteringIterator; |
| |
| // TODO handle table names that are illegal class names |
| // TODO handle table names that are illegal file names |
| // TODO handle column names that are illegal field/method names |
| // TODO format code per preferences |
| // TODO organize imports per preferences |
| // TODO prompt user to overwrite existing classes |
| /** |
| * This generator will generate an entity for a table. |
| */ |
| public class EntityGenerator { |
| final Config config; |
| private final IPackageFragment packageFragment; |
| private final GenTable genTable; |
| private final String entityClassName; |
| private final OverwriteConfirmer overwriteConfirmer; |
| private final IProgressMonitor monitor; |
| |
| |
| // ********** public API ********** |
| |
| public static void generateEntity(Config config, IPackageFragment packageFragment, GenTable genTable, OverwriteConfirmer overwriteConfirmer, IProgressMonitor monitor) { |
| if ((config == null) || (packageFragment == null) || (genTable == null)) { |
| throw new NullPointerException(); |
| } |
| new EntityGenerator(config, packageFragment, genTable, overwriteConfirmer, monitor).generateEntity(); |
| } |
| |
| |
| // ********** constructor/initialization ********** |
| |
| private EntityGenerator(Config config, IPackageFragment packageFragment, GenTable genTable, OverwriteConfirmer overwriteConfirmer, IProgressMonitor monitor) { |
| super(); |
| this.config = config; |
| this.packageFragment = packageFragment; |
| this.genTable = genTable; |
| this.entityClassName = this.fullyQualify(this.entityName()); |
| this.overwriteConfirmer = overwriteConfirmer; |
| this.monitor = monitor; |
| } |
| |
| |
| // ********** code gen ********** |
| |
| private void generateEntity() { |
| try { |
| this.generateEntity_(); |
| } catch (JavaModelException ex) { |
| throw new RuntimeException(ex); |
| } |
| } |
| |
| private void generateEntity_() throws JavaModelException { |
| String fileName = this.entityName() + ".java"; |
| String source = this.buildSource(); |
| try { |
| this.packageFragment.createCompilationUnit(fileName, source, false, this.monitor); |
| } catch (JavaModelException ex) { |
| if (ex.getJavaModelStatus().getCode() == IJavaModelStatusConstants.NAME_COLLISION) { |
| if (this.overwriteConfirmer.overwrite(this.entityClassName)) { |
| this.packageFragment.createCompilationUnit(fileName, source, true, this.monitor); |
| } |
| } else { |
| throw ex; |
| } |
| } |
| } |
| |
| /** |
| * build the "body" source first; then build the "package" and "imports" source |
| * and concatenate the "body" source to it |
| */ |
| private String buildSource() { |
| // build the body source first so we can gather up the import statements |
| BodySource bodySource = this.buildBodySource(); |
| |
| StringWriter sw = new StringWriter(bodySource.length() + 1000); |
| PrintWriter pw = new PrintWriter(sw); |
| this.printPackageAndImportsOn(pw, bodySource); |
| pw.print(bodySource.source()); |
| return sw.toString(); |
| } |
| |
| private BodySource buildBodySource() { |
| EntitySourceWriter pw = new EntitySourceWriter(this.packageName(), this.entityClassName); |
| this.printBodySourceOn(pw); |
| return pw; |
| } |
| |
| private void printBodySourceOn(EntitySourceWriter pw) { |
| this.printClassDeclarationOn(pw); |
| |
| pw.indent(); |
| this.printEntityPrimaryKeyFieldsOn(pw); |
| this.printEntityNonPrimaryKeyBasicFieldsOn(pw); |
| this.printEntityManyToOneFieldsOn(pw); |
| this.printEntityOneToManyFieldsOn(pw); |
| this.printEntityOwnedManyToManyFieldsOn(pw); |
| this.printEntityNonOwnedManyToManyFieldsOn(pw); |
| this.printSerialVersionUID(pw); |
| pw.println(); |
| |
| this.printZeroArgumentConstructorOn(this.entityName(), this.config.methodVisibility(), pw); |
| if (this.config.propertyAccessType() || this.config.generateGettersAndSetters()) { |
| this.printEntityPrimaryKeyGettersAndSettersOn(pw); |
| this.printEntityNonPrimaryKeyBasicGettersAndSettersOn(pw); |
| this.printEntityManyToOneGettersAndSettersOn(pw); |
| this.printEntityOneToManyGettersAndSettersOn(pw); |
| this.printEntityOwnedManyToManyGettersAndSettersOn(pw); |
| this.printEntityNonOwnedManyToManyGettersAndSettersOn(pw); |
| } |
| |
| this.printPrimaryKeyClassOn(pw); |
| pw.undent(); |
| |
| pw.print('}'); |
| pw.println(); |
| } |
| |
| private void printClassDeclarationOn(EntitySourceWriter pw) { |
| this.printEntityAnnotationOn(pw); |
| this.printTableAnnotationOn(pw); |
| this.printIdClassAnnotationOn(pw); |
| |
| pw.print("public class "); |
| pw.printTypeDeclaration(this.entityClassName); |
| if (config.serializable()) { |
| pw.print(" implements "); |
| pw.printTypeDeclaration(Serializable.class.getName()); |
| } |
| pw.print(" {"); |
| pw.println(); |
| } |
| |
| private void printEntityAnnotationOn(EntitySourceWriter pw) { |
| pw.printAnnotation(JPA.ENTITY); |
| pw.println(); |
| } |
| |
| private void printTableAnnotationOn(EntitySourceWriter pw) { |
| if ( ! this.table().matchesShortJavaClassName(this.entityName())) { |
| pw.printAnnotation(JPA.TABLE); |
| pw.print("(name=\""); |
| pw.print(this.table().getName()); |
| pw.print("\")"); |
| pw.println(); |
| } |
| } |
| |
| private void printIdClassAnnotationOn(EntitySourceWriter pw) { |
| if ((this.table().primaryKeyColumnsSize() > 1) && this.config.generateIdClassForCompoundPK()) { |
| pw.printAnnotation(JPA.ID_CLASS); |
| pw.print('('); |
| pw.printTypeDeclaration(this.entityClassName + ".PK"); |
| pw.print(".class)"); |
| pw.println(); |
| } |
| } |
| |
| private void printEntityPrimaryKeyFieldsOn(EntitySourceWriter pw) { |
| if ((this.table().primaryKeyColumnsSize() > 1) && this.config.generateEmbeddedIdForCompoundPK()) { |
| this.printEntityEmbeddedIdPrimaryKeyFieldOn(pw); |
| } else { |
| this.printEntityReadOnlyPrimaryKeyFieldsOn(pw); |
| this.printEntityWritablePrimaryKeyFieldsOn(pw); |
| } |
| } |
| |
| private void printEntityEmbeddedIdPrimaryKeyFieldOn(EntitySourceWriter pw) { |
| if (this.config.fieldAccessType()) { |
| pw.printAnnotation(JPA.EMBEDDED_ID); |
| pw.println(); |
| } |
| pw.printVisibility(this.config.fieldVisibility()); |
| pw.printTypeDeclaration(this.entityClassName + ".PK"); |
| pw.print(' '); |
| pw.print(this.genTable.fieldNameForEmbeddedId()); |
| pw.print(';'); |
| pw.println(); |
| pw.println(); |
| } |
| |
| private void printEntityReadOnlyPrimaryKeyFieldsOn(EntitySourceWriter pw) { |
| for (Iterator<Column> stream = this.genTable.readOnlyPrimaryKeyColumns(); stream.hasNext(); ) { |
| this.printEntityReadOnlyPrimaryKeyFieldOn(stream.next(), pw); |
| } |
| } |
| |
| private void printEntityReadOnlyPrimaryKeyFieldOn(Column column, EntitySourceWriter pw) { |
| String fieldName = this.genTable.fieldNameFor(column); |
| if (this.config.fieldAccessType()) { |
| pw.printAnnotation(JPA.ID); |
| pw.println(); |
| if (column.matchesJavaFieldName(fieldName)) { |
| this.printReadOnlyColumnAnnotationOn(pw); // no Column name needed |
| } else { |
| this.printReadOnlyColumnAnnotationOn(column.getName(), pw); |
| } |
| } |
| pw.printVisibility(this.config.fieldVisibility()); |
| pw.printTypeDeclaration(column.javaTypeDeclaration()); |
| pw.print(' '); |
| pw.print(fieldName); |
| pw.print(';'); |
| pw.println(); |
| pw.println(); |
| } |
| |
| private void printReadOnlyColumnAnnotationOn(String columnName, EntitySourceWriter pw) { |
| pw.printAnnotation(JPA.COLUMN); |
| pw.print("(name=\""); |
| pw.print(columnName); |
| pw.print("\", insertable=false, updatable=false)"); |
| pw.println(); |
| } |
| |
| private void printReadOnlyColumnAnnotationOn(EntitySourceWriter pw) { |
| pw.printAnnotation(JPA.COLUMN); |
| pw.print("(insertable=false, updatable=false)"); |
| pw.println(); |
| } |
| |
| private void printEntityWritablePrimaryKeyFieldsOn(EntitySourceWriter pw) { |
| for (Iterator<Column> stream = this.genTable.writablePrimaryKeyColumns(); stream.hasNext(); ) { |
| this.printEntityWritablePrimaryKeyFieldOn(stream.next(), pw); |
| } |
| } |
| |
| private void printEntityWritablePrimaryKeyFieldOn(Column column, EntitySourceWriter pw) { |
| String fieldName = this.genTable.fieldNameFor(column); |
| if (this.config.fieldAccessType()) { |
| pw.printAnnotation(JPA.ID); |
| pw.println(); |
| if ( ! column.matchesJavaFieldName(fieldName)) { |
| this.printColumnAnnotationOn(column.getName(), pw); |
| } |
| } |
| pw.printVisibility(this.config.fieldVisibility()); |
| pw.printTypeDeclaration(column.javaTypeDeclaration()); |
| pw.print(' '); |
| pw.print(fieldName); |
| pw.print(';'); |
| pw.println(); |
| pw.println(); |
| } |
| |
| private void printEntityNonPrimaryKeyBasicFieldsOn(EntitySourceWriter pw) { |
| for (Iterator<Column> stream = this.genTable.nonPrimaryKeyBasicColumns(); stream.hasNext(); ) { |
| this.printEntityNonPrimaryKeyBasicFieldOn(stream.next(), pw); |
| } |
| } |
| |
| private void printEntityNonPrimaryKeyBasicFieldOn(Column column, EntitySourceWriter pw) { |
| String fieldName = this.genTable.fieldNameFor(column); |
| if (this.config.fieldAccessType()) { |
| if ( ! column.matchesJavaFieldName(fieldName)) { |
| this.printColumnAnnotationOn(column.getName(), pw); |
| } |
| } |
| pw.printVisibility(this.config.fieldVisibility()); |
| pw.printTypeDeclaration(column.javaTypeDeclaration()); |
| pw.print(' '); |
| pw.print(fieldName); |
| pw.print(';'); |
| pw.println(); |
| pw.println(); |
| } |
| |
| private void printColumnAnnotationOn(String columnName, EntitySourceWriter pw) { |
| pw.printAnnotation(JPA.COLUMN); |
| pw.print("(name=\""); |
| pw.print(columnName); |
| pw.print("\")"); |
| pw.println(); |
| } |
| |
| private void printEntityManyToOneFieldsOn(EntitySourceWriter pw) { |
| for (Iterator<ManyToOneRelation> stream = this.genTable.manyToOneRelations(); stream.hasNext(); ) { |
| this.printEntityManyToOneFieldOn(stream.next(), pw); |
| } |
| } |
| |
| private void printEntityManyToOneFieldOn(ManyToOneRelation relation, EntitySourceWriter pw) { |
| String fieldName = this.genTable.fieldNameFor(relation); |
| if (this.config.fieldAccessType()) { |
| this.printManyToOneAnnotationOn(fieldName, relation, pw); |
| } |
| pw.printVisibility(this.config.fieldVisibility()); |
| pw.printTypeDeclaration(this.fullyQualify(relation.referencedEntityName())); |
| pw.print(' '); |
| pw.print(fieldName); |
| pw.print(';'); |
| pw.println(); |
| pw.println(); |
| } |
| |
| private void printManyToOneAnnotationOn(String fieldName, ManyToOneRelation relation, EntitySourceWriter pw) { |
| pw.printAnnotation(JPA.MANY_TO_ONE); |
| pw.println(); |
| ForeignKey fk = relation.getForeignKey(); |
| if (fk.matchesJavaFieldName(fieldName)) { |
| return; // no JoinColumn annotation needed |
| } |
| if (fk.referencesSingleColumnPrimaryKey()) { |
| pw.printAnnotation(JPA.JOIN_COLUMN); |
| pw.print("(name=\""); |
| pw.print(fk.columnPairs().next().getBaseColumn().getName()); |
| pw.print("\")"); |
| } else { |
| if (fk.columnPairsSize() > 1) { |
| pw.printAnnotation(JPA.JOIN_COLUMNS); |
| pw.print("({"); |
| pw.println(); |
| pw.indent(); |
| } |
| this.printJoinColumnAnnotationsOn(fk, pw); |
| if (fk.columnPairsSize() > 1) { |
| pw.undent(); |
| pw.println(); |
| pw.print("})"); |
| } |
| } |
| pw.println(); |
| } |
| |
| private void printJoinColumnAnnotationsOn(ForeignKey foreignKey, EntitySourceWriter pw) { |
| for (Iterator<ForeignKey.ColumnPair> stream = foreignKey.columnPairs(); stream.hasNext(); ) { |
| this.printJoinColumnAnnotationOn(stream.next(), pw); |
| if (stream.hasNext()) { |
| pw.println(','); |
| } |
| } |
| } |
| |
| private void printJoinColumnAnnotationOn(ForeignKey.ColumnPair columnPair, EntitySourceWriter pw) { |
| this.printJoinColumnAnnotationOn(columnPair.getBaseColumn().getName(), columnPair.getReferencedColumn().getName(), pw); |
| } |
| |
| /** |
| * assume that at least one of the two names is not null |
| */ |
| private void printJoinColumnAnnotationOn(String baseColumnName, String referencedColumnName, EntitySourceWriter pw) { |
| pw.printAnnotation(JPA.JOIN_COLUMN); |
| pw.print('('); |
| if (baseColumnName != null) { |
| pw.print("name=\""); |
| pw.print(baseColumnName); |
| } |
| if (referencedColumnName != null) { |
| if (baseColumnName != null) { |
| pw.print("\", "); |
| } |
| pw.print("referencedColumnName=\""); |
| pw.print(referencedColumnName); |
| } |
| pw.print("\")"); |
| } |
| |
| private void printEntityOneToManyFieldsOn(EntitySourceWriter pw) { |
| for (Iterator<OneToManyRelation> stream = this.genTable.oneToManyRelations(); stream.hasNext(); ) { |
| this.printEntityOneToManyFieldOn(stream.next(), pw); |
| } |
| } |
| |
| private void printEntityOneToManyFieldOn(OneToManyRelation relation, EntitySourceWriter pw) { |
| String fieldName = this.genTable.fieldNameFor(relation); |
| if (this.config.fieldAccessType()) { |
| this.printOneToManyAnnotationOn(fieldName, relation, pw); |
| } |
| pw.printVisibility(this.config.fieldVisibility()); |
| pw.printTypeDeclaration(this.config.getCollectionTypeName()); |
| pw.print('<'); |
| pw.printTypeDeclaration(this.fullyQualify(relation.referencedEntityName())); |
| pw.print('>'); |
| pw.print(' '); |
| pw.print(fieldName); |
| pw.print(';'); |
| pw.println(); |
| pw.println(); |
| } |
| |
| private void printOneToManyAnnotationOn(String fieldName, OneToManyRelation relation, EntitySourceWriter pw) { |
| pw.printAnnotation(JPA.ONE_TO_MANY); |
| pw.print("(mappedBy=\""); |
| pw.print(relation.mappedBy()); |
| pw.print("\")"); |
| pw.println(); |
| } |
| |
| private void printEntityOwnedManyToManyFieldsOn(EntitySourceWriter pw) { |
| for (Iterator<ManyToManyRelation> stream = this.genTable.ownedManyToManyRelations(); stream.hasNext(); ) { |
| this.printEntityOwnedManyToManyFieldOn(stream.next(), pw); |
| } |
| } |
| |
| private void printEntityOwnedManyToManyFieldOn(ManyToManyRelation relation, EntitySourceWriter pw) { |
| String fieldName = this.genTable.fieldNameFor(relation); |
| if (this.config.fieldAccessType()) { |
| this.printOwnedManyToManyAnnotationOn(fieldName, relation, pw); |
| } |
| pw.printVisibility(this.config.fieldVisibility()); |
| pw.printTypeDeclaration(this.config.getCollectionTypeName()); |
| pw.print('<'); |
| pw.printTypeDeclaration(this.fullyQualify(relation.nonOwningEntityName())); |
| pw.print('>'); |
| pw.print(' '); |
| pw.print(fieldName); |
| pw.print(';'); |
| pw.println(); |
| pw.println(); |
| } |
| |
| /** |
| * I guess you could build a state machine for all this crap, |
| * but that seems like overkill... |
| */ |
| private void printOwnedManyToManyAnnotationOn(String fieldName, ManyToManyRelation relation, EntitySourceWriter pw) { |
| pw.printAnnotation(JPA.MANY_TO_MANY); |
| pw.println(); |
| boolean first = true; |
| boolean comma = false; |
| if ( ! relation.joinTableNameIsDefault()) { |
| if (first) { |
| first = false; |
| pw.printAnnotation(JPA.JOIN_TABLE); |
| pw.print('('); |
| } |
| pw.print("name=\""); |
| pw.print(relation.getJoinTable().name()); |
| pw.print('\"'); |
| comma = true; |
| } |
| if ( ! relation.joinColumnsIsDefaultFor(fieldName)) { |
| if (first) { |
| first = false; |
| pw.printAnnotation(JPA.JOIN_TABLE); |
| pw.print('('); |
| } else if (comma) { |
| pw.print(','); |
| } |
| pw.println(); |
| pw.indent(); |
| this.printJoinTableJoinColumnsOn("joinColumns", fieldName, relation.getOwningForeignKey(), pw); |
| pw.undent(); |
| comma = true; |
| } |
| String inverseFieldName = relation.getNonOwningTable().fieldNameFor(relation); |
| if ( ! relation.inverseJoinColumnsIsDefaultFor(inverseFieldName)) { |
| if (first) { |
| first = false; |
| pw.printAnnotation(JPA.JOIN_TABLE); |
| pw.print('('); |
| } else if (comma) { |
| pw.print(','); |
| } |
| pw.println(); |
| pw.indent(); |
| this.printJoinTableJoinColumnsOn("inverseJoinColumns", inverseFieldName, relation.getNonOwningForeignKey(), pw); |
| pw.undent(); |
| comma = true; |
| } |
| if ( ! first) { |
| pw.print(')'); |
| } |
| pw.println(); |
| } |
| |
| private void printJoinTableJoinColumnsOn(String elementName, String fieldName, ForeignKey foreignKey, EntitySourceWriter pw) { |
| if (foreignKey.columnPairsSize() != 1) { |
| this.printJoinTableJoinColumnsOn(elementName, foreignKey, pw); |
| } else if (foreignKey.getReferencedTable().primaryKeyColumnsSize() != 1) { |
| // if the referenced table has a composite primary key, neither of the columns can be a default |
| // since both of the defaults require a single-column primary key |
| this.printJoinTableJoinColumnsOn(elementName, foreignKey, pw); |
| } else { |
| ForeignKey.ColumnPair columnPair = foreignKey.columnPairs().next(); |
| Column pkColumn = foreignKey.getReferencedTable().primaryKeyColumns().next(); |
| if (columnPair.getBaseColumn().matchesJavaFieldName(fieldName + "_" + pkColumn.getName())) { |
| if (columnPair.getReferencedColumn() == pkColumn) { |
| // we shouldn't get here... |
| } else { |
| pw.print(elementName); |
| pw.print('='); |
| this.printJoinColumnAnnotationOn(null, columnPair.getReferencedColumn().getName(), pw); |
| } |
| } else { |
| if (columnPair.getReferencedColumn() == pkColumn) { |
| pw.print(elementName); |
| pw.print('='); |
| this.printJoinColumnAnnotationOn(columnPair.getBaseColumn().getName(), null, pw); |
| } else { |
| this.printJoinTableJoinColumnsOn(elementName, foreignKey, pw); |
| } |
| } |
| } |
| } |
| |
| private void printJoinTableJoinColumnsOn(String elementName, ForeignKey foreignKey, EntitySourceWriter pw) { |
| pw.print(elementName); |
| pw.print('='); |
| if (foreignKey.columnPairsSize() > 1) { |
| pw.print('{'); |
| pw.println(); |
| pw.indent(); |
| } |
| this.printJoinColumnAnnotationsOn(foreignKey, pw); |
| if (foreignKey.columnPairsSize() > 1) { |
| pw.undent(); |
| pw.println(); |
| pw.print('}'); |
| pw.println(); |
| } |
| } |
| |
| private void printEntityNonOwnedManyToManyFieldsOn(EntitySourceWriter pw) { |
| for (Iterator<ManyToManyRelation> stream = this.genTable.nonOwnedManyToManyRelations(); stream.hasNext(); ) { |
| this.printEntityNonOwnedManyToManyFieldOn(stream.next(), pw); |
| } |
| } |
| |
| private void printEntityNonOwnedManyToManyFieldOn(ManyToManyRelation relation, EntitySourceWriter pw) { |
| String fieldName = this.genTable.fieldNameFor(relation); |
| if (this.config.fieldAccessType()) { |
| this.printNonOwnedManyToManyAnnotationOn(fieldName, relation, pw); |
| } |
| pw.printVisibility(this.config.fieldVisibility()); |
| pw.printTypeDeclaration(this.config.getCollectionTypeName()); |
| pw.print('<'); |
| pw.printTypeDeclaration(this.fullyQualify(relation.owningEntityName())); |
| pw.print('>'); |
| pw.print(' '); |
| pw.print(fieldName); |
| pw.print(';'); |
| pw.println(); |
| pw.println(); |
| } |
| |
| private void printNonOwnedManyToManyAnnotationOn(String fieldName, ManyToManyRelation relation, EntitySourceWriter pw) { |
| pw.printAnnotation(JPA.MANY_TO_MANY); |
| pw.print("(mappedBy=\""); |
| pw.print(relation.getMappedBy()); |
| pw.print("\")"); |
| pw.println(); |
| } |
| |
| private String fullyQualify(String shortClassName) { |
| String pkg = this.packageName(); |
| return (pkg.length() == 0) ? shortClassName : pkg + '.' + shortClassName; |
| } |
| |
| private void printSerialVersionUID(EntitySourceWriter pw) { |
| if (this.config.generateSerialVersionUID()) { |
| pw.print("private static final long serialVersionUID = 1L;"); |
| pw.println(); |
| } |
| } |
| |
| private void printZeroArgumentConstructorOn(String ctorName, String visibility, EntitySourceWriter pw) { |
| if (this.config.generateDefaultConstructor()) { |
| pw.printVisibility(visibility); |
| pw.print(ctorName); |
| pw.print("() {"); |
| pw.println(); |
| pw.indent(); |
| pw.println("super();"); |
| pw.undent(); |
| pw.print('}'); |
| pw.println(); |
| pw.println(); |
| } |
| } |
| |
| private void printEntityPrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) { |
| if ((this.table().primaryKeyColumnsSize() > 1) && this.config.generateEmbeddedIdForCompoundPK()) { |
| this.printEntityEmbeddedIdPrimaryKeyGetterAndSetterOn(pw); |
| } else { |
| this.printEntityReadOnlyPrimaryKeyGettersAndSettersOn(pw); |
| this.printEntityWritablePrimaryKeyGettersAndSettersOn(pw); |
| } |
| } |
| |
| private void printEntityEmbeddedIdPrimaryKeyGetterAndSetterOn(EntitySourceWriter pw) { |
| if (this.config.propertyAccessType()) { |
| pw.printAnnotation(JPA.EMBEDDED_ID); |
| pw.println(); |
| } |
| pw.printGetterAndSetter(this.genTable.fieldNameForEmbeddedId(), this.entityClassName + ".PK", this.config.methodVisibility()); |
| } |
| |
| private void printEntityReadOnlyPrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) { |
| for (Iterator<Column> stream = this.genTable.readOnlyPrimaryKeyColumns(); stream.hasNext(); ) { |
| this.printEntityReadOnlyPrimaryKeyGetterAndSetterOn(stream.next(), pw); |
| } |
| } |
| |
| private void printEntityReadOnlyPrimaryKeyGetterAndSetterOn(Column column, EntitySourceWriter pw) { |
| String propertyName = this.genTable.fieldNameFor(column); |
| if (this.config.propertyAccessType()) { |
| pw.printAnnotation(JPA.ID); |
| pw.println(); |
| if (column.matchesJavaFieldName(propertyName)) { |
| this.printReadOnlyColumnAnnotationOn(pw); // no Column name needed |
| } else { |
| this.printReadOnlyColumnAnnotationOn(column.getName(), pw); |
| } |
| } |
| |
| pw.printGetterAndSetter(propertyName, column.javaTypeDeclaration(), this.config.methodVisibility()); |
| } |
| |
| private void printEntityWritablePrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) { |
| for (Iterator<Column> stream = this.genTable.writablePrimaryKeyColumns(); stream.hasNext(); ) { |
| this.printEntityWritablePrimaryKeyGetterAndSetterOn(stream.next(), pw); |
| } |
| } |
| |
| private void printEntityWritablePrimaryKeyGetterAndSetterOn(Column column, EntitySourceWriter pw) { |
| String propertyName = this.genTable.fieldNameFor(column); |
| if (this.config.propertyAccessType()) { |
| pw.printAnnotation(JPA.ID); |
| pw.println(); |
| if ( ! column.matchesJavaFieldName(propertyName)) { |
| this.printColumnAnnotationOn(column.getName(), pw); |
| } |
| } |
| |
| pw.printGetterAndSetter(propertyName, column.javaTypeDeclaration(), this.config.methodVisibility()); |
| } |
| |
| private void printEntityNonPrimaryKeyBasicGettersAndSettersOn(EntitySourceWriter pw) { |
| for (Iterator<Column> stream = this.genTable.nonPrimaryKeyBasicColumns(); stream.hasNext(); ) { |
| this.printEntityNonPrimaryKeyBasicGetterAndSetterOn(stream.next(), pw); |
| } |
| } |
| |
| private void printEntityNonPrimaryKeyBasicGetterAndSetterOn(Column column, EntitySourceWriter pw) { |
| String propertyName = this.genTable.fieldNameFor(column); |
| if (this.config.propertyAccessType()) { |
| if ( ! column.matchesJavaFieldName(propertyName)) { |
| this.printColumnAnnotationOn(column.getName(), pw); |
| } |
| } |
| |
| pw.printGetterAndSetter(propertyName, column.javaTypeDeclaration(), this.config.methodVisibility()); |
| } |
| |
| private void printEntityManyToOneGettersAndSettersOn(EntitySourceWriter pw) { |
| for (Iterator<ManyToOneRelation> stream = this.genTable.manyToOneRelations(); stream.hasNext(); ) { |
| this.printEntityManyToOneGetterAndSetterOn(stream.next(), pw); |
| } |
| } |
| |
| private void printEntityManyToOneGetterAndSetterOn(ManyToOneRelation relation, EntitySourceWriter pw) { |
| String propertyName = this.genTable.fieldNameFor(relation); |
| if (this.config.propertyAccessType()) { |
| this.printManyToOneAnnotationOn(propertyName, relation, pw); |
| } |
| |
| String typeDeclaration = this.fullyQualify(relation.referencedEntityName()); |
| pw.printGetterAndSetter(propertyName, typeDeclaration, this.config.methodVisibility()); |
| } |
| |
| private void printEntityOneToManyGettersAndSettersOn(EntitySourceWriter pw) { |
| for (Iterator<OneToManyRelation> stream = this.genTable.oneToManyRelations(); stream.hasNext(); ) { |
| this.printEntityOneToManyGetterAndSetterOn(stream.next(), pw); |
| } |
| } |
| |
| private void printEntityOneToManyGetterAndSetterOn(OneToManyRelation relation, EntitySourceWriter pw) { |
| String propertyName = this.genTable.fieldNameFor(relation); |
| if (this.config.propertyAccessType()) { |
| this.printOneToManyAnnotationOn(propertyName, relation, pw); |
| } |
| |
| String elementTypeDeclaration = this.fullyQualify(relation.referencedEntityName()); |
| pw.printCollectionGetterAndSetter(propertyName, this.config.getCollectionTypeName(), elementTypeDeclaration, this.config.methodVisibility()); |
| } |
| |
| private void printEntityOwnedManyToManyGettersAndSettersOn(EntitySourceWriter pw) { |
| for (Iterator<ManyToManyRelation> stream = this.genTable.ownedManyToManyRelations(); stream.hasNext(); ) { |
| this.printEntityOwnedManyToManyGetterAndSetterOn(stream.next(), pw); |
| } |
| } |
| |
| private void printEntityOwnedManyToManyGetterAndSetterOn(ManyToManyRelation relation, EntitySourceWriter pw) { |
| String propertyName = this.genTable.fieldNameFor(relation); |
| if (this.config.propertyAccessType()) { |
| this.printOwnedManyToManyAnnotationOn(propertyName, relation, pw); |
| } |
| |
| String elementTypeDeclaration = this.fullyQualify(relation.nonOwningEntityName()); |
| pw.printCollectionGetterAndSetter(propertyName, this.config.getCollectionTypeName(), elementTypeDeclaration, this.config.methodVisibility()); |
| } |
| |
| private void printEntityNonOwnedManyToManyGettersAndSettersOn(EntitySourceWriter pw) { |
| for (Iterator<ManyToManyRelation> stream = this.genTable.nonOwnedManyToManyRelations(); stream.hasNext(); ) { |
| this.printEntityNonOwnedManyToManyGetterAndSetterOn(stream.next(), pw); |
| } |
| } |
| |
| private void printEntityNonOwnedManyToManyGetterAndSetterOn(ManyToManyRelation relation, EntitySourceWriter pw) { |
| String propertyName = this.genTable.fieldNameFor(relation); |
| if (this.config.propertyAccessType()) { |
| this.printNonOwnedManyToManyAnnotationOn(propertyName, relation, pw); |
| } |
| |
| String elementTypeDeclaration = this.fullyQualify(relation.owningEntityName()); |
| pw.printCollectionGetterAndSetter(propertyName, this.config.getCollectionTypeName(), elementTypeDeclaration, this.config.methodVisibility()); |
| } |
| |
| private void printPrimaryKeyClassOn(EntitySourceWriter pw) { |
| if (this.table().primaryKeyColumnsSize() <= 1) { |
| return; |
| } |
| pw.println(); |
| if (this.config.generateEmbeddedIdForCompoundPK()) { |
| pw.printAnnotation(JPA.EMBEDDABLE); |
| pw.println(); |
| } |
| pw.print("public static class PK implements "); |
| pw.printTypeDeclaration(Serializable.class.getName()); |
| pw.print(" {"); |
| pw.println(); |
| |
| pw.indent(); |
| this.printIdFieldsOn(pw); |
| this.printSerialVersionUID(pw); |
| pw.println(); |
| this.printZeroArgumentConstructorOn("PK", "public", pw); |
| |
| if (this.config.propertyAccessType() || this.config.generateGettersAndSetters()) { |
| this.printIdGettersAndSettersOn(pw); |
| } |
| |
| this.printEqualsMethodOn("PK", this.table().primaryKeyColumns(), pw); |
| this.printHashCodeMethodOn(this.table().primaryKeyColumns(), pw); |
| pw.undent(); |
| |
| pw.print('}'); |
| pw.println(); |
| pw.println(); |
| } |
| |
| private void printIdFieldsOn(EntitySourceWriter pw) { |
| for (Iterator<Column> stream = this.table().primaryKeyColumns(); stream.hasNext(); ) { |
| this.printIdFieldOn(stream.next(), pw); |
| } |
| } |
| |
| private void printIdFieldOn(Column column, EntitySourceWriter pw) { |
| String fieldName = this.genTable.fieldNameFor(column); |
| pw.printVisibility(this.config.fieldVisibility()); |
| pw.printTypeDeclaration(column.javaTypeDeclaration()); |
| pw.print(' '); |
| pw.print(fieldName); |
| pw.print(';'); |
| pw.println(); |
| } |
| |
| private void printIdGettersAndSettersOn(EntitySourceWriter pw) { |
| for (Iterator<Column> stream = this.table().primaryKeyColumns(); stream.hasNext(); ) { |
| this.printIdGetterAndSetterOn(stream.next(), pw); |
| } |
| } |
| |
| private void printIdGetterAndSetterOn(Column column, EntitySourceWriter pw) { |
| String propertyName = this.genTable.fieldNameFor(column); |
| pw.printGetterAndSetter(propertyName, column.javaTypeDeclaration(), this.config.methodVisibility()); |
| } |
| |
| private void printEqualsMethodOn(String className, Iterator<Column> columns, EntitySourceWriter pw) { |
| pw.printAnnotation("java.lang.Override"); |
| pw.println(); |
| |
| pw.println("public boolean equals(Object o) {"); |
| pw.indent(); |
| pw.println("if (o == this) {"); |
| pw.indent(); |
| pw.println("return true;"); |
| pw.undent(); |
| pw.print('}'); |
| pw.println(); |
| |
| pw.print("if ( ! (o instanceof "); |
| pw.print(className); |
| pw.print(")) {"); |
| pw.println(); |
| pw.indent(); |
| pw.println("return false;"); |
| pw.undent(); |
| pw.print('}'); |
| pw.println(); |
| |
| pw.print(className); |
| pw.print(" other = ("); |
| pw.print(className); |
| pw.print(") o;"); |
| pw.println(); |
| |
| pw.print("return "); |
| pw.indent(); |
| while (columns.hasNext()) { |
| this.printEqualsClauseOn(columns.next(), pw); |
| if (columns.hasNext()) { |
| pw.println(); |
| pw.print("&& "); |
| } |
| } |
| pw.print(';'); |
| pw.println(); |
| pw.undent(); |
| pw.undent(); |
| pw.print('}'); |
| pw.println(); |
| pw.println(); |
| } |
| |
| private void printEqualsClauseOn(Column column, EntitySourceWriter pw) { |
| String fieldName = this.genTable.fieldNameFor(column); |
| JavaType javaType = column.javaType(); |
| if (javaType.isPrimitive()) { |
| this.printPrimitiveEqualsClauseOn(fieldName, pw); |
| } else { |
| this.printReferenceEqualsClauseOn(fieldName, pw); |
| } |
| } |
| |
| private void printPrimitiveEqualsClauseOn(String fieldName, EntitySourceWriter pw) { |
| pw.print("(this."); |
| pw.print(fieldName); |
| pw.print(" == other."); |
| pw.print(fieldName); |
| pw.print(')'); |
| } |
| |
| private void printReferenceEqualsClauseOn(String fieldName, EntitySourceWriter pw) { |
| pw.print("this."); |
| pw.print(fieldName); |
| pw.print(".equals(other."); |
| pw.print(fieldName); |
| pw.print(')'); |
| } |
| |
| private void printHashCodeMethodOn(Iterator<Column> columns, EntitySourceWriter pw) { |
| pw.printAnnotation("java.lang.Override"); |
| pw.println(); |
| |
| pw.println("public int hashCode() {"); |
| pw.indent(); |
| pw.print("return "); |
| pw.indent(); |
| while (columns.hasNext()) { |
| this.printHashCodeClauseOn(columns.next(), pw); |
| if (columns.hasNext()) { |
| pw.println(); |
| pw.print("^ "); |
| } |
| } |
| pw.print(';'); |
| pw.println(); |
| pw.undent(); |
| pw.undent(); |
| pw.print('}'); |
| pw.println(); |
| pw.println(); |
| } |
| |
| private void printHashCodeClauseOn(Column column, EntitySourceWriter pw) { |
| String fieldName = this.genTable.fieldNameFor(column); |
| JavaType javaType = column.javaType(); |
| if (javaType.isPrimitive()) { |
| this.printPrimitiveHashCodeClauseOn(javaType.getElementTypeName(), fieldName, pw); |
| } else { |
| this.printReferenceHashCodeClauseOn(fieldName, pw); |
| } |
| } |
| |
| private void printPrimitiveHashCodeClauseOn(String primitiveName, String fieldName, EntitySourceWriter pw) { |
| if (primitiveName.equals("int") || primitiveName.equals("short") || primitiveName.equals("byte") || primitiveName.equals("char")) { |
| pw.print("this."); |
| pw.print(fieldName); |
| } else if (primitiveName.equals("long")) { // cribbed from Long#hashCode() |
| // ((int) (this.value ^ (this.value >>> 32))) |
| pw.print("((int) (this."); |
| pw.print(fieldName); |
| pw.print(" ^ (this."); |
| pw.print(fieldName); |
| pw.print(" >>> 32)))"); |
| } else if (primitiveName.equals("double")) { // cribbed from Double#hashCode() |
| // ((int) (java.lang.Double.doubleToLongBits(this.value) ^ (java.lang.Double.doubleToLongBits(this.value) >>> 32))) |
| pw.print("((int) ("); |
| pw.printTypeDeclaration("java.lang.Double"); |
| pw.print(".doubleToLongBits(this."); |
| pw.print(fieldName); |
| pw.print(") ^ ("); |
| pw.printTypeDeclaration("java.lang.Double"); |
| pw.print(".doubleToLongBits(this."); |
| pw.print(fieldName); |
| pw.print(") >>> 32)))"); |
| } else if (primitiveName.equals("float")) { // cribbed from Float#hashCode() |
| // java.lang.Float.floatToIntBits(this.value) |
| pw.printTypeDeclaration("java.lang.Float"); |
| pw.print(".floatToIntBits(this."); |
| pw.print(fieldName); |
| pw.print(')'); |
| } else if (primitiveName.equals("boolean")) { // cribbed from Boolean#hashCode() |
| // (this.value ? 1231 : 1237) |
| pw.print("(this."); |
| pw.print(fieldName); |
| pw.print(" ? 1231 : 1237)"); |
| } else { |
| throw new IllegalArgumentException(primitiveName); |
| } |
| } |
| |
| private void printReferenceHashCodeClauseOn(String fieldName, EntitySourceWriter pw) { |
| pw.print("this."); |
| pw.print(fieldName); |
| pw.print(".hashCode()"); |
| } |
| |
| private void printPackageAndImportsOn(PrintWriter pw, BodySource bodySource) { |
| if (this.packageName().length() != 0) { |
| pw.print("package "); |
| pw.print(this.packageName()); |
| pw.print(';'); |
| pw.println(); |
| pw.println(); |
| } |
| |
| for (Iterator<Map.Entry<String, String>> stream = bodySource.importEntries(); stream.hasNext(); ) { |
| Map.Entry<String, String> entry = stream.next(); |
| pw.print("import "); |
| pw.print(entry.getValue()); // package |
| pw.print('.'); |
| pw.print(entry.getKey()); // short class name |
| pw.print(';'); |
| pw.println(); |
| } |
| pw.println(); |
| } |
| |
| |
| // ********** convenience methods ********** |
| |
| private String packageName() { |
| return this.packageFragment.getElementName(); |
| } |
| |
| private Table table() { |
| return this.genTable.getTable(); |
| } |
| |
| private String entityName() { |
| return this.genTable.getEntityName(); |
| } |
| |
| |
| // ********** writer ********** |
| |
| private interface BodySource { |
| |
| /** |
| * return a sorted set of map entries; the key is the short class name, |
| * the value is the package name |
| */ |
| Iterator<Map.Entry<String, String>> importEntries(); |
| |
| /** |
| * return the body source code |
| */ |
| String source(); |
| |
| /** |
| * return the length of the body source code |
| */ |
| int length(); |
| |
| } |
| |
| /** |
| * Extend IndentingPrintWriter with some methods that facilitate building |
| * entity source code. |
| */ |
| private static class EntitySourceWriter extends IndentingPrintWriter implements BodySource { |
| final String packageName; |
| final String entityClassName; |
| // key = short class name; value = package name |
| private final Map<String, String> imports = new HashMap<String, String>(); |
| |
| EntitySourceWriter(String packageName, String entityClassName) { |
| super(new StringWriter(20000)); |
| this.packageName = packageName; |
| this.entityClassName = entityClassName; |
| } |
| |
| void printVisibility(String visibilityModifier) { |
| if (visibilityModifier.length() != 0) { |
| this.print(visibilityModifier); |
| this.print(' '); |
| } |
| } |
| |
| void printAnnotation(String annotationName) { |
| this.print('@'); |
| this.printTypeDeclaration(annotationName); |
| } |
| |
| void printTypeDeclaration(String typeDeclaration) { |
| this.print(this.importedTypeDeclaration(typeDeclaration)); |
| } |
| |
| /** |
| * Return the specified class's "imported" name. |
| * The class declaration must be of the form: |
| * "int" |
| * "int[]" (not "[I") |
| * "java.lang.Object" |
| * "java.lang.Object[]" (not "[Ljava.lang.Object;") |
| * "java.util.Map.Entry" (not "java.util.Map$Entry") |
| * "java.util.Map.Entry[][]" (not "[[Ljava.util.Map$Entry;") |
| */ |
| private String importedTypeDeclaration(String typeDeclaration) { |
| if (this.typeDeclarationIsMemberClass(typeDeclaration)) { |
| // no need for an import, just return the partially-qualified name |
| return this.memberClassTypeDeclaration(typeDeclaration); |
| } |
| int last = typeDeclaration.lastIndexOf('.'); |
| String pkg = (last == -1) ? "" : typeDeclaration.substring(0, last); |
| String shortTypeDeclaration = typeDeclaration.substring(last + 1); |
| String shortElementTypeName = shortTypeDeclaration; |
| while (shortElementTypeName.endsWith("[]")) { |
| shortElementTypeName = shortElementTypeName.substring(0, shortElementTypeName.length() - 2); |
| } |
| String prev = this.imports.get(shortElementTypeName); |
| if (prev == null) { |
| // this is the first class with this short element type name |
| this.imports.put(shortElementTypeName, pkg); |
| return shortTypeDeclaration; |
| } |
| if (prev.equals(pkg)) { |
| // this element type has already been imported |
| return shortTypeDeclaration; |
| } |
| // another class with the same short element type name has been |
| // previously imported, so this one must be used fully-qualified |
| return typeDeclaration; |
| } |
| |
| /** |
| * e.g. "foo.bar.Employee.PK" will return true |
| */ |
| private boolean typeDeclarationIsMemberClass(String typeDeclaration) { |
| return (typeDeclaration.length() > this.entityClassName.length()) |
| && typeDeclaration.startsWith(this.entityClassName) |
| && (typeDeclaration.charAt(this.entityClassName.length()) == '.'); |
| } |
| |
| /** |
| * e.g. "foo.bar.Employee.PK" will return "Employee.PK" |
| * this prevents collisions with other imported classes (e.g. "joo.jar.PK") |
| */ |
| private String memberClassTypeDeclaration(String typeDeclaration) { |
| int index = this.packageName.length(); |
| if (index != 0) { |
| index++; // bump past the '.' |
| } |
| return typeDeclaration.substring(index); |
| } |
| |
| public Iterator<Map.Entry<String, String>> importEntries() { |
| return new FilteringIterator<Map.Entry<String, String>>(this.sortedImportEntries()) { |
| @Override |
| @SuppressWarnings("unchecked") |
| protected boolean accept(Object next) { |
| String pkg = ((Map.Entry<String, String>) next).getValue(); |
| if (pkg.equals("") |
| || pkg.equals("java.lang") |
| || pkg.equals(EntitySourceWriter.this.packageName)) { |
| return false; |
| } |
| return true; |
| } |
| }; |
| } |
| |
| private Iterator<Map.Entry<String, String>> sortedImportEntries() { |
| TreeSet<Map.Entry<String, String>> sortedImports = new TreeSet<Map.Entry<String, String>>(this.buildImportEntriesComparator()); |
| sortedImports.addAll(this.imports.entrySet()); |
| return sortedImports.iterator(); |
| } |
| |
| private Comparator<Map.Entry<String, String>> buildImportEntriesComparator() { |
| return new Comparator<Map.Entry<String, String>>() { |
| public int compare(Map.Entry<String, String> e1, Map.Entry<String, String> e2) { |
| Collator collator = Collator.getInstance(); |
| int pkg = collator.compare(e1.getValue(), e2.getValue()); |
| return (pkg == 0) ? collator.compare(e1.getKey(), e2.getKey()) : pkg; |
| } |
| }; |
| } |
| |
| void printGetterAndSetter(String propertyName, String typeDeclaration, String visibility) { |
| this.printGetter(propertyName, typeDeclaration, visibility); |
| this.println(); |
| this.println(); |
| |
| this.printSetter(propertyName, typeDeclaration, visibility); |
| this.println(); |
| this.println(); |
| } |
| |
| private void printGetter(String propertyName, String typeDeclaration, String visibility) { |
| this.printVisibility(visibility); |
| this.printTypeDeclaration(typeDeclaration); |
| this.print(' '); |
| this.print(typeDeclaration.equals("boolean") ? "is" : "get"); |
| this.print(StringTools.capitalize(propertyName)); |
| this.print("() {"); |
| this.println(); |
| |
| this.indent(); |
| this.print("return this."); |
| this.print(propertyName); |
| this.print(';'); |
| this.println(); |
| this.undent(); |
| |
| this.print('}'); |
| } |
| |
| private void printSetter(String propertyName, String typeDeclaration, String visibility) { |
| this.printVisibility(visibility); |
| this.print("void set"); |
| this.print(StringTools.capitalize(propertyName)); |
| this.print('('); |
| this.printTypeDeclaration(typeDeclaration); |
| this.print(' '); |
| this.print(propertyName); |
| this.print(") {"); |
| this.println(); |
| |
| this.indent(); |
| this.print("this."); |
| this.print(propertyName); |
| this.print(" = "); |
| this.print(propertyName); |
| this.print(';'); |
| this.println(); |
| this.undent(); |
| |
| this.print('}'); |
| } |
| |
| void printCollectionGetterAndSetter(String propertyName, String collectionTypeDeclaration, String elementTypeDeclaration, String visibility) { |
| this.printCollectionGetter(propertyName, collectionTypeDeclaration, elementTypeDeclaration, visibility); |
| this.println(); |
| this.println(); |
| |
| this.printCollectionSetter(propertyName, collectionTypeDeclaration, elementTypeDeclaration, visibility); |
| this.println(); |
| this.println(); |
| } |
| |
| private void printCollectionGetter(String propertyName, String collectionTypeDeclaration, String elementTypeDeclaration, String visibility) { |
| this.printVisibility(visibility); |
| this.printTypeDeclaration(collectionTypeDeclaration); |
| this.print('<'); |
| this.printTypeDeclaration(elementTypeDeclaration); |
| this.print("> get"); |
| this.print(StringTools.capitalize(propertyName)); |
| this.print("() {"); |
| this.println(); |
| |
| this.indent(); |
| this.print("return this."); |
| this.print(propertyName); |
| this.print(';'); |
| this.println(); |
| this.undent(); |
| |
| this.print('}'); |
| } |
| |
| private void printCollectionSetter(String propertyName, String collectionTypeDeclaration, String elementTypeDeclaration, String visibility) { |
| this.printVisibility(visibility); |
| this.print("void set"); |
| this.print(StringTools.capitalize(propertyName)); |
| this.print('('); |
| this.printTypeDeclaration(collectionTypeDeclaration); |
| this.print('<'); |
| this.printTypeDeclaration(elementTypeDeclaration); |
| this.print('>'); |
| this.print(' '); |
| this.print(propertyName); |
| this.print(") {"); |
| this.println(); |
| |
| this.indent(); |
| this.print("this."); |
| this.print(propertyName); |
| this.print(" = "); |
| this.print(propertyName); |
| this.print(';'); |
| this.println(); |
| this.undent(); |
| |
| this.print('}'); |
| } |
| |
| public String source() { |
| return this.out.toString(); |
| } |
| |
| public int length() { |
| return ((StringWriter) this.out).getBuffer().length(); |
| } |
| |
| } |
| |
| |
| // ********** config ********** |
| |
| public static class Config { |
| private boolean convertToCamelCase = true; |
| private boolean propertyAccessType = false; // as opposed to "field" |
| private String collectionTypeName = Set.class.getName(); |
| private int fieldVisibility = Modifier.PRIVATE; |
| private int methodVisibility = Modifier.PUBLIC; |
| private boolean generateGettersAndSetters = true; |
| private boolean generateDefaultConstructor = true; |
| private boolean serializable = true; |
| private boolean generateSerialVersionUID = true; |
| private boolean generateEmbeddedIdForCompoundPK = true; // as opposed to IdClass |
| private Map<Table, String> overrideEntityNames = new HashMap<Table, String>(); |
| |
| public static final int PRIVATE = 0; |
| public static final int PACKAGE = 1; |
| public static final int PROTECTED = 2; |
| public static final int PUBLIC = 3; |
| |
| |
| public boolean convertToCamelCase() { |
| return this.convertToCamelCase; |
| } |
| public void setConvertToCamelCase(boolean convertToCamelCase) { |
| this.convertToCamelCase = convertToCamelCase; |
| } |
| |
| public boolean propertyAccessType() { |
| return this.propertyAccessType; |
| } |
| public void setPropertyAccessType(boolean propertyAccessType) { |
| this.propertyAccessType = propertyAccessType; |
| } |
| |
| public boolean fieldAccessType() { |
| return ! this.propertyAccessType; |
| } |
| public void setFieldAccessType(boolean fieldAccessType) { |
| this.propertyAccessType = ! fieldAccessType; |
| } |
| |
| public String getCollectionTypeName() { |
| return this.collectionTypeName; |
| } |
| public void setCollectionTypeName(String collectionTypeName) { |
| this.collectionTypeName = collectionTypeName; |
| } |
| |
| public int getFieldVisibility() { |
| return this.fieldVisibility; |
| } |
| /** entity fields cannot be 'public' */ |
| public void setFieldVisibility(int fieldVisibility) { |
| switch (fieldVisibility) { |
| case PRIVATE: |
| case PACKAGE: |
| case PROTECTED: |
| this.fieldVisibility = fieldVisibility; |
| break; |
| default: |
| throw new IllegalArgumentException("invalid field visibility: " + fieldVisibility); |
| } |
| } |
| String fieldVisibility() { |
| switch (this.fieldVisibility) { |
| case PRIVATE: |
| return "private"; |
| case PACKAGE: |
| return ""; |
| case PROTECTED: |
| return "protected"; |
| default: |
| throw new IllegalStateException("invalid field visibility: " + this.fieldVisibility); |
| } |
| } |
| |
| public int getMethodVisibility() { |
| return this.methodVisibility; |
| } |
| /** entity properties must be 'public' or 'protected' */ |
| public void setMethodVisibility(int methodVisibility) { |
| switch (methodVisibility) { |
| case PROTECTED: |
| case PUBLIC: |
| this.methodVisibility = methodVisibility; |
| break; |
| default: |
| throw new IllegalArgumentException("invalid method visibility: " + methodVisibility); |
| } |
| } |
| String methodVisibility() { |
| switch (this.methodVisibility) { |
| case PROTECTED: |
| return "protected"; |
| case PUBLIC: |
| return "public"; |
| default: |
| throw new IllegalStateException("invalid method visibility: " + this.methodVisibility); |
| } |
| } |
| |
| public boolean generateGettersAndSetters() { |
| return this.generateGettersAndSetters; |
| } |
| public void setGenerateGettersAndSetters(boolean generateGettersAndSetters) { |
| this.generateGettersAndSetters = generateGettersAndSetters; |
| } |
| |
| public boolean generateDefaultConstructor() { |
| return this.generateDefaultConstructor; |
| } |
| public void setGenerateDefaultConstructor(boolean generateDefaultConstructor) { |
| this.generateDefaultConstructor = generateDefaultConstructor; |
| } |
| |
| public boolean serializable() { |
| return this.serializable; |
| } |
| public void setSerializable(boolean serializable) { |
| this.serializable = serializable; |
| } |
| |
| public boolean generateSerialVersionUID() { |
| return this.generateSerialVersionUID; |
| } |
| public void setGenerateSerialVersionUID(boolean generateSerialVersionUID) { |
| this.generateSerialVersionUID = generateSerialVersionUID; |
| } |
| |
| public boolean generateEmbeddedIdForCompoundPK() { |
| return this.generateEmbeddedIdForCompoundPK; |
| } |
| public void setGenerateEmbeddedIdForCompoundPK(boolean generateEmbeddedIdForCompoundPK) { |
| this.generateEmbeddedIdForCompoundPK = generateEmbeddedIdForCompoundPK; |
| } |
| |
| public boolean generateIdClassForCompoundPK() { |
| return ! this.generateEmbeddedIdForCompoundPK; |
| } |
| public void setGenerateIdClassForCompoundPK(boolean generateIdClassForCompoundPK) { |
| this.generateEmbeddedIdForCompoundPK = ! generateIdClassForCompoundPK; |
| } |
| |
| /** |
| * key = table |
| * value = user-supplied override entity name |
| */ |
| public String getOverrideEntityName(Table table) { |
| return this.overrideEntityNames.get(table); |
| } |
| public void setOverrideEntityName(Table table, String overrideEntityName) { |
| this.overrideEntityNames.put(table, overrideEntityName); |
| } |
| public void clearOverrideEntityNames() { |
| this.overrideEntityNames.clear(); |
| } |
| public void setOverrideEntityNames(Map<Table, String> overrideEntityNames) { |
| this.clearOverrideEntityNames(); |
| for (Map.Entry<Table, String> entry : overrideEntityNames.entrySet()) { |
| this.setOverrideEntityName(entry.getKey(), entry.getValue()); |
| } |
| } |
| |
| } |
| |
| |
| // ********** config ********** |
| |
| public static interface OverwriteConfirmer { |
| /** |
| * Return whether the entity generator should overwrite the specified |
| * file. |
| */ |
| boolean overwrite(String className); |
| } |
| |
| } |