/*******************************************************************************
 * Copyright (c) 2006, 2007 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0, which accompanies this distribution
 * and is available at http://www.eclipse.org/legal/epl-v10.html.
 * 
 * Contributors:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.gen.internal;

import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.lang.reflect.Modifier;
import java.text.Collator;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jpt.core.internal.content.java.mappings.JPA;
import org.eclipse.jpt.db.internal.Column;
import org.eclipse.jpt.db.internal.ForeignKey;
import org.eclipse.jpt.db.internal.Table;
import org.eclipse.jpt.utility.internal.IndentingPrintWriter;
import org.eclipse.jpt.utility.internal.JavaType;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.jpt.utility.internal.iterators.FilteringIterator;

// TODO handle table names that are illegal class names
// TODO handle table names that are illegal file names
// TODO handle column names that are illegal field/method names
// TODO format code per preferences
// TODO organize imports per preferences
// TODO prompt user to overwrite existing classes
/**
 * This generator will generate an entity for a table.
 */
public class EntityGenerator {
	final Config config;
	private final IPackageFragment packageFragment;
	private final GenTable genTable;
	private final String entityClassName;
	private final OverwriteConfirmer overwriteConfirmer;
	private final IProgressMonitor monitor;


	// ********** public API **********

	public static void generateEntity(Config config, IPackageFragment packageFragment, GenTable genTable, OverwriteConfirmer overwriteConfirmer, IProgressMonitor monitor) {
		if ((config == null) || (packageFragment == null) || (genTable == null)) {
			throw new NullPointerException();
		}
		new EntityGenerator(config, packageFragment, genTable, overwriteConfirmer, monitor).generateEntity();
	}


	// ********** constructor/initialization **********

	private EntityGenerator(Config config, IPackageFragment packageFragment, GenTable genTable, OverwriteConfirmer overwriteConfirmer, IProgressMonitor monitor) {
		super();
		this.config = config;
		this.packageFragment = packageFragment;
		this.genTable = genTable;
		this.entityClassName = this.fullyQualify(this.entityName());
		this.overwriteConfirmer = overwriteConfirmer;
		this.monitor = monitor;
	}


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

	private void generateEntity() {
		try {
			this.generateEntity_();
		} catch (JavaModelException ex) {
			throw new RuntimeException(ex);
		}
	}

	private void generateEntity_() throws JavaModelException {
		String fileName = this.entityName() + ".java";
		String source = this.buildSource();
		try {
			this.packageFragment.createCompilationUnit(fileName, source, false, this.monitor);
		} catch (JavaModelException ex) {
			if (ex.getJavaModelStatus().getCode() == IJavaModelStatusConstants.NAME_COLLISION) {
				if (this.overwriteConfirmer.overwrite(this.entityClassName)) {
					this.packageFragment.createCompilationUnit(fileName, source, true, this.monitor);
				}
			} else {
				throw ex;
			}
		}
	}

	/**
	 * build the "body" source first; then build the "package" and "imports" source
	 * and concatenate the "body" source to it
	 */
	private String buildSource() {
		// build the body source first so we can gather up the import statements
		BodySource bodySource = this.buildBodySource();

		StringWriter sw = new StringWriter(bodySource.length() + 1000);
		PrintWriter pw = new PrintWriter(sw);
		this.printPackageAndImportsOn(pw, bodySource);
		pw.print(bodySource.source());
		return sw.toString();
	}

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

