/*******************************************************************************
 * Copyright (c) 2006, 2008 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.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jpt.core.resource.java.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;
	private final String pkClassName;


	// ********** 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;
		this.pkClassName = this.entityClassName + "PK";  // hack
	}


	// ********** code gen **********

	private void generateEntity() {
		int totalWork = pkClassIsGenerated() ? 40 : 20;
		try {
			this.monitor.beginTask("", totalWork);
			this.generateEntity_();
		} catch (JavaModelException ex) {
			throw new RuntimeException(ex);
		}
		finally {
			this.monitor.done();
		}
	}

	private void generateEntity_() throws JavaModelException {
		// build the body source first so we can gather up the import statements
		this.generateSourceFile(this.entityClassName, this.entityName() + ".java", this.buildSource(this.buildBodySource()));
		if (this.pkClassIsGenerated()) {
			this.generateSourceFile(this.pkClassName, this.pkName() + ".java", this.buildSource(this.buildPKBodySource()));
		}
		
	}

	private void generateSourceFile(String className, String fileName, String source) throws JavaModelException {
		try {
			this.packageFragment.createCompilationUnit(fileName, source, false, new SubProgressMonitor(this.monitor, 10));
		} catch (JavaModelException ex) {
			if (ex.getJavaModelStatus().getCode() == IJavaModelStatusConstants.NAME_COLLISION) {
				if (this.overwriteConfirmer.overwrite(className)) {
					this.packageFragment.createCompilationUnit(fileName, source, true, new SubProgressMonitor(this.monitor, 0));
				}
			} 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(BodySource bodySource) {
		StringWriter sw = new StringWriter(bodySource.length() + 1000);
		PrintWriter pw = new PrintWriter(sw);
		this.printPackageAndImportsOn(pw, bodySource);
		pw.print(bodySource.source());
		this.monitor.worked(10);
		return sw.toString();
	}

	private BodySource buildBodySource() {
		EntitySourceWriter pw = new EntitySourceWriter(this.packageName(), this.entityClassName);
		this.printBodySourceOn(pw);
		return pw;
	}

	private BodySource buildPKBodySource() {
		EntitySourceWriter pw = new EntitySourceWriter(this.packageName(), this.pkClassName);
		this.printPrimaryKeyClassOn(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);
			}
		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.pkClassIsGenerated() && this.config.generateIdClassForCompoundPK()) {
			pw.printAnnotation(JPA.ID_CLASS);
			pw.print('(');
			pw.printTypeDeclaration(pkClassName);
			pw.print(".class)");
			pw.println();
		}
	}

	private void printEntityPrimaryKeyFieldsOn(EntitySourceWriter pw) {
		if (this.pkClassIsGenerated() && 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.pkClassName);
		pw.print(' ');
		pw.print(this.genTable.fieldNameForEmbeddedId());
		pw.print(';');
		pw.println();
		pw.println();
	}

	private void printEntityReadOnlyPrimaryKeyFieldsOn(EntitySourceWriter pw) {
		this.printReadOnlyPrimaryKeyFieldsOn(pw, true);  // true=print ID annotation on fields
	}

	private void printReadOnlyPrimaryKeyFieldsOn(EntitySourceWriter pw, boolean printIdAnnotation) {
		for (Iterator<Column> stream = this.genTable.readOnlyPrimaryKeyColumns(); stream.hasNext(); ) {
			this.printReadOnlyPrimaryKeyFieldOn(stream.next(), pw, printIdAnnotation);
		}
	}

	// TODO if the field's type is java.util.Date, it needs @Temporal(DATE)
	// TODO if the primary key is auto-generated, the field must be an integral type
	private void printReadOnlyPrimaryKeyFieldOn(Column column, EntitySourceWriter pw, boolean printIdAnnotation) {
		String fieldName = this.genTable.fieldNameFor(column);
		if (this.config.fieldAccessType()) {
			if (printIdAnnotation) {
				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.primaryKeyJavaTypeDeclaration());
		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) {
		this.printWritablePrimaryKeyFieldsOn(pw, true);  // true=print ID annotation on fields
	}

	private void printWritablePrimaryKeyFieldsOn(EntitySourceWriter pw, boolean printIdAnnotation) {
		for (Iterator<Column> stream = this.genTable.writablePrimaryKeyColumns(); stream.hasNext(); ) {
			this.printWritablePrimaryKeyFieldOn(stream.next(), pw, printIdAnnotation);
		}
	}

	// TODO if the field's type is java.util.Date, it needs @Temporal(DATE)
	// TODO if the primary key is auto-generated, the field must be an integral type
	private void printWritablePrimaryKeyFieldOn(Column column, EntitySourceWriter pw, boolean printIdAnnotation) {
		String fieldName = this.genTable.fieldNameFor(column);
		if (this.config.fieldAccessType()) {
			if (printIdAnnotation) {
				pw.printAnnotation(JPA.ID);
				pw.println();
			}
			if ( ! column.matchesJavaFieldName(fieldName)) {
				this.printColumnAnnotationOn(column.getName(), pw);
			}
		}
		pw.printVisibility(this.config.fieldVisibility());
		pw.printTypeDeclaration(column.primaryKeyJavaTypeDeclaration());
		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);
			}
		}
		if (column.isLob()) {
			pw.printAnnotation(JPA.LOB);
			pw.println();
		}
		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.pkClassIsGenerated() && 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.pkClassName, this.config.methodVisibility());
	}

	private void printEntityReadOnlyPrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) {
		this.printReadOnlyPrimaryKeyGettersAndSettersOn(pw, true);  // true=print ID annotation on fields
	}

	private void printReadOnlyPrimaryKeyGettersAndSettersOn(EntitySourceWriter pw, boolean printIdAnnotation) {
		for (Iterator<Column> stream = this.genTable.readOnlyPrimaryKeyColumns(); stream.hasNext(); ) {
			this.printReadOnlyPrimaryKeyGetterAndSetterOn(stream.next(), pw, printIdAnnotation);
		}
	}

	// TODO if the property's type is java.util.Date, it needs @Temporal(DATE)
	// TODO if the primary key is auto-generated, the property must be an integral type
	private void printReadOnlyPrimaryKeyGetterAndSetterOn(Column column, EntitySourceWriter pw, boolean printIdAnnotation) {
		String propertyName = this.genTable.fieldNameFor(column);
		if (this.config.propertyAccessType()) {
			if (printIdAnnotation) {
				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.primaryKeyJavaTypeDeclaration(), this.config.methodVisibility());
	}

	private void printEntityWritablePrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) {
		this.printWritablePrimaryKeyGettersAndSettersOn(pw, true);  // true=print ID annotation on fields
	}

	private void printWritablePrimaryKeyGettersAndSettersOn(EntitySourceWriter pw, boolean printIdAnnotation) {
		for (Iterator<Column> stream = this.genTable.writablePrimaryKeyColumns(); stream.hasNext(); ) {
			this.printWritablePrimaryKeyGetterAndSetterOn(stream.next(), pw, printIdAnnotation);
		}
	}

	// TODO if the property's type is java.util.Date, it needs @Temporal(DATE)
	// TODO if the primary key is auto-generated, the property must be an integral type
	private void printWritablePrimaryKeyGetterAndSetterOn(Column column, EntitySourceWriter pw, boolean printIdAnnotation) {
		String propertyName = this.genTable.fieldNameFor(column);
		if (this.config.propertyAccessType()) {
			if (printIdAnnotation) {
				pw.printAnnotation(JPA.ID);
				pw.println();
			}
			if ( ! column.matchesJavaFieldName(propertyName)) {
				this.printColumnAnnotationOn(column.getName(), pw);
			}
		}

		pw.printGetterAndSetter(propertyName, column.primaryKeyJavaTypeDeclaration(), 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.config.generateEmbeddedIdForCompoundPK()) {
			pw.printAnnotation(JPA.EMBEDDABLE);
			pw.println();
		}
		pw.print("public class ");
		pw.printTypeDeclaration(this.pkClassName);
		pw.print(" implements ");
		pw.printTypeDeclaration(Serializable.class.getName());
		pw.print(" {");
		pw.println();

		pw.indent();
			if (this.config.generateEmbeddedIdForCompoundPK()) {
				this.printEmbeddableReadOnlyPrimaryKeyFieldsOn(pw);
				this.printEmbeddableWritablePrimaryKeyFieldsOn(pw);
			} else {
				this.printIdFieldsOn(pw);
			}
			this.printSerialVersionUID(pw);
			pw.println();
			this.printZeroArgumentConstructorOn(this.pkName(), "public", pw);

			if (this.config.propertyAccessType() || this.config.generateGettersAndSetters()) {
				if (this.config.generateEmbeddedIdForCompoundPK()) {
					this.printEmbeddableReadOnlyPrimaryKeyGettersAndSettersOn(pw);
					this.printEmbeddableWritablePrimaryKeyGettersAndSettersOn(pw);
				} else {
					this.printIdGettersAndSettersOn(pw);
				}
			}

			this.printPrimaryKeyEqualsMethodOn(this.pkName(), this.table().primaryKeyColumns(), pw);
			this.printPrimaryKeyHashCodeMethodOn(this.table().primaryKeyColumns(), pw);
		pw.undent();

		pw.print('}');
		pw.println();
	}

	private void printEmbeddableReadOnlyPrimaryKeyFieldsOn(EntitySourceWriter pw) {
		this.printReadOnlyPrimaryKeyFieldsOn(pw, false);  // false=do not print ID annotation on fields
	}

	private void printEmbeddableWritablePrimaryKeyFieldsOn(EntitySourceWriter pw) {
		this.printWritablePrimaryKeyFieldsOn(pw, false);  // false=do not print ID annotation on fields
	}

	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.primaryKeyJavaTypeDeclaration());
		pw.print(' ');
		pw.print(fieldName);
		pw.print(';');
		pw.println();
	}

	private void printEmbeddableReadOnlyPrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) {
		this.printReadOnlyPrimaryKeyGettersAndSettersOn(pw, false);  // false=do not print ID annotation on fields
	}

	private void printEmbeddableWritablePrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) {
		this.printWritablePrimaryKeyGettersAndSettersOn(pw, false);  // false=do not print ID annotation on fields
	}

	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.primaryKeyJavaTypeDeclaration(), this.config.methodVisibility());
	}

	private void printPrimaryKeyEqualsMethodOn(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.printPrimaryKeyEqualsClauseOn(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 printPrimaryKeyEqualsClauseOn(Column column, EntitySourceWriter pw) {
		String fieldName = this.genTable.fieldNameFor(column);
		JavaType javaType = column.primaryKeyJavaType();
		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 printPrimaryKeyHashCodeMethodOn(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.printPrimaryKeyHashCodeClauseOn(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 printPrimaryKeyHashCodeClauseOn(Column column, EntitySourceWriter pw) {
		String fieldName = this.genTable.fieldNameFor(column);
		JavaType javaType = column.primaryKeyJavaType();
		if (javaType.isPrimitive()) {
			this.printPrimitiveHashCodeClauseOn(javaType.elementTypeName(), 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();
	}

	private String pkName() {
		return this.entityName() + "PK";  // hack
	}

	private boolean pkClassIsGenerated() {
		return this.table().primaryKeyColumnsSize() > 1;
	}


	// ********** 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
	 * class source code.
	 */
	private static class EntitySourceWriter extends IndentingPrintWriter implements BodySource {
		final String packageName;
		final String className;
		// key = short class name; value = package name
		private final Map<String, String> imports = new HashMap<String, String>();

		EntitySourceWriter(String packageName, String className) {
			super(new StringWriter(20000));
			this.packageName = packageName;
			this.className = className;
		}

		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.className.length())
					&& typeDeclaration.startsWith(this.className)
					&& (typeDeclaration.charAt(this.className.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>, Map.Entry<String, String>>(this.sortedImportEntries()) {
				@Override
				protected boolean accept(Map.Entry<String, String> next) {
					String pkg = 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);
	}

}
