/*******************************************************************************
 * 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.SubMonitor;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.JavaModelException;
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.BooleanHolder;
import org.eclipse.jpt.utility.internal.IndentingPrintWriter;
import org.eclipse.jpt.utility.internal.NameTools;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.jpt.utility.internal.iterators.FilteringIterator;
import org.eclipse.osgi.util.NLS;

// TODO format generated code per preferences
// TODO organize generated imports per preferences
/**
 * 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 String pkClassName;


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

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


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

	private EntityGenerator(Config config, IPackageFragment packageFragment, GenTable genTable) {
		super();
		this.config = config;
		this.packageFragment = packageFragment;
		this.genTable = genTable;
		this.entityClassName = this.fullyQualify(this.getEntityName());
		this.pkClassName = this.entityClassName + '.' + config.getPrimaryKeyMemberClassName();
	}


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

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

	private void generateEntity_(IProgressMonitor progressMonitor) throws JavaModelException {
		SubMonitor sm = SubMonitor.convert(progressMonitor, this.buildTaskName(), 100);
		String fileName = this.getEntityName() + ".java";  //$NON-NLS-1$
		String source = this.buildSource();
		sm.worked(20);
		try {
			this.packageFragment.createCompilationUnit(fileName, source, false, sm.newChild(40));
		} catch (JavaModelException ex) {
			if (ex.getJavaModelStatus().getCode() == IJavaModelStatusConstants.NAME_COLLISION) {
				if (this.config.getOverwriteConfirmer().overwrite(this.entityClassName)) {
					this.packageFragment.createCompilationUnit(fileName, source, true, sm.newChild(40));
				}
			} else {
				throw ex;
			}
		}
		sm.setWorkRemaining(0);
	}

	private String buildTaskName() {
		return NLS.bind(JptGenMessages.EntityGenerator_taskName, this.getEntityName());
	}

	/**
	 * 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() + 2000);
		PrintWriter pw = new PrintWriter(sw);
		this.printPackageAndImportsOn(pw, bodySource);
		pw.print(bodySource.getSource());
		return sw.toString();
	}

	private BodySource buildBodySource() {
		EntitySourceWriter pw = new EntitySourceWriter(this.getPackageName(), 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.printSerialVersionUIDFieldOn(pw);
			pw.println();

			this.printZeroArgumentConstructorOn(this.getEntityName(), this.config.getMethodVisibilityClause(), pw);
			if (this.config.propertyAccessType() || this.config.generateGettersAndSetters()) {
				this.printEntityPrimaryKeyPropertiesOn(pw);
				this.printEntityNonPrimaryKeyBasicPropertiesOn(pw);
				this.printEntityManyToOnePropertiesOn(pw);
				this.printEntityOneToManyPropertiesOn(pw);
				this.printEntityOwnedManyToManyPropertiesOn(pw);
				this.printEntityNonOwnedManyToManyPropertiesOn(pw);
			}

			if (this.primaryKeyClassIsRequired()) {
				this.printPrimaryKeyClassOn(pw);
			}
		pw.undent();

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


	// ********** class declaration **********

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

		pw.print("public class ");  //$NON-NLS-1$
		pw.printTypeDeclaration(this.entityClassName);
		if (config.serializable()) {
			pw.print(" implements ");  //$NON-NLS-1$
			pw.printTypeDeclaration(Serializable.class.getName());
		}
		pw.print(" {");  //$NON-NLS-1$
		pw.println();
	}

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

	private void printTableAnnotationOn(EntitySourceWriter pw) {
		String tableName = this.config.getDatabaseAnnotationNameBuilder().buildTableAnnotationName(this.getEntityName(), this.getTable());
		if (tableName == null) {
			return;  // the default table name is OK
		}
		pw.printAnnotation(JPA.TABLE);
		pw.print("(name=");  //$NON-NLS-1$
		pw.printStringLiteral(tableName);
		pw.print(')');
		pw.println();
	}

	private void printIdClassAnnotationOn(EntitySourceWriter pw) {
		if (this.primaryKeyClassIsRequired() && this.config.generateIdClassForCompoundPK()) {
			pw.printAnnotation(JPA.ID_CLASS);
			pw.print('(');
			pw.printTypeDeclaration(this.pkClassName);
			pw.print(".class)");  //$NON-NLS-1$
			pw.println();
		}
	}


	// ********** primary key fields **********

	private void printEntityPrimaryKeyFieldsOn(EntitySourceWriter pw) {
		if (this.primaryKeyClassIsRequired() && 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();
		}
		this.printFieldOn(this.genTable.getAttributeNameForEmbeddedId(), this.pkClassName, pw);
	}

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

	private void printEntityWritablePrimaryKeyFieldsOn(EntitySourceWriter pw) {
		this.printPrimaryKeyFieldsOn(pw, false, true);  // false=writable; true=print ID annotation on fields
	}

	private void printPrimaryKeyFieldsOn(EntitySourceWriter pw, boolean readOnly, boolean printIdAnnotation) {
		for (Iterator<Column> stream = this.primaryKeyColumns(readOnly); stream.hasNext(); ) {
			this.printPrimaryKeyFieldOn(stream.next(), pw, readOnly, printIdAnnotation);
		}
	}

	private Iterator<Column> primaryKeyColumns(boolean readOnly) {
		return readOnly ? this.genTable.readOnlyPrimaryKeyColumns() : this.genTable.writablePrimaryKeyColumns();
	}

	// TODO if the field's type is java.util/sql.Date, it needs @Temporal(DATE)
	// TODO if the primary key is auto-generated, the field must be an integral type
	private void printPrimaryKeyFieldOn(Column column, EntitySourceWriter pw, boolean readOnly, boolean printIdAnnotation) {
		String fieldName = this.genTable.getAttributeNameFor(column);
		if (this.config.fieldAccessType()) {
			if (printIdAnnotation) {
				pw.printAnnotation(JPA.ID);
				pw.println();
			}
			String columnName = this.config.getDatabaseAnnotationNameBuilder().buildColumnAnnotationName(fieldName, column);
			if (readOnly) {
				this.printReadOnlyColumnAnnotationOn(columnName, pw);
			} else {
				this.printColumnAnnotationOn(columnName, pw);
			}
		}
		this.printFieldOn(fieldName, column.getPrimaryKeyJavaTypeDeclaration(), pw);
	}

	private void printReadOnlyColumnAnnotationOn(String columnName, EntitySourceWriter pw) {
		pw.printAnnotation(JPA.COLUMN);
		pw.print('(');
		if (columnName != null) {
			pw.print("name=");  //$NON-NLS-1$
			pw.printStringLiteral(columnName);
			pw.print(", ");  //$NON-NLS-1$
		}
		pw.print("insertable=false, updatable=false)");  //$NON-NLS-1$
		pw.println();
	}


	// ********** basic fields **********

	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.getAttributeNameFor(column);
		if (this.config.fieldAccessType()) {
			String columnName = this.config.getDatabaseAnnotationNameBuilder().buildColumnAnnotationName(fieldName, column);
			this.printColumnAnnotationOn(columnName, pw);
		}
		if (column.isLOB()) {
			pw.printAnnotation(JPA.LOB);
			pw.println();
		}
		this.printFieldOn(fieldName, column.getJavaTypeDeclaration(), pw);
	}

	private void printColumnAnnotationOn(String columnName, EntitySourceWriter pw) {
		if (columnName != null) {  // the column name is null if the default is OK
			pw.printAnnotation(JPA.COLUMN);
			pw.print("(name=");  //$NON-NLS-1$
			pw.printStringLiteral(columnName);
			pw.print(')');
			pw.println();
		}
	}


	// ********** many-to-one fields **********

	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.getAttributeNameFor(relation);
		if (this.config.fieldAccessType()) {
			this.printManyToOneAnnotationOn(fieldName, relation, pw);
		}
		this.printFieldOn(fieldName, this.fullyQualify(relation.getReferencedEntityName()), pw);
	}

	private void printManyToOneAnnotationOn(String attributeName, ManyToOneRelation relation, EntitySourceWriter pw) {
		pw.printAnnotation(JPA.MANY_TO_ONE);
		pw.println();
		ForeignKey foreignKey = relation.getForeignKey();
		if (foreignKey.referencesSingleColumnPrimaryKey()) {
			// if the FK references a single-column PK, 'referencedColumnName' is not required
			String joinColumnName = this.config.getDatabaseAnnotationNameBuilder().buildJoinColumnAnnotationName(attributeName, foreignKey);
			if (joinColumnName == null) {
				// no JoinColumn annotation needed: the default 'name' and 'referencedColumnName' work
			} else {
				// there is only a single join column here (just not the default name)
				this.printJoinColumnAnnotationOn(joinColumnName, null, pw);
				pw.println();
			}
		} else {
			this.printManyToOneJoinColumnsAnnotationOn(foreignKey, pw);
		}
	}

	private void printManyToOneJoinColumnsAnnotationOn(ForeignKey foreignKey, EntitySourceWriter pw) {
		if (foreignKey.columnPairsSize() > 1) {
			pw.printAnnotation(JPA.JOIN_COLUMNS);
			pw.print("({");  //$NON-NLS-1$
			pw.println();
			pw.indent();
		}
		this.printJoinColumnAnnotationsOn(foreignKey, pw);
		if (foreignKey.columnPairsSize() > 1) {
			pw.undent();
			pw.println();
			pw.print("})");  //$NON-NLS-1$
		}
		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(
			this.config.getDatabaseAnnotationNameBuilder().buildJoinColumnAnnotationName(columnPair.getBaseColumn()),
			this.config.getDatabaseAnnotationNameBuilder().buildJoinColumnAnnotationName(columnPair.getReferencedColumn()),
			pw
		);
	}

	/**
	 * 'baseColumnName' cannot be null;
	 * 'referencedColumnName' is null when the default is applicable (i.e. the
	 * referenced column is the single-column primary key column of the
	 * referenced table)
	 */
	private void printJoinColumnAnnotationOn(String baseColumnName, String referencedColumnName, EntitySourceWriter pw) {
		pw.printAnnotation(JPA.JOIN_COLUMN);
		pw.print("(name=");  //$NON-NLS-1$
		pw.printStringLiteral(baseColumnName);

		if (referencedColumnName != null) {
			pw.print(", referencedColumnName=");  //$NON-NLS-1$
			pw.printStringLiteral(referencedColumnName);
		}

		pw.print(')');
	}


	// ********** one-to-many fields **********

	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.getAttributeNameFor(relation);
		if (this.config.fieldAccessType()) {
			this.printOneToManyAnnotationOn(relation, pw);
		}
		this.printCollectionFieldOn(fieldName, this.fullyQualify(relation.getReferencedEntityName()), pw);
	}

	private void printOneToManyAnnotationOn(OneToManyRelation relation, EntitySourceWriter pw) {
		pw.printAnnotation(JPA.ONE_TO_MANY);
		pw.print("(mappedBy=\"");  //$NON-NLS-1$
		pw.print(relation.getMappedBy());
		pw.print("\")");  //$NON-NLS-1$
		pw.println();
	}


	// ********** owned many-to-many fields **********

	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.getAttributeNameFor(relation);
		if (this.config.fieldAccessType()) {
			this.printOwnedManyToManyAnnotationOn(fieldName, relation, pw);
		}
		this.printCollectionFieldOn(fieldName, this.fullyQualify(relation.getNonOwningEntityName()), pw);
	}

	/**
	 * only print the JoinTable annotation if one or more of the
	 * [generated] elements is not defaulted:
	 *     name
	 *     joinColumns
	 *     inverseJoinColumns
	 * thus the need for the 'printJoinTableAnnotation' flag
	 */
	private void printOwnedManyToManyAnnotationOn(String attributeName, ManyToManyRelation relation, EntitySourceWriter pw) {
		pw.printAnnotation(JPA.MANY_TO_MANY);
		pw.println();
		BooleanHolder printJoinTableAnnotation = new BooleanHolder(true);

		if ( ! relation.joinTableNameIsDefault()) {  // db-only test - no need to delegate to platform?
			printJoinTableAnnotation.setFalse();
			pw.printAnnotation(JPA.JOIN_TABLE);
			pw.print("(name=");  //$NON-NLS-1$
			pw.printStringLiteral(this.config.getDatabaseAnnotationNameBuilder().buildJoinTableAnnotationName(relation.getJoinGenTable().getTable()));
		}

		this.printJoinTableJoinColumnAnnotationsOn(
				"joinColumns",  //$NON-NLS-1$
				attributeName,
				relation.getOwningForeignKey(),
				printJoinTableAnnotation,
				pw
		);

		this.printJoinTableJoinColumnAnnotationsOn(
				"inverseJoinColumns",  //$NON-NLS-1$
				relation.getNonOwningGenTable().getAttributeNameFor(relation),
				relation.getNonOwningForeignKey(),
				printJoinTableAnnotation,
				pw
		);

		if (printJoinTableAnnotation.isFalse()) {
			pw.print(')');
			pw.println();
		}
	}

	/**
	 * 'elementName' is either "joinColumns" or "inverseJoinColumns"
	 */
	private void printJoinTableJoinColumnAnnotationsOn(String elementName, String attributeName, ForeignKey foreignKey, BooleanHolder printJoinTableAnnotation, EntitySourceWriter pw) {
		// we have to pre-calculate whether either 'name' and/or 'referencedColumnName'
		// is required because they are wrapped by the JoinTable annotation and we
		// need to print the JoinTable annotation first (if it hasn't already been printed)
		boolean printRef = ! foreignKey.referencesSingleColumnPrimaryKey();
		// if 'referencedColumnName' is required, 'name' is also required (i.e. it cannot be defaulted);
		// but we will calculate it later [1], since there could be multiple join columns
		String joinColumnName = (printRef) ?
					null  // 'joinColumnName' is not used
				:
					this.config.getDatabaseAnnotationNameBuilder().buildJoinColumnAnnotationName(attributeName, foreignKey);
		boolean printBase = (printRef || (joinColumnName != null));
		if (printBase || printRef) {
			if (printJoinTableAnnotation.isTrue()) {
				printJoinTableAnnotation.setFalse();
				pw.printAnnotation(JPA.JOIN_TABLE);
				pw.print('(');
			} else {
				pw.print(',');
			}
			pw.println();
			pw.indent();
				if (printRef) {
					// if 'printRef' is true, 'joinColumnName' will always be "IGNORED" (so we ignore it)
					this.printJoinTableJoinColumnAnnotationsOn(elementName, foreignKey, pw);  // [1]
				} else {
					// if the FK references a single-column PK, 'referencedColumnName' is not required
					if (printBase) {
						// there is only a single join column here (just not the default name)
						pw.print(elementName);
						pw.print('=');
						this.printJoinColumnAnnotationOn(joinColumnName, null, pw);
					} else {
						// no JoinColumn annotation needed: the default 'name' and 'referencedColumnName' work
					}
				}
			pw.undent();
		}
	}

	/**
	 * 'elementName' is either "joinColumns" or "inverseJoinColumns"
	 */
	private void printJoinTableJoinColumnAnnotationsOn(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();
		}
	}


	// ********** non-owned many-to-many fields **********

	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.getAttributeNameFor(relation);
		if (this.config.fieldAccessType()) {
			this.printNonOwnedManyToManyAnnotationOn(relation, pw);
		}
		this.printCollectionFieldOn(fieldName, this.fullyQualify(relation.getOwningEntityName()), pw);
	}

	private void printNonOwnedManyToManyAnnotationOn(ManyToManyRelation relation, EntitySourceWriter pw) {
		pw.printAnnotation(JPA.MANY_TO_MANY);
		pw.print("(mappedBy=\"");  //$NON-NLS-1$
		pw.print(relation.getMappedBy());
		pw.print("\")");  //$NON-NLS-1$
		pw.println();
	}


	// ********** misc **********

	private void printSerialVersionUIDFieldOn(EntitySourceWriter pw) {
		if (this.config.generateSerialVersionUID()) {
			pw.print("private static final long serialVersionUID = 1L;");  //$NON-NLS-1$
			pw.println();
		}
	}

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


	// ********** primary key properties **********

	private void printEntityPrimaryKeyPropertiesOn(EntitySourceWriter pw) {
		if (this.primaryKeyClassIsRequired() && this.config.generateEmbeddedIdForCompoundPK()) {
			this.printEntityEmbeddedIdPrimaryKeyPropertyOn(pw);
		} else {
			this.printEntityReadOnlyPrimaryKeyPropertiesOn(pw);
			this.printEntityWritablePrimaryKeyPropertiesOn(pw);
		}
	}

	private void printEntityEmbeddedIdPrimaryKeyPropertyOn(EntitySourceWriter pw) {
		if (this.config.propertyAccessType()) {
			pw.printAnnotation(JPA.EMBEDDED_ID);
			pw.println();
		}
		this.printPropertyOn(this.genTable.getAttributeNameForEmbeddedId(), this.pkClassName, pw);
	}

	private void printEntityReadOnlyPrimaryKeyPropertiesOn(EntitySourceWriter pw) {
		this.printPrimaryKeyPropertiesOn(pw, true, true);  // true=read-only; true=print ID annotation on getters
	}

	private void printEntityWritablePrimaryKeyPropertiesOn(EntitySourceWriter pw) {
		this.printPrimaryKeyPropertiesOn(pw, false, true);  // false=writable; true=print ID annotation on getters
	}

	private void printPrimaryKeyPropertiesOn(EntitySourceWriter pw, boolean readOnly, boolean printIdAnnotation) {
		for (Iterator<Column> stream = this.primaryKeyColumns(readOnly); stream.hasNext(); ) {
			this.printPrimaryKeyPropertyOn(stream.next(), pw, readOnly, printIdAnnotation);
		}
	}

	// TODO if the property's type is java.util/sql.Date, it needs @Temporal(DATE)
	// TODO if the primary key is auto-generated, the property must be an integral type
	private void printPrimaryKeyPropertyOn(Column column, EntitySourceWriter pw, boolean readOnly, boolean printIdAnnotation) {
		String propertyName = this.genTable.getAttributeNameFor(column);
		if (this.config.propertyAccessType()) {
			if (printIdAnnotation) {
				pw.printAnnotation(JPA.ID);
				pw.println();
			}
			String columnName = this.config.getDatabaseAnnotationNameBuilder().buildColumnAnnotationName(propertyName, column);
			if (readOnly) {
				this.printReadOnlyColumnAnnotationOn(columnName, pw);
			} else {
				this.printColumnAnnotationOn(columnName, pw);
			}
		}
		this.printPropertyOn(propertyName, column.getPrimaryKeyJavaTypeDeclaration(), pw);
	}


	// ********** basic properties **********

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

	private void printEntityNonPrimaryKeyBasicPropertyOn(Column column, EntitySourceWriter pw) {
		String propertyName = this.genTable.getAttributeNameFor(column);
		if (this.config.propertyAccessType()) {
			String columnName = this.config.getDatabaseAnnotationNameBuilder().buildColumnAnnotationName(propertyName, column);
			this.printColumnAnnotationOn(columnName, pw);
		}
		this.printPropertyOn(propertyName, column.getJavaTypeDeclaration(), pw);
	}


	// ********** many-to-one properties **********

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

	private void printEntityManyToOnePropertyOn(ManyToOneRelation relation, EntitySourceWriter pw) {
		String propertyName = this.genTable.getAttributeNameFor(relation);
		if (this.config.propertyAccessType()) {
			this.printManyToOneAnnotationOn(propertyName, relation, pw);
		}
		String typeDeclaration = this.fullyQualify(relation.getReferencedEntityName());
		this.printPropertyOn(propertyName, typeDeclaration, pw);
	}


	// ********** one-to-many properties **********

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

	private void printEntityOneToManyPropertyOn(OneToManyRelation relation, EntitySourceWriter pw) {
		String propertyName = this.genTable.getAttributeNameFor(relation);
		if (this.config.propertyAccessType()) {
			this.printOneToManyAnnotationOn(relation, pw);
		}
		String elementTypeDeclaration = this.fullyQualify(relation.getReferencedEntityName());
		this.printCollectionPropertyOn(propertyName, elementTypeDeclaration, pw);
	}


	// ********** owned many-to-many properties **********

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

	private void printEntityOwnedManyToManyPropertyOn(ManyToManyRelation relation, EntitySourceWriter pw) {
		String propertyName = this.genTable.getAttributeNameFor(relation);
		if (this.config.propertyAccessType()) {
			this.printOwnedManyToManyAnnotationOn(propertyName, relation, pw);
		}
		String elementTypeDeclaration = this.fullyQualify(relation.getNonOwningEntityName());
		this.printCollectionPropertyOn(propertyName, elementTypeDeclaration, pw);
	}


	// ********** non-owned many-to-many properties **********

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

	private void printEntityNonOwnedManyToManyPropertyOn(ManyToManyRelation relation, EntitySourceWriter pw) {
		String propertyName = this.genTable.getAttributeNameFor(relation);
		if (this.config.propertyAccessType()) {
			this.printNonOwnedManyToManyAnnotationOn(relation, pw);
		}
		String elementTypeDeclaration = this.fullyQualify(relation.getOwningEntityName());
		this.printCollectionPropertyOn(propertyName, elementTypeDeclaration, pw);
	}


	// ********** compound primary key class **********

	private void printPrimaryKeyClassOn(EntitySourceWriter pw) {
		pw.println();
		if (this.config.generateEmbeddedIdForCompoundPK()) {
			pw.printAnnotation(JPA.EMBEDDABLE);
			pw.println();
		}
		pw.print("public static class ");  //$NON-NLS-1$
		pw.print(this.config.getPrimaryKeyMemberClassName());
		pw.print(" implements ");  //$NON-NLS-1$
		pw.printTypeDeclaration(Serializable.class.getName());
		pw.print(" {");  //$NON-NLS-1$
		pw.println();

		pw.indent();
			if (this.config.generateEmbeddedIdForCompoundPK()) {
				this.printEmbeddableReadOnlyPrimaryKeyFieldsOn(pw);
				this.printEmbeddableWritablePrimaryKeyFieldsOn(pw);
			} else {
				this.printIdFieldsOn(pw);
			}
			this.printSerialVersionUIDFieldOn(pw);
			pw.println();
			this.printZeroArgumentConstructorOn(this.config.getPrimaryKeyMemberClassName(), "public", pw);  //$NON-NLS-1$

			if (this.config.propertyAccessType() || this.config.generateGettersAndSetters()) {
				if (this.config.generateEmbeddedIdForCompoundPK()) {
					this.printEmbeddableReadOnlyPrimaryKeyPropertiesOn(pw);
					this.printEmbeddableWritablePrimaryKeyPropertiesOn(pw);
				} else {
					this.printIdPropertiesOn(pw);
				}
			}

			this.printPrimaryKeyEqualsMethodOn(this.config.getPrimaryKeyMemberClassName(), this.getTable().primaryKeyColumns(), pw);
			this.printPrimaryKeyHashCodeMethodOn(this.getTable().primaryKeyColumns(), pw);
		pw.undent();

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


	// ********** compound primary key class fields **********

	private void printEmbeddableReadOnlyPrimaryKeyFieldsOn(EntitySourceWriter pw) {
		this.printPrimaryKeyFieldsOn(pw, true, false);  // true=read-only; false=do not print ID annotation on fields
	}

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

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

	private void printIdFieldOn(Column column, EntitySourceWriter pw) {
		this.printFieldOn(this.genTable.getAttributeNameFor(column), column.getPrimaryKeyJavaTypeDeclaration(), pw);
	}


	// ********** compound primary key class properties **********

	private void printEmbeddableReadOnlyPrimaryKeyPropertiesOn(EntitySourceWriter pw) {
		this.printPrimaryKeyPropertiesOn(pw, true, false);  // true=read-only; false=do not print ID annotation on getters
	}

	private void printEmbeddableWritablePrimaryKeyPropertiesOn(EntitySourceWriter pw) {
		this.printPrimaryKeyPropertiesOn(pw, false, false);  // false=writable; false=do not print ID annotation on getters
	}

	private void printIdPropertiesOn(EntitySourceWriter pw) {
		for (Iterator<Column> stream = this.getTable().primaryKeyColumns(); stream.hasNext(); ) {
			this.printIdPropertyOn(stream.next(), pw);
		}
	}

	private void printIdPropertyOn(Column column, EntitySourceWriter pw) {
		this.printPropertyOn(this.genTable.getAttributeNameFor(column), column.getPrimaryKeyJavaTypeDeclaration(), pw);
	}


	// ********** compound primary key class equals **********

	private void printPrimaryKeyEqualsMethodOn(String className, Iterator<Column> columns, EntitySourceWriter pw) {
		pw.printAnnotation("java.lang.Override");  //$NON-NLS-1$
		pw.println();

		pw.println("public boolean equals(Object o) {");  //$NON-NLS-1$
		pw.indent();
			pw.println("if (o == this) {");  //$NON-NLS-1$
			pw.indent();
				pw.println("return true;");  //$NON-NLS-1$
			pw.undent();
			pw.print('}');
			pw.println();

			pw.print("if ( ! (o instanceof ");  //$NON-NLS-1$
			pw.print(className);
			pw.print(")) {");  //$NON-NLS-1$
			pw.println();
			pw.indent();
				pw.println("return false;");  //$NON-NLS-1$
			pw.undent();
			pw.print('}');
			pw.println();

			pw.print(className);
			pw.print(" other = (");  //$NON-NLS-1$
			pw.print(className);
			pw.print(") o;");  //$NON-NLS-1$
			pw.println();

			pw.print("return ");  //$NON-NLS-1$
			pw.indent();
				while (columns.hasNext()) {
					this.printPrimaryKeyEqualsClauseOn(columns.next(), pw);
					if (columns.hasNext()) {
						pw.println();
						pw.print("&& ");  //$NON-NLS-1$
					}
				}
				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.getAttributeNameFor(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.");  //$NON-NLS-1$
		pw.print(fieldName);
		pw.print(" == other.");  //$NON-NLS-1$
		pw.print(fieldName);
		pw.print(')');
	}

	private void printReferenceEqualsClauseOn(String fieldName, EntitySourceWriter pw) {
		pw.print("this.");  //$NON-NLS-1$
		pw.print(fieldName);
		pw.print(".equals(other.");  //$NON-NLS-1$
		pw.print(fieldName);
		pw.print(')');
	}


	// ********** compound primary key class hash code **********

	private void printPrimaryKeyHashCodeMethodOn(Iterator<Column> columns, EntitySourceWriter pw) {
		pw.printAnnotation("java.lang.Override");  //$NON-NLS-1$
		pw.println();

		pw.println("public int hashCode() {");  //$NON-NLS-1$
		pw.indent();
			pw.println("final int prime = 31;");  //$NON-NLS-1$
			pw.println("int hash = 17;");  //$NON-NLS-1$
			while (columns.hasNext()) {
				pw.print("hash = hash * prime + ");  //$NON-NLS-1$
				this.printPrimaryKeyHashCodeClauseOn(columns.next(), pw);
				pw.print(';');
				pw.println();
			}
			pw.println("return hash;");  //$NON-NLS-1$
		pw.undent();
		pw.print('}');
		pw.println();
		pw.println();
	}

	private void printPrimaryKeyHashCodeClauseOn(Column column, EntitySourceWriter pw) {
		String fieldName = this.genTable.getAttributeNameFor(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")) {  //$NON-NLS-1$
			// this.value
			pw.print("this.");  //$NON-NLS-1$
			pw.print(fieldName);
		} else if (primitiveName.equals("short")  //$NON-NLS-1$
				|| primitiveName.equals("byte")  //$NON-NLS-1$
				|| primitiveName.equals("char")) {  //$NON-NLS-1$
			// ((int) this.value)  - explicit cast
			pw.print("((int) this.");  //$NON-NLS-1$
			pw.print(fieldName);
			pw.print(')');
		} else if (primitiveName.equals("long")) {  // cribbed from Long#hashCode()  //$NON-NLS-1$
			// ((int) (this.value ^ (this.value >>> 32)))
			pw.print("((int) (this.");  //$NON-NLS-1$
			pw.print(fieldName);
			pw.print(" ^ (this.");  //$NON-NLS-1$
			pw.print(fieldName);
			pw.print(" >>> 32)))");  //$NON-NLS-1$
		} else if (primitiveName.equals("float")) {  // cribbed from Float#hashCode()  //$NON-NLS-1$
			// java.lang.Float.floatToIntBits(this.value)
			pw.printTypeDeclaration("java.lang.Float");  //$NON-NLS-1$
			pw.print(".floatToIntBits(this.");  //$NON-NLS-1$
			pw.print(fieldName);
			pw.print(')');
		} else if (primitiveName.equals("double")) {  // cribbed from Double#hashCode()  //$NON-NLS-1$
			//	((int) (java.lang.Double.doubleToLongBits(this.value) ^ (java.lang.Double.doubleToLongBits(this.value) >>> 32)))
			pw.print("((int) (");  //$NON-NLS-1$
			pw.printTypeDeclaration("java.lang.Double");  //$NON-NLS-1$
			pw.print(".doubleToLongBits(this.");  //$NON-NLS-1$
			pw.print(fieldName);
			pw.print(") ^ (");  //$NON-NLS-1$
			pw.printTypeDeclaration("java.lang.Double");  //$NON-NLS-1$
			pw.print(".doubleToLongBits(this.");  //$NON-NLS-1$
			pw.print(fieldName);
			pw.print(") >>> 32)))");  //$NON-NLS-1$
		} else if (primitiveName.equals("boolean")) {  //$NON-NLS-1$
			// (this.value ? 1 : 0)
			pw.print("(this.");  //$NON-NLS-1$
			pw.print(fieldName);
			pw.print(" ? 1 : 0)");  //$NON-NLS-1$
		} else {
			throw new IllegalArgumentException(primitiveName);
		}
	}

	private void printReferenceHashCodeClauseOn(String fieldName, EntitySourceWriter pw) {
		pw.print("this.");  //$NON-NLS-1$
		pw.print(fieldName);
		pw.print(".hashCode()");  //$NON-NLS-1$
	}


	// ********** package and imports **********

	private void printPackageAndImportsOn(PrintWriter pw, BodySource bodySource) {
		if (this.getPackageName().length() != 0) {
			pw.print("package ");  //$NON-NLS-1$
			pw.print(this.getPackageName());
			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 ");  //$NON-NLS-1$
			pw.print(entry.getValue());  // package
			pw.print('.');
			pw.print(entry.getKey());  // short class name
			pw.print(';');
			pw.println();
		}
		pw.println();
	}


	// ********** fields **********

	/**
	 * visibility is set in the config
	 */
	private void printFieldOn(String fieldName, String typeDeclaration, EntitySourceWriter pw) {
		pw.printField(
				fieldName,
				typeDeclaration,
				this.config.getFieldVisibilityClause()
		);
	}

	/**
	 * visibility and collection type are set in the config
	 */
	private void printCollectionFieldOn(String fieldName, String elementTypeDeclaration, EntitySourceWriter pw) {
		pw.printParameterizedField(
				fieldName,
				this.config.getCollectionTypeName(),
				elementTypeDeclaration,
				this.config.getFieldVisibilityClause()
		);
	}


	// ********** properties **********

	/**
	 * visibility is set in the config
	 */
	private void printPropertyOn(String propertyName, String typeDeclaration, EntitySourceWriter pw) {
		pw.printGetterAndSetter(
				propertyName,
				typeDeclaration,
				this.config.getMethodVisibilityClause()
		);
	}

	/**
	 * visibility and collection type are set in the config
	 */
	private void printCollectionPropertyOn(String propertyName, String elementTypeDeclaration, EntitySourceWriter pw) {
		pw.printCollectionGetterAndSetter(
				propertyName,
				this.config.getCollectionTypeName(),
				elementTypeDeclaration,
				this.config.getMethodVisibilityClause()
		);
	}


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

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

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

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

	private boolean primaryKeyClassIsRequired() {
		return this.getTable().primaryKeyColumnsSize() > 1;
	}

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

	@Override
	public String toString() {
		return StringTools.buildToStringFor(this, this.genTable.getName() + " => " + this.entityClassName);  //$NON-NLS-1$
	}


	// ********** source 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 getSource();

		/**
		 * 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;
		}

		/**
		 * Convert the specified string to a String Literal and print it,
		 * adding the surrounding double-quotes and escaping characters
		 * as necessary.
		 */
		void printStringLiteral(String string) {
			StringTools.convertToJavaStringLiteralOn(string, this);
		}

		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.buildImportedTypeDeclaration(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 buildImportedTypeDeclaration(String typeDeclaration) {
			if (this.typeDeclarationIsMemberClass(typeDeclaration)) {
				// no need for an import, just return the partially-qualified name
				return this.buildMemberClassTypeDeclaration(typeDeclaration);
			}
			int last = typeDeclaration.lastIndexOf('.');
			String pkg = (last == -1) ? "" : typeDeclaration.substring(0, last);  //$NON-NLS-1$
			String shortTypeDeclaration = typeDeclaration.substring(last + 1);
			String shortElementTypeName = shortTypeDeclaration;
			while (shortElementTypeName.endsWith("[]")) {  //$NON-NLS-1$
				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 buildMemberClassTypeDeclaration(String typeDeclaration) {
			int index = this.packageName.length();
			if (index != 0) {
				index++;  // bump past the '.'
			}
			return typeDeclaration.substring(index);
		}

		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 printField(String fieldName, String typeDeclaration, String visibility) {
			this.printVisibility(visibility);
			this.printTypeDeclaration(typeDeclaration);
			this.print(' ');
			this.print(fieldName);
			this.print(';');
			this.println();
			this.println();
		}

		void printParameterizedField(String fieldName, String typeDeclaration, String parameterTypeDeclaration, String visibility) {
			this.printVisibility(visibility);
			this.printTypeDeclaration(typeDeclaration);
			this.print('<');
			this.printTypeDeclaration(parameterTypeDeclaration);
			this.print('>');
			this.print(' ');
			this.print(fieldName);
			this.print(';');
			this.println();
			this.println();
		}

		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");  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			this.print(StringTools.capitalize(propertyName));
			this.print("() {");  //$NON-NLS-1$
			this.println();

			this.indent();
				this.print("return this.");  //$NON-NLS-1$
				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");  //$NON-NLS-1$
			this.print(StringTools.capitalize(propertyName));
			this.print('(');
			this.printTypeDeclaration(typeDeclaration);
			this.print(' ');
			this.print(propertyName);
			this.print(") {");  //$NON-NLS-1$
			this.println();

			this.indent();
				this.print("this.");  //$NON-NLS-1$
				this.print(propertyName);
				this.print(" = ");  //$NON-NLS-1$
				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");  //$NON-NLS-1$
			this.print(StringTools.capitalize(propertyName));
			this.print("() {");  //$NON-NLS-1$
			this.println();

			this.indent();
				this.print("return this.");  //$NON-NLS-1$
				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");  //$NON-NLS-1$
			this.print(StringTools.capitalize(propertyName));
			this.print('(');
			this.printTypeDeclaration(collectionTypeDeclaration);
			this.print('<');
			this.printTypeDeclaration(elementTypeDeclaration);
			this.print('>');
			this.print(' ');
			this.print(propertyName);
			this.print(") {");  //$NON-NLS-1$
			this.println();

			this.indent();
				this.print("this.");  //$NON-NLS-1$
				this.print(propertyName);
				this.print(" = ");  //$NON-NLS-1$
				this.print(propertyName);
				this.print(';');
				this.println();
			this.undent();

			this.print('}');
		}


		// ********** BodySource implementation **********

		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("")  //$NON-NLS-1$
							|| pkg.equals("java.lang")  //$NON-NLS-1$
							|| pkg.equals(EntitySourceWriter.this.packageName)) {
						return false;
					}
					return true;
				}
			};
		}

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

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

	}


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

	public static class Config {
		private boolean convertToJavaStyleIdentifiers = true;

		private boolean propertyAccessType = false;  // as opposed to "field"

		private String collectionTypeName = Set.class.getName();
		private String collectionAttributeNameSuffix = "Collection";  // e.g. "private Set<Foo> fooCollection"  //$NON-NLS-1$

		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 String embeddedIdAttributeName = "pk";  //$NON-NLS-1$
		private String primaryKeyMemberClassName = "PK";  //$NON-NLS-1$

		/**
		 * key = table
		 * value = entity name
		 */
		private HashMap<Table, String> tables = new HashMap<Table, String>();

		private DatabaseAnnotationNameBuilder databaseAnnotationNameBuilder = DatabaseAnnotationNameBuilder.Default.INSTANCE;

		private OverwriteConfirmer overwriteConfirmer = OverwriteConfirmer.Never.INSTANCE;

		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 convertToJavaStyleIdentifiers() {
			return this.convertToJavaStyleIdentifiers;
		}
		public void setConvertToJavaStyleIdentifiers(boolean convertToJavaStyleIdentifiers) {
			this.convertToJavaStyleIdentifiers = convertToJavaStyleIdentifiers;
		}

		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.checkRequiredString(collectionTypeName, "collection type name is required");  //$NON-NLS-1$
			this.collectionTypeName = collectionTypeName;
		}

		public String getCollectionAttributeNameSuffix() {
			return this.collectionAttributeNameSuffix;
		}
		public void setCollectionAttributeNameSuffix(String collectionAttributeNameSuffix) {
			this.collectionAttributeNameSuffix = collectionAttributeNameSuffix;
		}

		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);  //$NON-NLS-1$
			}
		}
		String getFieldVisibilityClause() {
			switch (this.fieldVisibility) {
				case PRIVATE:
					return "private";  //$NON-NLS-1$
				case PACKAGE:
					return "";  //$NON-NLS-1$
				case PROTECTED:
					return "protected";  //$NON-NLS-1$
				default:
					throw new IllegalStateException("invalid field visibility: " + this.fieldVisibility);  //$NON-NLS-1$
			}
		}

		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);  //$NON-NLS-1$
			}
		}
		String getMethodVisibilityClause() {
			switch (this.methodVisibility) {
				case PROTECTED:
					return "protected";  //$NON-NLS-1$
				case PUBLIC:
					return "public";  //$NON-NLS-1$
				default:
					throw new IllegalStateException("invalid method visibility: " + this.methodVisibility);  //$NON-NLS-1$
			}
		}

		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;
		}

		public String getEmbeddedIdAttributeName() {
			return this.embeddedIdAttributeName;
		}
		public void setEmbeddedIdAttributeName(String embeddedIdAttributeName) {
			this.checkRequiredString(embeddedIdAttributeName, "EmbeddedId attribute name is required");  //$NON-NLS-1$
			this.embeddedIdAttributeName = embeddedIdAttributeName;
		}

		public String getPrimaryKeyMemberClassName() {
			return this.primaryKeyMemberClassName;
		}
		public void setPrimaryKeyMemberClassName(String primaryKeyMemberClassName) {
			this.checkRequiredString(primaryKeyMemberClassName, "primary key member class name is required");  //$NON-NLS-1$
			this.primaryKeyMemberClassName = primaryKeyMemberClassName;
		}

		String getEntityName(Table table) {
			return this.tables.get(table);
		}
		Iterator<Table> tables() {
			return this.tables.keySet().iterator();
		}
		int tablesSize() {
			return this.tables.size();
		}
		public void addTable(Table table, String entityName) {
			if (table == null) {
				throw new NullPointerException("table is required");  //$NON-NLS-1$
			}
			this.checkRequiredString(entityName, "entity name is required");  //$NON-NLS-1$
			if (this.tables.containsKey(table)) {
				throw new IllegalArgumentException("duplicate table: " + table.getName());  //$NON-NLS-1$
			}
			if (this.tables.values().contains(entityName)) {
				throw new IllegalArgumentException("duplicate entity name: " + entityName);  //$NON-NLS-1$
			}
			if ( ! NameTools.stringConsistsOfJavaIdentifierCharacters(entityName)) {
				throw new IllegalArgumentException("entity name is not a valid Java identifier: " + entityName);  //$NON-NLS-1$
			}
			if (NameTools.JAVA_RESERVED_WORDS_SET.contains(entityName)) {
				throw new IllegalArgumentException("entity name is a Java reserved word: " + entityName);  //$NON-NLS-1$
			}
			this.tables.put(table, entityName);
		}

		public DatabaseAnnotationNameBuilder getDatabaseAnnotationNameBuilder() {
			return this.databaseAnnotationNameBuilder;
		}
		public void setDatabaseAnnotationNameBuilder(DatabaseAnnotationNameBuilder databaseAnnotationNameBuilder) {
			if (databaseAnnotationNameBuilder == null) {
				throw new NullPointerException("database annotation name builder is required");  //$NON-NLS-1$
			}
			this.databaseAnnotationNameBuilder = databaseAnnotationNameBuilder;
		}

		public OverwriteConfirmer getOverwriteConfirmer() {
			return this.overwriteConfirmer;
		}
		public void setOverwriteConfirmer(OverwriteConfirmer overwriteConfirmer) {
			if (overwriteConfirmer == null) {
				throw new NullPointerException("overwrite confirmer is required");  //$NON-NLS-1$
			}
			this.overwriteConfirmer = overwriteConfirmer;
		}

		private void checkRequiredString(String string, String message) {
			if ((string == null) || (string.length() == 0)) {
				throw new IllegalArgumentException(message);
			}
		}

	}


	// ********** overwrite confirmer **********

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


		final class Always implements OverwriteConfirmer {
			public static final OverwriteConfirmer INSTANCE = new Always();
			public static OverwriteConfirmer instance() {
				return INSTANCE;
			}
			// ensure single instance
			private Always() {
				super();
			}
			// everything will be overwritten
			public boolean overwrite(String arg0) {
				return true;
			}
			@Override
			public String toString() {
				return "OverwriteConfirmer.Always";  //$NON-NLS-1$
			}
		}


		final class Never implements OverwriteConfirmer {
			public static final OverwriteConfirmer INSTANCE = new Never();
			public static OverwriteConfirmer instance() {
				return INSTANCE;
			}
			// ensure single instance
			private Never() {
				super();
			}
			// nothing will be overwritten
			public boolean overwrite(String arg0) {
				return false;
			}
			@Override
			public String toString() {
				return "OverwriteConfirmer.Never";  //$NON-NLS-1$
			}
		}

	}


	// ********** annotation name builder **********

	/**
	 * Provide a pluggable way to determine whether and how the entity generator
	 * prints the names of various database objects.
	 */
	public static interface DatabaseAnnotationNameBuilder {

		/**
		 * Given the name of an entity and the table to which it is mapped,
		 * build and return a string to be used as the value for the entity's
		 * Table annotation's 'name' element. Return null if the entity
		 * maps to the table by default.
		 */
		String buildTableAnnotationName(String entityName, Table table);

		/**
		 * Given the name of an attribute (field or property) and the column
		 * to which it is mapped,
		 * build and return a string to be used as the value for the attribute's
		 * Column annotation's 'name' element. Return null if the attribute
		 * maps to the column by default.
		 */
		String buildColumnAnnotationName(String attributeName, Column column);

		/**
		 * Given the name of an attribute (field or property) and the
		 * many-to-one or many-to-many foreign key to which it is mapped,
		 * build and return a string to be used as the value for the attribute's
		 * JoinColumn annotation's 'name' element. Return null if the attribute
		 * maps to the join column by default.
		 * The specified foreign key consists of a single column pair whose
		 * referenced column is the single-column primary key of the foreign
		 * key's referenced table.
		 */
		String buildJoinColumnAnnotationName(String attributeName, ForeignKey foreignKey);

		/**
		 * Build and return a string to be used as the value for a JoinColumn
		 * annotation's 'name' or 'referencedColumnName' element.
		 * This is called for many-to-one and many-to-many mappings when
		 * the default join column name and/or referenced column name are/is
		 * not applicable.
		 * @see buildJoinColumnAnnotationName(String, ForeignKey)
		 */
		String buildJoinColumnAnnotationName(Column column);

		/**
		 * Build and return a string to be used as the value for a JoinTable
		 * annotation's 'name' element.
		 * This is called for many-to-many mappings when the default
		 * join table name is not applicable.
		 */
		String buildJoinTableAnnotationName(Table table);


		/**
		 * The default implementation simple returns the database object's name,
		 * unaltered.
		 */
		final class Default implements DatabaseAnnotationNameBuilder {
			public static final DatabaseAnnotationNameBuilder INSTANCE = new Default();
			public static DatabaseAnnotationNameBuilder instance() {
				return INSTANCE;
			}
			// ensure single instance
			private Default() {
				super();
			}
			public String buildTableAnnotationName(String entityName, Table table) {
				return table.getName();
			}
			public String buildColumnAnnotationName(String attributeName, Column column) {
				return column.getName();
			}
			public String buildJoinColumnAnnotationName(String attributeName, ForeignKey foreignKey) {
				return foreignKey.getColumnPair().getBaseColumn().getName();
			}
			public String buildJoinColumnAnnotationName(Column column) {
				return column.getName();
			}
			public String buildJoinTableAnnotationName(Table table) {
				return table.getName();
			}
			@Override
			public String toString() {
				return "DatabaseAnnotationNameBuilder.Default";  //$NON-NLS-1$
			}
		}

	}

}
