/*******************************************************************************
 * Copyright (c) 2006, 2012 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.jpa.core.internal;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceProxy;
import org.eclipse.core.resources.IResourceProxyVisitor;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.ElementChangedEvent;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jpt.common.core.JptCommonCorePlugin;
import org.eclipse.jpt.common.core.JptResourceModel;
import org.eclipse.jpt.common.core.JptResourceModelListener;
import org.eclipse.jpt.common.core.internal.resource.java.binary.BinaryTypeCache;
import org.eclipse.jpt.common.core.internal.resource.java.source.SourceTypeCompilationUnit;
import org.eclipse.jpt.common.core.internal.utility.PlatformTools;
import org.eclipse.jpt.common.core.internal.utility.command.NotifyingRepeatingJobCommandWrapper;
import org.eclipse.jpt.common.core.internal.utility.command.RepeatingJobCommandWrapper;
import org.eclipse.jpt.common.core.resource.ProjectResourceLocator;
import org.eclipse.jpt.common.core.resource.java.JavaResourceAbstractType;
import org.eclipse.jpt.common.core.resource.java.JavaResourceCompilationUnit;
import org.eclipse.jpt.common.core.resource.java.JavaResourceNode;
import org.eclipse.jpt.common.core.resource.java.JavaResourcePackage;
import org.eclipse.jpt.common.core.resource.java.JavaResourcePackageFragmentRoot;
import org.eclipse.jpt.common.core.resource.java.JavaResourcePackageInfoCompilationUnit;
import org.eclipse.jpt.common.core.resource.java.JavaResourceTypeCache;
import org.eclipse.jpt.common.core.utility.command.JobCommand;
import org.eclipse.jpt.common.core.utility.command.JobCommandExecutor;
import org.eclipse.jpt.common.core.utility.command.NotifyingRepeatingJobCommand;
import org.eclipse.jpt.common.core.utility.command.RepeatingJobCommand;
import org.eclipse.jpt.common.utility.Filter;
import org.eclipse.jpt.common.utility.internal.BitTools;
import org.eclipse.jpt.common.utility.internal.CollectionTools;
import org.eclipse.jpt.common.utility.internal.StringTools;
import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
import org.eclipse.jpt.common.utility.internal.iterables.CompositeIterable;
import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable;
import org.eclipse.jpt.common.utility.internal.iterables.FilteringIterable;
import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneIterable;
import org.eclipse.jpt.common.utility.internal.iterables.SnapshotCloneIterable;
import org.eclipse.jpt.common.utility.internal.iterables.TransformationIterable;
import org.eclipse.jpt.jpa.core.JpaDataSource;
import org.eclipse.jpt.jpa.core.JpaFacet;
import org.eclipse.jpt.jpa.core.JpaFile;
import org.eclipse.jpt.jpa.core.JpaPlatform;
import org.eclipse.jpt.jpa.core.JpaProject;
import org.eclipse.jpt.jpa.core.JptJpaCorePlugin;
import org.eclipse.jpt.jpa.core.context.JpaRootContextNode;
import org.eclipse.jpt.jpa.core.context.java.JavaTypeMappingDefinition;
import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages;
import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages;
import org.eclipse.jpt.jpa.core.jpa2.JpaProject2_0;
import org.eclipse.jpt.jpa.core.jpa2.context.JpaRootContextNode2_0;
import org.eclipse.jpt.jpa.core.libprov.JpaLibraryProviderInstallOperationConfig;
import org.eclipse.jpt.jpa.core.resource.xml.JpaXmlResource;
import org.eclipse.jpt.jpa.db.Catalog;
import org.eclipse.jpt.jpa.db.ConnectionProfile;
import org.eclipse.jpt.jpa.db.Database;
import org.eclipse.jpt.jpa.db.Schema;
import org.eclipse.jpt.jpa.db.SchemaContainer;
import org.eclipse.jst.common.project.facet.core.libprov.ILibraryProvider;
import org.eclipse.jst.common.project.facet.core.libprov.LibraryProviderFramework;
import org.eclipse.jst.j2ee.model.internal.validation.ValidationCancelledException;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.common.internal.emfworkbench.WorkbenchResourceHelper;
import org.eclipse.wst.common.project.facet.core.IFacetedProject;
import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;

/**
 * JPA project. Holds all the JPA stuff.
 * <p>
 * The JPA platform provides the hooks for vendor-specific stuff.
 * <p>
 * The JPA files are the "resource" model (i.e. objects that correspond directly
 * to Eclipse resources; e.g. Java source code files, XML files, JAR files).
 * <p>
 * The root context node is the "context" model (i.e. objects that attempt to
 * model the JPA spec, using the "resource" model as an adapter to the Eclipse
 * resources).
 * <p>
 * The data source is an adapter to the DTP meta-data model.
 */
