/*******************************************************************************
 * 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.core.internal;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
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.runtime.CoreException;
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.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.core.JpaDataSource;
import org.eclipse.jpt.core.JpaFile;
import org.eclipse.jpt.core.JpaPlatform;
import org.eclipse.jpt.core.JpaProject;
import org.eclipse.jpt.core.JpaResourceModel;
import org.eclipse.jpt.core.JpaResourceModelListener;
import org.eclipse.jpt.core.JptCorePlugin;
import org.eclipse.jpt.core.context.JpaRootContextNode;
import org.eclipse.jpt.core.internal.resource.java.binary.BinaryPersistentTypeCache;
import org.eclipse.jpt.core.internal.resource.java.source.SourceCompilationUnit;
import org.eclipse.jpt.core.internal.utility.PlatformTools;
import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
import org.eclipse.jpt.core.jpa2.JpaProject2_0;
import org.eclipse.jpt.core.jpa2.context.JpaRootContextNode2_0;
import org.eclipse.jpt.core.jpa2.resource.java.JavaResourcePersistentType2_0;
import org.eclipse.jpt.core.resource.java.JavaResourceCompilationUnit;
import org.eclipse.jpt.core.resource.java.JavaResourceNode;
import org.eclipse.jpt.core.resource.java.JavaResourcePackageFragmentRoot;
import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType;
import org.eclipse.jpt.core.resource.java.JavaResourcePersistentTypeCache;
import org.eclipse.jpt.core.resource.xml.JpaXmlResource;
import org.eclipse.jpt.db.Catalog;
import org.eclipse.jpt.db.ConnectionProfile;
import org.eclipse.jpt.db.Database;
import org.eclipse.jpt.db.Schema;
import org.eclipse.jpt.db.SchemaContainer;
import org.eclipse.jpt.utility.CommandExecutor;
import org.eclipse.jpt.utility.Filter;
import org.eclipse.jpt.utility.internal.BitTools;
import org.eclipse.jpt.utility.internal.CollectionTools;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.jpt.utility.internal.ThreadLocalCommandExecutor;
import org.eclipse.jpt.utility.internal.iterables.ArrayIterable;
import org.eclipse.jpt.utility.internal.iterables.CompositeIterable;
import org.eclipse.jpt.utility.internal.iterables.EmptyIterable;
import org.eclipse.jpt.utility.internal.iterables.FilteringIterable;
import org.eclipse.jpt.utility.internal.iterables.LiveCloneIterable;
import org.eclipse.jpt.utility.internal.iterables.SubIterableWrapper;
import org.eclipse.jpt.utility.internal.iterables.TransformationIterable;
import org.eclipse.jst.j2ee.model.internal.validation.ValidationCancelledException;
import org.eclipse.wst.common.internal.emfworkbench.WorkbenchResourceHelper;
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.
 * 
 * The JPA platform provides the hooks for vendor-specific stuff.
 * 
 * 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).
 * 
 * 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).
 * 
 * The data source is an adapter to the DTP meta-data model.
 */
