/*******************************************************************************
 * 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.dataTypeIsLOB()) {
			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$
			}
		}

	}

}
