/*******************************************************************************
 * 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.jpa1.context.orm;

import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Vector;
import org.eclipse.core.resources.IFile;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType;
import org.eclipse.jpt.common.core.utility.BodySourceWriter;
import org.eclipse.jpt.common.core.utility.TextRange;
import org.eclipse.jpt.core.JpaStructureNode;
import org.eclipse.jpt.core.JptCorePlugin;
import org.eclipse.jpt.core.context.AccessType;
import org.eclipse.jpt.core.context.PersistentType;
import org.eclipse.jpt.core.context.ReadOnlyPersistentAttribute;
import org.eclipse.jpt.core.context.java.JavaPersistentType;
import org.eclipse.jpt.core.context.orm.EntityMappings;
import org.eclipse.jpt.core.context.orm.OrmAttributeMapping;
import org.eclipse.jpt.core.context.orm.OrmAttributeMappingDefinition;
import org.eclipse.jpt.core.context.orm.OrmPersistentAttribute;
import org.eclipse.jpt.core.context.orm.OrmPersistentType;
import org.eclipse.jpt.core.context.orm.OrmReadOnlyPersistentAttribute;
import org.eclipse.jpt.core.context.orm.OrmStructureNodes;
import org.eclipse.jpt.core.context.orm.OrmTypeMapping;
import org.eclipse.jpt.core.context.orm.OrmTypeMappingDefinition;
import org.eclipse.jpt.core.internal.context.ContextContainerTools;
import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode;
import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
import org.eclipse.jpt.core.jpa2.context.MetamodelSourceType;
import org.eclipse.jpt.core.jpa2.context.java.JavaPersistentType2_0;
import org.eclipse.jpt.core.jpa2.context.orm.OrmPersistentType2_0;
import org.eclipse.jpt.core.resource.java.JavaResourcePersistentAttribute;
import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType;
import org.eclipse.jpt.core.resource.orm.Attributes;
import org.eclipse.jpt.core.resource.orm.OrmPackage;
import org.eclipse.jpt.core.resource.orm.XmlAttributeMapping;
import org.eclipse.jpt.core.resource.orm.XmlTypeMapping;
import org.eclipse.jpt.core.resource.xml.EmfTools;
import org.eclipse.jpt.utility.internal.ClassName;
import org.eclipse.jpt.utility.internal.CollectionTools;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.jpt.utility.internal.Tools;
import org.eclipse.jpt.utility.internal.iterables.ChainIterable;
import org.eclipse.jpt.utility.internal.iterables.CompositeIterable;
import org.eclipse.jpt.utility.internal.iterables.CompositeListIterable;
import org.eclipse.jpt.utility.internal.iterables.EmptyIterable;
import org.eclipse.jpt.utility.internal.iterables.FilteringIterable;
import org.eclipse.jpt.utility.internal.iterables.ListIterable;
import org.eclipse.jpt.utility.internal.iterables.LiveCloneListIterable;
import org.eclipse.jpt.utility.internal.iterables.SingleElementIterable;
import org.eclipse.jpt.utility.internal.iterables.SnapshotCloneIterable;
import org.eclipse.jpt.utility.internal.iterables.SuperListIterableWrapper;
import org.eclipse.jpt.utility.internal.iterables.TransformationIterable;
import org.eclipse.jpt.utility.internal.iterators.EmptyListIterator;
import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;

/**
 * <code>orm.xml</code> persistent type:<ul>
 * <li>mapping
 * <li>access
 * <li>attributes
 * <li>super persistent type
 * <li>Java persistent type
 * </ul>
 */