public abstract class AbstractJpaProject
	extends AbstractJpaNode
	implements JpaProject2_0
{
	/**
	 * 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 persistent types (binary). Populated upon demand.
	 */
	protected final JavaResourcePersistentTypeCache externalJavaResourcePersistentTypeCache;

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

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

	/**
	 * A pluggable updater that can be used to "update" the JPA project either
	 * synchronously or asynchronously (or not at all). A synchronous updater
	 * is the default, allowing a newly-constructed JPA project to be "updated"
	 * upon return from the constructor. For performance reasons, a UI should
	 * immediately change this to an asynchronous updater. A synchronous
	 * updater can be used when the project is being manipulated by a "batch"
	 * (or non-UI) client (e.g. when testing the "update" behavior). A null
	 * updater can used during tests that do not care whether "updates" occur.
	 * Clients will need to explicitly configure the updater if they require
	 * something other than a synchronous updater.
	 */
	protected Updater updater;

	/**
	 * 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 String userOverrideDefaultCatalog;

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

	/**
	 * Flag indicating whether the project should "discover" annotated
	 * classes automatically, as opposed to requiring the classes to be
	 * listed in persistence.xml.
	 */
	protected boolean discoversAnnotatedClasses;

	/**
	 * Support for modifying documents shared with the UI.
	 */
	protected final ThreadLocalCommandExecutor modifySharedDocumentCommandExecutor;

	/**
	 * 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 String metamodelSourceFolderName;


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

	protected AbstractJpaProject(JpaProject.Config config) {
		super(null);  // JPA project is the root of the containment tree
		if ((config.getProject() == null) || (config.getJpaPlatform() == null)) {
			throw new NullPointerException();
		}
		this.project = config.getProject();
		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.modifySharedDocumentCommandExecutor = this.buildModifySharedDocumentCommandExecutor();

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

		this.externalJavaResourcePersistentTypeCache = this.buildExternalJavaResourcePersistentTypeCache();

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

		this.rootContextNode = this.buildRootContextNode();

		// "update" the project before returning
		this.setUpdater_(new SynchronousJpaProjectUpdater(this));

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

	@Override
	protected boolean requiresParent() {
		return false;
	}
	
	@Override
	public IResource getResource() {
		return this.project;
	}

	protected ThreadLocalCommandExecutor buildModifySharedDocumentCommandExecutor() {
		return new ThreadLocalCommandExecutor();
	}

	protected JpaResourceModelListener buildResourceModelListener() {
		return new DefaultResourceModelListener();
	}

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

	protected JavaResourcePersistentTypeCache buildExternalJavaResourcePersistentTypeCache() {
		return new BinaryPersistentTypeCache(this.jpaPlatform.getAnnotationProvider());
	}

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

	// ***** inner class
	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
			}
		}
	}


	// ********** miscellaneous **********

	/**
	 * 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 String getName() {
		return this.project.getName();
	}
	
	@Override
	public void toString(StringBuilder sb) {
		sb.append(this.getName());
	}

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

	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.getDbCatalog(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.getDbCatalog(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.getDbCatalog(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;
		JptCorePlugin.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;
		JptCorePlugin.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;
		JptCorePlugin.setDiscoverAnnotatedClasses(this.project, discoversAnnotatedClasses);
		this.firePropertyChanged(DISCOVERS_ANNOTATED_CLASSES_PROPERTY, old, discoversAnnotatedClasses);
	}
	
	
	// ********** JPA files **********

	public Iterator<JpaFile> jpaFiles() {
		return this.getJpaFiles().iterator();
	}

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

	public int jpaFilesSize() {
		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.getJavaProject().isOnClasspath(file)) {
			return null;  // the file must be on the Java classpath
		}

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

	/**
	 * 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 persistent types (source or binary) **********

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

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

	protected JavaResourcePersistentType buildPersistableExternalJavaResourcePersistentType(IType jdtType) {
		JavaResourcePersistentType jrpt = this.buildExternalJavaResourcePersistentType(jdtType);
		return ((jrpt != null) && jrpt.isPersistable()) ? jrpt : null;
	}

	protected JavaResourcePersistentType buildExternalJavaResourcePersistentType(IType jdtType) {
		return jdtType.isBinary() ?
				this.buildBinaryExternalJavaResourcePersistentType(jdtType) :
				this.buildSourceExternalJavaResourcePersistentType(jdtType);
	}

	protected JavaResourcePersistentType buildBinaryExternalJavaResourcePersistentType(IType jdtType) {
		return this.externalJavaResourcePersistentTypeCache.addPersistentType(jdtType);
	}

	protected JavaResourcePersistentType buildSourceExternalJavaResourcePersistentType(IType jdtType) {
		JavaResourceCompilationUnit jrcu = this.getExternalJavaResourceCompilationUnit(jdtType.getCompilationUnit());
		String jdtTypeName = jdtType.getFullyQualifiedName('.');  // JDT member type names use '$'
		for (Iterator<JavaResourcePersistentType> stream = jrcu.persistentTypes(); stream.hasNext(); ) {
			JavaResourcePersistentType jrpt = stream.next();
			if (jrpt.getQualifiedName().equals(jdtTypeName)) {
				return jrpt;
			}
		}
		// 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 JavaResourcePersistentTypeCache getExternalJavaResourcePersistentTypeCache() {
		return this.externalJavaResourcePersistentTypeCache;
	}


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

	public Iterator<JavaResourceCompilationUnit> externalJavaResourceCompilationUnits() {
		return this.getExternalJavaResourceCompilationUnits().iterator();
	}

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

	public int externalJavaResourceCompilationUnitsSize() {
		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 SourceCompilationUnit(
					jdtCompilationUnit,
					this.jpaPlatform.getAnnotationProvider(),
					this.jpaPlatform.getAnnotationEditFormatter(),
					this.modifySharedDocumentCommandExecutor
				);
	}

	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 convertToPlatformFile(String fileName) {
		return JptCorePlugin.getPlatformFile(this.project, fileName);
	}


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

	public JpaXmlResource getPersistenceXmlResource() {
		return (JpaXmlResource) this.getResourceModel(
				JptCorePlugin.DEFAULT_PERSISTENCE_XML_FILE_PATH,
				JptCorePlugin.PERSISTENCE_XML_CONTENT_TYPE
			);
	}

	public JpaXmlResource getDefaultOrmXmlResource() {
		return this.getMappingFileXmlResource(JptCorePlugin.DEFAULT_ORM_XML_FILE_PATH);
	}

	public JpaXmlResource getMappingFileXmlResource(String fileName) {
		return (JpaXmlResource) this.getResourceModel(fileName, JptCorePlugin.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 JpaResourceModel getResourceModel(String fileName, IContentType contentType) {
		IFile file = this.convertToPlatformFile(fileName);
		return 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 JpaResourceModel getResourceModel(IFile file, IContentType contentType) {
		JpaFile jpaFile = this.getJpaFile(file);
		return (jpaFile == null) ? null : jpaFile.getResourceModel(contentType);
	}


	// ********** annotated Java source classes **********
	
	public Iterator<String> annotatedJavaSourceClassNames() {
		return this.getAnnotatedJavaSourceClassNames().iterator();
	}
	
	protected Iterable<String> getAnnotatedJavaSourceClassNames() {
		return new TransformationIterable<JavaResourcePersistentType, String>(this.getInternalAnnotatedSourceJavaResourcePersistentTypes()) {
			@Override
			protected String transform(JavaResourcePersistentType jrpType) {
				return jrpType.getQualifiedName();
			}
		};
	}
	
	/**
	 * return only those valid annotated Java resource persistent types that are part of the 
	 * JPA project, ignoring those in JARs referenced in persistence.xml
	 * @see org.eclipse.jpt.core.internal.utility.jdt.JPTTools#typeIsPersistable(org.eclipse.jpt.core.internal.utility.jdt.JPTTools.TypeAdapter)
	 */
	protected Iterable<JavaResourcePersistentType> getInternalAnnotatedSourceJavaResourcePersistentTypes() {
		return new FilteringIterable<JavaResourcePersistentType>(this.getInternalSourceJavaResourcePersistentTypes()) {
			@Override
			protected boolean accept(JavaResourcePersistentType jrpType) {
				return jrpType.isPersistable() && jrpType.isAnnotated();  // i.e. the type is valid and has a valid type annotation
			}
		};
	}
	
	public Iterator<String> mappedJavaSourceClassNames() {
		return this.getMappedJavaSourceClassNames().iterator();
	}

	protected Iterable<String> getMappedJavaSourceClassNames() {
		return new TransformationIterable<JavaResourcePersistentType, String>(this.getInternalMappedSourceJavaResourcePersistentTypes()) {
			@Override
			protected String transform(JavaResourcePersistentType jrpType) {
				return jrpType.getQualifiedName();
			}
		};
	}

	/**
	 * return only those valid "mapped" (i.e. annotated with @Entity, @Embeddable, etc.) Java 
	 * resource persistent types that are part of the JPA project, ignoring those in JARs 
	 * referenced in persistence.xml
	 */
	protected Iterable<JavaResourcePersistentType> getInternalMappedSourceJavaResourcePersistentTypes() {
		return new FilteringIterable<JavaResourcePersistentType>(this.getInternalAnnotatedSourceJavaResourcePersistentTypes()) {
			@Override
			protected boolean accept(JavaResourcePersistentType jrpType) {
				return jrpType.isMapped();  // i.e. the type is already persistable and annotated
			}
		};
	}

	/**
	 * return only those Java resource persistent types that are
	 * part of the JPA project, ignoring those in JARs referenced in persistence.xml
	 */
	protected Iterable<JavaResourcePersistentType2_0> getInternalSourceJavaResourcePersistentTypes2_0() {
		return new SubIterableWrapper<JavaResourcePersistentType, JavaResourcePersistentType2_0>(this.getInternalSourceJavaResourcePersistentTypes());
	}

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

	/**
	 * return only those Java resource persistent types that are
	 * part of the JPA project, ignoring those in JARs referenced in persistence.xml
	 */
	protected Iterable<Iterable<JavaResourcePersistentType>> getInternalSourceJavaResourcePersistentTypeSets() {
		return new TransformationIterable<JavaResourceCompilationUnit, Iterable<JavaResourcePersistentType>>(this.getInternalJavaResourceCompilationUnits()) {
			@Override
			protected Iterable<JavaResourcePersistentType> transform(final JavaResourceCompilationUnit compilationUnit) {
				return new Iterable<JavaResourcePersistentType>() {
					public Iterator<JavaResourcePersistentType> iterator() {
						return compilationUnit.persistentTypes();  // *all* the types in the compilation unit
					}
				};
			}
		};
	}

	protected Iterable<JavaResourceCompilationUnit> getInternalJavaResourceCompilationUnits() {
		return new TransformationIterable<JpaFile, JavaResourceCompilationUnit>(this.getJavaSourceJpaFiles()) {
			@Override
			protected JavaResourceCompilationUnit transform(JpaFile jpaFile) {
				return (JavaResourceCompilationUnit) jpaFile.getResourceModel();
			}
		};
	}

	/**
	 * return JPA files with Java source "content"
	 */
	protected Iterable<JpaFile> getJavaSourceJpaFiles() {
		return this.getJpaFiles(JptCorePlugin.JAVA_SOURCE_CONTENT_TYPE);
	}


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

	public JavaResourcePersistentType getJavaResourcePersistentType(String typeName) {
		for (JavaResourcePersistentType jrpType : this.getPersistableJavaResourcePersistentTypes()) {
			if (jrpType.getQualifiedName().equals(typeName)) {
				return jrpType;
			}
		}
		// if we don't have a type already, try to build new one from the project classpath
		return this.buildPersistableExternalJavaResourcePersistentType(typeName);
	}

	/**
	 * return *all* the "persistable" Java resource persistent types, including those in JARs referenced in
	 * persistence.xml
	 * @see org.eclipse.jpt.core.internal.utility.jdt.JPTTools#typeIsPersistable(org.eclipse.jpt.core.internal.utility.jdt.JPTTools.TypeAdapter)
	 */
	protected Iterable<JavaResourcePersistentType> getPersistableJavaResourcePersistentTypes() {
		return new FilteringIterable<JavaResourcePersistentType>(this.getJavaResourcePersistentTypes()) {
			@Override
			protected boolean accept(JavaResourcePersistentType jrpType) {
				return jrpType.isPersistable();
			}
		};
	}

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

	/**
	 * return *all* the Java resource persistent types, including those in JARs referenced in
	 * persistence.xml
	 */
	protected Iterable<Iterable<JavaResourcePersistentType>> getJavaResourcePersistentTypeSets() {
		return new TransformationIterable<JavaResourceNode.Root, Iterable<JavaResourcePersistentType>>(this.getJavaResourceNodeRoots()) {
			@Override
			protected Iterable<JavaResourcePersistentType> transform(final JavaResourceNode.Root root) {
				return new Iterable<JavaResourcePersistentType>() {
					public Iterator<JavaResourcePersistentType> iterator() {
						return root.persistentTypes();  // *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.externalJavaResourcePersistentTypeCache)
				);
	}


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

	// TODO
	public JavaResourcePackageFragmentRoot getJavaResourcePackageFragmentRoot(String jarFileName) {
//		return this.getJarResourcePackageFragmentRoot(this.convertToPlatformFile(jarFileName));
		return this.getJavaResourcePackageFragmentRoot(this.getProject().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"
	 */
	protected Iterable<JpaFile> getJarJpaFiles() {
		return this.getJpaFiles(JptCorePlugin.JAR_CONTENT_TYPE);
	}


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

	public Iterable<JavaResourcePersistentType2_0> getGeneratedMetamodelTypes() {
		if (this.metamodelSourceFolderName == null) {
			return EmptyIterable.instance();
		}
		final IPackageFragmentRoot genSourceFolder = this.getMetamodelPackageFragmentRoot();
		return new FilteringIterable<JavaResourcePersistentType2_0>(this.getInternalSourceJavaResourcePersistentTypes2_0()) {
			@Override
			protected boolean accept(JavaResourcePersistentType2_0 jrpt) {
				return jrpt.isGeneratedMetamodel(genSourceFolder);
			}
		};
	}

	public JavaResourcePersistentType2_0 getGeneratedMetamodelType(IFile file) {
		JavaResourceCompilationUnit jrcu = this.getJavaResourceCompilationUnit(file);
		if (jrcu == null) {
			return null;  // hmmm...
		}
		Iterator<JavaResourcePersistentType> types = jrcu.persistentTypes();
		if ( ! types.hasNext()) {
			return null;  // no types in the file
		}
		JavaResourcePersistentType2_0 jrpt = (JavaResourcePersistentType2_0) types.next();
		if (types.hasNext()) {
			return null;  // should have only a single type in the file
		}
		return jrpt.isGeneratedMetamodel() ? jrpt : null;
	}

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

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

	public void setMetamodelSourceFolderName(String metamodelSourceFolderName) {
		String old = this.metamodelSourceFolderName;
		this.metamodelSourceFolderName = metamodelSourceFolderName;
		if (this.attributeValueHasChanged(old, metamodelSourceFolderName)) {
			JptCorePlugin.setMetamodelSourceFolderName(this.project, metamodelSourceFolderName);
			this.firePropertyChanged(METAMODEL_SOURCE_FOLDER_NAME_PROPERTY, old, metamodelSourceFolderName);
			if (metamodelSourceFolderName == null) {
				this.disposeMetamodel();
			} else {
				this.initializeMetamodel();
			}
		}
	}

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

	/**
	 * Synchronize the metamodel for 2.0-compatible JPA projects.
	 */
	public void synchronizeMetamodel() {
		if (this.isJpa2_0Compatible()) {
			if (this.metamodelSourceFolderName != null) {
				((JpaRootContextNode2_0) this.rootContextNode).synchronizeMetamodel();
			}
		}
	}

	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.getProject().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) {
			JptCorePlugin.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 CHANGED
	 * (as opposed to ADDED or REMOVED) Java element and the specified flag is set.
	 * (The delta flags are only significant if the delta "kind" is 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.update(this.getInternalJavaResourceCompilationUnits());
		} else {
			// TODO see if changed project is on our classpath?
			this.update(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.getJavaProject().isOnClasspath(jpaFile.getFile())) {
				this.removeJpaFile(jpaFile);
			}
		}
	}

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

	protected void update(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
		} else if (this.classpathEntryHasBeenRemoved(delta)) {  // should be mutually-exclusive w/added (?)
			// TODO
		}
	}

	/**
	 * 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 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 java notification for ADDED or REMOVED;
		// these are handled via resource notification
		return delta.getKind() == IJavaElementDelta.CHANGED;
	}


	// ********** validation **********
	
	public Iterator<IMessage> validationMessages(IReporter reporter) {
		List<IMessage> messages = new ArrayList<IMessage>();
		this.validate(messages, reporter);
		return messages.iterator();
	}
	
	protected void validate(List<IMessage> messages, IReporter reporter) {
		if (reporter.isCancelled()) {
			throw new ValidationCancelledException();
		}
		this.validateConnection(messages);
		this.rootContextNode.validate(messages, reporter);
	}

	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.updater.stop();
		this.dataSource.dispose();
	}
	
	
	// ********** resource model listener **********
	
	protected class DefaultResourceModelListener 
		implements JpaResourceModelListener 
	{
		protected DefaultResourceModelListener() {
			super();
		}
		
		public void resourceModelChanged(JpaResourceModel 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(JpaResourceModel jpaResourceModel) {
			IFile file = WorkbenchResourceHelper.getFile((JpaXmlResource)jpaResourceModel);
			AbstractJpaProject.this.removeJpaFile(file);
			AbstractJpaProject.this.addJpaFile(file);
		}
		
		public void resourceModelUnloaded(JpaResourceModel jpaResourceModel) {
			IFile file = WorkbenchResourceHelper.getFile((JpaXmlResource)jpaResourceModel);
			AbstractJpaProject.this.removeJpaFile(file);
		}
	}
	
	
	// ********** 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.getProject())) {
			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 ResourceDeltaVisitor() {
			@Override
			public boolean fileChangeIsSignificant(IFile file, int deltaKind) {
				return AbstractJpaProject.this.synchronizeJpaFiles(file, deltaKind);
			}
		};
	}

	/**
	 * 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 that we are interested in
			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 build a new JPA file
		// (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 ResourceDeltaVisitor() {
			@Override
			public boolean fileChangeIsSignificant(IFile file, int deltaKind) {
				return AbstractJpaProject.this.synchronizeExternalFiles(file, deltaKind);
			}
		};
	}

	/**
	 * 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(JptCorePlugin.JAVA_SOURCE_CONTENT_TYPE)) {
			return true;
		}
		if (contentType.equals(JptCorePlugin.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(JptCorePlugin.JAVA_SOURCE_CONTENT_TYPE)) {
			return this.removeExternalJavaResourceCompilationUnit(file);
		}
		if (contentType.equals(JptCorePlugin.JAR_CONTENT_TYPE)) {
			return this.externalJavaResourcePersistentTypeCache.removePersistentTypes(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;
		}

	}


	// ********** support for modifying documents shared with the UI **********

	public void setThreadLocalModifySharedDocumentCommandExecutor(CommandExecutor commandExecutor) {
		this.modifySharedDocumentCommandExecutor.set(commandExecutor);
	}

	public CommandExecutor getModifySharedDocumentCommandExecutor() {
		return this.modifySharedDocumentCommandExecutor;
	}


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

	// TODO ...
	protected void synchronizeContextModel(@SuppressWarnings("unused") JpaResourceModel jpaResourceModel) {
		this.synchronizeContextModel();
	}

	public void synchronizeContextModel() {
		this.update();
	}


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

	public Updater getUpdater() {
		return this.updater;
	}

	public void setUpdater(Updater updater) {
		if (updater == null) {
			throw new NullPointerException();
		}
		this.updater.stop();
		this.setUpdater_(updater);
	}

	protected void setUpdater_(Updater updater) {
		this.updater = updater;
		this.updater.start();
	}

	/**
	 * Delegate to the updater so clients can configure how updates occur.
	 */
	public void update() {
		this.updater.update();
	}

	/**
	 * Called by the updater.
	 */
	public IStatus update(IProgressMonitor monitor) {
		this.update_(monitor);
		return Status.OK_STATUS;
	}

	protected void update_(IProgressMonitor monitor) {
		this.rootContextNode.update(monitor);
		this.rootContextNode.postUpdate();
	}

	/**
	 * Also called by the updater.
	 */
	public void updateQuiesced() {
		this.synchronizeMetamodel();
	}

}
