/*******************************************************************************
 * Copyright (c) 2006, 2011 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0, which accompanies this distribution
 * and is available at http://www.eclipse.org/legal/epl-v10.html.
 *
 * Contributors:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.jpa.core.internal.jpa1.context.orm;

import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
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.resource.java.JavaResourceAbstractType;
import org.eclipse.jpt.common.core.resource.java.JavaResourceAnnotatedElement.Kind;
import org.eclipse.jpt.common.core.resource.java.JavaResourceField;
import org.eclipse.jpt.common.core.resource.java.JavaResourceMethod;
import org.eclipse.jpt.common.core.resource.java.JavaResourceType;
import org.eclipse.jpt.common.core.utility.BodySourceWriter;
import org.eclipse.jpt.common.core.utility.TextRange;
import org.eclipse.jpt.common.utility.Filter;
import org.eclipse.jpt.common.utility.internal.ClassName;
import org.eclipse.jpt.common.utility.internal.CollectionTools;
import org.eclipse.jpt.common.utility.internal.StringTools;
import org.eclipse.jpt.common.utility.internal.Tools;
import org.eclipse.jpt.common.utility.internal.iterables.ChainIterable;
import org.eclipse.jpt.common.utility.internal.iterables.CompositeIterable;
import org.eclipse.jpt.common.utility.internal.iterables.CompositeListIterable;
import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable;
import org.eclipse.jpt.common.utility.internal.iterables.EmptyListIterable;
import org.eclipse.jpt.common.utility.internal.iterables.FilteringIterable;
import org.eclipse.jpt.common.utility.internal.iterables.ListIterable;
import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneListIterable;
import org.eclipse.jpt.common.utility.internal.iterables.SingleElementIterable;
import org.eclipse.jpt.common.utility.internal.iterables.SuperListIterableWrapper;
import org.eclipse.jpt.common.utility.internal.iterables.TransformationIterable;
import org.eclipse.jpt.jpa.core.JpaStructureNode;
import org.eclipse.jpt.jpa.core.JptJpaCorePlugin;
import org.eclipse.jpt.jpa.core.context.AccessType;
import org.eclipse.jpt.jpa.core.context.PersistentType;
import org.eclipse.jpt.jpa.core.context.ReadOnlyPersistentAttribute;
import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType;
import org.eclipse.jpt.jpa.core.context.orm.EntityMappings;
import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMapping;
import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMappingDefinition;
import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute;
import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentType;
import org.eclipse.jpt.jpa.core.context.orm.OrmReadOnlyPersistentAttribute;
import org.eclipse.jpt.jpa.core.context.orm.OrmStructureNodes;
import org.eclipse.jpt.jpa.core.context.orm.OrmTypeMapping;
import org.eclipse.jpt.jpa.core.context.orm.OrmTypeMappingDefinition;
import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools;
import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaPersistentType;
import org.eclipse.jpt.jpa.core.internal.context.java.PropertyAccessor;
import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode;
import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages;
import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages;
import org.eclipse.jpt.jpa.core.jpa2.context.MetamodelSourceType;
import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaPersistentType2_0;
import org.eclipse.jpt.jpa.core.jpa2.context.orm.OrmPersistentType2_0;
import org.eclipse.jpt.jpa.core.resource.orm.Attributes;
import org.eclipse.jpt.jpa.core.resource.orm.OrmPackage;
import org.eclipse.jpt.jpa.core.resource.orm.XmlAttributeMapping;
import org.eclipse.jpt.jpa.core.resource.orm.XmlTypeMapping;
import org.eclipse.jpt.jpa.core.resource.xml.EmfTools;
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 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.javaPersistentType != null) ?
				this.javaPersistentType.getName() :
				this.getMappingClassName();
	}

	protected String getMappingClassName() {
		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() {
		JavaResourceAbstractType resourceType = this.resolveJavaResourceType();
		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.getJavaResourceType() == resourceType) {
					this.javaPersistentType.update();
				} else {
					this.javaPersistentType.dispose();
					this.setJavaPersistentType(this.buildJavaPersistentType(resourceType));
				}
			}
		}
	}

	/**
	 * Use {@link #getMappingClassName()} instead of {@link #getName()} to
	 * look up the Java resource type because {@link #getName()}
	 * simply delegates to the existing Java resource persistent type. (In
	 * which case we wouldn't need to resolve it, would we?) [bug 339560]
	 * @see #updateJavaPersistentType()
	 */
	protected JavaResourceAbstractType resolveJavaResourceType() {
		return this.getEntityMappings().resolveJavaResourceType(this.getMappingClassName());
	}

	/**
	 * Return null it's an enum; don't build a JavaPersistentType
	 */
	protected JavaPersistentType buildJavaPersistentType(JavaResourceAbstractType jrat) {
		return jrat.getKind() == Kind.TYPE ? this.buildJavaPersistentType((JavaResourceType) jrat) : null;
	}

	protected JavaPersistentType buildJavaPersistentType(JavaResourceType 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 **********

	@SuppressWarnings("unchecked")
	public ListIterable<OrmReadOnlyPersistentAttribute> getAttributes() {
		return new CompositeListIterable<OrmReadOnlyPersistentAttribute>(this.getReadOnlySpecifiedAttributes(), this.getVirtualAttributes());
	}
	
	//TODO remove this compatibility method in the Juno release
	public ListIterator<OrmReadOnlyPersistentAttribute> attributes() {
		return this.getAttributes().iterator();
	}


	public int getAttributesSize() {
		return this.getSpecifiedAttributesSize() + this.getVirtualAttributesSize();
	}

	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 Iterable<ReadOnlyPersistentAttribute> getAllAttributes() {
		return new CompositeIterable<ReadOnlyPersistentAttribute>(
				new TransformationIterable<PersistentType, Iterable<ReadOnlyPersistentAttribute>>(this.getInheritanceHierarchy()) {
					@Override
					protected Iterable<ReadOnlyPersistentAttribute> transform(PersistentType pt) {
						return new SuperListIterableWrapper<ReadOnlyPersistentAttribute>(pt.getAttributes());
					}
				}
			);
	}
	
	//TODO remove this compatibility method in the Juno release
	public Iterator<ReadOnlyPersistentAttribute> allAttributes() {
		return getAllAttributes().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)
		if (specifiedAttribute.getJavaResourceAttribute() != null) {
			if (specifiedAttribute.getJavaResourceAttribute().getKind() == Kind.FIELD) {
				JavaResourceField javaResourceField = (JavaResourceField) specifiedAttribute.getJavaResourceAttribute();
				if (this.javaResourceFieldWillBeVirtual(javaResourceField, specifiedAttribute)) {
					virtualAttribute = this.buildVirtualAttribute(javaResourceField);
					this.virtualAttributes.add(virtualIndex, virtualAttribute);
				}
			}
			else {
				PropertyAccessor propertyAccessor = (PropertyAccessor) specifiedAttribute.getJavaPersistentAttribute().getAccessor();
				JavaResourceMethod resourceGetter = propertyAccessor.getResourceGetter();
				JavaResourceMethod resourceSetter = propertyAccessor.getResourceSetter();
				
				if (this.javaResourcePropertyWillBeVirtual(resourceGetter, resourceSetter, specifiedAttribute)) {
					virtualAttribute = this.buildVirtualAttribute(resourceGetter, resourceSetter);
					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 javaResourceFieldWillBeVirtual(JavaResourceField javaResourceField, OrmPersistentAttribute specifiedAttributeToBeRemoved) {
		return CollectionTools.contains(this.getJavaResourceFields(), javaResourceField) &&
				(this.getSpecifiedAttributeFor(javaResourceField, specifiedAttributeToBeRemoved) == null);
	}

	/**
	 * 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 javaResourcePropertyWillBeVirtual(JavaResourceMethod javaResourceGetter, JavaResourceMethod javaResourceSetter, OrmPersistentAttribute specifiedAttributeToBeRemoved) {
		return CollectionTools.contains(this.getJavaResourceMethods(), javaResourceGetter) &&
				CollectionTools.contains(this.getJavaResourceMethods(), javaResourceSetter) &&
				(this.getSpecifiedAttributeFor(javaResourceGetter, javaResourceSetter, 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 ListIterable<OrmPersistentAttribute> getSpecifiedAttributes() {
		return new LiveCloneListIterable<OrmPersistentAttribute>(this.specifiedAttributes);
	}

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

	public int getSpecifiedAttributesSize() {
		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 ListIterable<OrmReadOnlyPersistentAttribute> getVirtualAttributes() {
		return new LiveCloneListIterable<OrmReadOnlyPersistentAttribute>(this.virtualAttributes);
	}

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

	/**
	 * The attributes are synchronized during the <em>update</em> because
	 * the list of resource attributes is determined by the access type
	 * which can be controlled in a number of different places....
	 */
	protected void updateVirtualAttributes() {
		if (getVirtualJavaAccess() == AccessType.FIELD) {
			this.syncFieldAccessVirtualAttributes();
		}
		else if (getVirtualJavaAccess() == AccessType.PROPERTY) {
			this.syncPropertyAccessVirtualAttributes();
		}
	}

	/**
	 * Initialize the attributes for AccessType.FIELD
	 * 1. all non-transient, non-static fields
	 * 2. all annotated methods(getters/setters)
	 */
	private void syncFieldAccessVirtualAttributes() {
		HashSet<OrmReadOnlyPersistentAttribute> contextAttributes = CollectionTools.set(this.getVirtualAttributes());

		this.syncFieldVirtualAttributes(contextAttributes, buildNonTransientNonStaticResourceFieldsFilter());
		if (!getMapping().isMetadataComplete()) {
			this.syncAnnotatedPropertyVirtualAttributes(contextAttributes);
		}

		// remove any leftover context attributes
		for (OrmReadOnlyPersistentAttribute contextAttribute : contextAttributes) {
			this.removeVirtualAttribute(contextAttribute);
		}
	}

	/**
	 * Initialize the attributes for XmlAccessType.PROPERTY
	 * 1. all getter/setter javabeans pairs
	 * 2. all annotated fields
	 * 3. all annotated methods getters/setters that don't have a matching pair
	 */
	private void syncPropertyAccessVirtualAttributes() {
		HashSet<OrmReadOnlyPersistentAttribute> contextAttributes = CollectionTools.set(this.getVirtualAttributes());

		if (!getMapping().isMetadataComplete()) {
			this.syncFieldVirtualAttributes(contextAttributes, AbstractJavaPersistentType.ANNOTATED_RESOURCE_FIELDS_FILTER);
		}

		Collection<JavaResourceMethod> resourceMethods = CollectionTools.collection(this.getJavaResourceMethods());
		//iterate through all resource methods searching for persistable getters
		for (JavaResourceMethod getterMethod : this.getJavaResourceMethods(this.buildPersistablePropertyGetterMethodsFilter())) {
			JavaResourceMethod setterMethod = AbstractJavaPersistentType.getValidSiblingSetMethod(getterMethod, resourceMethods);
			if (javaResourcePropertyIsVirtual(getterMethod, setterMethod)) {
				if (AbstractJavaPersistentType.methodsArePersistableProperties(getterMethod, setterMethod)) {
					boolean match = false;
					for (Iterator<OrmReadOnlyPersistentAttribute> stream = contextAttributes.iterator(); stream.hasNext();) {
						OrmReadOnlyPersistentAttribute contextAttribute = stream.next();
						if (contextAttribute.isFor(getterMethod, setterMethod)) {
							match = true;
							contextAttribute.update();
							stream.remove();
							break;
						}
					}
					if (!match) {
						this.addVirtualAttribute(getVirtualAttributesSize(), this.buildVirtualAttribute(getterMethod, setterMethod));
					}
				}
			}
			resourceMethods.remove(getterMethod);
			resourceMethods.remove(setterMethod);
		}
		this.syncRemainingResourceVirtualMethods(contextAttributes, resourceMethods);

		// remove any leftover context attributes
		for (OrmReadOnlyPersistentAttribute contextAttribute : contextAttributes) {
			this.removeVirtualAttribute(contextAttribute);
		}
	}

	private void syncAnnotatedPropertyVirtualAttributes(HashSet<OrmReadOnlyPersistentAttribute> contextAttributes) {
		Collection<JavaResourceMethod> resourceMethods = CollectionTools.collection(this.getJavaResourceMethods());
		//iterate through all resource methods searching for persistable getters
		for (JavaResourceMethod getterMethod : this.getJavaResourceMethods(buildPersistablePropertyGetterMethodsFilter())) {
			JavaResourceMethod setterMethod = AbstractJavaPersistentType.getValidSiblingSetMethod(getterMethod, resourceMethods);
			if (javaResourcePropertyIsVirtual(getterMethod, setterMethod)) {
				if (getterMethod.isAnnotated() || (setterMethod != null && setterMethod.isAnnotated())) {
					boolean match = false;
					for (Iterator<OrmReadOnlyPersistentAttribute> stream = contextAttributes.iterator(); stream.hasNext();) {
						OrmReadOnlyPersistentAttribute contextAttribute = stream.next();
						if (contextAttribute.isFor(getterMethod, setterMethod)) {
							match = true;
							contextAttribute.update();
							stream.remove();
							break;
						}
					}
					if (!match) {
						this.addVirtualAttribute(getVirtualAttributesSize(), this.buildVirtualAttribute(getterMethod, setterMethod));
					}
				}
			}
			resourceMethods.remove(getterMethod);
			resourceMethods.remove(setterMethod);
		}
		this.syncRemainingResourceVirtualMethods(contextAttributes, resourceMethods);
	}

	private void syncFieldVirtualAttributes(HashSet<OrmReadOnlyPersistentAttribute> contextAttributes, Filter<JavaResourceField> filter) {
		for (JavaResourceField resourceField : this.getVirtualJavaResourceFields(filter)) {
			boolean match = false;
			for (Iterator<OrmReadOnlyPersistentAttribute> stream = contextAttributes.iterator(); stream.hasNext(); ) {
				OrmReadOnlyPersistentAttribute contextAttribute = stream.next();
				if (contextAttribute.isFor(resourceField)) {
					match = true;
					contextAttribute.update();
					stream.remove();
					break;
				}
			}
			if (!match) {
				// added elements are sync'ed during construction or will be
				// updated during the next "update" (which is triggered by
				// their addition to the model)
				this.addVirtualAttribute(this.getVirtualAttributesSize(), this.buildVirtualAttribute(resourceField));
			}
		}
	}

	private void syncRemainingResourceVirtualMethods(HashSet<OrmReadOnlyPersistentAttribute> contextAttributes, Collection<JavaResourceMethod> resourceMethods) {
		//iterate through remaining resource methods and search for those that are annotated.
		//all getter methods will already be used.
		for (JavaResourceMethod resourceMethod : resourceMethods) {
			if (resourceMethod.isAnnotated()) {
				boolean match = false;
				//annotated setter(or other random method) with no corresponding getter, bring into context model for validation purposes
				for (Iterator<OrmReadOnlyPersistentAttribute> stream = contextAttributes.iterator(); stream.hasNext();) {
					OrmReadOnlyPersistentAttribute contextAttribute = stream.next();
					if (contextAttribute.isFor(null, resourceMethod)) {
						match = true;
						contextAttribute.update();
						stream.remove();
						break;
					}
				}
				if (!match) {
					this.addVirtualAttribute(getVirtualAttributesSize(), this.buildVirtualAttribute(null, resourceMethod));
				}
			}
		}
	}

	/**
	 * Return all the Java resource fields that do not have a 
	 * corresponding <code>orm.xml</code> mapping currently
	 * specified in the <code>orm.xml</code> persistent type.
	 */
	protected Iterable<JavaResourceField> getVirtualJavaResourceFields() {
		return new FilteringIterable<JavaResourceField>(this.getJavaResourceFields()) {
				@Override
				protected boolean accept(JavaResourceField javaResourceField) {
					return GenericOrmPersistentType.this.javaResourceFieldIsVirtual(javaResourceField);
				}
			};
	}

	protected Iterable<JavaResourceField> getJavaResourceFields() {
		JavaResourceType javaResourceType = this.getJavaResourceType();
		if (javaResourceType == null) {
			return EmptyListIterable.instance();
		}
		return javaResourceType.getFields();
	}

	protected Iterable<JavaResourceField> getVirtualJavaResourceFields(Filter<JavaResourceField> filter) {
		return new FilteringIterable<JavaResourceField>(getVirtualJavaResourceFields(), filter);
	}

	protected Iterable<JavaResourceMethod> getJavaResourceMethods(Filter<JavaResourceMethod> filter) {
		return new FilteringIterable<JavaResourceMethod>(getJavaResourceMethods(), filter);
	}

	protected Iterable<JavaResourceMethod> getJavaResourceMethods() {
		JavaResourceType javaResourceType = this.getJavaResourceType();
		if (javaResourceType == null) {
			return EmptyListIterable.instance();
		}
		return javaResourceType.getMethods();
	}

	public static Filter<JavaResourceField> buildNonTransientNonStaticResourceFieldsFilter() {
		return AbstractJavaPersistentType.buildNonTransientNonStaticResourceFieldsFilter();
	}

	protected Filter<JavaResourceMethod> buildPersistablePropertyGetterMethodsFilter() {
		return new Filter<JavaResourceMethod>() {
			public boolean accept(JavaResourceMethod resourceMethod) {
				return AbstractJavaPersistentType.methodIsPersistablePropertyGetter(resourceMethod, getJavaResourceMethods());
			}
		};
	}

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

	/**
	 * 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 == null ? null : this.javaPersistentType.getSpecifiedAccess();
		return (javaAccess != null) ? javaAccess : this.defaultAccess;
	}

	protected boolean javaResourceFieldIsVirtual(JavaResourceField javaResourceField) {
		return this.getSpecifiedAttributeFor(javaResourceField) == null;
	}

	protected OrmPersistentAttribute getSpecifiedAttributeFor(JavaResourceField javaResourceField) {
		return this.getSpecifiedAttributeFor(javaResourceField, null);
	}

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

	protected boolean javaResourcePropertyIsVirtual(JavaResourceMethod javaResourceGetter, JavaResourceMethod javaResourceSetter) {
		return this.getSpecifiedAttributeFor(javaResourceGetter, javaResourceSetter) == null;
	}

	protected OrmPersistentAttribute getSpecifiedAttributeFor(JavaResourceMethod javaResourceGetter, JavaResourceMethod javaResourceSetter) {
		return this.getSpecifiedAttributeFor(javaResourceGetter, javaResourceSetter, null);
	}

	/**
	 * Return the specified attribute corresponding to the specified Java
	 * resource field, ignoring the specified excluded attribute (since
	 * there can be more than one specified attribute per Java resource
	 * attribute; albeit erroneously).
	 */
	protected OrmPersistentAttribute getSpecifiedAttributeFor(JavaResourceMethod javaResourceGetter, JavaResourceMethod javaResourceSetter, OrmPersistentAttribute exclude) {
		for (OrmPersistentAttribute ormAttribute : this.getSpecifiedAttributes()) {
			if (ormAttribute == exclude) {
				continue;  // skip
			}
			if (ormAttribute.isFor(javaResourceGetter, javaResourceSetter)) {
				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, OrmReadOnlyPersistentAttribute virtualAttribute) {
		this.addItemToList(index, virtualAttribute, this.virtualAttributes, VIRTUAL_ATTRIBUTES_LIST);
	}

	protected OrmReadOnlyPersistentAttribute buildVirtualAttribute(JavaResourceField javaResourceField) {
		return this.getContextNodeFactory().buildVirtualOrmPersistentField(this, javaResourceField);
	}

	protected OrmReadOnlyPersistentAttribute buildVirtualAttribute(JavaResourceMethod javaResourceGetter, JavaResourceMethod javaResourceSetter) {
		return this.getContextNodeFactory().buildVirtualOrmPersistentProperty(this, javaResourceGetter, javaResourceSetter);
	}

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


	// ********** 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.getInheritanceHierarchy(), this) ? null : spt;
	}

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


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

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

	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) {
			JptJpaCorePlugin.log(t);
		}
	}

	protected void validateAttributes(List<IMessage> messages, IReporter reporter) {
		for (OrmReadOnlyPersistentAttribute attribute : this.getAttributes()) {
			this.validateAttribute(attribute, messages, reporter);
		}
	}

	protected void validateAttribute(OrmReadOnlyPersistentAttribute attribute, List<IMessage> messages, IReporter reporter) {
		try {
			attribute.validate(messages, reporter);
		} catch(Throwable t) {
			JptJpaCorePlugin.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);
	}

	public PersistentType getOverriddenPersistentType() {
		return this.mapping.isMetadataComplete() ? null : this.javaPersistentType;
	}

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