public class GenericOrmPersistentType
	extends AbstractOrmXmlContextNode
	implements OrmPersistentType2_0
{
	protected OrmTypeMapping mapping;  // never null

	protected JavaPersistentType javaPersistentType;

	protected AccessType specifiedAccess;
	protected AccessType defaultAccess;  // never null

	protected final Vector<OrmPersistentAttribute> specifiedAttributes = new Vector<OrmPersistentAttribute>();
	protected final SpecifiedAttributeContainerAdapter specifiedAttributeContainerAdapter = new SpecifiedAttributeContainerAdapter();

	protected final Vector<OrmReadOnlyPersistentAttribute> virtualAttributes = new Vector<OrmReadOnlyPersistentAttribute>();
	protected final VirtualAttributeContainerAdapter virtualAttributeContainerAdapter = new VirtualAttributeContainerAdapter();

	protected PersistentType superPersistentType;

	protected String declaringTypeName;

	protected final MetamodelSourceType.Synchronizer metamodelSynchronizer;


	public GenericOrmPersistentType(EntityMappings parent, XmlTypeMapping xmlTypeMapping) {
		super(parent);
		this.mapping = this.buildMapping(xmlTypeMapping);
		// 'javaPersistentType' is resolved in the update
		this.specifiedAccess = this.buildSpecifiedAccess();
		this.defaultAccess = AccessType.FIELD;  // keep this non-null
		this.initializeSpecifiedAttributes();
		this.metamodelSynchronizer = this.buildMetamodelSynchronizer();
	}


	// ********** synchronize/update **********

	@Override
	public void synchronizeWithResourceModel() {
		super.synchronizeWithResourceModel();
		this.mapping.synchronizeWithResourceModel();
		this.syncJavaPersistentType();
		this.setSpecifiedAccess_(this.buildSpecifiedAccess());
		this.syncSpecifiedAttributes();
		this.synchronizeNodesWithResourceModel(this.getVirtualAttributes());
	}

	@Override
	public void update() {
		super.update();
		this.mapping.update();
		this.updateJavaPersistentType();
		this.setDefaultAccess(this.buildDefaultAccess());
		this.updateNodes(this.getSpecifiedAttributes());
		this.updateVirtualAttributes();
		this.setSuperPersistentType(this.buildSuperPersistentType());
		this.setDeclaringTypeName(this.buildDeclaringTypeName());
	}


	// ********** mapping **********

	public OrmTypeMapping getMapping() {
		return this.mapping;
	}

	public String getMappingKey() {
		return this.mapping.getKey();
	}

	public void setMappingKey(String mappingKey) {
		if (this.valuesAreDifferent(this.getMappingKey(), mappingKey)) {
			this.setMappingKey_(mappingKey);
		}
	}

	protected void setMappingKey_(String mappingKey) {
		OrmTypeMapping old = this.mapping;
		OrmTypeMappingDefinition mappingDefinition = this.getMappingFileDefinition().getTypeMappingDefinition(mappingKey);
		XmlTypeMapping xmlTypeMapping = mappingDefinition.buildResourceMapping(this.getResourceNodeFactory());
		this.mapping = this.buildMapping(xmlTypeMapping);
		this.getEntityMappings().changeMapping(this, old, this.mapping);
		this.firePropertyChanged(MAPPING_PROPERTY, old, this.mapping);
	}

	protected OrmTypeMapping buildMapping(XmlTypeMapping xmlTypeMapping) {
		OrmTypeMappingDefinition md = this.getMappingFileDefinition().getTypeMappingDefinition(xmlTypeMapping.getMappingKey());
		return md.buildContextMapping(this, xmlTypeMapping, this.getContextNodeFactory());
	}

	protected XmlTypeMapping getXmlTypeMapping() {
		return this.mapping.getXmlTypeMapping();
	}

	public boolean isMapped() {
		return true;
	}


	// ********** name **********

	public String getName() {
		return this.convertMappingClassName(this.mapping.getClass_());
	}

	public String getSimpleName(){
		String className = this.getName();
		return StringTools.stringIsEmpty(className) ? null : ClassName.getSimpleName(className);
	}

	/**
	 * We clear out {@link #javaPersistentType} here because we cannot compare its name
	 * to the mapping's class name, since it may have been prefixed by the entity
	 * mappings package.
	 */
	public void mappingClassChanged(String oldClass, String newClass) {
		this.firePropertyChanged(NAME_PROPERTY, this.convertMappingClassName(oldClass), this.convertMappingClassName(newClass));
		// clear out the Java type here, it will be rebuilt during "update"
		if (this.javaPersistentType != null) {
			this.javaPersistentType.dispose();
			this.setJavaPersistentType(null);
		}
	}

	/**
	 * Nested class names are specified with a <code>'$'</code>
	 * in <code>orm.xml</code>.
	 */
	protected String convertMappingClassName(String name) {
		return (name == null) ? null : name.replace('$', '.');
	}


	// ********** Java persistent type **********

	public JavaPersistentType getJavaPersistentType() {
		return this.javaPersistentType;
	}

	protected void setJavaPersistentType(JavaPersistentType javaPersistentType) {
		JavaPersistentType old = this.javaPersistentType;
		this.javaPersistentType = javaPersistentType;
		this.firePropertyChanged(JAVA_PERSISTENT_TYPE_PROPERTY, old, javaPersistentType);
	}

	/**
	 * If the persistent type's mapping's class (name) changes during
	 * <em>sync</em>, the Java persistent type will be cleared out in
	 * {@link #mappingClassChanged(String, String)}. If we get here and
	 * the Java persistent type is still present, we can
	 * <em>sync</em> it. Of course, it might still be obsolete if the
	 * entity mappings's package has changed....
	 *
	 * @see #updateJavaPersistentType()
	 */
	protected void syncJavaPersistentType() {
		if (this.javaPersistentType != null) {
			this.javaPersistentType.synchronizeWithResourceModel();
		}
	}

	/**
	 * @see #syncJavaPersistentType()
	 */
	protected void updateJavaPersistentType() {
		JavaResourcePersistentType resourceType = this.resolveJavaResourcePersistentType();
		if (resourceType == null) {
			if (this.javaPersistentType != null) {
				this.javaPersistentType.dispose();
				this.setJavaPersistentType(null);
			}
		} else {
			if (this.javaPersistentType == null) {
				this.setJavaPersistentType(this.buildJavaPersistentType(resourceType));
			} else {
				if (this.javaPersistentType.getResourcePersistentType() == resourceType) {
					this.javaPersistentType.update();
				} else {
					this.javaPersistentType.dispose();
					this.setJavaPersistentType(this.buildJavaPersistentType(resourceType));
				}
			}
		}
	}

	protected JavaResourcePersistentType resolveJavaResourcePersistentType() {
		return this.getEntityMappings().resolveJavaResourcePersistentType(this.getName());
	}

	protected JavaPersistentType buildJavaPersistentType(JavaResourcePersistentType jrpt) {
		return this.getJpaFactory().buildJavaPersistentType(this, jrpt);
	}


	// ********** access **********

	public AccessType getAccess() {
		return (this.specifiedAccess != null) ? this.specifiedAccess : this.defaultAccess;
	}

	public AccessType getSpecifiedAccess() {
		return this.specifiedAccess;
	}

	public void setSpecifiedAccess(AccessType access) {
		this.setSpecifiedAccess_(access);
		this.getXmlTypeMapping().setAccess(AccessType.toOrmResourceModel(access));
	}

	protected void setSpecifiedAccess_(AccessType access) {
		AccessType old = this.specifiedAccess;
		this.specifiedAccess = access;
		this.firePropertyChanged(SPECIFIED_ACCESS_PROPERTY, old, access);
	}

	protected AccessType buildSpecifiedAccess() {
		return AccessType.fromOrmResourceModel(this.getXmlTypeMapping().getAccess());
	}

	public AccessType getDefaultAccess() {
		return this.defaultAccess;
	}

	protected void setDefaultAccess(AccessType access) {
		AccessType old = this.defaultAccess;
		this.defaultAccess = access;
		this.firePropertyChanged(DEFAULT_ACCESS_PROPERTY, old, access);
	}

	protected AccessType buildDefaultAccess() {
		if ( ! this.mapping.isMetadataComplete()) {
			if (this.javaPersistentType != null) {
				if (this.javaPersistentTypeHasSpecifiedAccess()) {
					return this.javaPersistentType.getAccess();
				}
				if (this.superPersistentType != null) {
					return this.superPersistentType.getAccess();
				}
			}
		}
		AccessType access = this.getMappingFileRoot().getAccess();
		return (access != null) ? access : AccessType.FIELD;  // default to FIELD if no specified access found
	}

	/**
	 * pre-condition: {@link #javaPersistentType} is not <code>null</code>
	 */
	protected boolean javaPersistentTypeHasSpecifiedAccess() {
		return (this.javaPersistentType.getSpecifiedAccess() != null) ||
				this.javaPersistentType.hasAnyAnnotatedAttributes();
	}

	public AccessType getOwnerOverrideAccess() {
		return this.getEntityMappings().getOverridePersistentTypeAccess();
	}

	public AccessType getOwnerDefaultAccess() {
		return this.getEntityMappings().getDefaultPersistentTypeAccess();
	}


	// ********** attributes **********

	public ListIterator<OrmReadOnlyPersistentAttribute> attributes() {
		return this.getAttributes().iterator();
	}

	@SuppressWarnings("unchecked")
	public ListIterable<OrmReadOnlyPersistentAttribute> getAttributes() {
		return new CompositeListIterable<OrmReadOnlyPersistentAttribute>(this.getReadOnlySpecifiedAttributes(), this.getVirtualAttributes());
	}

	public int attributesSize() {
		return this.specifiedAttributesSize() + this.virtualAttributesSize();
	}

	public Iterator<String> attributeNames() {
		return this.getAttributeNames().iterator();
	}

	public Iterable<String> getAttributeNames() {
		return this.convertToNames(this.getAttributes());
	}

	public OrmReadOnlyPersistentAttribute getAttributeNamed(String attributeName) {
		Iterator<OrmReadOnlyPersistentAttribute> stream = this.getAttributesNamed(attributeName).iterator();
		return stream.hasNext() ? stream.next() : null;
	}

	public Iterator<ReadOnlyPersistentAttribute> allAttributes() {
		return this.getAllAttributes().iterator();
	}

	public Iterable<ReadOnlyPersistentAttribute> getAllAttributes() {
		return new CompositeIterable<ReadOnlyPersistentAttribute>(
				new TransformationIterable<PersistentType, Iterable<ReadOnlyPersistentAttribute>>(this.getInheritanceHierarchy()) {
					@Override
					protected Iterable<ReadOnlyPersistentAttribute> transform(PersistentType pt) {
						return new SnapshotCloneIterable<ReadOnlyPersistentAttribute>(pt.attributes());
					}
				}
			);
	}

	public Iterator<String> allAttributeNames() {
		return this.getAllAttributeNames().iterator();
	}

	public Iterable<String> getAllAttributeNames() {
		return this.convertToNames(this.getAllAttributes());
	}

	protected Iterable<OrmReadOnlyPersistentAttribute> getAttributesNamed(final String attributeName) {
		return new FilteringIterable<OrmReadOnlyPersistentAttribute>(this.getAttributes()) {
			@Override
			protected boolean accept(OrmReadOnlyPersistentAttribute attribute) {
				return Tools.valuesAreEqual(attributeName, attribute.getName());
			}
		};
	}

	public ReadOnlyPersistentAttribute resolveAttribute(String attributeName) {
		Iterator<OrmReadOnlyPersistentAttribute> attributes = this.getAttributesNamed(attributeName).iterator();
		if (attributes.hasNext()) {
			OrmReadOnlyPersistentAttribute attribute = attributes.next();
			return attributes.hasNext() ? null /* more than one */: attribute;
		}
		// recurse
		return (this.superPersistentType == null) ? null : this.superPersistentType.resolveAttribute(attributeName);
	}

	protected Iterable<String> convertToNames(Iterable<? extends ReadOnlyPersistentAttribute> attributes) {
		return new TransformationIterable<ReadOnlyPersistentAttribute, String>(attributes) {
			@Override
			protected String transform(ReadOnlyPersistentAttribute attribute) {
				return attribute.getName();
			}
		};
	}


	// ********** attribute conversions **********

	public OrmPersistentAttribute convertAttributeToSpecified(OrmReadOnlyPersistentAttribute virtualAttribute) {
		return this.convertAttributeToSpecified(virtualAttribute, virtualAttribute.getMappingKey());
	}

	public OrmPersistentAttribute convertAttributeToSpecified(OrmReadOnlyPersistentAttribute virtualAttribute, String mappingKey) {
		if ( ! virtualAttribute.isVirtual()) {
			throw new IllegalArgumentException("Attribute is already specified: " + virtualAttribute); //$NON-NLS-1$
		}
		if (mappingKey == null) {
			// this typically happens when the virtual attribute does not have a mapping
			throw new IllegalArgumentException("Use convertAttributeToSpecified(OrmReadOnlyPersistentAttribute, String) instead and specify a mapping key"); //$NON-NLS-1$
		}
		return this.convertAttributeToSpecified_(virtualAttribute, mappingKey);
	}

	/**
	 * <em>Silently</em> remove the virtual attribute and add specified
	 * attribute before triggering an <em>update</em> or the dangling
	 * virtual attribute will be removed preemptively.
	 */
	protected OrmPersistentAttribute convertAttributeToSpecified_(OrmReadOnlyPersistentAttribute virtualAttribute, String mappingKey) {
		// silently remove the virtual attribute
		int virtualIndex = this.virtualAttributes.indexOf(virtualAttribute);
		this.virtualAttributes.remove(virtualIndex);
		virtualAttribute.dispose();

		// silently add the specified attribute
		OrmAttributeMappingDefinition md = this.getMappingFileDefinition().getAttributeMappingDefinition(mappingKey);
		XmlAttributeMapping xmlMapping = md.buildResourceMapping(this.getResourceNodeFactory());

		OrmPersistentAttribute specifiedAttribute = this.buildSpecifiedAttribute(xmlMapping);
		// we need to add the attribute to the right spot in the list - stupid spec...
		int specifiedIndex = this.getSpecifiedAttributeInsertionIndex(specifiedAttribute);
		this.specifiedAttributes.add(specifiedIndex, specifiedAttribute);

		// this will trigger the initial update;
		// no changes to either collection (virtual or specified) should be detected at this point
		specifiedAttribute.getMapping().setName(virtualAttribute.getName());

		// fire the list change events
		this.fireItemRemoved(VIRTUAL_ATTRIBUTES_LIST, virtualIndex, virtualAttribute);
		this.fireItemAdded(SPECIFIED_ATTRIBUTES_LIST, specifiedIndex, specifiedAttribute);

		// it should be safe to update the XML now
		Attributes xmlAttributes = this.getXmlAttributesForUpdate();
		specifiedAttribute.getMapping().addXmlAttributeMappingTo(xmlAttributes);
		// possibly a NOP, but needed when we trigger the creation of a new 'attributes'
		this.getXmlTypeMapping().setAttributes(xmlAttributes);

		// copy over the specified access(?)
		AccessType oldAccess = virtualAttribute.getJavaPersistentAttribute().getSpecifiedAccess();
		if (oldAccess != null) {
			specifiedAttribute.setSpecifiedAccess(oldAccess);
		}
		return specifiedAttribute;
	}

	// TODO this is used only by our tests...
	// we cannot delegate to getAttributeNamed(String).convertToSpecified()
	// because the tests use this method to add "orphan" xml attributes (that
	// do not have a corresponding java attribute :( )
	public OrmPersistentAttribute addSpecifiedAttribute(String mappingKey, String attributeName) {
		// force the creation of an empty xml attribute container beforehand or it will trigger
		// a sync and, if we do this after adding the attribute, clear out our context attributes
		Attributes xmlAttributes = this.getXmlAttributesForUpdate();
		this.getXmlTypeMapping().setAttributes(xmlAttributes);  // possibly a NOP

		OrmAttributeMappingDefinition md = this.getMappingFileDefinition().getAttributeMappingDefinition(mappingKey);
		XmlAttributeMapping xmlMapping = md.buildResourceMapping(this.getResourceNodeFactory());

		OrmPersistentAttribute specifiedAttribute = this.buildSpecifiedAttribute(xmlMapping);
		// we need to add the attribute to the right spot in the list - stupid spec...
		int specifiedIndex = this.getSpecifiedAttributeInsertionIndex(specifiedAttribute);
		// the virtual attributes list should remain unchanged since the specified attribute has no name
		this.addItemToList(specifiedIndex, specifiedAttribute, this.specifiedAttributes, SPECIFIED_ATTRIBUTES_LIST);
		specifiedAttribute.getMapping().addXmlAttributeMappingTo(xmlAttributes);

		// this will trigger the update of the virtual attributes list
		specifiedAttribute.getMapping().setName(attributeName);

		return specifiedAttribute;
	}

	protected int getSpecifiedAttributeInsertionIndex(OrmPersistentAttribute attribute) {
		return CollectionTools.insertionIndexOf(this.specifiedAttributes, attribute, this.getAttributeComparator());
	}

	protected Comparator<OrmPersistentAttribute> getAttributeComparator() {
		return ATTRIBUTE_COMPARATOR;
	}

	protected static final Comparator<OrmPersistentAttribute> ATTRIBUTE_COMPARATOR =
		new Comparator<OrmPersistentAttribute>() {
			public int compare(OrmPersistentAttribute attribute1, OrmPersistentAttribute attribute2) {
				int seq1 = attribute1.getMapping().getXmlSequence();
				int seq2 = attribute2.getMapping().getXmlSequence();
				return (seq1 == seq2) ? 0 : (seq1 < seq2) ? -1 : 1;
			}
		};

	/**
	 * <em>Silently</em> add the new virtual attribute before removing the
	 * specified attribute, or the <em>update</em> will discover the missing
	 * virtual attribute and add it preemptively.
	 */
	public OrmReadOnlyPersistentAttribute convertAttributeToVirtual(OrmPersistentAttribute specifiedAttribute) {
		if (specifiedAttribute.isVirtual()) {
			throw new IllegalArgumentException("Attribute is already virtual: " + specifiedAttribute); //$NON-NLS-1$
		}

		int virtualIndex = this.virtualAttributes.size();
		OrmReadOnlyPersistentAttribute virtualAttribute = null;
		// make sure the corresponding resource Java attribute actually exists in the *current* type;
		// do *not* take the context Java attribute directly from the specified ORM
		// attribute we are converting since it may have come from a superclass;
		// instead, use its resource Java attribute (which will match both name and access type,
		// but we still need to check its parent type)
		JavaResourcePersistentAttribute javaResourceAttribute = specifiedAttribute.getJavaResourcePersistentAttribute();
		if ((javaResourceAttribute != null) && this.javaResourceAttributeWillBeVirtual(javaResourceAttribute, specifiedAttribute)) {
			virtualAttribute = this.buildVirtualAttribute(javaResourceAttribute);
			this.virtualAttributes.add(virtualIndex, virtualAttribute);
		}

		this.removeSpecifiedAttribute(specifiedAttribute);  // trigger update

		if (virtualAttribute != null) {
			this.fireItemAdded(VIRTUAL_ATTRIBUTES_LIST, virtualIndex, virtualAttribute);
		}
		return virtualAttribute;
	}

	/**
	 * Return whether the specified Java resource attribute will be a
	 * <em>virtual</em> attribute when the specified specified attribute is
	 * removed from the type. The Java resource attribute must be among the
	 * valid Java resource attributes and it must not correspond to any of the
	 * remaining specified attributes.
	 */
	protected boolean javaResourceAttributeWillBeVirtual(JavaResourcePersistentAttribute javaResourceAttribute, OrmPersistentAttribute specifiedAttributeToBeRemoved) {
		return CollectionTools.contains(this.getJavaResourceAttributes(), javaResourceAttribute) &&
				(this.getSpecifiedAttributeFor(javaResourceAttribute, specifiedAttributeToBeRemoved) == null);
	}


	// ********** xml attributes **********

	/**
	 * Return <code>null</code> if the <code>attributes</code> element is missing.
	 */
	protected Attributes getXmlAttributes() {
		return this.getXmlTypeMapping().getAttributes();
	}

	/**
	 * Build a new <code>attributes</code> element if it is not present;
	 * but do <em>not</em> add it to the XML type mapping. Callers will have
	 * to add it to the XML type mapping when appropriate.
	 */
	protected Attributes getXmlAttributesForUpdate() {
		Attributes xmlAttributes = this.getXmlAttributes();
		return (xmlAttributes != null) ? xmlAttributes : this.buildXmlAttributes();
	}

	protected Attributes buildXmlAttributes() {
		return EmfTools.create(this.getResourceNodeFactory(), OrmPackage.eINSTANCE.getAttributes(), Attributes.class);
	}

	protected void removeXmlAttributesIfUnset() {
		if (this.getXmlAttributes().isUnset()) {
			this.getXmlTypeMapping().setAttributes(null);
		}
	}


	// ********** specified attributes **********

	public ListIterator<OrmPersistentAttribute> specifiedAttributes() {
		return this.getSpecifiedAttributes().iterator();
	}

	protected ListIterable<OrmPersistentAttribute> getSpecifiedAttributes() {
		return new LiveCloneListIterable<OrmPersistentAttribute>(this.specifiedAttributes);
	}

	protected ListIterable<OrmReadOnlyPersistentAttribute> getReadOnlySpecifiedAttributes() {
		return new SuperListIterableWrapper<OrmReadOnlyPersistentAttribute>(this.getSpecifiedAttributes());
	}

	public int specifiedAttributesSize() {
		return this.specifiedAttributes.size();
	}

	protected void removeSpecifiedAttribute(OrmPersistentAttribute attribute) {
		this.removeSpecifiedAttribute_(attribute);
		attribute.getMapping().removeXmlAttributeMappingFrom(this.getXmlAttributes());
		this.removeXmlAttributesIfUnset();
	}

	public void changeMapping(OrmPersistentAttribute attribute, OrmAttributeMapping oldMapping, OrmAttributeMapping newMapping) {
		// keep the context model in sync with each change to the resource model
		int sourceIndex = this.specifiedAttributes.indexOf(attribute);
		this.specifiedAttributes.remove(sourceIndex);
		oldMapping.removeXmlAttributeMappingFrom(this.getXmlAttributes());

		int targetIndex = this.getSpecifiedAttributeInsertionIndex(attribute);
		this.specifiedAttributes.add(targetIndex, attribute);
		newMapping.addXmlAttributeMappingTo(this.getXmlAttributes());

		oldMapping.initializeOn(newMapping);

		this.fireItemMoved(SPECIFIED_ATTRIBUTES_LIST, targetIndex, sourceIndex);
	}

	protected void initializeSpecifiedAttributes() {
		for (XmlAttributeMapping xmlMapping : this.getXmlAttributeMappings()) {
			this.specifiedAttributes.add(this.buildSpecifiedAttribute(xmlMapping));
		}
	}

	protected Iterable<XmlAttributeMapping> getXmlAttributeMappings() {
		Attributes xmlAttributes = this.getXmlAttributes();
		return (xmlAttributes != null) ? xmlAttributes.getAttributeMappings() : EmptyIterable.<XmlAttributeMapping>instance();
	}

	protected OrmPersistentAttribute buildSpecifiedAttribute(XmlAttributeMapping xmlMapping) {
		return this.getContextNodeFactory().buildOrmPersistentAttribute(this, xmlMapping);
	}

	protected void syncSpecifiedAttributes() {
		ContextContainerTools.synchronizeWithResourceModel(this.specifiedAttributeContainerAdapter);
	}

	protected void moveSpecifiedAttribute_(int index, OrmPersistentAttribute attribute) {
		this.moveItemInList(index, attribute, this.specifiedAttributes, SPECIFIED_ATTRIBUTES_LIST);
	}

	protected void addSpecifiedAttribute_(int index, XmlAttributeMapping xmlMapping) {
		OrmPersistentAttribute attribute = this.buildSpecifiedAttribute(xmlMapping);
		this.addItemToList(index, attribute, this.specifiedAttributes, SPECIFIED_ATTRIBUTES_LIST);
	}

	protected void removeSpecifiedAttribute_(OrmPersistentAttribute attribute) {
		this.removeItemFromList(attribute, this.specifiedAttributes, SPECIFIED_ATTRIBUTES_LIST);
	}

	/**
	 * specified attribute container adapter
	 */
	protected class SpecifiedAttributeContainerAdapter
		implements ContextContainerTools.Adapter<OrmPersistentAttribute, XmlAttributeMapping>
	{
		public Iterable<OrmPersistentAttribute> getContextElements() {
			return GenericOrmPersistentType.this.getSpecifiedAttributes();
		}
		public Iterable<XmlAttributeMapping> getResourceElements() {
			return GenericOrmPersistentType.this.getXmlAttributeMappings();
		}
		public XmlAttributeMapping getResourceElement(OrmPersistentAttribute contextElement) {
			return contextElement.getMapping().getXmlAttributeMapping();
		}
		public void moveContextElement(int index, OrmPersistentAttribute element) {
			GenericOrmPersistentType.this.moveSpecifiedAttribute_(index, element);
		}
		public void addContextElement(int index, XmlAttributeMapping resourceElement) {
			GenericOrmPersistentType.this.addSpecifiedAttribute_(index, resourceElement);
		}
		public void removeContextElement(OrmPersistentAttribute element) {
			GenericOrmPersistentType.this.removeSpecifiedAttribute_(element);
		}
	}


	// ********** virtual attributes **********

	public ListIterator<OrmReadOnlyPersistentAttribute> virtualAttributes() {
		return this.getVirtualAttributes().iterator();
	}

	public ListIterable<OrmReadOnlyPersistentAttribute> getVirtualAttributes() {
		return new LiveCloneListIterable<OrmReadOnlyPersistentAttribute>(this.virtualAttributes);
	}

	public int virtualAttributesSize() {
		return this.virtualAttributes.size();
	}

	protected void updateVirtualAttributes() {
		ContextContainerTools.update(this.virtualAttributeContainerAdapter);
	}

	/**
	 * Return all the Java resource attributes that have the appropriate access
	 * and do not have a corresponding <code>orm.xml</code> mapping currently
	 * specified in the <code>orm.xml</code> persistent type.
	 */
	protected Iterable<JavaResourcePersistentAttribute> getVirtualJavaResourceAttributes() {
		return new FilteringIterable<JavaResourcePersistentAttribute>(this.getJavaResourceAttributes()) {
				@Override
				protected boolean accept(JavaResourcePersistentAttribute javaResourceAttribute) {
					return GenericOrmPersistentType.this.javaResourceAttributeIsVirtual(javaResourceAttribute);
				}
			};
	}

	protected Iterable<JavaResourcePersistentAttribute> getJavaResourceAttributes() {
		return CollectionTools.iterable(this.javaResourceAttributes());
	}

	/**
	 * Return the Java resource attributes with the appropriate access type.
	 */
	protected Iterator<JavaResourcePersistentAttribute> javaResourceAttributes() {
		JavaResourcePersistentType javaResourceType = this.getJavaResourceType();
		return (javaResourceType != null) ?
				javaResourceType.persistableAttributes(this.getVirtualJavaAccess().getJavaAccessType()) :
				EmptyListIterator.<JavaResourcePersistentAttribute>instance();
	}

	protected JavaResourcePersistentType getJavaResourceType() {
		return (this.javaPersistentType == null) ? null : this.javaPersistentType.getResourcePersistentType();
	}

	/**
	 * Return the access type that determines which Java attributes are to be
	 * used for the <code>orm.xml</code> type's <em>virtual</em> attributes.
	 */
	protected AccessType getVirtualJavaAccess() {
		if (this.specifiedAccess != null) {
			return this.specifiedAccess;
		}
		if (this.mapping.isMetadataComplete()) {
			return this.defaultAccess;
		}
		AccessType javaAccess = this.javaPersistentType.getSpecifiedAccess();
		return (javaAccess != null) ? javaAccess : this.defaultAccess;
	}

	protected boolean javaResourceAttributeIsVirtual(JavaResourcePersistentAttribute javaResourceAttribute) {
		return this.getSpecifiedAttributeFor(javaResourceAttribute) == null;
	}

	protected OrmPersistentAttribute getSpecifiedAttributeFor(JavaResourcePersistentAttribute javaResourceAttribute) {
		return this.getSpecifiedAttributeFor(javaResourceAttribute, null);
	}

	/**
	 * Return the specified attribute corresponding to the specified Java
	 * resource attribute, ignoring the specified excluded attribute (since
	 * there can be more than one specified attribute per Java resource
	 * attribute; albeit erroneously).
	 */
	protected OrmPersistentAttribute getSpecifiedAttributeFor(JavaResourcePersistentAttribute javaResourceAttribute, OrmPersistentAttribute exclude) {
		for (OrmPersistentAttribute ormAttribute : this.getSpecifiedAttributes()) {
			if (ormAttribute == exclude) {
				continue;  // skip
			}
			if (ormAttribute.getJavaResourcePersistentAttribute() == javaResourceAttribute) {
				return ormAttribute;
			}
		}
		return null;
	}

	protected void moveVirtualAttribute(int index, OrmReadOnlyPersistentAttribute virtualAttribute) {
		this.moveItemInList(index, virtualAttribute, this.virtualAttributes, VIRTUAL_ATTRIBUTES_LIST);
	}

	protected void addVirtualAttribute(int index, JavaResourcePersistentAttribute javaResourceAttribute) {
		OrmReadOnlyPersistentAttribute virtualAttribute = this.buildVirtualAttribute(javaResourceAttribute);
		this.addItemToList(index, virtualAttribute, this.virtualAttributes, VIRTUAL_ATTRIBUTES_LIST);
	}

	protected OrmReadOnlyPersistentAttribute buildVirtualAttribute(JavaResourcePersistentAttribute javaResourceAttribute) {
		return this.getContextNodeFactory().buildVirtualOrmPersistentAttribute(this, javaResourceAttribute);
	}

	protected void removeVirtualAttribute(OrmReadOnlyPersistentAttribute virtualAttribute) {
		virtualAttribute.dispose();
		this.removeItemFromList(virtualAttribute, this.virtualAttributes, VIRTUAL_ATTRIBUTES_LIST);
	}

	/**
	 * virtual attribute container adapter
	 */
	protected class VirtualAttributeContainerAdapter
		implements ContextContainerTools.Adapter<OrmReadOnlyPersistentAttribute, JavaResourcePersistentAttribute>
	{
		public Iterable<OrmReadOnlyPersistentAttribute> getContextElements() {
			return GenericOrmPersistentType.this.getVirtualAttributes();
		}
		public Iterable<JavaResourcePersistentAttribute> getResourceElements() {
			return GenericOrmPersistentType.this.getVirtualJavaResourceAttributes();
		}
		public JavaResourcePersistentAttribute getResourceElement(OrmReadOnlyPersistentAttribute contextElement) {
			return contextElement.getJavaResourcePersistentAttribute();
		}
		public void moveContextElement(int index, OrmReadOnlyPersistentAttribute element) {
			GenericOrmPersistentType.this.moveVirtualAttribute(index, element);
		}
		public void addContextElement(int index, JavaResourcePersistentAttribute resourceElement) {
			GenericOrmPersistentType.this.addVirtualAttribute(index, resourceElement);
		}
		public void removeContextElement(OrmReadOnlyPersistentAttribute element) {
			GenericOrmPersistentType.this.removeVirtualAttribute(element);
		}
	}


	// ********** super persistent type **********

	public PersistentType getSuperPersistentType() {
		return this.superPersistentType;
	}

	protected void setSuperPersistentType(PersistentType persistentType) {
		PersistentType old = this.superPersistentType;
		this.superPersistentType = persistentType;
		this.firePropertyChanged(SUPER_PERSISTENT_TYPE_PROPERTY, old, persistentType);
	}

	protected PersistentType buildSuperPersistentType() {
		PersistentType spt = this.buildSuperPersistentType_();
		if (spt == null) {
			return null;
		}
		// check for circular inheritance
		return CollectionTools.contains(spt.inheritanceHierarchy(), this) ? null : spt;
	}

	protected PersistentType buildSuperPersistentType_() {
		return (this.javaPersistentType == null) ? null : this.javaPersistentType.getSuperPersistentType();
	}


	// ********** inheritance **********

	public Iterator<PersistentType> inheritanceHierarchy() {
		return this.getInheritanceHierarchy().iterator();
	}

	public Iterable<PersistentType> getInheritanceHierarchy() {
		return this.getInheritanceHierarchyOf(this);
	}

	public Iterator<PersistentType> ancestors() {
		return this.getAncestors().iterator();
	}

	public Iterable<PersistentType> getAncestors() {
		return this.getInheritanceHierarchyOf(this.superPersistentType);
	}

	protected Iterable<PersistentType> getInheritanceHierarchyOf(PersistentType start) {
		// using a chain iterable to traverse up the inheritance tree
		return new ChainIterable<PersistentType>(start) {
			@Override
			protected PersistentType nextLink(PersistentType persistentType) {
				return persistentType.getSuperPersistentType();
			}
		};
	}


	// ********** declaring type name **********

	public String getDeclaringTypeName() {
		return this.declaringTypeName;
	}

	protected void setDeclaringTypeName(String name) {
		String old = this.declaringTypeName;
		this.declaringTypeName = name;
		this.firePropertyChanged(DECLARING_TYPE_NAME_PROPERTY, old, name);
	}

	protected String buildDeclaringTypeName() {
		return this.isJpa2_0Compatible() ? this.buildDeclaringTypeName_() : null;
	}

	protected String buildDeclaringTypeName_() {
		return (this.javaPersistentType == null) ?
				null : ((JavaPersistentType2_0) this.javaPersistentType).getDeclaringTypeName();
	}


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

	protected MetamodelSourceType.Synchronizer buildMetamodelSynchronizer() {
		return this.isJpa2_0Compatible() ?
				this.getJpaFactory2_0().buildMetamodelSynchronizer(this) :
				null;
	}

	public IFile getMetamodelFile() {
		return (this.javaPersistentType == null) ? null : this.metamodelSynchronizer.getFile();
	}

	public void initializeMetamodel() {
		// do nothing - probably shouldn't be called...
	}

	public boolean isManaged() {
		return true;
	}

	/**
	 * All <code>orm.xml</code> persistent types must be able to generate a static metamodel
	 * because 1.0 <code>orm.xml</code> files can be referenced from 2.0 persistence.xml files.
	 */
	public void synchronizeMetamodel(Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
		if (this.javaPersistentType != null) {
			this.metamodelSynchronizer.synchronize(memberTypeTree);
		}
	}

	public void printBodySourceOn(BodySourceWriter pw, Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
		if (this.javaPersistentType != null) {
			this.metamodelSynchronizer.printBodySourceOn(pw, memberTypeTree);
		}
	}

	public void disposeMetamodel() {
		// do nothing - probably shouldn't be called...
	}


	// ********** JpaStructureNode implementation **********

	public String getId() {
		return OrmStructureNodes.PERSISTENT_TYPE_ID;
	}

	public JpaStructureNode getStructureNode(int textOffset) {
		for (OrmPersistentAttribute attribute : this.getSpecifiedAttributes()) {
			if (attribute.contains(textOffset)) {
				return attribute;
			}
		}
		return this;
	}

	public TextRange getSelectionTextRange() {
		return this.mapping.getSelectionTextRange();
	}

	public void dispose() {
		if (this.javaPersistentType != null) {
			this.javaPersistentType.dispose();
		}
		for (OrmReadOnlyPersistentAttribute virtualAttribute : this.getVirtualAttributes()) {
			virtualAttribute.dispose();
		}
	}


	// ********** PersistentType.Owner implementation **********

	public AccessType getOverridePersistentTypeAccess() {
		if (this.specifiedAccess != null) {
			return this.specifiedAccess;
		}

		if (this.superPersistentType instanceof OrmPersistentType) {
			AccessType accessType = ((OrmPersistentType) this.superPersistentType).getSpecifiedAccess();
			if (accessType != null) {
				return accessType;
			}
		}

		if (this.mapping.isMetadataComplete()) {
			AccessType accessType = this.getOwnerDefaultAccess();
			if (accessType != null) {
				return accessType;
			}
		}

		// no override access type
		return null;
	}

	public AccessType getDefaultPersistentTypeAccess() {
		if (this.superPersistentType instanceof OrmPersistentType) {
			AccessType accessType = ((OrmPersistentType) this.superPersistentType).getDefaultAccess();
			if (accessType != null) {
				return accessType;
			}
		}

		return this.getOwnerDefaultAccess();
	}


	//*********** refactoring ***********

	public Iterable<DeleteEdit> createDeleteTypeEdits(IType type) {
		return this.isFor(type.getFullyQualifiedName('.')) ?
				new SingleElementIterable<DeleteEdit>(this.mapping.createDeleteEdit()) :
				EmptyIterable.<DeleteEdit>instance();
	}

	@SuppressWarnings("unchecked")
	public Iterable<ReplaceEdit> createRenameTypeEdits(IType originalType, String newName) {
		return new CompositeIterable<ReplaceEdit>(
				this.mapping.createRenameTypeEdits(originalType, newName),
				this.createSpecifiedAttributesRenameTypeEdits(originalType, newName)
			);
	}

	protected Iterable<ReplaceEdit> createSpecifiedAttributesRenameTypeEdits(final IType originalType, final String newName) {
		return new CompositeIterable<ReplaceEdit>(
			new TransformationIterable<OrmPersistentAttribute, Iterable<ReplaceEdit>>(this.getSpecifiedAttributes()) {
				@Override
				protected Iterable<ReplaceEdit> transform(OrmPersistentAttribute persistentAttribute) {
					return persistentAttribute.createRenameTypeEdits(originalType, newName);
				}
			}
		);
	}

	@SuppressWarnings("unchecked")
	public Iterable<ReplaceEdit> createMoveTypeEdits(IType originalType, IPackageFragment newPackage) {
		return new CompositeIterable<ReplaceEdit>(
				this.mapping.createMoveTypeEdits(originalType, newPackage),
				this.createSpecifiedAttributesMoveTypeEdits(originalType, newPackage)
			);
	}

	protected Iterable<ReplaceEdit> createSpecifiedAttributesMoveTypeEdits(final IType originalType, final IPackageFragment newPackage) {
		return new CompositeIterable<ReplaceEdit>(
			new TransformationIterable<OrmPersistentAttribute, Iterable<ReplaceEdit>>(this.getSpecifiedAttributes()) {
				@Override
				protected Iterable<ReplaceEdit> transform(OrmPersistentAttribute persistentAttribute) {
					return persistentAttribute.createMoveTypeEdits(originalType, newPackage);
				}
			}
		);
	}

	@SuppressWarnings("unchecked")
	public Iterable<ReplaceEdit> createRenamePackageEdits(IPackageFragment originalPackage, String newName) {
		return new CompositeIterable<ReplaceEdit>(
				this.mapping.createRenamePackageEdits(originalPackage, newName),
				this.createSpecifiedAttributesRenamePackageEdits(originalPackage, newName)
			);
	}

	protected Iterable<ReplaceEdit> createSpecifiedAttributesRenamePackageEdits(final IPackageFragment originalPackage, final String newName) {
		return new CompositeIterable<ReplaceEdit>(
			new TransformationIterable<OrmPersistentAttribute, Iterable<ReplaceEdit>>(this.getSpecifiedAttributes()) {
				@Override
				protected Iterable<ReplaceEdit> transform(OrmPersistentAttribute persistentAttribute) {
					return persistentAttribute.createRenamePackageEdits(originalPackage, newName);
				}
			}
		);
	}


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

	@Override
	public void validate(List<IMessage> messages, IReporter reporter) {
		super.validate(messages, reporter);
		this.validateClass(messages);
		this.validateMapping(messages, reporter);
		this.validateAttributes(messages, reporter);
	}

	protected void validateClass(List<IMessage> messages) {
		if (this.javaPersistentType == null) {
			messages.add(
				DefaultJpaValidationMessages.buildMessage(
					IMessage.HIGH_SEVERITY,
					JpaValidationMessages.PERSISTENT_TYPE_UNRESOLVED_CLASS,
					new String[] {this.getName()},
					this,
					this.mapping.getClassTextRange()
				)
			);
		}
	}

	protected void validateMapping(List<IMessage> messages, IReporter reporter) {
		try {
			this.mapping.validate(messages, reporter);
		} catch(Throwable t) {
			JptCorePlugin.log(t);
		}
	}

	protected void validateAttributes(List<IMessage> messages, IReporter reporter) {
		for (Iterator<OrmReadOnlyPersistentAttribute> stream = this.attributes(); stream.hasNext(); ) {
			this.validateAttribute(stream.next(), messages, reporter);
		}
	}

	protected void validateAttribute(OrmReadOnlyPersistentAttribute attribute, List<IMessage> messages, IReporter reporter) {
		try {
			attribute.validate(messages, reporter);
		} catch(Throwable t) {
			JptCorePlugin.log(t);
		}
	}

	public TextRange getValidationTextRange() {
		return this.mapping.getValidationTextRange();
	}


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

	@Override
	public EntityMappings getParent() {
		return (EntityMappings) super.getParent();
	}

	protected EntityMappings getEntityMappings() {
		return this.getParent();
	}

	public String getDefaultPackage() {
		return this.getEntityMappings().getPackage();
	}

	public boolean isFor(String typeName) {
		String name = this.getName();
		if (name == null) {
			return false;
		}
		if (name.equals(typeName)) {
			return true;
		}
		String defaultPackage = this.getDefaultPackage();
		if (defaultPackage == null) {
			return false;
		}
		return (defaultPackage + '.' +  name).equals(typeName);
	}

	public boolean isIn(IPackageFragment packageFragment) {
		String packageName = this.getPackageName();
		if (Tools.valuesAreEqual(packageName, packageFragment.getElementName())) {
			return true;
		}
		String defaultPackage = this.getDefaultPackage();
		if (defaultPackage == null) {
			return false;
		}
		packageName = (packageName == null) ? defaultPackage : defaultPackage + '.' + packageName;
		return packageName.equals(packageFragment.getElementName());
	}

	protected String getPackageName() {
		String className = this.getName();
		if (className == null) {
			return null;
		}
		int lastPeriod = className.lastIndexOf('.');
		return (lastPeriod == -1) ? null : className.substring(0, lastPeriod);
	}

	public boolean contains(int textOffset) {
		return this.mapping.containsOffset(textOffset);
	}

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