/*******************************************************************************
 * Copyright (c) 2006, 2010 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.old;

import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.lang.reflect.Modifier;
import com.ibm.icu.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.BooleanReference;
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 (Column column : this.getPrimaryKeyColumns(readOnly)) {
			this.printPrimaryKeyFieldOn(column, pw, readOnly, printIdAnnotation);
		}
	}

	private Iterable<Column> getPrimaryKeyColumns(boolean readOnly) {
		return readOnly ? this.genTable.getReadOnlyPrimaryKeyColumns() : this.genTable.getWritablePrimaryKeyColumns();
	}

	// 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 (Column column : this.genTable.getNonPrimaryKeyBasicColumns()) {
			this.printEntityNonPrimaryKeyBasicFieldOn(column, 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.getColumnPairsSize() > 1) {
			pw.printAnnotation(JPA.JOIN_COLUMNS);
			pw.print("({");  //$NON-NLS-1$
			pw.println();
			pw.indent();
		}
		this.printJoinColumnAnnotationsOn(foreignKey, pw);
		if (foreignKey.getColumnPairsSize() > 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.getColumnPairs().iterator(); 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.getAttributeNameForOwned(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();
		BooleanReference printJoinTableAnnotation = new BooleanReference(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().getAttributeNameForNonOwned(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, BooleanReference 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.getColumnPairsSize() > 1) {
			pw.print('{');
			pw.println();
			pw.indent();
		}
		this.printJoinColumnAnnotationsOn(foreignKey, pw);
		if (foreignKey.getColumnPairsSize() > 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.getAttributeNameForNonOwned(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 (Column column : this.getPrimaryKeyColumns(readOnly)) {
			this.printPrimaryKeyPropertyOn(column, 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 (Column column : this.genTable.getNonPrimaryKeyBasicColumns()) {
			this.printEntityNonPrimaryKeyBasicPropertyOn(column, 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.getAttributeNameForOwned(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.getAttributeNameForNonOwned(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().getPrimaryKeyColumns(), pw);
			this.printPrimaryKeyHashCodeMethodOn(this.getTable().getPrimaryKeyColumns(), 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 (Column column : this.getTable().getPrimaryKeyColumns()) {
			this.printIdFieldOn(column, 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 (Column column : this.getTable().getPrimaryKeyColumns()) {
			this.printIdPropertyOn(column, 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, Iterable<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();
				for (Iterator<Column> stream = columns.iterator(); stream.hasNext(); ) {
					this.printPrimaryKeyEqualsClauseOn(stream.next(), pw);
					if (stream.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(Iterable<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$
			for (Column column : columns) {
				pw.print("hash = hash * prime + ");  //$NON-NLS-1$
				this.printPrimaryKeyHashCodeClauseOn(column, 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().getPrimaryKeyColumnsSize() > 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>>(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$
			}
		}

	}

}