	private void printBodySourceOn(EntitySourceWriter pw) {
		this.printClassDeclarationOn(pw);

		pw.indent();
			this.printEntityPrimaryKeyFieldsOn(pw);
			this.printEntityNonPrimaryKeyBasicFieldsOn(pw);
			this.printEntityManyToOneFieldsOn(pw);
			this.printEntityOneToManyFieldsOn(pw);
			this.printEntityOwnedManyToManyFieldsOn(pw);
			this.printEntityNonOwnedManyToManyFieldsOn(pw);
			this.printSerialVersionUID(pw);
			pw.println();

			this.printZeroArgumentConstructorOn(this.entityName(), this.config.methodVisibility(), pw);
			if (this.config.propertyAccessType() || this.config.generateGettersAndSetters()) {
				this.printEntityPrimaryKeyGettersAndSettersOn(pw);
				this.printEntityNonPrimaryKeyBasicGettersAndSettersOn(pw);
				this.printEntityManyToOneGettersAndSettersOn(pw);
				this.printEntityOneToManyGettersAndSettersOn(pw);
				this.printEntityOwnedManyToManyGettersAndSettersOn(pw);
				this.printEntityNonOwnedManyToManyGettersAndSettersOn(pw);
			}

			this.printPrimaryKeyClassOn(pw);
		pw.undent();

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

	private void printClassDeclarationOn(EntitySourceWriter pw) {
		this.printEntityAnnotationOn(pw);
		this.printTableAnnotationOn(pw);
		this.printIdClassAnnotationOn(pw);

		pw.print("public class ");
		pw.printTypeDeclaration(this.entityClassName);
		if (config.serializable()) {
			pw.print(" implements ");
			pw.printTypeDeclaration(Serializable.class.getName());
		}
		pw.print(" {");
		pw.println();
	}

	private void printEntityAnnotationOn(EntitySourceWriter pw) {
		pw.printAnnotation(JPA.ENTITY);
		pw.println();
	}

	private void printTableAnnotationOn(EntitySourceWriter pw) {
		if ( ! this.table().matchesShortJavaClassName(this.entityName())) {
			pw.printAnnotation(JPA.TABLE);
			pw.print("(name=\"");
			pw.print(this.table().getName());
			pw.print("\")");
			pw.println();
		}
	}

	private void printIdClassAnnotationOn(EntitySourceWriter pw) {
		if ((this.table().primaryKeyColumnsSize() > 1) && this.config.generateIdClassForCompoundPK()) {
			pw.printAnnotation(JPA.ID_CLASS);
			pw.print('(');
			pw.printTypeDeclaration(this.entityClassName + ".PK");
			pw.print(".class)");
			pw.println();
		}
	}

	private void printEntityPrimaryKeyFieldsOn(EntitySourceWriter pw) {
		if ((this.table().primaryKeyColumnsSize() > 1) && this.config.generateEmbeddedIdForCompoundPK()) {
			this.printEntityEmbeddedIdPrimaryKeyFieldOn(pw);
		} else {
			this.printEntityReadOnlyPrimaryKeyFieldsOn(pw);
			this.printEntityWritablePrimaryKeyFieldsOn(pw);
		}
	}

	private void printEntityEmbeddedIdPrimaryKeyFieldOn(EntitySourceWriter pw) {
		if (this.config.fieldAccessType()) {
			pw.printAnnotation(JPA.EMBEDDED_ID);
			pw.println();
		}
		pw.printVisibility(this.config.fieldVisibility());
		pw.printTypeDeclaration(this.entityClassName + ".PK");
		pw.print(' ');
		pw.print(this.genTable.fieldNameForEmbeddedId());
		pw.print(';');
		pw.println();
		pw.println();
	}

	private void printEntityReadOnlyPrimaryKeyFieldsOn(EntitySourceWriter pw) {
		for (Iterator<Column> stream = this.genTable.readOnlyPrimaryKeyColumns(); stream.hasNext(); ) {
			this.printEntityReadOnlyPrimaryKeyFieldOn(stream.next(), pw);
		}
	}

	private void printEntityReadOnlyPrimaryKeyFieldOn(Column column, EntitySourceWriter pw) {
		String fieldName = this.genTable.fieldNameFor(column);
		if (this.config.fieldAccessType()) {
			pw.printAnnotation(JPA.ID);
			pw.println();
			if (column.matchesJavaFieldName(fieldName)) {
				this.printReadOnlyColumnAnnotationOn(pw);  // no Column name needed
			} else {
				this.printReadOnlyColumnAnnotationOn(column.getName(), pw);
			}
		}
		pw.printVisibility(this.config.fieldVisibility());
		pw.printTypeDeclaration(column.javaTypeDeclaration());
		pw.print(' ');
		pw.print(fieldName);
		pw.print(';');
		pw.println();
		pw.println();
	}

	private void printReadOnlyColumnAnnotationOn(String columnName, EntitySourceWriter pw) {
		pw.printAnnotation(JPA.COLUMN);
		pw.print("(name=\"");
		pw.print(columnName);
		pw.print("\", insertable=false, updatable=false)");
		pw.println();
	}

	private void printReadOnlyColumnAnnotationOn(EntitySourceWriter pw) {
		pw.printAnnotation(JPA.COLUMN);
		pw.print("(insertable=false, updatable=false)");
		pw.println();
	}

	private void printEntityWritablePrimaryKeyFieldsOn(EntitySourceWriter pw) {
		for (Iterator<Column> stream = this.genTable.writablePrimaryKeyColumns(); stream.hasNext(); ) {
			this.printEntityWritablePrimaryKeyFieldOn(stream.next(), pw);
		}
	}

	private void printEntityWritablePrimaryKeyFieldOn(Column column, EntitySourceWriter pw) {
		String fieldName = this.genTable.fieldNameFor(column);
		if (this.config.fieldAccessType()) {
			pw.printAnnotation(JPA.ID);
			pw.println();
			if ( ! column.matchesJavaFieldName(fieldName)) {
				this.printColumnAnnotationOn(column.getName(), pw);
			}
		}
		pw.printVisibility(this.config.fieldVisibility());
		pw.printTypeDeclaration(column.javaTypeDeclaration());
		pw.print(' ');
		pw.print(fieldName);
		pw.print(';');
		pw.println();
		pw.println();
	}

	private void printEntityNonPrimaryKeyBasicFieldsOn(EntitySourceWriter pw) {
		for (Iterator<Column> stream = this.genTable.nonPrimaryKeyBasicColumns(); stream.hasNext(); ) {
			this.printEntityNonPrimaryKeyBasicFieldOn(stream.next(), pw);
		}
	}

	private void printEntityNonPrimaryKeyBasicFieldOn(Column column, EntitySourceWriter pw) {
		String fieldName = this.genTable.fieldNameFor(column);
		if (this.config.fieldAccessType()) {
			if ( ! column.matchesJavaFieldName(fieldName)) {
				this.printColumnAnnotationOn(column.getName(), pw);
			}
		}
		pw.printVisibility(this.config.fieldVisibility());
		pw.printTypeDeclaration(column.javaTypeDeclaration());
		pw.print(' ');
		pw.print(fieldName);
		pw.print(';');
		pw.println();
		pw.println();
	}

	private void printColumnAnnotationOn(String columnName, EntitySourceWriter pw) {
		pw.printAnnotation(JPA.COLUMN);
		pw.print("(name=\"");
		pw.print(columnName);
		pw.print("\")");
		pw.println();
	}

	private void printEntityManyToOneFieldsOn(EntitySourceWriter pw) {
		for (Iterator<ManyToOneRelation> stream = this.genTable.manyToOneRelations(); stream.hasNext(); ) {
			this.printEntityManyToOneFieldOn(stream.next(), pw);
		}
	}

	private void printEntityManyToOneFieldOn(ManyToOneRelation relation, EntitySourceWriter pw) {
		String fieldName = this.genTable.fieldNameFor(relation);
		if (this.config.fieldAccessType()) {
			this.printManyToOneAnnotationOn(fieldName, relation, pw);
		}
		pw.printVisibility(this.config.fieldVisibility());
		pw.printTypeDeclaration(this.fullyQualify(relation.referencedEntityName()));
		pw.print(' ');
		pw.print(fieldName);
		pw.print(';');
		pw.println();
		pw.println();
	}

	private void printManyToOneAnnotationOn(String fieldName, ManyToOneRelation relation, EntitySourceWriter pw) {
		pw.printAnnotation(JPA.MANY_TO_ONE);
		pw.println();
		ForeignKey fk = relation.getForeignKey();
		if (fk.matchesJavaFieldName(fieldName)) {
			return;  // no JoinColumn annotation needed
		}
		if (fk.referencesSingleColumnPrimaryKey()) {
			pw.printAnnotation(JPA.JOIN_COLUMN);
			pw.print("(name=\"");
			pw.print(fk.columnPairs().next().getBaseColumn().getName());
			pw.print("\")");
		} else {
			if (fk.columnPairsSize() > 1) {
				pw.printAnnotation(JPA.JOIN_COLUMNS);
				pw.print("({");
				pw.println();
				pw.indent();
			}
			this.printJoinColumnAnnotationsOn(fk, pw);
			if (fk.columnPairsSize() > 1) {
				pw.undent();
				pw.println();
				pw.print("})");
			}
		}
		pw.println();
	}

	private void printJoinColumnAnnotationsOn(ForeignKey foreignKey, EntitySourceWriter pw) {
		for (Iterator<ForeignKey.ColumnPair> stream = foreignKey.columnPairs(); stream.hasNext(); ) {
			this.printJoinColumnAnnotationOn(stream.next(), pw);
			if (stream.hasNext()) {
				pw.println(',');
			}
		}
	}

	private void printJoinColumnAnnotationOn(ForeignKey.ColumnPair columnPair, EntitySourceWriter pw) {
		this.printJoinColumnAnnotationOn(columnPair.getBaseColumn().getName(), columnPair.getReferencedColumn().getName(), pw);
	}

	/**
	 * assume that at least one of the two names is not null
	 */
	private void printJoinColumnAnnotationOn(String baseColumnName, String referencedColumnName, EntitySourceWriter pw) {
		pw.printAnnotation(JPA.JOIN_COLUMN);
		pw.print('(');
		if (baseColumnName != null) {
			pw.print("name=\"");
			pw.print(baseColumnName);
		}
		if (referencedColumnName != null) {
			if (baseColumnName != null) {
				pw.print("\", ");
			}
			pw.print("referencedColumnName=\"");
			pw.print(referencedColumnName);
		}
		pw.print("\")");
	}

	private void printEntityOneToManyFieldsOn(EntitySourceWriter pw) {
		for (Iterator<OneToManyRelation> stream = this.genTable.oneToManyRelations(); stream.hasNext(); ) {
			this.printEntityOneToManyFieldOn(stream.next(), pw);
		}
	}

	private void printEntityOneToManyFieldOn(OneToManyRelation relation, EntitySourceWriter pw) {
		String fieldName = this.genTable.fieldNameFor(relation);
		if (this.config.fieldAccessType()) {
			this.printOneToManyAnnotationOn(fieldName, relation, pw);
		}
		pw.printVisibility(this.config.fieldVisibility());
		pw.printTypeDeclaration(this.config.getCollectionTypeName());
		pw.print('<');
		pw.printTypeDeclaration(this.fullyQualify(relation.referencedEntityName()));
		pw.print('>');
		pw.print(' ');
		pw.print(fieldName);
		pw.print(';');
		pw.println();
		pw.println();
	}

	private void printOneToManyAnnotationOn(String fieldName, OneToManyRelation relation, EntitySourceWriter pw) {
		pw.printAnnotation(JPA.ONE_TO_MANY);
		pw.print("(mappedBy=\"");
		pw.print(relation.mappedBy());
		pw.print("\")");
		pw.println();
	}

	private void printEntityOwnedManyToManyFieldsOn(EntitySourceWriter pw) {
		for (Iterator<ManyToManyRelation>  stream = this.genTable.ownedManyToManyRelations(); stream.hasNext(); ) {
			this.printEntityOwnedManyToManyFieldOn(stream.next(), pw);
		}
	}

	private void printEntityOwnedManyToManyFieldOn(ManyToManyRelation relation, EntitySourceWriter pw) {
		String fieldName = this.genTable.fieldNameFor(relation);
		if (this.config.fieldAccessType()) {
			this.printOwnedManyToManyAnnotationOn(fieldName, relation, pw);
		}
		pw.printVisibility(this.config.fieldVisibility());
		pw.printTypeDeclaration(this.config.getCollectionTypeName());
		pw.print('<');
		pw.printTypeDeclaration(this.fullyQualify(relation.nonOwningEntityName()));
		pw.print('>');
		pw.print(' ');
		pw.print(fieldName);
		pw.print(';');
		pw.println();
		pw.println();
	}

	/**
	 * I guess you could build a state machine for all this crap,
	 * but that seems like overkill...
	 */
	private void printOwnedManyToManyAnnotationOn(String fieldName, ManyToManyRelation relation, EntitySourceWriter pw) {
		pw.printAnnotation(JPA.MANY_TO_MANY);
		pw.println();
		boolean first = true;
		boolean comma = false;
		if ( ! relation.joinTableNameIsDefault()) {
			if (first) {
				first = false;
				pw.printAnnotation(JPA.JOIN_TABLE);
				pw.print('(');
			}
			pw.print("name=\"");
			pw.print(relation.getJoinTable().name());
			pw.print('\"');
			comma = true;
		}
		if ( ! relation.joinColumnsIsDefaultFor(fieldName)) {
			if (first) {
				first = false;
				pw.printAnnotation(JPA.JOIN_TABLE);
				pw.print('(');
			} else if (comma) {
				pw.print(',');
			}
			pw.println();
			pw.indent();
			this.printJoinTableJoinColumnsOn("joinColumns", fieldName, relation.getOwningForeignKey(), pw);
			pw.undent();
			comma = true;
		}
		String inverseFieldName = relation.getNonOwningTable().fieldNameFor(relation);
		if ( ! relation.inverseJoinColumnsIsDefaultFor(inverseFieldName)) {
			if (first) {
				first = false;
				pw.printAnnotation(JPA.JOIN_TABLE);
				pw.print('(');
			} else if (comma) {
				pw.print(',');
			}
			pw.println();
			pw.indent();
			this.printJoinTableJoinColumnsOn("inverseJoinColumns", inverseFieldName, relation.getNonOwningForeignKey(), pw);
			pw.undent();
			comma = true;
		}
		if ( ! first) {
			pw.print(')');
		}
		pw.println();
	}

	private void printJoinTableJoinColumnsOn(String elementName, String fieldName, ForeignKey foreignKey, EntitySourceWriter pw) {
		if (foreignKey.columnPairsSize() != 1) {
			this.printJoinTableJoinColumnsOn(elementName, foreignKey, pw);
		} else if (foreignKey.getReferencedTable().primaryKeyColumnsSize() != 1) {
			// if the referenced table has a composite primary key, neither of the columns can be a default
			// since both of the defaults require a single-column primary key
			this.printJoinTableJoinColumnsOn(elementName, foreignKey, pw);
		} else {
			ForeignKey.ColumnPair columnPair = foreignKey.columnPairs().next();
			Column pkColumn = foreignKey.getReferencedTable().primaryKeyColumns().next();
			if (columnPair.getBaseColumn().matchesJavaFieldName(fieldName + "_" + pkColumn.getName())) {
				if (columnPair.getReferencedColumn() == pkColumn) {
					// we shouldn't get here...
				} else {
					pw.print(elementName);
					pw.print('=');
					this.printJoinColumnAnnotationOn(null, columnPair.getReferencedColumn().getName(), pw);
				}
			} else {
				if (columnPair.getReferencedColumn() == pkColumn) {
					pw.print(elementName);
					pw.print('=');
					this.printJoinColumnAnnotationOn(columnPair.getBaseColumn().getName(), null, pw);
				} else {
					this.printJoinTableJoinColumnsOn(elementName, foreignKey, pw);
				}
			}
		}
	}

	private void printJoinTableJoinColumnsOn(String elementName, ForeignKey foreignKey, EntitySourceWriter pw) {
		pw.print(elementName);
		pw.print('=');
		if (foreignKey.columnPairsSize() > 1) {
			pw.print('{');
			pw.println();
			pw.indent();
		}
		this.printJoinColumnAnnotationsOn(foreignKey, pw);
		if (foreignKey.columnPairsSize() > 1) {
			pw.undent();
			pw.println();
			pw.print('}');
			pw.println();
		}
	}

	private void printEntityNonOwnedManyToManyFieldsOn(EntitySourceWriter pw) {
		for (Iterator<ManyToManyRelation> stream = this.genTable.nonOwnedManyToManyRelations(); stream.hasNext(); ) {
			this.printEntityNonOwnedManyToManyFieldOn(stream.next(), pw);
		}
	}

	private void printEntityNonOwnedManyToManyFieldOn(ManyToManyRelation relation, EntitySourceWriter pw) {
		String fieldName = this.genTable.fieldNameFor(relation);
		if (this.config.fieldAccessType()) {
			this.printNonOwnedManyToManyAnnotationOn(fieldName, relation, pw);
		}
		pw.printVisibility(this.config.fieldVisibility());
		pw.printTypeDeclaration(this.config.getCollectionTypeName());
		pw.print('<');
		pw.printTypeDeclaration(this.fullyQualify(relation.owningEntityName()));
		pw.print('>');
		pw.print(' ');
		pw.print(fieldName);
		pw.print(';');
		pw.println();
		pw.println();
	}

	private void printNonOwnedManyToManyAnnotationOn(String fieldName, ManyToManyRelation relation, EntitySourceWriter pw) {
		pw.printAnnotation(JPA.MANY_TO_MANY);
		pw.print("(mappedBy=\"");
		pw.print(relation.getMappedBy());
		pw.print("\")");
		pw.println();
	}

	private String fullyQualify(String shortClassName) {
		String pkg = this.packageName();
		return (pkg.length() == 0) ? shortClassName : pkg + '.' + shortClassName;
	}

	private void printSerialVersionUID(EntitySourceWriter pw) {
		if (this.config.generateSerialVersionUID()) {
			pw.print("private static final long serialVersionUID = 1L;");
			pw.println();
		}
	}

	private void printZeroArgumentConstructorOn(String ctorName, String visibility, EntitySourceWriter pw) {
		if (this.config.generateDefaultConstructor()) {
			pw.printVisibility(visibility);
			pw.print(ctorName);
			pw.print("() {");
			pw.println();
			pw.indent();
				pw.println("super();");
			pw.undent();
			pw.print('}');
			pw.println();
			pw.println();
		}
	}

	private void printEntityPrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) {
		if ((this.table().primaryKeyColumnsSize() > 1) && this.config.generateEmbeddedIdForCompoundPK()) {
			this.printEntityEmbeddedIdPrimaryKeyGetterAndSetterOn(pw);
		} else {
			this.printEntityReadOnlyPrimaryKeyGettersAndSettersOn(pw);
			this.printEntityWritablePrimaryKeyGettersAndSettersOn(pw);
		}
	}

