/*******************************************************************************
 * 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.Column;
import org.eclipse.jpt.db.ForeignKey;
import org.eclipse.jpt.db.Table;
import org.eclipse.jpt.utility.JavaType;
import org.eclipse.jpt.utility.internal.IndentingPrintWriter;
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 **********

	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.getPrimaryKeyJavaTypeDeclaration());
		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.getPrimaryKeyJavaTypeDeclaration());
		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.dataTypeIsLOB()) {
			pw.printAnnotation(JPA.LOB);
			pw.println();
		}
		pw.printVisibility(this.config.fieldVisibility());
		pw.printTypeDeclaration(column.getJavaTypeDeclaration());
		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.defaultMatchesJavaFieldName(fieldName)) {
			return;  // no JoinColumn annotation needed
		}
		if (fk.referencesSingleColumnPrimaryKey()) {
			pw.printAnnotation(JPA.JOIN_COLUMN);
			pw.print("(name=\"");
			pw.print(fk.columnPair().baseColumn().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.baseColumn().getName(), columnPair.referencedColumn().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.columnPair();
			Column pkColumn = foreignKey.getReferencedTable().primaryKeyColumn();
			if (columnPair.baseColumn().matchesJavaFieldName(fieldName + "_" + pkColumn.getName())) {
				if (columnPair.referencedColumn() == pkColumn) {
					// we shouldn't get here...
				} else {
					pw.print(elementName);
					pw.print('=');
					this.printJoinColumnAnnotationOn(null, columnPair.referencedColumn().getName(), pw);
				}
			} else {
				if (columnPair.referencedColumn() == pkColumn) {
					pw.print(elementName);
					pw.print('=');
					this.printJoinColumnAnnotationOn(columnPair.baseColumn().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.getPrimaryKeyJavaTypeDeclaration(), 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.getPrimaryKeyJavaTypeDeclaration(), 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.getJavaTypeDeclaration(), 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.getPrimaryKeyJavaTypeDeclaration());
		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.getPrimaryKeyJavaTypeDeclaration(), 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.getPrimaryKeyJavaType();
		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.println("final int prime = 31;");
			pw.println("int hash = 17;");
			while (columns.hasNext()) {
				pw.print("hash = hash * prime + ");
				this.printPrimaryKeyHashCodeClauseOn(columns.next(), pw);
				pw.print(';');
				pw.println();
			}
			pw.println("return hash;");
		pw.undent();
		pw.print('}');
		pw.println();
		pw.println();
	}

	private void printPrimaryKeyHashCodeClauseOn(Column column, EntitySourceWriter pw) {
		String fieldName = this.genTable.fieldNameFor(column);
		JavaType javaType = column.getPrimaryKeyJavaType();
		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")) {
			// this.value
			pw.print("this.");
			pw.print(fieldName);
		} else if (primitiveName.equals("short") || primitiveName.equals("byte") || primitiveName.equals("char")) {  // explicit cast
			// ((int) this.value)
			pw.print("((int) this.");
			pw.print(fieldName);
			pw.print(')');
		} 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("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("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("boolean")) {
			// (this.value ? 1 : 0)
			pw.print("(this.");
			pw.print(fieldName);
			pw.print(" ? 1 : 0)");
		} 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);
	}

}