public abstract class AbstractJpaProject
	extends AbstractJpaNode
	implements JpaProject2_0
{
	/**
	 * The JPA project manager.
	 */
	protected final Manager manager;

	/**
	 * The Eclipse project corresponding to the JPA project.
	 */
	protected final IProject project;

	/**
	 * The vendor-specific JPA platform that builds the JPA project
	 * and all its contents.
	 */
	protected final JpaPlatform jpaPlatform;

	/**
	 * The JPA files associated with the JPA project:
	 *     persistence.xml
	 *     orm.xml
	 *     java
	 */
	protected final Vector<JpaFile> jpaFiles = new Vector<JpaFile>();

	/**
	 * The "external" Java resource compilation units (source). Populated upon demand.
	 */
	protected final Vector<JavaResourceCompilationUnit> externalJavaResourceCompilationUnits = new Vector<JavaResourceCompilationUnit>();

	/**
	 * The "external" Java resource types (binary). Populated upon demand.
	 */
	protected final JavaResourceTypeCache externalJavaResourceTypeCache;

	/**
	 * Resource models notify this listener when they change. A project update
	 * should occur any time a resource model changes.
	 */
	protected final JptResourceModelListener resourceModelListener;

	/**
	 * The root of the model representing the collated resources associated with
	 * the JPA project.
	 */
	protected final JpaRootContextNode rootContextNode;

	/**
	 * A repeating command that keeps the JPA project's context model
	 * synchronized with its resource model, either synchronously or
	 * asynchronously (or not at all), depending on the JPA project manager.
	 */
	protected volatile RepeatingJobCommand synchronizeContextModelCommand;
	protected volatile boolean synchronizingContextModel = false;

	/**
	 * A pluggable synchronizer that "updates" the JPA project, either
	 * synchronously or asynchronously (or not at all), depending on the JPA
	 * project manager.
	 */
	protected volatile NotifyingRepeatingJobCommand updateCommand;
	protected final NotifyingRepeatingJobCommand.Listener updateCommandListener;

	/**
	 * The data source that wraps the DTP model.
	 */
	// TODO move to persistence unit... :-(
	protected final JpaDataSource dataSource;

	/**
	 * A catalog name used to override the connection's default catalog.
	 */
	protected volatile String userOverrideDefaultCatalog;

	/**
	 * A schema name used to override the connection's default schema.
	 */
	protected volatile String userOverrideDefaultSchema;

	/**
	 * Flag indicating whether the project should "discover" annotated
	 * classes automatically, as opposed to requiring the classes to be
	 * listed in <code>persistence.xml</code>. Stored as a preference.
	 * @see #setDiscoversAnnotatedClasses(boolean)
	 */
	protected volatile boolean discoversAnnotatedClasses;

	/**
	 * The name of the Java project source folder that holds the generated
	 * metamodel. If the name is <code>null</code> the metamodel is not
	 * generated.
	 */
	protected volatile String metamodelSourceFolderName;


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

	protected AbstractJpaProject(JpaProject.Config config) {
		super(null);  // JPA project is the root of the containment tree
		if ((config.getJpaProjectManager() == null) || (config.getProject() == null) || (config.getJpaPlatform() == null)) {
			throw new NullPointerException();
		}
		this.manager = config.getJpaProjectManager();
		this.project = config.getProject();
		this.synchronizeContextModelCommand = this.buildSynchronizeContextModelCommand();
		this.updateCommand = this.buildTempUpdateCommand();  // temporary command
		this.jpaPlatform = config.getJpaPlatform();
		this.dataSource = this.getJpaFactory().buildJpaDataSource(this, config.getConnectionProfileName());
		this.userOverrideDefaultCatalog = config.getUserOverrideDefaultCatalog();
		this.userOverrideDefaultSchema = config.getUserOverrideDefaultSchema();
		this.discoversAnnotatedClasses = config.discoverAnnotatedClasses();

		this.resourceModelListener = this.buildResourceModelListener();
		// build the JPA files corresponding to the Eclipse project's files
		InitialResourceProxyVisitor visitor = this.buildInitialResourceProxyVisitor();
		visitor.visitProject(this.project);

		this.externalJavaResourceTypeCache = this.buildExternalJavaResourceTypeCache();

		if (this.isJpa2_0Compatible()) {
			this.metamodelSourceFolderName = ((JpaProject2_0.Config) config).getMetamodelSourceFolderName();
			if (this.metamodelSoureFolderNameIsInvalid()) {
				this.metamodelSourceFolderName = null;
			}
		}

		this.rootContextNode = this.buildRootContextNode();

		this.updateCommandListener = this.buildUpdateCommandListener();
		this.initializeContextModel();

		// start listening to this cache once the context model has been built
		// and all the external types are faulted in
		this.externalJavaResourceTypeCache.addResourceModelListener(this.resourceModelListener);
	}

	@Override
	protected boolean requiresParent() {
		return false;
	}

	@Override
	public IResource getResource() {
		return this.project;
	}

	protected JavaResourceTypeCache buildExternalJavaResourceTypeCache() {
		return new BinaryTypeCache(this.jpaPlatform.getAnnotationProvider());
	}

	protected JpaRootContextNode buildRootContextNode() {
		return this.getJpaFactory().buildRootContextNode(this);
	}

	/**
	 * Execute a synchronous <em>sync</em> and <em>update</em> before returning
	 * from the constructor.
	 */
	protected void initializeContextModel() {
		// there *shouldn't* be any changes to the resource model yet...
		this.synchronizeContextModelCommand.start();

		// perform a synchronous update...
		this.updateCommand.start();
		this.update();
		try {
			this.updateCommand.stop();
		} catch (InterruptedException ex) {
			// the initial update is synchronous, so this shouldn't happen...
			// but let our thread know it was interrupted during a wait
			Thread.currentThread().interrupt();
		}

		// ...then delegate further updates to the JPA project manager
		this.updateCommand = this.buildUpdateCommand();
		this.updateCommand.addListener(this.updateCommandListener);
		this.updateCommand.start();
	}


	// ********** initial resource proxy visitor **********

	protected InitialResourceProxyVisitor buildInitialResourceProxyVisitor() {
		return new InitialResourceProxyVisitor();
	}

	protected class InitialResourceProxyVisitor
		implements IResourceProxyVisitor
	{
		protected InitialResourceProxyVisitor() {
			super();
		}
		protected void visitProject(IProject p) {
			try {
				p.accept(this, IResource.NONE);
			} catch (CoreException ex) {
				// shouldn't happen - we don't throw any CoreExceptions
				throw new RuntimeException(ex);
			}
		}
		// add a JPA file for every [appropriate] file encountered by the visitor
		public boolean visit(IResourceProxy resource) {
			switch (resource.getType()) {
				case IResource.ROOT :  // shouldn't happen
					return true;  // visit children
				case IResource.PROJECT :
					return true;  // visit children
				case IResource.FOLDER :
					return true;  // visit children
				case IResource.FILE :
					AbstractJpaProject.this.addJpaFile_((IFile) resource.requestResource());
					return false;  // no children
				default :
					return false;  // no children
			}
		}
		@Override
		public String toString() {
			return StringTools.buildToStringFor(this, AbstractJpaProject.this);
		}
	}


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

	/**
	 * Ignore changes to this collection. Adds can be ignored since they are triggered
	 * by requests that will, themselves, trigger updates (typically during the
	 * update of an object that calls a setter with the newly-created resource
	 * type). Deletes will be accompanied by manual updates.
	 */
	@Override
	protected void addNonUpdateAspectNamesTo(Set<String> nonUpdateAspectNames) {
		super.addNonUpdateAspectNamesTo(nonUpdateAspectNames);
		nonUpdateAspectNames.add(EXTERNAL_JAVA_RESOURCE_COMPILATION_UNITS_COLLECTION);
	}


	// ********** general queries **********

	@Override
	public JpaProject getJpaProject() {
		return this;
	}

	public Manager getManager() {
		return this.manager;
	}

	public String getName() {
		return this.project.getName();
	}

	@Override
	public void toString(StringBuilder sb) {
		sb.append(this.getName());
	}

	public IProject getProject() {
		return this.project;
	}

	@Override
	public IJavaProject getJavaProject() {
		return JavaCore.create(this.project);
	}

	@Override
	public JpaPlatform getJpaPlatform() {
		return this.jpaPlatform;
	}

	@SuppressWarnings("unchecked")
	protected Iterable<JavaResourceCompilationUnit> getCombinedJavaResourceCompilationUnits() {
		return new CompositeIterable<JavaResourceCompilationUnit>(
					this.getInternalJavaResourceCompilationUnits(),
					this.getExternalJavaResourceCompilationUnits()
				);
	}


	// ********** database **********

	@Override
	public JpaDataSource getDataSource() {
		return this.dataSource;
	}

	public ConnectionProfile getConnectionProfile() {
		return this.dataSource.getConnectionProfile();
	}

	/**
	 * If we don't have a catalog (i.e. we don't even have a <em>default</em>
	 * catalog), then the database probably does not support catalogs.
	 */
	public Catalog getDefaultDbCatalog() {
		String catalog = this.getDefaultCatalog();
		return (catalog == null) ? null : this.resolveDbCatalog(catalog);
	}

	public String getDefaultCatalog() {
		String catalog = this.getUserOverrideDefaultCatalog();
		return (catalog != null) ? catalog : this.getDatabaseDefaultCatalog();
	}

	protected String getDatabaseDefaultCatalog() {
		Database db = this.getDatabase();
		return (db == null ) ? null : db.getDefaultCatalogIdentifier();
	}

	/**
	 * If we don't have a catalog (i.e. we don't even have a <em>default</em> catalog),
	 * then the database probably does not support catalogs; and we need to
	 * get the schema directly from the database.
	 */
	public SchemaContainer getDefaultDbSchemaContainer() {
		String catalog = this.getDefaultCatalog();
		return (catalog != null) ? this.resolveDbCatalog(catalog) : this.getDatabase();
	}

	public Schema getDefaultDbSchema() {
		SchemaContainer sc = this.getDefaultDbSchemaContainer();
		return (sc == null) ? null : sc.getSchemaForIdentifier(this.getDefaultSchema());
	}

	public String getDefaultSchema() {
		String schema = this.getUserOverrideDefaultSchema();
		if (schema != null) {
			return schema;
		}

		String catalog = this.getDefaultCatalog();
		if (catalog == null) {
			// if there is no default catalog (either user-override or database-determined),
			// the database probably does not support catalogs;
			// return the database's default schema
			return this.getDatabaseDefaultSchema();
		}

		Catalog dbCatalog = this.resolveDbCatalog(catalog);
		if (dbCatalog != null) {
			return dbCatalog.getDefaultSchemaIdentifier();
		}

		// if we could not find a catalog on the database that matches the default
		// catalog name, return the database's default schema(?) - hmmm
		return this.getDatabaseDefaultSchema();
	}

	protected String getDatabaseDefaultSchema() {
		Database db = this.getDatabase();
		return (db == null ) ? null : db.getDefaultSchemaIdentifier();
	}


	// ********** user override default catalog **********

	public String getUserOverrideDefaultCatalog() {
		return this.userOverrideDefaultCatalog;
	}

	public void setUserOverrideDefaultCatalog(String catalog) {
		String old = this.userOverrideDefaultCatalog;
		this.userOverrideDefaultCatalog = catalog;
		JptJpaCorePlugin.setUserOverrideDefaultCatalog(this.project, catalog);
		this.firePropertyChanged(USER_OVERRIDE_DEFAULT_CATALOG_PROPERTY, old, catalog);
	}


	// ********** user override default schema **********

	public String getUserOverrideDefaultSchema() {
		return this.userOverrideDefaultSchema;
	}

	public void setUserOverrideDefaultSchema(String schema) {
		String old = this.userOverrideDefaultSchema;
		this.userOverrideDefaultSchema = schema;
		JptJpaCorePlugin.setUserOverrideDefaultSchema(this.project, schema);
		this.firePropertyChanged(USER_OVERRIDE_DEFAULT_SCHEMA_PROPERTY, old, schema);
	}


	// ********** discover annotated classes **********

	public boolean discoversAnnotatedClasses() {
		return this.discoversAnnotatedClasses;
	}

	public void setDiscoversAnnotatedClasses(boolean discoversAnnotatedClasses) {
		boolean old = this.discoversAnnotatedClasses;
		this.discoversAnnotatedClasses = discoversAnnotatedClasses;
		JptJpaCorePlugin.setDiscoverAnnotatedClasses(this.project, discoversAnnotatedClasses);
		this.firePropertyChanged(DISCOVERS_ANNOTATED_CLASSES_PROPERTY, old, discoversAnnotatedClasses);
	}


	// ********** JPA files **********

	public Iterable<JpaFile> getJpaFiles() {
		return new LiveCloneIterable<JpaFile>(this.jpaFiles);  // read-only
	}

	public int getJpaFilesSize() {
		return this.jpaFiles.size();
	}

	protected Iterable<JpaFile> getJpaFiles(final IContentType contentType) {
		return new FilteringIterable<JpaFile>(this.getJpaFiles()) {
			@Override
			protected boolean accept(JpaFile jpaFile) {
				return jpaFile.getContentType().isKindOf(contentType);
			}
		};
	}

	@Override
	public JpaFile getJpaFile(IFile file) {
		for (JpaFile jpaFile : this.getJpaFiles()) {
			if (jpaFile.getFile().equals(file)) {
				return jpaFile;
			}
		}
		return null;
	}

	/**
	 * Add a JPA file for the specified file, if appropriate.
	 * Return true if a JPA File was created and added, false otherwise
	 */
	protected boolean addJpaFile(IFile file) {
		JpaFile jpaFile = this.addJpaFile_(file);
		if (jpaFile != null) {
			this.fireItemAdded(JPA_FILES_COLLECTION, jpaFile);
			return true;
		}
		return false;
	}

	/**
	 * Add a JPA file for the specified file, if appropriate, without firing
	 * an event; useful during construction.
	 * Return the new JPA file, null if it was not created.
	 */
	protected JpaFile addJpaFile_(IFile file) {
		if (this.fileIsJavaRelated(file)) {
			if ( ! this.getJavaProject().isOnClasspath(file)) {
				return null;  // java-related files must be on the Java classpath
			}
		}
		else if ( ! this.fileResourceLocationIsValid(file)) {
			return null;
		}

		JpaFile jpaFile = this.buildJpaFile(file);
		if (jpaFile == null) {
			return null;
		}
		jpaFile.getResourceModel().addResourceModelListener(this.resourceModelListener);
		this.jpaFiles.add(jpaFile);
		return jpaFile;
	}

	/**
	 * <code>.java</code> or <code>.jar</code>
	 */
	protected boolean fileIsJavaRelated(IFile file) {
		IContentType contentType = PlatformTools.getContentType(file);
		return (contentType != null) && this.contentTypeIsJavaRelated(contentType);
	}

	/**
	 * pre-condition: content type is not <code>null</code>
	 */
	protected boolean contentTypeIsJavaRelated(IContentType contentType) {
		return contentType.isKindOf(JptCommonCorePlugin.JAVA_SOURCE_CONTENT_TYPE) ||
				contentType.isKindOf(JptCommonCorePlugin.JAR_CONTENT_TYPE);
	}

	protected boolean fileResourceLocationIsValid(IFile file) {
		return this.getProjectResourceLocator().resourceLocationIsValid(file.getParent());
	}

	protected ProjectResourceLocator getProjectResourceLocator() {
		return (ProjectResourceLocator) this.project.getAdapter(ProjectResourceLocator.class);
	}
	
	/**
	 * Log any developer exceptions and don't build a JPA file rather
	 * than completely failing to build the JPA Project.
	 */
	protected JpaFile buildJpaFile(IFile file) {
		try {
			return this.getJpaPlatform().buildJpaFile(this, file);
		} catch (Exception ex) {
			JptJpaCorePlugin.log("Error building JPA file: " + file.getFullPath(), ex); //$NON-NLS-1$
			return null;
		}
	}

	/**
	 * Remove the JPA file corresponding to the specified IFile, if it exists.
	 * Return true if a JPA File was removed, false otherwise
	 */
	protected boolean removeJpaFile(IFile file) {
		JpaFile jpaFile = this.getJpaFile(file);
		if (jpaFile != null) {  // a JpaFile is not added for every IFile
			this.removeJpaFile(jpaFile);
			return true;
		}
		return false;
	}

	/**
	 * Stop listening to the JPA file and remove it.
	 */
	protected void removeJpaFile(JpaFile jpaFile) {
		jpaFile.getResourceModel().removeResourceModelListener(this.resourceModelListener);
		if ( ! this.removeItemFromCollection(jpaFile, this.jpaFiles, JPA_FILES_COLLECTION)) {
			throw new IllegalArgumentException(jpaFile.toString());
		}
	}


	// ********** external Java resource types (source or binary) **********

	protected JavaResourceAbstractType buildExternalJavaResourceType(String typeName) {
		IType jdtType = this.findType(typeName);
		return (jdtType == null) ? null : this.buildExternalJavaResourceType(jdtType);
	}

	protected IType findType(String typeName) {
		try {
			return this.getJavaProject().findType(typeName);
		} catch (JavaModelException ex) {
			return null;  // ignore exception?
		}
	}

	protected JavaResourceAbstractType buildExternalJavaResourceType(IType jdtType) {
		return jdtType.isBinary() ?
				this.buildBinaryExternalJavaResourceType(jdtType) :
				this.buildSourceExternalJavaResourceType(jdtType);
	}

	protected JavaResourceAbstractType buildBinaryExternalJavaResourceType(IType jdtType) {
		return this.externalJavaResourceTypeCache.addType(jdtType);
	}

	protected JavaResourceAbstractType buildSourceExternalJavaResourceType(IType jdtType) {
		JavaResourceCompilationUnit jrcu = this.getExternalJavaResourceCompilationUnit(jdtType.getCompilationUnit());
		String jdtTypeName = jdtType.getFullyQualifiedName('.');  // JDT member type names use '$'
		for (JavaResourceAbstractType jrat : jrcu.getTypes()) {
			if (jrat.getQualifiedName().equals(jdtTypeName)) {
				return jrat;
			}
		}
		// we can get here if the project JRE is removed;
		// see SourceCompilationUnit#getPrimaryType(CompilationUnit)
		// bug 225332
		return null;
	}


	// ********** external Java resource persistent types (binary) **********

	public JavaResourceTypeCache getExternalJavaResourceTypeCache() {
		return this.externalJavaResourceTypeCache;
	}


	// ********** external Java resource compilation units (source) **********

	public Iterable<JavaResourceCompilationUnit> getExternalJavaResourceCompilationUnits() {
		return new LiveCloneIterable<JavaResourceCompilationUnit>(this.externalJavaResourceCompilationUnits);  // read-only
	}

	public int getExternalJavaResourceCompilationUnitsSize() {
		return this.externalJavaResourceCompilationUnits.size();
	}

	/**
	 * Return the resource model compilation unit corresponding to the specified
	 * JDT compilation unit. If it does not exist, build it.
	 */
	protected JavaResourceCompilationUnit getExternalJavaResourceCompilationUnit(ICompilationUnit jdtCompilationUnit) {
		for (JavaResourceCompilationUnit jrcu : this.getExternalJavaResourceCompilationUnits()) {
			if (jrcu.getCompilationUnit().equals(jdtCompilationUnit)) {
				// we will get here if the JRCU could not build its persistent type...
				return jrcu;
			}
		}
		return this.addExternalJavaResourceCompilationUnit(jdtCompilationUnit);
	}

	/**
	 * Add an external Java resource compilation unit.
	 */
	protected JavaResourceCompilationUnit addExternalJavaResourceCompilationUnit(ICompilationUnit jdtCompilationUnit) {
		JavaResourceCompilationUnit jrcu = this.buildJavaResourceCompilationUnit(jdtCompilationUnit);
		this.addItemToCollection(jrcu, this.externalJavaResourceCompilationUnits, EXTERNAL_JAVA_RESOURCE_COMPILATION_UNITS_COLLECTION);
		jrcu.addResourceModelListener(this.resourceModelListener);
		return jrcu;
	}

	protected JavaResourceCompilationUnit buildJavaResourceCompilationUnit(ICompilationUnit jdtCompilationUnit) {
		return new SourceTypeCompilationUnit(
					jdtCompilationUnit,
					this.jpaPlatform.getAnnotationProvider(),
					this.jpaPlatform.getAnnotationEditFormatter(),
					this.manager.getModifySharedDocumentCommandExecutor()
				);
	}

	protected boolean removeExternalJavaResourceCompilationUnit(IFile file) {
		for (JavaResourceCompilationUnit jrcu : this.getExternalJavaResourceCompilationUnits()) {
			if (jrcu.getFile().equals(file)) {
				this.removeExternalJavaResourceCompilationUnit(jrcu);
				return true;
			}
		}
		return false;
	}

	protected void removeExternalJavaResourceCompilationUnit(JavaResourceCompilationUnit jrcu) {
		jrcu.removeResourceModelListener(this.resourceModelListener);
		this.removeItemFromCollection(jrcu, this.externalJavaResourceCompilationUnits, EXTERNAL_JAVA_RESOURCE_COMPILATION_UNITS_COLLECTION);
	}


	// ********** context model **********

	public JpaRootContextNode getRootContextNode() {
		return this.rootContextNode;
	}


	// ********** utility **********

	public IFile getPlatformFile(IPath runtimePath) {
		return this.getProjectResourceLocator().getPlatformFile(runtimePath);
	}


	// ********** XML files **********

	public JpaXmlResource getPersistenceXmlResource() {
		return (JpaXmlResource) this.getResourceModel(
				JptJpaCorePlugin.DEFAULT_PERSISTENCE_XML_RUNTIME_PATH,
				JptJpaCorePlugin.PERSISTENCE_XML_CONTENT_TYPE
			);
	}

	public JpaXmlResource getDefaultOrmXmlResource() {
		return this.getMappingFileXmlResource(JptJpaCorePlugin.DEFAULT_ORM_XML_RUNTIME_PATH);
	}

	public JpaXmlResource getMappingFileXmlResource(IPath runtimePath) {
		return (JpaXmlResource) this.getResourceModel(runtimePath, JptJpaCorePlugin.MAPPING_FILE_CONTENT_TYPE);
	}

	/**
	 * If the specified file exists, is significant to the JPA project, and its
	 * content is a "kind of" the specified content type, return the JPA
	 * resource model corresponding to the file; otherwise, return null.
	 */
	protected JptResourceModel getResourceModel(IPath runtimePath, IContentType contentType) {
		IFile file = this.getPlatformFile(runtimePath);
		return ((file != null) && file.exists()) ? this.getResourceModel(file, contentType) :  null;
	}

	/**
	 * If the specified file is significant to the JPA project and its content
	 * is a "kind of" the specified content type, return the JPA resource model
	 * corresponding to the file; otherwise, return null.
	 */
	protected JptResourceModel getResourceModel(IFile file, IContentType contentType) {
		JpaFile jpaFile = this.getJpaFile(file);
		return (jpaFile == null) ? null : jpaFile.getResourceModel(contentType);
	}


	// ********** annotated Java source classes **********

	public Iterable<String> getAnnotatedJavaSourceClassNames() {
		return new TransformationIterable<JavaResourceAbstractType, String>(this.getInternalAnnotatedSourceJavaResourceTypes()) {
			@Override
			protected String transform(JavaResourceAbstractType jraType) {
				return jraType.getQualifiedName();
			}
		};
	}

	/**
	 * Return only those valid annotated Java resource persistent types that are
	 * directly part of the JPA project, ignoring those in JARs referenced in
	 * <code>persistence.xml</code>.
	 * @see org.eclipse.jpt.common.core.internal.utility.jdt.JPTTools#typeIsPersistable(org.eclipse.jpt.common.core.internal.utility.jdt.JPTTools.TypeAdapter)
	 */
	protected Iterable<JavaResourceAbstractType> getInternalAnnotatedSourceJavaResourceTypes() {
		return new FilteringIterable<JavaResourceAbstractType>(this.getInternalSourceJavaResourceTypes()) {
			@Override
			protected boolean accept(JavaResourceAbstractType jraType) {
				return jraType.isAnnotated();  // i.e. the type has a valid type annotation
			}
		};
	}

	/**
	 * Return only the names of those valid <em>mapped</em> (i.e. annotated with
	 * <code>@Entity</code>, <code>@Embeddable</code>, etc.) Java resource
	 * persistent types that are directly part of the JPA project, ignoring
	 * those in JARs referenced in <code>persistence.xml</code>.
	 */
	public Iterable<String> getMappedJavaSourceClassNames() {
		return new TransformationIterable<JavaResourceAbstractType, String>(this.getInternalMappedSourceJavaResourceTypes()) {
			@Override
			protected String transform(JavaResourceAbstractType jraType) {
				return jraType.getQualifiedName();
			}
		};
	}

	/**
	 * Return only those valid <em>mapped</em> (i.e. annotated with
	 * <code>@Entity</code>, <code>@Embeddable</code>, etc.) Java resource
	 * persistent types that are directly part of the JPA project, ignoring
	 * those in JARs referenced in <code>persistence.xml</code>.
	 */
	protected Iterable<JavaResourceAbstractType> getInternalMappedSourceJavaResourceTypes() {
		final Iterable<String> typeMappingAnnotationNames = this.getTypeMappingAnnotationNames();
		return new FilteringIterable<JavaResourceAbstractType>(this.getInternalAnnotatedSourceJavaResourceTypes()) {
			@Override
			protected boolean accept(JavaResourceAbstractType jraType) {
				return jraType.isAnnotatedWithAnyOf(typeMappingAnnotationNames);
			}
		};
	}

	public Iterable<String> getTypeMappingAnnotationNames() {
		return new TransformationIterable<JavaTypeMappingDefinition, String>(this.getJpaPlatform().getJavaTypeMappingDefinitions()) {
			@Override
			protected String transform(JavaTypeMappingDefinition o) {
				return o.getAnnotationName();
			}
		};
	}

	/**
	 * Return only those Java resource persistent types that are directly
	 * part of the JPA project, ignoring those in JARs referenced in
	 * <code>persistence.xml</code>
	 */
	protected Iterable<JavaResourceAbstractType> getInternalSourceJavaResourceTypes() {
		return new CompositeIterable<JavaResourceAbstractType>(this.getInternalSourceJavaResourceTypeLists());
	}

	/**
	 * Return only those Java resource persistent types that are directly
	 * part of the JPA project, ignoring those in JARs referenced in
	 * <code>persistence.xml</code>
	 */
	protected Iterable<Iterable<JavaResourceAbstractType>> getInternalSourceJavaResourceTypeLists() {
		return new TransformationIterable<JavaResourceCompilationUnit, Iterable<JavaResourceAbstractType>>(this.getInternalJavaResourceCompilationUnits()) {
			@Override
			protected Iterable<JavaResourceAbstractType> transform(final JavaResourceCompilationUnit compilationUnit) {
				return compilationUnit.getTypes();  // *all* the types in the compilation unit
			}
		};
	}

	/**
	 * Return the JPA project's resource compilation units.
	 */
	protected Iterable<JavaResourceCompilationUnit> getInternalJavaResourceCompilationUnits() {
		return new TransformationIterable<JpaFile, JavaResourceCompilationUnit>(this.getJavaSourceJpaFiles()) {
			@Override
			protected JavaResourceCompilationUnit transform(JpaFile jpaFile) {
				return (JavaResourceCompilationUnit) jpaFile.getResourceModel();
			}
		};
	}

	/**
	 * Return the JPA project's JPA files with Java source <em>content</em>.
	 */
	protected Iterable<JpaFile> getJavaSourceJpaFiles() {
		return this.getJpaFiles(JptCommonCorePlugin.JAVA_SOURCE_CONTENT_TYPE);
	}


	// ********** Java resource persistent type look-up **********

	public JavaResourceAbstractType getJavaResourceType(String typeName) {
		for (JavaResourceAbstractType jraType : this.getJavaResourceTypes()) {
			if (jraType.getQualifiedName().equals(typeName)) {
				return jraType;
			}
		}
		// if we don't have a type already, try to build new one from the project classpath
		return this.buildExternalJavaResourceType(typeName);
	}

	public JavaResourceAbstractType getJavaResourceType(String typeName, JavaResourceAbstractType.Kind kind) {
		JavaResourceAbstractType resourceType = this.getJavaResourceType(typeName);
		if ((resourceType == null) || (resourceType.getKind() != kind)) {
			return null;
		}
		return resourceType;
	}


	/**
	 * return *all* the Java resource persistent types, including those in JARs referenced in
	 * persistence.xml
	 */
	protected Iterable<JavaResourceAbstractType> getJavaResourceTypes() {
		return new CompositeIterable<JavaResourceAbstractType>(this.getJavaResourceTypeSets());
	}

	/**
	 * return *all* the Java resource persistent types, including those in JARs referenced in
	 * persistence.xml
	 */
	protected Iterable<Iterable<JavaResourceAbstractType>> getJavaResourceTypeSets() {
		return new TransformationIterable<JavaResourceNode.Root, Iterable<JavaResourceAbstractType>>(this.getJavaResourceNodeRoots()) {
			@Override
			protected Iterable<JavaResourceAbstractType> transform(final JavaResourceNode.Root root) {
				return root.getTypes();  // *all* the types held by the root
			}
		};
	}

	@SuppressWarnings("unchecked")
	protected Iterable<JavaResourceNode.Root> getJavaResourceNodeRoots() {
		return new CompositeIterable<JavaResourceNode.Root>(
					this.getInternalJavaResourceCompilationUnits(),
					this.getInternalJavaResourcePackageFragmentRoots(),
					this.getExternalJavaResourceCompilationUnits(),
					Collections.singleton(this.externalJavaResourceTypeCache)
				);
	}


	// ********** Java resource persistent package look-up **********

	public JavaResourcePackage getJavaResourcePackage(String packageName) {
		for (JavaResourcePackage jrp : this.getJavaResourcePackages()) {
			if (jrp.getName().equals(packageName)) {
				return jrp;
			}
		}
		return null;
	}

	public Iterable<JavaResourcePackage> getJavaResourcePackages(){
		return new FilteringIterable<JavaResourcePackage>(
				new TransformationIterable<JpaFile, JavaResourcePackage>(this.getPackageInfoSourceJpaFiles()) {
				@Override
				protected JavaResourcePackage transform(JpaFile jpaFile) {
					return ((JavaResourcePackageInfoCompilationUnit) jpaFile.getResourceModel()).getPackage();
				}
			})
			{
			@Override
			protected boolean accept(JavaResourcePackage packageInfo) {
				return packageInfo != null;
			}
		};
	}

	/**
	 * return JPA files with package-info source "content"
	 */
	protected Iterable<JpaFile> getPackageInfoSourceJpaFiles() {
		return this.getJpaFiles(JptCommonCorePlugin.JAVA_SOURCE_PACKAGE_INFO_CONTENT_TYPE);
	}


	// ********** JARs **********

	// TODO
	public JavaResourcePackageFragmentRoot getJavaResourcePackageFragmentRoot(String jarFileName) {
//		return this.getJarResourcePackageFragmentRoot(this.convertToPlatformFile(jarFileName));
		return this.getJavaResourcePackageFragmentRoot(this.project.getFile(jarFileName));
	}

	protected JavaResourcePackageFragmentRoot getJavaResourcePackageFragmentRoot(IFile jarFile) {
		for (JavaResourcePackageFragmentRoot pfr : this.getInternalJavaResourcePackageFragmentRoots()) {
			if (pfr.getFile().equals(jarFile)) {
				return pfr;
			}
		}
		return null;
	}

	protected Iterable<JavaResourcePackageFragmentRoot> getInternalJavaResourcePackageFragmentRoots() {
		return new TransformationIterable<JpaFile, JavaResourcePackageFragmentRoot>(this.getJarJpaFiles()) {
			@Override
			protected JavaResourcePackageFragmentRoot transform(JpaFile jpaFile) {
				return (JavaResourcePackageFragmentRoot) jpaFile.getResourceModel();
			}
		};
	}

	/**
	 * return JPA files with JAR "content"
	 */
	public Iterable<JpaFile> getJarJpaFiles() {
		return this.getJpaFiles(JptCommonCorePlugin.JAR_CONTENT_TYPE);
	}


	// ********** metamodel **********

	public Iterable<JavaResourceAbstractType> getGeneratedMetamodelTopLevelTypes() {
		if (this.metamodelSourceFolderName == null) {
			return EmptyIterable.instance();
		}
		final IPackageFragmentRoot genSourceFolder = this.getMetamodelPackageFragmentRoot();
		return new FilteringIterable<JavaResourceAbstractType>(this.getInternalSourceJavaResourceTypes()) {
			@Override
			protected boolean accept(JavaResourceAbstractType jrat) {
				return MetamodelTools.isGeneratedMetamodelTopLevelType(jrat, genSourceFolder);
			}
		};
	}

	public JavaResourceAbstractType getGeneratedMetamodelTopLevelType(IFile file) {
		JavaResourceCompilationUnit jrcu = this.getJavaResourceCompilationUnit(file);
		if (jrcu == null) {
			return null;  // hmmm...
		}
		JavaResourceAbstractType primaryType = jrcu.getPrimaryType();
		if (primaryType == null) {
			return null;  // no types in the file
		}
		return MetamodelTools.isGeneratedMetamodelTopLevelType(primaryType) ? primaryType : null;
	}

	protected JavaResourceCompilationUnit getJavaResourceCompilationUnit(IFile file) {
		return (JavaResourceCompilationUnit) this.getResourceModel(file, JptCommonCorePlugin.JAVA_SOURCE_CONTENT_TYPE);
	}

	public String getMetamodelSourceFolderName() {
		return this.metamodelSourceFolderName;
	}

	public void setMetamodelSourceFolderName(String folderName) {
		if (this.setMetamodelSourceFolderName_(folderName)) {
			JptJpaCorePlugin.setMetamodelSourceFolderName(this.project, folderName);
			if (folderName == null) {
				this.disposeMetamodel();
			} else {
				this.initializeMetamodel();
			}
		}
	}

	protected boolean setMetamodelSourceFolderName_(String folderName) {
		String old = this.metamodelSourceFolderName;
		this.metamodelSourceFolderName = folderName;
		return this.firePropertyChanged(METAMODEL_SOURCE_FOLDER_NAME_PROPERTY, old, folderName);
	}

	public void initializeMetamodel() {
		if (this.isJpa2_0Compatible()) {
			((JpaRootContextNode2_0) this.rootContextNode).initializeMetamodel();
		}
	}

	/**
	 * Synchronize the metamodel for 2.0-compatible JPA projects.
	 */
	public IStatus synchronizeMetamodel(IProgressMonitor monitor) {
		if (this.isJpa2_0Compatible()) {
			if (this.metamodelSourceFolderName != null) {
				this.scheduleSynchronizeMetamodelJob();
			}
		}
		return Status.OK_STATUS;
	}

	/**
	 * We dispatch a job even when the JPA project manager is "synchronous"
	 * because we will synchronously execute an update when we receive a
	 * resource change event that is fired when a file is changed; and we
	 * cannot modify another file in response to a file change because the
	 * rules are incompatible. For example, if the <code>persistence.xml</code>
	 * file changes, we will receive a resource change event while the
	 * <code>persistence.xml</code> file is locked. We will not be able to
	 * lock and modify the necessary metamodel source files under this lock.
	 */
	protected void scheduleSynchronizeMetamodelJob() {
		this.buildSynchronizeMetamodelJob().schedule();
	}

	protected Job buildSynchronizeMetamodelJob() {
		Job job = this.buildSynchronizeMetamodelJob_();
		// lock the project so we are synchronized with the JPA project manager
		job.setRule(this.project);
		return job;
	}

	protected Job buildSynchronizeMetamodelJob_() {
		return new SynchronizeMetamodelJob(this.buildSynchronizeMetamodelJobName());
	}

	protected String buildSynchronizeMetamodelJobName() {
		return NLS.bind(JptCoreMessages.METAMODEL_SYNC_JOB_NAME, this.getName());
	}

	/**
	 * Use a {@link WorkspaceJob} to
	 * suppress the resource change events until we are finished synchronizing
	 * the metamodel.
	 */
	protected class SynchronizeMetamodelJob
		extends WorkspaceJob
	{
		protected SynchronizeMetamodelJob(String name) {
			super(name);
		}
		@Override
		public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
			return AbstractJpaProject.this.synchronizeMetamodel_(monitor);
		}
		@Override
		public String toString() {
			return StringTools.buildToStringFor(this, AbstractJpaProject.this);
		}
	}

	/**
	 * Called by the {@link SynchronizeMetamodelJob#runInWorkspace(IProgressMonitor)}.
	 */
	protected IStatus synchronizeMetamodel_(IProgressMonitor monitor) {
		return ((JpaRootContextNode2_0) this.rootContextNode).synchronizeMetamodel(monitor);
	}

	public void disposeMetamodel() {
		if (this.isJpa2_0Compatible()) {
			((JpaRootContextNode2_0) this.rootContextNode).disposeMetamodel();
		}
	}

	public IPackageFragmentRoot getMetamodelPackageFragmentRoot() {
		return this.getJavaProject().getPackageFragmentRoot(this.getMetaModelSourceFolder());
	}

	protected IFolder getMetaModelSourceFolder() {
		return this.project.getFolder(this.metamodelSourceFolderName);
	}

	/**
	 * If the metamodel source folder is no longer a Java project source
	 * folder, clear it out.
	 */
	protected void checkMetamodelSourceFolderName() {
		if (this.metamodelSoureFolderNameIsInvalid()) {
			this.setMetamodelSourceFolderName(null);
		}
	}

	protected boolean metamodelSoureFolderNameIsInvalid() {
		return ! this.metamodelSourceFolderNameIsValid();
	}

	protected boolean metamodelSourceFolderNameIsValid() {
		return CollectionTools.contains(this.getJavaSourceFolderNames(), this.metamodelSourceFolderName);
	}


	// ********** Java source folder names **********

	public Iterable<String> getJavaSourceFolderNames() {
		try {
			return this.getJavaSourceFolderNames_();
		} catch (JavaModelException ex) {
			JptJpaCorePlugin.log(ex);
			return EmptyIterable.instance();
		}
	}

	protected Iterable<String> getJavaSourceFolderNames_() throws JavaModelException {
		return new TransformationIterable<IPackageFragmentRoot, String>(this.getJavaSourceFolders()) {
			@Override
			protected String transform(IPackageFragmentRoot pfr) {
				try {
					return this.transform_(pfr);
				} catch (JavaModelException ex) {
					return "Error: " + pfr.getPath(); //$NON-NLS-1$
				}
			}
			private String transform_(IPackageFragmentRoot pfr) throws JavaModelException {
				return pfr.getUnderlyingResource().getProjectRelativePath().toString();
			}
		};
	}

	protected Iterable<IPackageFragmentRoot> getJavaSourceFolders() throws JavaModelException {
		return new FilteringIterable<IPackageFragmentRoot>(
				this.getPackageFragmentRoots(),
				SOURCE_PACKAGE_FRAGMENT_ROOT_FILTER
			);
	}

	protected static final Filter<IPackageFragmentRoot> SOURCE_PACKAGE_FRAGMENT_ROOT_FILTER =
		new Filter<IPackageFragmentRoot>() {
			public boolean accept(IPackageFragmentRoot pfr) {
				try {
					return this.accept_(pfr);
				} catch (JavaModelException ex) {
					return false;
				}
			}
			private boolean accept_(IPackageFragmentRoot pfr) throws JavaModelException {
				return pfr.exists() && (pfr.getKind() == IPackageFragmentRoot.K_SOURCE);
			}
		};

	protected Iterable<IPackageFragmentRoot> getPackageFragmentRoots() throws JavaModelException {
		return new ArrayIterable<IPackageFragmentRoot>(this.getJavaProject().getPackageFragmentRoots());
	}


	// ********** Java events **********

	// TODO handle changes to external projects
	public void javaElementChanged(ElementChangedEvent event) {
		this.processJavaDelta(event.getDelta());
	}

	/**
	 * We recurse back here from {@link #processJavaDeltaChildren(IJavaElementDelta)}.
	 */
	protected void processJavaDelta(IJavaElementDelta delta) {
		switch (delta.getElement().getElementType()) {
			case IJavaElement.JAVA_MODEL :
				this.processJavaModelDelta(delta);
				break;
			case IJavaElement.JAVA_PROJECT :
				this.processJavaProjectDelta(delta);
				break;
			case IJavaElement.PACKAGE_FRAGMENT_ROOT :
				this.processJavaPackageFragmentRootDelta(delta);
				break;
			case IJavaElement.PACKAGE_FRAGMENT :
				this.processJavaPackageFragmentDelta(delta);
				break;
			case IJavaElement.COMPILATION_UNIT :
				this.processJavaCompilationUnitDelta(delta);
				break;
			default :
				break; // ignore the elements inside a compilation unit
		}
	}

	protected void processJavaDeltaChildren(IJavaElementDelta delta) {
		for (IJavaElementDelta child : delta.getAffectedChildren()) {
			this.processJavaDelta(child); // recurse
		}
	}

	/**
	 * Return whether the specified Java element delta is for a
	 * {@link IJavaElementDelta#CHANGED CHANGED}
	 * (as opposed to {@link IJavaElementDelta#ADDED ADDED} or
	 * {@link IJavaElementDelta#REMOVED REMOVED}) Java element
	 * and the specified flag is set.
	 * (The delta flags are only significant if the delta
	 * {@link IJavaElementDelta#getKind() kind} is
	 * {@link IJavaElementDelta#CHANGED CHANGED}.)
	 */
	protected boolean deltaFlagIsSet(IJavaElementDelta delta, int flag) {
		return (delta.getKind() == IJavaElementDelta.CHANGED) &&
				BitTools.flagIsSet(delta.getFlags(), flag);
	}

	// ***** model
	protected void processJavaModelDelta(IJavaElementDelta delta) {
		// process the Java model's projects
		this.processJavaDeltaChildren(delta);
	}

	// ***** project
	protected void processJavaProjectDelta(IJavaElementDelta delta) {
		// process the Java project's package fragment roots
		this.processJavaDeltaChildren(delta);

		// a classpath change can have pretty far-reaching effects...
		if (this.classpathHasChanged(delta)) {
			this.rebuild((IJavaProject) delta.getElement());
		}
	}

	/**
	 * The specified Java project's classpath changed. Rebuild the JPA project
	 * as appropriate.
	 */
	protected void rebuild(IJavaProject javaProject) {
		// if the classpath has changed, we need to update everything since
		// class references could now be resolved (or not) etc.
		if (javaProject.equals(this.getJavaProject())) {
			this.removeDeadJpaFiles();
			this.checkMetamodelSourceFolderName();
			this.synchronizeWithJavaSource(this.getInternalJavaResourceCompilationUnits());
		} else {
			// TODO see if changed project is on our classpath?
			this.synchronizeWithJavaSource(this.getExternalJavaResourceCompilationUnits());
		}
	}

	/**
	 * Loop through all our JPA files, remove any that are no longer on the
	 * classpath.
	 */
	protected void removeDeadJpaFiles() {
		for (JpaFile jpaFile : this.getJpaFiles()) {
			if (this.jpaFileIsDead(jpaFile)) {
				this.removeJpaFile(jpaFile);
			}
		}
	}

	protected boolean jpaFileIsDead(JpaFile jpaFile) {
		return ! this.jpaFileIsAlive(jpaFile);
	}

	/**
	 * Sometimes (e.g. during tests), when a project has been deleted, we get a
	 * Java change event that indicates the Java project is CHANGED (as
	 * opposed to REMOVED, which is what typically happens). The event's delta
	 * indicates that everything in the Java project has been deleted and the
	 * classpath has changed. All entries in the classpath have been removed;
	 * but single entry for the Java project's root folder has been added. (!)
	 * This means any file in the project is on the Java project's classpath.
	 * This classpath change is what triggers us to rebuild the JPA project; so
	 * we put an extra check here to make sure the JPA file's resource file is
	 * still present.
	 * <p>
	 * This would not be a problem if Dali received the resource change event
	 * <em>before</em> JDT and simply removed the JPA project; but JDT receives
	 * the resource change event first and converts it into the problematic
	 * Java change event....
	 */
	protected boolean jpaFileIsAlive(JpaFile jpaFile) {
		IFile file = jpaFile.getFile();
		if ( ! file.exists()) {
			return false;
		}
		if (this.fileIsJavaRelated(file)) {
			return this.getJavaProject().isOnClasspath(file);
		}
		return this.fileResourceLocationIsValid(file);
	}

	/**
	 * pre-condition:
	 * delta.getElement().getElementType() == IJavaElement.JAVA_PROJECT
	 */
	protected boolean classpathHasChanged(IJavaElementDelta delta) {
		return this.deltaFlagIsSet(delta, IJavaElementDelta.F_RESOLVED_CLASSPATH_CHANGED);
	}

	protected void synchronizeWithJavaSource(Iterable<JavaResourceCompilationUnit> javaResourceCompilationUnits) {
		for (JavaResourceCompilationUnit javaResourceCompilationUnit : javaResourceCompilationUnits) {
			javaResourceCompilationUnit.synchronizeWithJavaSource();
		}
	}

	// ***** package fragment root
	protected void processJavaPackageFragmentRootDelta(IJavaElementDelta delta) {
		// process the Java package fragment root's package fragments
		this.processJavaDeltaChildren(delta);

		if (this.classpathEntryHasBeenAdded(delta)) {
			// TODO bug 277218
		} else if (this.classpathEntryHasBeenRemoved(delta)) {  // should be mutually-exclusive w/added (?)
			// TODO bug 277218
		}
	}

	/**
	 * pre-condition:
	 * delta.getElement().getElementType() == IJavaElement.PACKAGE_FRAGMENT_ROOT
	 */
	protected boolean classpathEntryHasBeenAdded(IJavaElementDelta delta) {
		return this.deltaFlagIsSet(delta, IJavaElementDelta.F_ADDED_TO_CLASSPATH);
	}

	/**
	 * pre-condition:
	 * delta.getElement().getElementType() == IJavaElement.PACKAGE_FRAGMENT_ROOT
	 */
	protected boolean classpathEntryHasBeenRemoved(IJavaElementDelta delta) {
		return this.deltaFlagIsSet(delta, IJavaElementDelta.F_REMOVED_FROM_CLASSPATH);
	}

	// ***** package fragment
	protected void processJavaPackageFragmentDelta(IJavaElementDelta delta) {
		// process the java package fragment's compilation units
		this.processJavaDeltaChildren(delta);
	}

	// ***** compilation unit
	protected void processJavaCompilationUnitDelta(IJavaElementDelta delta) {
		if (this.javaCompilationUnitDeltaIsRelevant(delta)) {
			ICompilationUnit compilationUnit = (ICompilationUnit) delta.getElement();
			for (JavaResourceCompilationUnit jrcu : this.getCombinedJavaResourceCompilationUnits()) {
				if (jrcu.getCompilationUnit().equals(compilationUnit)) {
					jrcu.synchronizeWithJavaSource();
					// TODO ? this.resolveJavaTypes();  // might have new member types now...
					break;  // there *shouldn't* be any more...
				}
			}
		}
		// ignore the java compilation unit's children
	}

	protected boolean javaCompilationUnitDeltaIsRelevant(IJavaElementDelta delta) {
		// ignore Java notification for ADDED or REMOVED;
		// these are handled via resource notification
		if (delta.getKind() != IJavaElementDelta.CHANGED) {
			return false;
		}

		// ignore changes to/from primary working copy - no content has changed;
		// and make sure there are no other flags set that indicate *both* a
		// change to/from primary working copy *and* content has changed
		if (BitTools.onlyFlagIsSet(delta.getFlags(), IJavaElementDelta.F_PRIMARY_WORKING_COPY)) {
			return false;
		}

		// ignore when the compilation unit's resource is deleted;
		// because the AST parser will log an exception for the missing file
		if (BitTools.onlyFlagIsSet(delta.getFlags(), IJavaElementDelta.F_PRIMARY_RESOURCE)) {
			ICompilationUnit compilationUnit = (ICompilationUnit) delta.getElement();
			if ( ! this.compilationUnitResourceExists(compilationUnit)) {
				return false;
			}
		}

		return true;
	}

	protected boolean compilationUnitResourceExists(ICompilationUnit compilationUnit) {
		try {
			return compilationUnit.getCorrespondingResource().exists();
		} catch (JavaModelException ex) {
			return false;
		}
	}


	// ********** validation **********

	public Iterable<IMessage> getValidationMessages(IReporter reporter) {
		List<IMessage> messages = new ArrayList<IMessage>();
		this.validate(messages, reporter);
		return new SnapshotCloneIterable<IMessage>(messages);
	}

	protected void validate(List<IMessage> messages, IReporter reporter) {
		if (reporter.isCancelled()) {
			throw new ValidationCancelledException();
		}
		this.validateLibraryProvider(messages);
		this.validateConnection(messages);
		this.rootContextNode.validate(messages, reporter);
	}

	protected void validateLibraryProvider(List<IMessage> messages) {
		try {
			this.validateLibraryProvider_(messages);
		} catch (CoreException ex) {
			JptJpaCorePlugin.log(ex);
		}
	}

	protected void validateLibraryProvider_(List<IMessage> messages) throws CoreException {
		Map<String, Object> enablementVariables = new HashMap<String, Object>();
		enablementVariables.put(JpaLibraryProviderInstallOperationConfig.JPA_PLATFORM_ENABLEMENT_EXP, this.getJpaPlatform().getId());
		enablementVariables.put(JpaLibraryProviderInstallOperationConfig.JPA_PLATFORM_DESCRIPTION_ENABLEMENT_EXP, this.getJpaPlatform().getDescription());

		ILibraryProvider libraryProvider = LibraryProviderFramework.getCurrentProvider(this.project, JpaFacet.FACET);
		IFacetedProject facetedProject = ProjectFacetsManager.create(this.project);
		IProjectFacetVersion facetVersion = facetedProject.getInstalledVersion(JpaFacet.FACET);
		if ( ! libraryProvider.isEnabledFor(facetedProject, facetVersion, enablementVariables)) {
			messages.add(
				DefaultJpaValidationMessages.buildMessage(
					IMessage.HIGH_SEVERITY,
					JpaValidationMessages.PROJECT_INVALID_LIBRARY_PROVIDER,
					this
				)
			);
		}
	}

	protected void validateConnection(List<IMessage> messages) {
		String cpName = this.dataSource.getConnectionProfileName();
		if (StringTools.stringIsEmpty(cpName)) {
			messages.add(
				DefaultJpaValidationMessages.buildMessage(
					IMessage.NORMAL_SEVERITY,
					JpaValidationMessages.PROJECT_NO_CONNECTION,
					this
				)
			);
			return;
		}
		ConnectionProfile cp = this.dataSource.getConnectionProfile();
		if (cp == null) {
			messages.add(
				DefaultJpaValidationMessages.buildMessage(
					IMessage.NORMAL_SEVERITY,
					JpaValidationMessages.PROJECT_INVALID_CONNECTION,
					new String[] {cpName},
					this
				)
			);
			return;
		}
		if (cp.isInactive()) {
			messages.add(
				DefaultJpaValidationMessages.buildMessage(
					IMessage.NORMAL_SEVERITY,
					JpaValidationMessages.PROJECT_INACTIVE_CONNECTION,
					new String[] {cpName},
					this
				)
			);
		}
	}


	// ********** dispose **********

	public void dispose() {
		this.stopCommand(this.synchronizeContextModelCommand);
		this.stopCommand(this.updateCommand);
		this.updateCommand.removeListener(this.updateCommandListener);
		this.dataSource.dispose();
		// the XML resources are held indefinitely by the WTP translator framework,
		// so we better remove our listener or the JPA project will not be GCed
		for (JpaFile jpaFile : this.getJpaFiles()) {
			jpaFile.getResourceModel().removeResourceModelListener(this.resourceModelListener);
		}
	}

	protected void stopCommand(RepeatingJobCommand command) {
		try {
			command.stop();
		} catch (InterruptedException ex) {
			// allow the dispose to complete;
			// but let our thread know it was interrupted during a wait
			Thread.currentThread().interrupt();
		}
	}


	// ********** resource model listener **********

	protected JptResourceModelListener buildResourceModelListener() {
		return new ResourceModelListener();
	}

	protected class ResourceModelListener
		implements JptResourceModelListener
	{
		protected ResourceModelListener() {
			super();
		}
		public void resourceModelChanged(JptResourceModel jpaResourceModel) {
//			String msg = Thread.currentThread() + " resource model change: " + jpaResourceModel;
//			System.out.println(msg);
//			new Exception(msg).printStackTrace(System.out);
			AbstractJpaProject.this.synchronizeContextModel(jpaResourceModel);
		}

		public void resourceModelReverted(JptResourceModel jpaResourceModel) {
			IFile file = WorkbenchResourceHelper.getFile((JpaXmlResource)jpaResourceModel);
			AbstractJpaProject.this.removeJpaFile(file);
			AbstractJpaProject.this.addJpaFile(file);
		}

		public void resourceModelUnloaded(JptResourceModel jpaResourceModel) {
			IFile file = WorkbenchResourceHelper.getFile((JpaXmlResource)jpaResourceModel);
			AbstractJpaProject.this.removeJpaFile(file);
		}

		@Override
		public String toString() {
			return StringTools.buildToStringFor(this, AbstractJpaProject.this);
		}
	}

	/**
	 * Called from {@link ResourceModelListener#resourceModelChanged(JptResourceModel)}.
	 */
	// TODO pass down the resource model (for a possible optimization?)
	protected void synchronizeContextModel(@SuppressWarnings("unused") JptResourceModel jpaResourceModel) {
		this.synchronizeContextModel();
	}


	// ********** resource events **********

	// TODO need to do the same thing for external projects and compilation units
	public void projectChanged(IResourceDelta delta) {
		if (delta.getResource().equals(this.project)) {
			this.internalProjectChanged(delta);
		} else {
			this.externalProjectChanged(delta);
		}
	}

	protected void internalProjectChanged(IResourceDelta delta) {
		ResourceDeltaVisitor resourceDeltaVisitor = this.buildInternalResourceDeltaVisitor();
		resourceDeltaVisitor.visitDelta(delta);
		// at this point, if we have added and/or removed JpaFiles, an "update" will have been triggered;
		// any changes to the resource model during the "resolve" will trigger further "updates";
		// there should be no need to "resolve" external Java types (they can't have references to
		// the internal Java types)
		if (resourceDeltaVisitor.encounteredSignificantChange()) {
			this.resolveInternalJavaTypes();
		}
	}

	protected ResourceDeltaVisitor buildInternalResourceDeltaVisitor() {
		return new InternalResourceDeltaVisitor();
	}

	protected class InternalResourceDeltaVisitor
		extends ResourceDeltaVisitor
	{
		protected InternalResourceDeltaVisitor() {
			super();
		}
		@Override
		public boolean fileChangeIsSignificant(IFile file, int deltaKind) {
			return AbstractJpaProject.this.synchronizeJpaFiles(file, deltaKind);
		}
		@Override
		public String toString() {
			return StringTools.buildToStringFor(this, AbstractJpaProject.this);
		}
	}

	/**
	 * Internal resource delta visitor callback.
	 * Return true if a JpaFile was either added or removed.
	 */
	protected boolean synchronizeJpaFiles(IFile file, int deltaKind) {
		switch (deltaKind) {
			case IResourceDelta.ADDED :
				return this.addJpaFile(file);
			case IResourceDelta.REMOVED :
				return this.removeJpaFile(file);
			case IResourceDelta.CHANGED :
				return this.checkForChangedFileContent(file);
			case IResourceDelta.ADDED_PHANTOM :
				break;  // ignore
			case IResourceDelta.REMOVED_PHANTOM :
				break;  // ignore
			default :
				break;  // only worried about added/removed/changed files
		}

		return false;
	}

	protected boolean checkForChangedFileContent(IFile file) {
		JpaFile jpaFile = this.getJpaFile(file);
		if (jpaFile == null) {
			// the file might have changed its content to something significant to Dali
			return this.addJpaFile(file);
		}

		if (jpaFile.getContentType().equals(PlatformTools.getContentType(file))) {
			// content has not changed - ignore
			return false;
		}

		// the content type changed, we need to remove the old JPA file and build a new one
		// (e.g. the schema of an orm.xml file changed from JPA to EclipseLink)
		this.removeJpaFile(jpaFile);
		this.addJpaFile(file);
		return true;  // at the least, we have removed a JPA file
	}

	protected void resolveInternalJavaTypes() {
		for (JavaResourceCompilationUnit jrcu : this.getInternalJavaResourceCompilationUnits()) {
			jrcu.resolveTypes();
		}
	}

	protected void externalProjectChanged(IResourceDelta delta) {
		if (this.getJavaProject().isOnClasspath(delta.getResource())) {
			ResourceDeltaVisitor resourceDeltaVisitor = this.buildExternalResourceDeltaVisitor();
			resourceDeltaVisitor.visitDelta(delta);
			// force an "update" here since adding and/or removing an external Java type
			// will only trigger an "update" if the "resolve" causes something in the resource model to change
			if (resourceDeltaVisitor.encounteredSignificantChange()) {
				this.update();
				this.resolveExternalJavaTypes();
				this.resolveInternalJavaTypes();
			}
		}
	}

	protected ResourceDeltaVisitor buildExternalResourceDeltaVisitor() {
		return new ExternalResourceDeltaVisitor();
	}

	protected class ExternalResourceDeltaVisitor
		extends ResourceDeltaVisitor
	{
		protected ExternalResourceDeltaVisitor() {
			super();
		}
		@Override
		public boolean fileChangeIsSignificant(IFile file, int deltaKind) {
			return AbstractJpaProject.this.synchronizeExternalFiles(file, deltaKind);
		}
		@Override
		public String toString() {
			return StringTools.buildToStringFor(this, AbstractJpaProject.this);
		}
	}

	/**
	 * external resource delta visitor callback
	 * Return true if an "external" Java resource compilation unit
	 * was added or removed.
	 */
	protected boolean synchronizeExternalFiles(IFile file, int deltaKind) {
		switch (deltaKind) {
			case IResourceDelta.ADDED :
				return this.externalFileAdded(file);
			case IResourceDelta.REMOVED :
				return this.externalFileRemoved(file);
			case IResourceDelta.CHANGED :
				break;  // ignore
			case IResourceDelta.ADDED_PHANTOM :
				break;  // ignore
			case IResourceDelta.REMOVED_PHANTOM :
				break;  // ignore
			default :
				break;  // only worried about added/removed/changed files
		}

		return false;
	}

	protected boolean externalFileAdded(IFile file) {
		IContentType contentType = PlatformTools.getContentType(file);
		if (contentType == null) {
			return false;
		}
		if (contentType.equals(JptCommonCorePlugin.JAVA_SOURCE_CONTENT_TYPE)) {
			return true;
		}
		if (contentType.equals(JptCommonCorePlugin.JAR_CONTENT_TYPE)) {
			return true;
		}
		return false;
	}

	protected boolean externalFileRemoved(IFile file) {
		IContentType contentType = PlatformTools.getContentType(file);
		if (contentType == null) {
			return false;
		}
		if (contentType.equals(JptCommonCorePlugin.JAVA_SOURCE_CONTENT_TYPE)) {
			return this.removeExternalJavaResourceCompilationUnit(file);
		}
		if (contentType.equals(JptCommonCorePlugin.JAR_CONTENT_TYPE)) {
			return this.externalJavaResourceTypeCache.removeTypes(file);
		}
		return false;
	}

	protected void resolveExternalJavaTypes() {
		for (JavaResourceCompilationUnit jrcu : this.getExternalJavaResourceCompilationUnits()) {
			jrcu.resolveTypes();
		}
	}

	// ***** resource delta visitors
	/**
	 * add or remove a JPA file for every [appropriate] file encountered by the visitor
	 */
	protected abstract class ResourceDeltaVisitor
		implements IResourceDeltaVisitor
	{
		protected boolean encounteredSignificantChange = false;

		protected ResourceDeltaVisitor() {
			super();
		}

		protected void visitDelta(IResourceDelta delta) {
			try {
				delta.accept(this);
			} catch (CoreException ex) {
				// shouldn't happen - we don't throw any CoreExceptions
				throw new RuntimeException(ex);
			}
		}

		public boolean visit(IResourceDelta delta) {
			IResource res = delta.getResource();
			switch (res.getType()) {
				case IResource.ROOT :
					return true;  // visit children
				case IResource.PROJECT :
					return true;  // visit children
				case IResource.FOLDER :
					return true;  // visit children
				case IResource.FILE :
					this.fileChanged((IFile) res, delta.getKind());
					return false;  // no children
				default :
					return false;  // no children (probably shouldn't get here...)
			}
		}

		protected void fileChanged(IFile file, int deltaKind) {
			if (this.fileChangeIsSignificant(file, deltaKind)) {
				this.encounteredSignificantChange = true;
			}
		}

		protected abstract boolean fileChangeIsSignificant(IFile file, int deltaKind);

		/**
		 * Return whether the visitor encountered some sort of "significant"
		 * change while traversing the IResourceDelta
		 * (e.g. a JPA file was added or removed).
		 */
		protected boolean encounteredSignificantChange() {
			return this.encounteredSignificantChange;
		}

		@Override
		public String toString() {
			return StringTools.buildToStringFor(this, AbstractJpaProject.this);
		}
	}


	// ********** synchronize context model with resource model **********

	protected RepeatingJobCommand buildSynchronizeContextModelCommand() {
		return new RepeatingJobCommandWrapper(
					this.buildSynchronizeContextModelJobCommand(),
					this.buildStartSynchronizeContextModelJobCommandExecutor(),
					this.manager.getExceptionHandler()
				);
	}

	protected JobCommand buildSynchronizeContextModelJobCommand() {
		return new SynchronizeContextModelJobCommand();
	}

	protected JobCommandExecutor buildStartSynchronizeContextModelJobCommandExecutor() {
		return new ManagerJobCommandExecutor(this.buildSynchronizeContextModelJobName());
	}

	protected String buildSynchronizeContextModelJobName() {
		return NLS.bind(JptCoreMessages.CONTEXT_MODEL_SYNC_JOB_NAME, this.getName());
	}

	/**
	 * The JPA project's resource model has changed; synchronize the JPA
	 * project's context model with it. This method is typically called when the
	 * resource model state has changed when it is synchronized with its
	 * underlying Eclipse resource as the result of an Eclipse resource change
	 * event. This method can also be called when a client (e.g. a JUnit test
	 * case) has manipulated the resource model via its API (as opposed to
	 * modifying the underlying Eclipse resource directly) and needs the context
	 * model to be synchronized accordingly (since manipulating the resource
	 * model via its API will not trigger this method). Whether the context
	 * model is synchronously (or asynchronously) depends on the JPA project
	 * manager.
	 */
	public void synchronizeContextModel() {
		try {
			this.synchronizingContextModel = true;
			this.synchronizeContextModelCommand.execute(null);  // this progress monitor is ignored
		} finally {
			this.synchronizingContextModel = false;
		}

		// There are some changes to the resource model that will not change
		// the existing context model and trigger an update (e.g. adding an
		// @Entity annotation when the JPA project is automatically
		// discovering annotated classes); so we explicitly execute an update
		// here to discover those changes.
		// TODO change sync so it will *always* trigger an update?
		this.update();
	}

	protected class SynchronizeContextModelJobCommand
		implements JobCommand
	{
		public IStatus execute(IProgressMonitor monitor) {
			return AbstractJpaProject.this.synchronizeContextModel(monitor);
		}
		@Override
		public String toString() {
			return StringTools.buildToStringFor(this, AbstractJpaProject.this);
		}
	}

	/**
	 * Called by the {@link SynchronizeContextModelJobCommand#execute(IProgressMonitor)}.
	 */
	// TODO pass the monitor down
	protected IStatus synchronizeContextModel(@SuppressWarnings("unused") IProgressMonitor monitor) {
		this.rootContextNode.synchronizeWithResourceModel();
		return Status.OK_STATUS;
	}


	// ********** JPA project "update" **********

	/**
	 * The first update is executed synchronously during construction.
	 * Once that is complete, we delegate to the JPA project manager.
	 */
	protected NotifyingRepeatingJobCommand buildTempUpdateCommand() {
		return new NotifyingRepeatingJobCommandWrapper(this.buildUpdateJobCommand(), this.manager.getExceptionHandler());
	}

	protected NotifyingRepeatingJobCommand buildUpdateCommand() {
		return new NotifyingRepeatingJobCommandWrapper(
					this.buildUpdateJobCommand(),
					this.buildStartUpdateJobCommandExecutor(),
					this.manager.getExceptionHandler()
				);
	}

	protected JobCommand buildUpdateJobCommand() {
		return new UpdateJobCommand();
	}

	protected JobCommandExecutor buildStartUpdateJobCommandExecutor() {
		return new ManagerJobCommandExecutor(this.buildUpdateJobName());
	}

	protected String buildUpdateJobName() {
		return NLS.bind(JptCoreMessages.UPDATE_JOB_NAME, this.getName());
	}

	@Override
	public void stateChanged() {
		super.stateChanged();
		this.update();
	}

	/**
	 * The JPA project's state has changed, "update" those parts of the
	 * JPA project that are dependent on other parts of the JPA project.
	 * <p>
	 * Delegate to the JPA project manager so clients can configure how
	 * updates occur.
	 * <p>
	 * Ignore any <em>updates</em> that occur while we are synchronizing
	 * the context model with the resource model because we will <em>update</em>
	 * the context model at the completion of the <em>sync</em>. This is really
	 * only useful for synchronous <em>syncs</em> and <em>updates</em>; since
	 * the job scheduling rules will prevent the <em>sync</em> and
	 * <em>update</em> jobs from running concurrently.
	 */
	protected void update() {
		if ( ! this.synchronizingContextModel) {
			this.updateCommand.execute(null);  // this progress monitor is ignored
		}
	}

	protected class UpdateJobCommand
		implements JobCommand
	{
		public IStatus execute(IProgressMonitor monitor) {
			return AbstractJpaProject.this.update(monitor);
		}
		@Override
		public String toString() {
			return StringTools.buildToStringFor(this, AbstractJpaProject.this);
		}
	}

	/**
	 * Called by the {@link UpdateJobCommand#execute(IProgressMonitor)}.
	 */
	// TODO pass the monitor down
	protected IStatus update(@SuppressWarnings("unused") IProgressMonitor monitor) {
		this.rootContextNode.update();
		return Status.OK_STATUS;
	}


	// ********** update command listener **********

	protected NotifyingRepeatingJobCommand.Listener buildUpdateCommandListener() {
		return new UpdateCommandListener();
	}

	protected class UpdateCommandListener
		implements NotifyingRepeatingJobCommand.Listener
	{
		public IStatus executionQuiesced(JobCommand command, IProgressMonitor monitor) {
			return AbstractJpaProject.this.updateQuiesced(monitor);
		}
		@Override
		public String toString() {
			return StringTools.buildToStringFor(this, AbstractJpaProject.this);
		}
	}

	/**
	 * This is the callback used by the update command to notify the JPA
	 * project that the "update" has quiesced (i.e. the "update" has completed
	 * and there are no outstanding requests for further "updates").
	 * Called by {@link UpdateCommandListener#executionQuiesced(JobCommand, IProgressMonitor)}.
	 */
 	protected IStatus updateQuiesced(IProgressMonitor monitor) {
		return this.synchronizeMetamodel(monitor);
	}


	// ********** job command executor **********

 	/**
	 * Delegate execution to the JPA project manager, which will determine
	 * whether commands are executed synchronously or asynchronously.
	 * 
	 * @see #buildStartSynchronizeContextModelJobCommandExecutor()
	 * @see #buildStartUpdateJobCommandExecutor()
	 */
	protected class ManagerJobCommandExecutor
		implements JobCommandExecutor
	{
		protected final String defaultJobName;
		protected ManagerJobCommandExecutor(String defaultJobName) {
			super();
			if (defaultJobName == null) {
				throw new NullPointerException();
			}
			this.defaultJobName = defaultJobName;
		}
		/**
		 * This should be the only method called on this executor....
		 */
		public void execute(JobCommand command) {
			this.execute(command, this.defaultJobName);
		}
		public void execute(JobCommand command, String jobName) {
			AbstractJpaProject.this.manager.execute(command, jobName, AbstractJpaProject.this);
		}
		public void execute(JobCommand command, String jobName, ISchedulingRule schedulingRule) {
			// the JPA project manager will supply the scheduling rule
			this.execute(command, jobName);
		}
		@Override
		public String toString() {
			return StringTools.buildToStringFor(this, this.defaultJobName);
		}
	}
}