	private void printEntityEmbeddedIdPrimaryKeyGetterAndSetterOn(EntitySourceWriter pw) {
		if (this.config.propertyAccessType()) {
			pw.printAnnotation(JPA.EMBEDDED_ID);
			pw.println();
		}
		pw.printGetterAndSetter(this.genTable.fieldNameForEmbeddedId(), this.entityClassName + ".PK", this.config.methodVisibility());
	}

	private void printEntityReadOnlyPrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) {
		for (Iterator<Column> stream = this.genTable.readOnlyPrimaryKeyColumns(); stream.hasNext(); ) {
			this.printEntityReadOnlyPrimaryKeyGetterAndSetterOn(stream.next(), pw);
		}
	}

	private void printEntityReadOnlyPrimaryKeyGetterAndSetterOn(Column column, EntitySourceWriter pw) {
		String propertyName = this.genTable.fieldNameFor(column);
		if (this.config.propertyAccessType()) {
			pw.printAnnotation(JPA.ID);
			pw.println();
			if (column.matchesJavaFieldName(propertyName)) {
				this.printReadOnlyColumnAnnotationOn(pw);  // no Column name needed
			} else {
				this.printReadOnlyColumnAnnotationOn(column.getName(), pw);
			}
		}

		pw.printGetterAndSetter(propertyName, column.javaTypeDeclaration(), this.config.methodVisibility());
	}

	private void printEntityWritablePrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) {
		for (Iterator<Column> stream = this.genTable.writablePrimaryKeyColumns(); stream.hasNext(); ) {
			this.printEntityWritablePrimaryKeyGetterAndSetterOn(stream.next(), pw);
		}
	}

	private void printEntityWritablePrimaryKeyGetterAndSetterOn(Column column, EntitySourceWriter pw) {
		String propertyName = this.genTable.fieldNameFor(column);
		if (this.config.propertyAccessType()) {
			pw.printAnnotation(JPA.ID);
			pw.println();
			if ( ! column.matchesJavaFieldName(propertyName)) {
				this.printColumnAnnotationOn(column.getName(), pw);
			}
		}

		pw.printGetterAndSetter(propertyName, column.javaTypeDeclaration(), this.config.methodVisibility());
	}

	private void printEntityNonPrimaryKeyBasicGettersAndSettersOn(EntitySourceWriter pw) {
		for (Iterator<Column> stream = this.genTable.nonPrimaryKeyBasicColumns(); stream.hasNext(); ) {
			this.printEntityNonPrimaryKeyBasicGetterAndSetterOn(stream.next(), pw);
		}
	}

	private void printEntityNonPrimaryKeyBasicGetterAndSetterOn(Column column, EntitySourceWriter pw) {
		String propertyName = this.genTable.fieldNameFor(column);
		if (this.config.propertyAccessType()) {
			if ( ! column.matchesJavaFieldName(propertyName)) {
				this.printColumnAnnotationOn(column.getName(), pw);
			}
		}

		pw.printGetterAndSetter(propertyName, column.javaTypeDeclaration(), this.config.methodVisibility());
	}

	private void printEntityManyToOneGettersAndSettersOn(EntitySourceWriter pw) {
		for (Iterator<ManyToOneRelation> stream = this.genTable.manyToOneRelations(); stream.hasNext(); ) {
			this.printEntityManyToOneGetterAndSetterOn(stream.next(), pw);
		}
	}

	private void printEntityManyToOneGetterAndSetterOn(ManyToOneRelation relation, EntitySourceWriter pw) {
		String propertyName = this.genTable.fieldNameFor(relation);
		if (this.config.propertyAccessType()) {
			this.printManyToOneAnnotationOn(propertyName, relation, pw);
		}

		String typeDeclaration = this.fullyQualify(relation.referencedEntityName());
		pw.printGetterAndSetter(propertyName, typeDeclaration, this.config.methodVisibility());
	}

	private void printEntityOneToManyGettersAndSettersOn(EntitySourceWriter pw) {
		for (Iterator<OneToManyRelation> stream = this.genTable.oneToManyRelations(); stream.hasNext(); ) {
			this.printEntityOneToManyGetterAndSetterOn(stream.next(), pw);
		}
	}

	private void printEntityOneToManyGetterAndSetterOn(OneToManyRelation relation, EntitySourceWriter pw) {
		String propertyName = this.genTable.fieldNameFor(relation);
		if (this.config.propertyAccessType()) {
			this.printOneToManyAnnotationOn(propertyName, relation, pw);
		}

		String elementTypeDeclaration = this.fullyQualify(relation.referencedEntityName());
		pw.printCollectionGetterAndSetter(propertyName, this.config.getCollectionTypeName(), elementTypeDeclaration, this.config.methodVisibility());
	}

	private void printEntityOwnedManyToManyGettersAndSettersOn(EntitySourceWriter pw) {
		for (Iterator<ManyToManyRelation> stream = this.genTable.ownedManyToManyRelations(); stream.hasNext(); ) {
			this.printEntityOwnedManyToManyGetterAndSetterOn(stream.next(), pw);
		}
	}

	private void printEntityOwnedManyToManyGetterAndSetterOn(ManyToManyRelation relation, EntitySourceWriter pw) {
		String propertyName = this.genTable.fieldNameFor(relation);
		if (this.config.propertyAccessType()) {
			this.printOwnedManyToManyAnnotationOn(propertyName, relation, pw);
		}

		String elementTypeDeclaration = this.fullyQualify(relation.nonOwningEntityName());
		pw.printCollectionGetterAndSetter(propertyName, this.config.getCollectionTypeName(), elementTypeDeclaration, this.config.methodVisibility());
	}

	private void printEntityNonOwnedManyToManyGettersAndSettersOn(EntitySourceWriter pw) {
		for (Iterator<ManyToManyRelation> stream = this.genTable.nonOwnedManyToManyRelations(); stream.hasNext(); ) {
			this.printEntityNonOwnedManyToManyGetterAndSetterOn(stream.next(), pw);
		}
	}

	private void printEntityNonOwnedManyToManyGetterAndSetterOn(ManyToManyRelation relation, EntitySourceWriter pw) {
		String propertyName = this.genTable.fieldNameFor(relation);
		if (this.config.propertyAccessType()) {
			this.printNonOwnedManyToManyAnnotationOn(propertyName, relation, pw);
		}

		String elementTypeDeclaration = this.fullyQualify(relation.owningEntityName());
		pw.printCollectionGetterAndSetter(propertyName, this.config.getCollectionTypeName(), elementTypeDeclaration, this.config.methodVisibility());
	}

	private void printPrimaryKeyClassOn(EntitySourceWriter pw) {
		if (this.table().primaryKeyColumnsSize() <= 1) {
			return;
		}
		pw.println();
		if (this.config.generateEmbeddedIdForCompoundPK()) {
			pw.printAnnotation(JPA.EMBEDDABLE);
			pw.println();
		}
		pw.print("public static class PK implements ");
		pw.printTypeDeclaration(Serializable.class.getName());
		pw.print(" {");
		pw.println();

		pw.indent();
			this.printIdFieldsOn(pw);
			this.printSerialVersionUID(pw);
			pw.println();
			this.printZeroArgumentConstructorOn("PK", "public", pw);

			if (this.config.propertyAccessType() || this.config.generateGettersAndSetters()) {
				this.printIdGettersAndSettersOn(pw);
			}

			this.printEqualsMethodOn("PK", this.table().primaryKeyColumns(), pw);
			this.printHashCodeMethodOn(this.table().primaryKeyColumns(), pw);
		pw.undent();

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

	private void printIdFieldsOn(EntitySourceWriter pw) {
		for (Iterator<Column> stream = this.table().primaryKeyColumns(); stream.hasNext(); ) {
			this.printIdFieldOn(stream.next(), pw);
		}
	}

	private void printIdFieldOn(Column column, EntitySourceWriter pw) {
		String fieldName = this.genTable.fieldNameFor(column);
		pw.printVisibility(this.config.fieldVisibility());
		pw.printTypeDeclaration(column.javaTypeDeclaration());
		pw.print(' ');
		pw.print(fieldName);
		pw.print(';');
		pw.println();
	}

	private void printIdGettersAndSettersOn(EntitySourceWriter pw) {
		for (Iterator<Column> stream = this.table().primaryKeyColumns(); stream.hasNext(); ) {
			this.printIdGetterAndSetterOn(stream.next(), pw);
		}
	}

	private void printIdGetterAndSetterOn(Column column, EntitySourceWriter pw) {
		String propertyName = this.genTable.fieldNameFor(column);
		pw.printGetterAndSetter(propertyName, column.javaTypeDeclaration(), this.config.methodVisibility());
	}

	private void printEqualsMethodOn(String className, Iterator<Column> columns, EntitySourceWriter pw) {
		pw.printAnnotation("java.lang.Override");
		pw.println();

		pw.println("public boolean equals(Object o) {");
		pw.indent();
			pw.println("if (o == this) {");
			pw.indent();
				pw.println("return true;");
			pw.undent();
			pw.print('}');
			pw.println();

			pw.print("if ( ! (o instanceof ");
			pw.print(className);
			pw.print(")) {");
			pw.println();
			pw.indent();
				pw.println("return false;");
			pw.undent();
			pw.print('}');
			pw.println();

			pw.print(className);
			pw.print(" other = (");
			pw.print(className);
			pw.print(") o;");
			pw.println();

			pw.print("return ");
			pw.indent();
				while (columns.hasNext()) {
					this.printEqualsClauseOn(columns.next(), pw);
					if (columns.hasNext()) {
						pw.println();
						pw.print("&& ");
					}
				}
				pw.print(';');
				pw.println();
			pw.undent();
		pw.undent();
		pw.print('}');
		pw.println();
		pw.println();
	}

	private void printEqualsClauseOn(Column column, EntitySourceWriter pw) {
		String fieldName = this.genTable.fieldNameFor(column);
		JavaType javaType = column.javaType();
		if (javaType.isPrimitive()) {
			this.printPrimitiveEqualsClauseOn(fieldName, pw);
		} else {
			this.printReferenceEqualsClauseOn(fieldName, pw);
		}
	}

	private void printPrimitiveEqualsClauseOn(String fieldName, EntitySourceWriter pw) {
		pw.print("(this.");
		pw.print(fieldName);
		pw.print(" == other.");
		pw.print(fieldName);
		pw.print(')');
	}

	private void printReferenceEqualsClauseOn(String fieldName, EntitySourceWriter pw) {
		pw.print("this.");
		pw.print(fieldName);
		pw.print(".equals(other.");
		pw.print(fieldName);
		pw.print(')');
	}

	private void printHashCodeMethodOn(Iterator<Column> columns, EntitySourceWriter pw) {
		pw.printAnnotation("java.lang.Override");
		pw.println();

		pw.println("public int hashCode() {");
		pw.indent();
			pw.print("return ");
			pw.indent();
				while (columns.hasNext()) {
					this.printHashCodeClauseOn(columns.next(), pw);
					if (columns.hasNext()) {
						pw.println();
						pw.print("^ ");
					}
				}
				pw.print(';');
				pw.println();
			pw.undent();
		pw.undent();
		pw.print('}');
		pw.println();
		pw.println();
	}

	private void printHashCodeClauseOn(Column column, EntitySourceWriter pw) {
		String fieldName = this.genTable.fieldNameFor(column);
		JavaType javaType = column.javaType();
		if (javaType.isPrimitive()) {
			this.printPrimitiveHashCodeClauseOn(javaType.getElementTypeName(), fieldName, pw);
		} else {
			this.printReferenceHashCodeClauseOn(fieldName, pw);
		}
	}

	private void printPrimitiveHashCodeClauseOn(String primitiveName, String fieldName, EntitySourceWriter pw) {
		if (primitiveName.equals("int") || primitiveName.equals("short") || primitiveName.equals("byte") || primitiveName.equals("char")) {
			pw.print("this.");
			pw.print(fieldName);
		} else if (primitiveName.equals("long")) {  // cribbed from Long#hashCode()
			// ((int) (this.value ^ (this.value >>> 32)))
			pw.print("((int) (this.");
			pw.print(fieldName);
			pw.print(" ^ (this.");
			pw.print(fieldName);
			pw.print(" >>> 32)))");
		} else if (primitiveName.equals("double")) {  // cribbed from Double#hashCode()
			//	((int) (java.lang.Double.doubleToLongBits(this.value) ^ (java.lang.Double.doubleToLongBits(this.value) >>> 32)))
			pw.print("((int) (");
			pw.printTypeDeclaration("java.lang.Double");
			pw.print(".doubleToLongBits(this.");
			pw.print(fieldName);
			pw.print(") ^ (");
			pw.printTypeDeclaration("java.lang.Double");
			pw.print(".doubleToLongBits(this.");
			pw.print(fieldName);
			pw.print(") >>> 32)))");
		} else if (primitiveName.equals("float")) {  // cribbed from Float#hashCode()
			// java.lang.Float.floatToIntBits(this.value)
			pw.printTypeDeclaration("java.lang.Float");
			pw.print(".floatToIntBits(this.");
			pw.print(fieldName);
			pw.print(')');
		} else if (primitiveName.equals("boolean")) {  // cribbed from Boolean#hashCode()
			// (this.value ? 1231 : 1237)
			pw.print("(this.");
			pw.print(fieldName);
			pw.print(" ? 1231 : 1237)");
		} else {
			throw new IllegalArgumentException(primitiveName);
		}
	}

	private void printReferenceHashCodeClauseOn(String fieldName, EntitySourceWriter pw) {
		pw.print("this.");
		pw.print(fieldName);
		pw.print(".hashCode()");
	}

	private void printPackageAndImportsOn(PrintWriter pw, BodySource bodySource) {
		if (this.packageName().length() != 0) {
			pw.print("package ");
			pw.print(this.packageName());
			pw.print(';');
			pw.println();
			pw.println();
		}

		for (Iterator<Map.Entry<String, String>> stream = bodySource.importEntries(); stream.hasNext(); ) {
			Map.Entry<String, String> entry = stream.next();
			pw.print("import ");
			pw.print(entry.getValue());  // package
			pw.print('.');
			pw.print(entry.getKey());  // short class name
			pw.print(';');
			pw.println();
		}
		pw.println();
	}


	// ********** convenience methods **********

	private String packageName() {
		return this.packageFragment.getElementName();
	}

	private Table table() {
		return this.genTable.getTable();
	}

	private String entityName() {
		return this.genTable.getEntityName();
	}


	// ********** writer **********

	private interface BodySource {

		/**
		 * return a sorted set of map entries; the key is the short class name,
		 * the value is the package name
		 */
		Iterator<Map.Entry<String, String>> importEntries();

		/**
		 * return the body source code
		 */
		String source();

		/**
		 * return the length of the body source code
		 */
		int length();

	}

	/**
	 * Extend IndentingPrintWriter with some methods that facilitate building
	 * entity source code.
	 */
	private static class EntitySourceWriter extends IndentingPrintWriter implements BodySource {
		final String packageName;
		final String entityClassName;
		// key = short class name; value = package name
		private final Map<String, String> imports = new HashMap<String, String>();

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

		void printVisibility(String visibilityModifier) {
			if (visibilityModifier.length() != 0) {
				this.print(visibilityModifier);
				this.print(' ');
			}
		}

		void printAnnotation(String annotationName) {
			this.print('@');
			this.printTypeDeclaration(annotationName);
		}

		void printTypeDeclaration(String typeDeclaration) {
			this.print(this.importedTypeDeclaration(typeDeclaration));
		}

		/**
		 * Return the specified class's "imported" name.
		 * The class declaration must be of the form:
		 *     "int"
		 *     "int[]" (not "[I")
		 *     "java.lang.Object"
		 *     "java.lang.Object[]" (not "[Ljava.lang.Object;")
		 *     "java.util.Map.Entry" (not "java.util.Map$Entry")
		 *     "java.util.Map.Entry[][]" (not "[[Ljava.util.Map$Entry;")
		 */
		private String importedTypeDeclaration(String typeDeclaration) {
			if (this.typeDeclarationIsMemberClass(typeDeclaration)) {
				// no need for an import, just return the partially-qualified name
				return this.memberClassTypeDeclaration(typeDeclaration);
			}
			int last = typeDeclaration.lastIndexOf('.');
			String pkg = (last == -1) ? "" : typeDeclaration.substring(0, last);
			String shortTypeDeclaration = typeDeclaration.substring(last + 1);
			String shortElementTypeName = shortTypeDeclaration;
			while (shortElementTypeName.endsWith("[]")) {
				shortElementTypeName = shortElementTypeName.substring(0, shortElementTypeName.length() - 2);
			}
			String prev = this.imports.get(shortElementTypeName);
			if (prev == null) {
				// this is the first class with this short element type name
				this.imports.put(shortElementTypeName, pkg);
				return shortTypeDeclaration;
			}
			if (prev.equals(pkg)) {
				// this element type has already been imported
				return shortTypeDeclaration;
			}
			// another class with the same short element type name has been
			// previously imported, so this one must be used fully-qualified
			return typeDeclaration;
		}

		/**
		 * e.g. "foo.bar.Employee.PK" will return true
		 */
		private boolean typeDeclarationIsMemberClass(String typeDeclaration) {
			return (typeDeclaration.length() > this.entityClassName.length())
					&& typeDeclaration.startsWith(this.entityClassName)
					&& (typeDeclaration.charAt(this.entityClassName.length()) == '.');
		}

		/**
		 * e.g. "foo.bar.Employee.PK" will return "Employee.PK"
		 * this prevents collisions with other imported classes (e.g. "joo.jar.PK")
		 */
		private String memberClassTypeDeclaration(String typeDeclaration) {
			int index = this.packageName.length();
			if (index != 0) {
				index++;  // bump past the '.'
			}
			return typeDeclaration.substring(index);
		}

		public Iterator<Map.Entry<String, String>> importEntries() {
			return new FilteringIterator<Map.Entry<String, String>>(this.sortedImportEntries()) {
				@Override
				@SuppressWarnings("unchecked")
				protected boolean accept(Object next) {
					String pkg = ((Map.Entry<String, String>) next).getValue();
					if (pkg.equals("")
							|| pkg.equals("java.lang")
							|| pkg.equals(EntitySourceWriter.this.packageName)) {
						return false;
					}
					return true;
				}
			};
		}

		private Iterator<Map.Entry<String, String>> sortedImportEntries() {
			TreeSet<Map.Entry<String, String>> sortedImports = new TreeSet<Map.Entry<String, String>>(this.buildImportEntriesComparator());
			sortedImports.addAll(this.imports.entrySet());
			return sortedImports.iterator();
		}

		private Comparator<Map.Entry<String, String>> buildImportEntriesComparator() {
			return new Comparator<Map.Entry<String, String>>() {
				public int compare(Map.Entry<String, String> e1, Map.Entry<String, String> e2) {
					Collator collator = Collator.getInstance();
					int pkg = collator.compare(e1.getValue(), e2.getValue());
					return (pkg == 0) ? collator.compare(e1.getKey(), e2.getKey()) : pkg;
				}
			};
		}

		void printGetterAndSetter(String propertyName, String typeDeclaration, String visibility) {
			this.printGetter(propertyName, typeDeclaration, visibility);
			this.println();
			this.println();

			this.printSetter(propertyName, typeDeclaration, visibility);
			this.println();
			this.println();
		}

		private void printGetter(String propertyName, String typeDeclaration, String visibility) {
			this.printVisibility(visibility);
			this.printTypeDeclaration(typeDeclaration);
			this.print(' ');
			this.print(typeDeclaration.equals("boolean") ? "is" : "get");
			this.print(StringTools.capitalize(propertyName));
			this.print("() {");
			this.println();

			this.indent();
				this.print("return this.");
				this.print(propertyName);
				this.print(';');
				this.println();
			this.undent();

			this.print('}');
		}

		private void printSetter(String propertyName, String typeDeclaration, String visibility) {
			this.printVisibility(visibility);
			this.print("void set");
			this.print(StringTools.capitalize(propertyName));
			this.print('(');
			this.printTypeDeclaration(typeDeclaration);
			this.print(' ');
			this.print(propertyName);
			this.print(") {");
			this.println();

			this.indent();
				this.print("this.");
				this.print(propertyName);
				this.print(" = ");
				this.print(propertyName);
				this.print(';');
				this.println();
			this.undent();

			this.print('}');
		}

		void printCollectionGetterAndSetter(String propertyName, String collectionTypeDeclaration, String elementTypeDeclaration, String visibility) {
			this.printCollectionGetter(propertyName, collectionTypeDeclaration, elementTypeDeclaration, visibility);
			this.println();
			this.println();

			this.printCollectionSetter(propertyName, collectionTypeDeclaration, elementTypeDeclaration, visibility);
			this.println();
			this.println();
		}

		private void printCollectionGetter(String propertyName, String collectionTypeDeclaration, String elementTypeDeclaration, String visibility) {
			this.printVisibility(visibility);
			this.printTypeDeclaration(collectionTypeDeclaration);
			this.print('<');
			this.printTypeDeclaration(elementTypeDeclaration);
			this.print("> get");
			this.print(StringTools.capitalize(propertyName));
			this.print("() {");
			this.println();

			this.indent();
				this.print("return this.");
				this.print(propertyName);
				this.print(';');
				this.println();
			this.undent();

			this.print('}');
		}

		private void printCollectionSetter(String propertyName, String collectionTypeDeclaration, String elementTypeDeclaration, String visibility) {
			this.printVisibility(visibility);
			this.print("void set");
			this.print(StringTools.capitalize(propertyName));
			this.print('(');
			this.printTypeDeclaration(collectionTypeDeclaration);
			this.print('<');
			this.printTypeDeclaration(elementTypeDeclaration);
			this.print('>');
			this.print(' ');
			this.print(propertyName);
			this.print(") {");
			this.println();

			this.indent();
				this.print("this.");
				this.print(propertyName);
				this.print(" = ");
				this.print(propertyName);
				this.print(';');
				this.println();
			this.undent();

			this.print('}');
		}

		public String source() {
			return this.out.toString();
		}

		public int length() {
			return ((StringWriter) this.out).getBuffer().length();
		}

	}


	// ********** config **********

	public static class Config {
		private boolean convertToCamelCase = true;
		private boolean propertyAccessType = false;  // as opposed to "field"
		private String collectionTypeName = Set.class.getName();
		private int fieldVisibility = Modifier.PRIVATE;
		private int methodVisibility = Modifier.PUBLIC;
		private boolean generateGettersAndSetters = true;
		private boolean generateDefaultConstructor = true;
		private boolean serializable = true;
		private boolean generateSerialVersionUID = true;
		private boolean generateEmbeddedIdForCompoundPK = true;  // as opposed to IdClass
		private Map<Table, String> overrideEntityNames = new HashMap<Table, String>();

		public static final int PRIVATE = 0;
		public static final int PACKAGE = 1;
		public static final int PROTECTED = 2;
		public static final int PUBLIC = 3;


		public boolean convertToCamelCase() {
			return this.convertToCamelCase;
		}
		public void setConvertToCamelCase(boolean convertToCamelCase) {
			this.convertToCamelCase = convertToCamelCase;
		}

		public boolean propertyAccessType() {
			return this.propertyAccessType;
		}
		public void setPropertyAccessType(boolean propertyAccessType) {
			this.propertyAccessType = propertyAccessType;
		}

		public boolean fieldAccessType() {
			return ! this.propertyAccessType;
		}
		public void setFieldAccessType(boolean fieldAccessType) {
			this.propertyAccessType = ! fieldAccessType;
		}

		public String getCollectionTypeName() {
			return this.collectionTypeName;
		}
		public void setCollectionTypeName(String collectionTypeName) {
			this.collectionTypeName = collectionTypeName;
		}

		public int getFieldVisibility() {
			return this.fieldVisibility;
		}
		/** entity fields cannot be 'public' */
		public void setFieldVisibility(int fieldVisibility) {
			switch (fieldVisibility) {
				case PRIVATE:
				case PACKAGE:
				case PROTECTED:
					this.fieldVisibility = fieldVisibility;
					break;
				default:
					throw new IllegalArgumentException("invalid field visibility: " + fieldVisibility);
			}
		}
		String fieldVisibility() {
			switch (this.fieldVisibility) {
				case PRIVATE:
					return "private";
				case PACKAGE:
					return "";
				case PROTECTED:
					return "protected";
				default:
					throw new IllegalStateException("invalid field visibility: " + this.fieldVisibility);
			}
		}

		public int getMethodVisibility() {
			return this.methodVisibility;
		}
		/** entity properties must be 'public' or 'protected' */
		public void setMethodVisibility(int methodVisibility) {
			switch (methodVisibility) {
				case PROTECTED:
				case PUBLIC:
					this.methodVisibility = methodVisibility;
					break;
				default:
					throw new IllegalArgumentException("invalid method visibility: " + methodVisibility);
			}
		}
		String methodVisibility() {
			switch (this.methodVisibility) {
				case PROTECTED:
					return "protected";
				case PUBLIC:
					return "public";
				default:
					throw new IllegalStateException("invalid method visibility: " + this.methodVisibility);
			}
		}

		public boolean generateGettersAndSetters() {
			return this.generateGettersAndSetters;
		}
		public void setGenerateGettersAndSetters(boolean generateGettersAndSetters) {
			this.generateGettersAndSetters = generateGettersAndSetters;
		}

		public boolean generateDefaultConstructor() {
			return this.generateDefaultConstructor;
		}
		public void setGenerateDefaultConstructor(boolean generateDefaultConstructor) {
			this.generateDefaultConstructor = generateDefaultConstructor;
		}

		public boolean serializable() {
			return this.serializable;
		}
		public void setSerializable(boolean serializable) {
			this.serializable = serializable;
		}

		public boolean generateSerialVersionUID() {
			return this.generateSerialVersionUID;
		}
		public void setGenerateSerialVersionUID(boolean generateSerialVersionUID) {
			this.generateSerialVersionUID = generateSerialVersionUID;
		}

		public boolean generateEmbeddedIdForCompoundPK() {
			return this.generateEmbeddedIdForCompoundPK;
		}
		public void setGenerateEmbeddedIdForCompoundPK(boolean generateEmbeddedIdForCompoundPK) {
			this.generateEmbeddedIdForCompoundPK = generateEmbeddedIdForCompoundPK;
		}

		public boolean generateIdClassForCompoundPK() {
			return ! this.generateEmbeddedIdForCompoundPK;
		}
		public void setGenerateIdClassForCompoundPK(boolean generateIdClassForCompoundPK) {
			this.generateEmbeddedIdForCompoundPK = ! generateIdClassForCompoundPK;
		}

		/**
		 * key = table
		 * value = user-supplied override entity name
		 */
		public String getOverrideEntityName(Table table) {
			return this.overrideEntityNames.get(table);
		}
		public void setOverrideEntityName(Table table, String overrideEntityName) {
			this.overrideEntityNames.put(table, overrideEntityName);
		}
		public void clearOverrideEntityNames() {
			this.overrideEntityNames.clear();
		}
		public void setOverrideEntityNames(Map<Table, String> overrideEntityNames) {
			this.clearOverrideEntityNames();
			for (Map.Entry<Table, String> entry : overrideEntityNames.entrySet()) {
				this.setOverrideEntityName(entry.getKey(), entry.getValue());
			}
		}

	}


	// ********** config **********

	public static interface OverwriteConfirmer {
		/**
		 * Return whether the entity generator should overwrite the specified
		 * file.
		 */
		boolean overwrite(String className);
	}

}
