/*******************************************************************************
 * Copyright (c) 2007, 2009 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.context.persistence;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.Vector;
import org.eclipse.core.runtime.content.IContentType;
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.Embeddable;
import org.eclipse.jpt.core.context.Entity;
import org.eclipse.jpt.core.context.Generator;
import org.eclipse.jpt.core.context.MappingFilePersistenceUnitDefaults;
import org.eclipse.jpt.core.context.PersistentType;
import org.eclipse.jpt.core.context.Query;
import org.eclipse.jpt.core.context.TypeMapping;
import org.eclipse.jpt.core.context.persistence.ClassRef;
import org.eclipse.jpt.core.context.persistence.JarFileRef;
import org.eclipse.jpt.core.context.persistence.MappingFileRef;
import org.eclipse.jpt.core.context.persistence.Persistence;
import org.eclipse.jpt.core.context.persistence.PersistenceStructureNodes;
import org.eclipse.jpt.core.context.persistence.PersistenceUnit;
import org.eclipse.jpt.core.context.persistence.PersistenceUnitTransactionType;
import org.eclipse.jpt.core.internal.context.AbstractXmlContextNode;
import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
import org.eclipse.jpt.core.resource.persistence.PersistenceFactory;
import org.eclipse.jpt.core.resource.persistence.XmlJarFileRef;
import org.eclipse.jpt.core.resource.persistence.XmlJavaClassRef;
import org.eclipse.jpt.core.resource.persistence.XmlMappingFileRef;
import org.eclipse.jpt.core.resource.persistence.XmlPersistenceUnit;
import org.eclipse.jpt.core.resource.persistence.XmlProperties;
import org.eclipse.jpt.core.resource.persistence.XmlProperty;
import org.eclipse.jpt.core.utility.TextRange;
import org.eclipse.jpt.utility.internal.CollectionTools;
import org.eclipse.jpt.utility.internal.HashBag;
import org.eclipse.jpt.utility.internal.iterators.CloneIterator;
import org.eclipse.jpt.utility.internal.iterators.CloneListIterator;
import org.eclipse.jpt.utility.internal.iterators.CompositeIterator;
import org.eclipse.jpt.utility.internal.iterators.CompositeListIterator;
import org.eclipse.jpt.utility.internal.iterators.EmptyIterator;
import org.eclipse.jpt.utility.internal.iterators.FilteringIterator;
import org.eclipse.jpt.utility.internal.iterators.TransformationIterator;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;

/**
 * @see PersistenceUnit
 */
public abstract class AbstractPersistenceUnit
	extends AbstractXmlContextNode
	implements PersistenceUnit
{
	protected XmlPersistenceUnit xmlPersistenceUnit;

	protected String name;

	protected PersistenceUnitTransactionType specifiedTransactionType;
	protected PersistenceUnitTransactionType defaultTransactionType;

	protected String description;

	protected String provider;

	protected String jtaDataSource;
	protected String nonJtaDataSource;

	protected final Vector<MappingFileRef> specifiedMappingFileRefs = new Vector<MappingFileRef>();
	protected MappingFileRef impliedMappingFileRef;

	protected final Vector<JarFileRef> jarFileRefs = new Vector<JarFileRef>();

	protected final Vector<ClassRef> specifiedClassRefs = new Vector<ClassRef>();
	protected final Vector<ClassRef> impliedClassRefs = new Vector<ClassRef>();

	protected Boolean specifiedExcludeUnlistedClasses;

	protected final Vector<Property> properties = new Vector<Property>();

	/* global generator definitions, defined elsewhere in model */
	protected final Vector<Generator> generators = new Vector<Generator>();

	/* global query definitions, defined elsewhere in model */
	protected final Vector<Query> queries = new Vector<Query>();
	
	protected final Set<String> rootEntities = new HashSet<String>();
	
	protected AccessType defaultAccess;
	protected String defaultCatalog;
	protected String defaultSchema;
	protected boolean defaultCascadePersist;


	// ********** construction/initialization **********

	/**
	 * NB: Be careful changing the order of the statements in this method
	 * (bug 258701 is one reason).
	 */
	protected AbstractPersistenceUnit(Persistence parent, XmlPersistenceUnit xmlPersistenceUnit) {
		super(parent);
		this.xmlPersistenceUnit = xmlPersistenceUnit;
		this.name = xmlPersistenceUnit.getName();
		this.specifiedExcludeUnlistedClasses = xmlPersistenceUnit.getExcludeUnlistedClasses();
		this.specifiedTransactionType = this.buildSpecifiedTransactionType();
		this.defaultTransactionType = this.buildDefaultTransactionType();
		this.description = xmlPersistenceUnit.getDescription();
		this.provider = xmlPersistenceUnit.getProvider();
		this.jtaDataSource = xmlPersistenceUnit.getJtaDataSource();
		this.nonJtaDataSource = xmlPersistenceUnit.getNonJtaDataSource();
		this.specifiedExcludeUnlistedClasses = xmlPersistenceUnit.getExcludeUnlistedClasses();

		this.initializeJarFileRefs();

		this.initializeProperties();

		//initialize specified classRefs before mappingFileRefs because of 
		//JpaFile rootStructureNode, we want the mapping file to "win",
		//as it would in a Jpa runtime implementation
		this.initializeSpecifiedClassRefs();
		this.initializeMappingFileRefs();
		//initialize implied classRefs last since they depend on both
		//specified classRefs and mappingFileRefs
		this.initializeImpliedClassRefs();
		this.initializePersistenceUnitDefaults();
	}

	/**
	 * These lists are just copies of what is distributed across the context
	 * model; so, if they have (virtually) changed, the resulting update has
	 * already been triggered. We don't need to trigger another one here.
	 */
	@Override
	protected void addNonUpdateAspectNamesTo(Set<String> nonUpdateAspectNames) {
		super.addNonUpdateAspectNamesTo(nonUpdateAspectNames);
		nonUpdateAspectNames.add(GENERATORS_LIST);
		nonUpdateAspectNames.add(QUERIES_LIST);
	}

	protected void initializeJarFileRefs() {
		for (XmlJarFileRef xmlJarFileRef : this.xmlPersistenceUnit.getJarFiles()) {
			this.jarFileRefs.add(this.buildJarFileRef(xmlJarFileRef));
		}
	}

	protected void initializeProperties() {
		XmlProperties xmlProperties = this.xmlPersistenceUnit.getProperties();
		if (xmlProperties == null) {
			return;
		}
		for (XmlProperty xmlProperty : xmlProperties.getProperties()) {
			this.properties.add(this.buildProperty(xmlProperty));
		}
	}

	protected void initializeSpecifiedClassRefs() {
		for (XmlJavaClassRef xmlJavaClassRef : this.xmlPersistenceUnit.getClasses()) {
			this.specifiedClassRefs.add(this.buildClassRef(xmlJavaClassRef));
		}
	}

	protected void initializeMappingFileRefs() {
		for (XmlMappingFileRef xmlMappingFileRef : this.xmlPersistenceUnit.getMappingFiles()) {
			this.specifiedMappingFileRefs.add(this.buildSpecifiedMappingFileRef(xmlMappingFileRef));
		}
		if ( ! this.impliedMappingFileIsSpecified() && this.impliedMappingFileExists()) {
			this.impliedMappingFileRef = this.buildImpliedMappingFileRef();
		}
	}

	protected void initializeImpliedClassRefs() {
		if ( ! this.excludesUnlistedClasses()) {
			this.initializeImpliedClassRefs_();
		}
	}

	protected void initializeImpliedClassRefs_() {
		for (Iterator<String> stream = this.getJpaProject().annotatedClassNames(); stream.hasNext(); ) {
			String typeName = stream.next();
			if ( ! this.specifiesPersistentType(typeName)) {
				this.impliedClassRefs.add(this.buildClassRef(typeName));
			}
		}
	}

	protected void initializePersistenceUnitDefaults() {
		MappingFilePersistenceUnitDefaults defaults = this.getDefaults();
		this.defaultAccess = this.buildDefaultAccess(defaults);
		this.defaultCatalog = this.buildDefaultCatalog(defaults);
		this.defaultSchema = this.buildDefaultSchema(defaults);
		this.defaultCascadePersist = this.buildDefaultCascadePersist(defaults);
	}


	// ********** JpaContextNode implementation **********

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

	@Override
	public PersistenceUnit getPersistenceUnit() {
		return this;
	}


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

	public String getId() {
		return PersistenceStructureNodes.PERSISTENCE_UNIT_ID;
	}
	
	public IContentType getContentType() {
		return getParent().getContentType();
	}

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

	public void dispose() {
		for (Iterator<ClassRef> stream = this.classRefs(); stream.hasNext(); ) {
			stream.next().dispose();
		}
		for (Iterator<MappingFileRef> stream = this.mappingFileRefs(); stream.hasNext(); ) {
			stream.next().dispose();
		}
	}


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

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

	public void setName(String name) {
		String old = this.name;
		this.name = name;
		this.xmlPersistenceUnit.setName(name);
		this.firePropertyChanged(NAME_PROPERTY, old, name);
	}


	// ********** transaction type **********

	public PersistenceUnitTransactionType getTransactionType() {
		return (this.specifiedTransactionType != null) ? this.specifiedTransactionType : this.defaultTransactionType;
	}

	public PersistenceUnitTransactionType getSpecifiedTransactionType() {
		return this.specifiedTransactionType;
	}

	public void setSpecifiedTransactionType(PersistenceUnitTransactionType specifiedTransactionType) {
		PersistenceUnitTransactionType old = this.specifiedTransactionType;
		this.specifiedTransactionType = specifiedTransactionType;
		this.xmlPersistenceUnit.setTransactionType(PersistenceUnitTransactionType.toXmlResourceModel(specifiedTransactionType));
		this.firePropertyChanged(SPECIFIED_TRANSACTION_TYPE_PROPERTY, old, specifiedTransactionType);
	}

	public PersistenceUnitTransactionType getDefaultTransactionType() {
		return this.defaultTransactionType;
	}

	protected void setDefaultTransactionType(PersistenceUnitTransactionType defaultTransactionType) {
		PersistenceUnitTransactionType old = this.defaultTransactionType;
		this.defaultTransactionType = defaultTransactionType;
		this.firePropertyChanged(DEFAULT_TRANSACTION_TYPE_PROPERTY, old, defaultTransactionType);
	}


	// ********** description **********

	public String getDescription() {
		return this.description;
	}

	public void setDescription(String description) {
		String old = this.description;
		this.description = description;
		this.xmlPersistenceUnit.setDescription(description);
		this.firePropertyChanged(DESCRIPTION_PROPERTY, old, description);
	}


	// ********** provider **********

	public String getProvider() {
		return this.provider;
	}

	public void setProvider(String provider) {
		String old = this.provider;
		this.provider = provider;
		this.xmlPersistenceUnit.setProvider(provider);
		this.firePropertyChanged(PROVIDER_PROPERTY, old, provider);
	}


	// ********** JTA/non-JTA data source **********

	public String getJtaDataSource() {
		return this.jtaDataSource;
	}

	public void setJtaDataSource(String jtaDataSource) {
		String old = this.jtaDataSource;
		this.jtaDataSource = jtaDataSource;
		this.xmlPersistenceUnit.setJtaDataSource(jtaDataSource);
		this.firePropertyChanged(JTA_DATA_SOURCE_PROPERTY, old, jtaDataSource);
	}

	public String getNonJtaDataSource() {
		return this.nonJtaDataSource;
	}

	public void setNonJtaDataSource(String nonJtaDataSource) {
		String old = this.nonJtaDataSource;
		this.nonJtaDataSource = nonJtaDataSource;
		this.xmlPersistenceUnit.setNonJtaDataSource(nonJtaDataSource);
		this.firePropertyChanged(NON_JTA_DATA_SOURCE_PROPERTY, old, nonJtaDataSource);
	}


	// ********** mapping file refs **********

	public ListIterator<MappingFileRef> mappingFileRefs() {
		return (this.impliedMappingFileRef == null) ? this.specifiedMappingFileRefs() : this.combinedMappingFileRefs();
	}

	protected ListIterator<MappingFileRef> combinedMappingFileRefs() {
		return new CompositeListIterator<MappingFileRef>(this.specifiedMappingFileRefs(), this.impliedMappingFileRef);
	}

	public int mappingFileRefsSize() {
		return (this.impliedMappingFileRef == null) ? this.specifiedMappingFileRefsSize() : this.combinedMappingFileRefsSize();
	}

	protected int combinedMappingFileRefsSize() {
		return this.specifiedMappingFileRefsSize() + 1;
	}

	public Iterator<MappingFileRef> mappingFileRefsContaining(final String typeName) {
		return new FilteringIterator<MappingFileRef, MappingFileRef> (this.mappingFileRefs()) {
			@Override
			protected boolean accept(MappingFileRef mappingFileRef) {
				return mappingFileRef.getPersistentType(typeName) != null;
			}
		};
	}


	// ********** specified mapping file refs **********

	public ListIterator<MappingFileRef> specifiedMappingFileRefs() {
		return new CloneListIterator<MappingFileRef>(this.specifiedMappingFileRefs);
	}

	public int specifiedMappingFileRefsSize() {
		return this.specifiedMappingFileRefs.size();
	}

	public MappingFileRef addSpecifiedMappingFileRef() {
		return this.addSpecifiedMappingFileRef(this.specifiedMappingFileRefs.size());
	}

	public MappingFileRef addSpecifiedMappingFileRef(int index) {
		XmlMappingFileRef xmlMappingFileRef = this.buildXmlMappingFileRef();
		MappingFileRef mappingFileRef = this.buildSpecifiedMappingFileRef(xmlMappingFileRef);
		this.specifiedMappingFileRefs.add(index, mappingFileRef);
		this.xmlPersistenceUnit.getMappingFiles().add(index, xmlMappingFileRef);
		this.fireItemAdded(SPECIFIED_MAPPING_FILE_REFS_LIST, index, mappingFileRef);
		return mappingFileRef;
	}

	protected XmlMappingFileRef buildXmlMappingFileRef() {
		return PersistenceFactory.eINSTANCE.createXmlMappingFileRef();
	}

	public void removeSpecifiedMappingFileRef(MappingFileRef mappingFileRef) {
		this.removeSpecifiedMappingFileRef(this.specifiedMappingFileRefs.indexOf(mappingFileRef));
	}

	public void removeSpecifiedMappingFileRef(int index) {
		MappingFileRef mappingFileRef = this.specifiedMappingFileRefs.remove(index);
		mappingFileRef.dispose();
		this.xmlPersistenceUnit.getMappingFiles().remove(index);
		this.fireItemRemoved(SPECIFIED_MAPPING_FILE_REFS_LIST, index, mappingFileRef);
	}

	protected void addSpecifiedMappingFileRef_(MappingFileRef mappingFileRef) {
		this.addItemToList(mappingFileRef, this.specifiedMappingFileRefs, SPECIFIED_MAPPING_FILE_REFS_LIST);
	}

	protected void removeSpecifiedMappingFileRef_(MappingFileRef mappingFileRef) {
		mappingFileRef.dispose();
		this.removeItemFromList(mappingFileRef, this.specifiedMappingFileRefs, SPECIFIED_MAPPING_FILE_REFS_LIST);
	}


	// ********** implied mapping file ref **********

	public MappingFileRef getImpliedMappingFileRef() {
		return this.impliedMappingFileRef;
	}

	protected MappingFileRef setImpliedMappingFileRef() {
		if (this.impliedMappingFileRef != null) {
			throw new IllegalStateException("The implied mapping file ref is already set."); //$NON-NLS-1$
		}
		this.impliedMappingFileRef = this.buildImpliedMappingFileRef();
		this.firePropertyChanged(IMPLIED_MAPPING_FILE_REF_PROPERTY, null, this.impliedMappingFileRef);
		return this.impliedMappingFileRef;
	}

	protected MappingFileRef buildImpliedMappingFileRef() {
		return this.getJpaFactory().buildImpliedMappingFileRef(this);
	}

	protected void unsetImpliedMappingFileRef() {
		if (this.impliedMappingFileRef == null) {
			throw new IllegalStateException("The implied mapping file ref is already unset."); //$NON-NLS-1$
		}
		MappingFileRef old = this.impliedMappingFileRef;
		this.impliedMappingFileRef.dispose();
		this.impliedMappingFileRef = null;
		this.firePropertyChanged(IMPLIED_MAPPING_FILE_REF_PROPERTY, old, null);
	}


	// ********** JAR file refs **********

	public ListIterator<JarFileRef> jarFileRefs() {
		return new CloneListIterator<JarFileRef>(this.jarFileRefs);
	}

	public int jarFileRefsSize() {
		return this.jarFileRefs.size();
	}

	public JarFileRef addJarFileRef() {
		return this.addJarFileRef(this.jarFileRefs.size());
	}

	public JarFileRef addJarFileRef(int index) {
		XmlJarFileRef xmlJarFileRef = this.buildXmlJarFileRef();
		JarFileRef jarFileRef = this.buildJarFileRef(xmlJarFileRef);
		this.jarFileRefs.add(index, jarFileRef);
		this.xmlPersistenceUnit.getJarFiles().add(index, xmlJarFileRef);
		this.fireItemAdded(JAR_FILE_REFS_LIST, index, jarFileRef);
		return jarFileRef;
	}

	protected XmlJarFileRef buildXmlJarFileRef() {
		return PersistenceFactory.eINSTANCE.createXmlJarFileRef();
	}

	public void removeJarFileRef(JarFileRef jarFileRef) {
		this.removeJarFileRef(this.jarFileRefs.indexOf(jarFileRef));
	}

	public void removeJarFileRef(int index) {
		JarFileRef jarFileRef = this.jarFileRefs.remove(index);
		jarFileRef.dispose();
		this.xmlPersistenceUnit.getJarFiles().remove(index);
		this.fireItemRemoved(JAR_FILE_REFS_LIST, index, jarFileRef);
	}

	protected void addJarFileRef_(JarFileRef jarFileRef) {
		this.addItemToList(jarFileRef, this.jarFileRefs, JAR_FILE_REFS_LIST);
	}

	protected void removeJarFileRef_(JarFileRef jarFileRef) {
		jarFileRef.dispose();
		this.removeItemFromList(jarFileRef, this.jarFileRefs, JAR_FILE_REFS_LIST);
	}


	// ********** class refs **********

	@SuppressWarnings("unchecked")
	public Iterator<ClassRef> classRefs() {
		return new CompositeIterator<ClassRef>(
						this.specifiedClassRefs(),
						this.impliedClassRefs()
					);
	}

	public int classRefsSize() {
		return this.specifiedClassRefs.size() + this.impliedClassRefs.size();
	}


	// ********** specified class refs **********

	public ListIterator<ClassRef> specifiedClassRefs() {
		return new CloneListIterator<ClassRef>(this.specifiedClassRefs);
	}

	public int specifiedClassRefsSize() {
		return this.specifiedClassRefs.size();
	}

	public ClassRef addSpecifiedClassRef() {
		return this.addSpecifiedClassRef(this.specifiedClassRefs.size());
	}

	public ClassRef addSpecifiedClassRef(int index) {
		XmlJavaClassRef xmlClassRef = this.buildXmlJavaClassRef();
		ClassRef classRef = this.buildClassRef(xmlClassRef);
		this.specifiedClassRefs.add(index, classRef);
		this.xmlPersistenceUnit.getClasses().add(index, xmlClassRef);
		this.fireItemAdded(SPECIFIED_CLASS_REFS_LIST, index, classRef);
		return classRef;
	}

	protected XmlJavaClassRef buildXmlJavaClassRef() {
		return PersistenceFactory.eINSTANCE.createXmlJavaClassRef();
	}

	public void removeSpecifiedClassRef(ClassRef classRef) {
		this.removeSpecifiedClassRef(this.specifiedClassRefs.indexOf(classRef));
	}

	public void removeSpecifiedClassRef(int index) {
		ClassRef classRef = this.specifiedClassRefs.remove(index);
		classRef.dispose();
		this.xmlPersistenceUnit.getClasses().remove(index);
		this.fireItemRemoved(SPECIFIED_CLASS_REFS_LIST, index, classRef);
	}

	protected void addSpecifiedClassRef_(ClassRef classRef) {
		this.addItemToList(classRef, this.specifiedClassRefs, SPECIFIED_CLASS_REFS_LIST);
	}

	protected void removeSpecifiedClassRef_(ClassRef classRef) {
		classRef.dispose();
		this.removeItemFromList(classRef, this.specifiedClassRefs, SPECIFIED_CLASS_REFS_LIST);
	}


	// ********** implied class refs **********

	public Iterator<ClassRef> impliedClassRefs() {
		return new CloneIterator<ClassRef>(this.impliedClassRefs);
	}

	public int impliedClassRefsSize() {
		return this.impliedClassRefs.size();
	}

	protected ClassRef addImpliedClassRef(String className) {
		ClassRef classRef = this.buildClassRef(className);
		this.addItemToCollection(classRef, this.impliedClassRefs, IMPLIED_CLASS_REFS_COLLECTION);
		return classRef;
	}

	protected ClassRef buildClassRef(String className) {
		return this.getJpaFactory().buildClassRef(this, className);
	}

	protected void removeImpliedClassRef(ClassRef classRef) {
		classRef.dispose();
		this.removeItemFromCollection(classRef, this.impliedClassRefs, IMPLIED_CLASS_REFS_COLLECTION);
	}


	// ********** exclude unlisted classes **********

	public boolean excludesUnlistedClasses() {
		return (this.specifiedExcludeUnlistedClasses != null) ? this.specifiedExcludeUnlistedClasses.booleanValue() : this.getDefaultExcludeUnlistedClasses();
	}

	public Boolean getSpecifiedExcludeUnlistedClasses() {
		return this.specifiedExcludeUnlistedClasses;
	}

	public void setSpecifiedExcludeUnlistedClasses(Boolean specifiedExcludeUnlistedClasses) {
		Boolean old = this.specifiedExcludeUnlistedClasses;
		this.specifiedExcludeUnlistedClasses = specifiedExcludeUnlistedClasses;
		this.xmlPersistenceUnit.setExcludeUnlistedClasses(this.specifiedExcludeUnlistedClasses);
		this.firePropertyChanged(SPECIFIED_EXCLUDE_UNLISTED_CLASSES_PROPERTY, old, specifiedExcludeUnlistedClasses);
	}

	public boolean getDefaultExcludeUnlistedClasses() {
		return false;  // ???
	}


	// ********** properties **********

	public ListIterator<Property> properties() {
		return new CloneListIterator<Property>(this.properties);
	}

	public int propertiesSize() {
		return this.properties.size();
	}

	public Property getProperty(String propertyName) {
		if (propertyName == null) {
			throw new NullPointerException();
		}
		synchronized (this.properties) {
			for (Property property : this.properties) {
				if (propertyName.equals(property.getName())) {
					return property;
				}
			}
		}
		return null;
	}

	public Iterator<Property> propertiesWithNamePrefix(final String propertyNamePrefix) {
		if (propertyNamePrefix == null) {
			throw new NullPointerException();
		}
		return new FilteringIterator<Property, Property>(this.properties()) {
			@Override
			protected boolean accept(Property property) {
				String pName = property.getName();
				return (pName != null) && pName.startsWith(propertyNamePrefix);
			}
		};
	}

	public Property addProperty() {
		return this.addProperty(this.properties.size());
	}

	public Property addProperty(int index) {
		return this.addProperty(this.buildXmlProperty(), index);
	}

	protected XmlProperty buildXmlProperty() {
		return PersistenceFactory.eINSTANCE.createXmlProperty();
	}

	protected Property addProperty(XmlProperty xmlProperty, int index) {
		Property property = this.buildProperty(xmlProperty);

		XmlProperties xmlProperties = this.xmlPersistenceUnit.getProperties();
		if (xmlProperties == null) {
			xmlProperties = this.buildXmlProperties();
			this.xmlPersistenceUnit.setProperties(xmlProperties);
		}

		this.properties.add(index, property);
		xmlProperties.getProperties().add(index, xmlProperty);
		this.fireItemAdded(PROPERTIES_LIST, index, property);
		return property;
	}

	protected Property buildProperty(XmlProperty xmlProperty) {
		return this.getJpaFactory().buildProperty(this, xmlProperty);
	}

	protected XmlProperties buildXmlProperties() {
		return PersistenceFactory.eINSTANCE.createXmlProperties();
	}

	public void setProperty(String propertyName, String value) {
		this.setProperty(propertyName, value, false);
	}

	public void setProperty(String propertyName, String value, boolean duplicatePropertyNamesAllowed) {
		Property prev = this.getProperty(propertyName);
		if (prev == null) {
			if (value != null) {
				this.addProperty(propertyName, value);  // add [first] property
			}
		} else {
			if (duplicatePropertyNamesAllowed) {
				if (value == null) {
					// do nothing?
				} else {
					this.addProperty(propertyName, value);  // add [duplicate] property
				}
			} else {
				if (value == null) {
					this.removeProperty(prev);  // remove existing property
				} else {
					prev.setValue(value);  // change existing property
				}
			}
		}
	}

	protected void addProperty(String propertyName, String value) {
		Property property = this.addProperty();
		property.setName(propertyName);
		property.setValue(value);
	}

	public void removeProperty(Property property) {
		synchronized (this.properties) {
			this.removeProperty(this.properties.indexOf(property));
		}
	}

	public void removeProperty(String propertyName) {
		if (propertyName == null) {
			throw new NullPointerException();
		}
		synchronized (this.properties) {
			for (ListIterator<Property> stream = this.properties.listIterator(); stream.hasNext(); ) {
				Property property = stream.next();
				if (propertyName.equals(property.getName())) {
					this.removeProperty(stream.previousIndex());
					return;
				}
			}
		}
		throw new IllegalArgumentException("invalid property name: " + propertyName); //$NON-NLS-1$
	}

	public void removeProperty(String propertyName, String value) {
		if ((propertyName == null) || (value == null)) {
			throw new NullPointerException();
		}
		synchronized (this.properties) {
			for (ListIterator<Property> stream = this.properties.listIterator(); stream.hasNext(); ) {
				Property property = stream.next();
				if (propertyName.equals(property.getName()) && value.equals(property.getValue())) {
					this.removeProperty(stream.previousIndex());
					return;
				}
			}
		}
		throw new IllegalArgumentException("invalid property name/value pair: " + propertyName + " = " + value); //$NON-NLS-1$ //$NON-NLS-2$
	}

	protected void removeProperty(int index) {
		Property removedProperty = this.properties.remove(index);
		this.xmlPersistenceUnit.getProperties().getProperties().remove(index);

		if (this.xmlPersistenceUnit.getProperties().getProperties().isEmpty()) {
			this.xmlPersistenceUnit.setProperties(null);
		}

		this.fireItemRemoved(PROPERTIES_LIST, index, removedProperty);
	}

	protected void addProperty_(Property property) {
		this.addItemToList(property, this.properties, PROPERTIES_LIST);
	}

	protected void removeProperty_(Property property) {
		this.removeItemFromList(property, this.properties, PROPERTIES_LIST);
	}


	// ********** ORM persistence unit defaults **********

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

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

	public String getDefaultCatalog() {
		return this.defaultCatalog;
	}

	protected void setDefaultCatalog(String defaultCatalog) {
		String old = this.defaultCatalog;
		this.defaultCatalog = defaultCatalog;
		this.firePropertyChanged(DEFAULT_CATALOG_PROPERTY, old, defaultCatalog);
	}

	public String getDefaultSchema() {
		return this.defaultSchema;
	}

	protected void setDefaultSchema(String defaultSchema) {
		String old = this.defaultSchema;
		this.defaultSchema = defaultSchema;
		this.firePropertyChanged(DEFAULT_SCHEMA_PROPERTY, old, defaultSchema);
	}

	public boolean getDefaultCascadePersist() {
		return this.defaultCascadePersist;
	}

	protected void setDefaultCascadePersist(boolean defaultCascadePersist) {
		boolean old = this.defaultCascadePersist;
		this.defaultCascadePersist = defaultCascadePersist;
		this.firePropertyChanged(DEFAULT_CASCADE_PERSIST_PROPERTY, old, defaultCascadePersist);
	}


	// ********** generators **********

	public ListIterator<Generator> generators() {
		return new CloneListIterator<Generator>(this.generators);
	}

	public int generatorsSize() {
		return this.generators.size();
	}

	public void addGenerator(Generator generator) {
		this.generators.add(generator);
	}

	public String[] uniqueGeneratorNames() {
		HashSet<String> names = new HashSet<String>(this.generators.size());
		this.addNonNullGeneratorNamesTo(names);
		return names.toArray(new String[names.size()]);
	}

	protected void addNonNullGeneratorNamesTo(Set<String> names) {
		for (Iterator<Generator> stream = this.generators(); stream.hasNext(); ) {
			String generatorName = stream.next().getName();
			if (generatorName != null) {
				names.add(generatorName);
			}
		}
	}


	// ********** queries **********

	public ListIterator<Query> queries() {
		return new CloneListIterator<Query>(this.queries);
	}

	public int queriesSize() {
		return this.queries.size();
	}

	public void addQuery(Query query) {
		this.queries.add(query);
	}

	public void addRootWithSubEntities(String entityName) {
		this.rootEntities.add(entityName);
	}
	
	public boolean isRootWithSubEntities(String entityName) {
		return this.rootEntities.contains(entityName);
	}
	
	// ********** updating **********

	public void update(XmlPersistenceUnit xpu) {
		this.xmlPersistenceUnit = xpu;

		// the 'generators' and 'queries' lists are simply cleared out with each
		// "update" and completely rebuilt as the "update" cascades through
		// the persistence unit. When the persistence unit's "update" is
		// complete, the lists have been populated and we fire the change event.
		// @see #addGenerator(Generator) (and references)
		// @see #addQuery(Query) (and references)
		this.generators.clear();
		this.queries.clear();

		this.rootEntities.clear();
		
		this.setName(xpu.getName());
		this.setSpecifiedTransactionType(this.buildSpecifiedTransactionType());
		this.setDefaultTransactionType(this.buildDefaultTransactionType());
		this.setDescription(xpu.getDescription());
		this.setProvider(xpu.getProvider());
		this.setJtaDataSource(xpu.getJtaDataSource());
		this.setNonJtaDataSource(xpu.getNonJtaDataSource());
		this.updateJarFileRefs();

		// update 'specifiedClassRefs' before 'mappingFileRefs' because of 
		// JpaFile rootStructureNode, we want the mapping file to "win",
		// as it would in a JPA runtime implementation
		this.updateSpecifiedClassRefs();
		this.updateMappingFileRefs();

		// update 'impliedClassRefs' last since it depends on the contents of
		// both 'specifiedClassRefs' and 'mappingFileRefs'
		this.updateImpliedClassRefs();

		this.setSpecifiedExcludeUnlistedClasses(xpu.getExcludeUnlistedClasses());
		this.updateProperties();
		this.updatePersistenceUnitDefaults();

		// see comment at top of method
		this.fireListChanged(GENERATORS_LIST);
		this.fireListChanged(QUERIES_LIST);
	}
	
	@Override
	public void postUpdate() {
		super.postUpdate();
		for (ClassRef classRef : CollectionTools.iterable(this.specifiedClassRefs())) {
			classRef.postUpdate();
		}
		for (ClassRef classRef : CollectionTools.iterable(this.impliedClassRefs())) {
			classRef.postUpdate();
		}
		for (MappingFileRef mappingFileRef : CollectionTools.iterable(this.specifiedMappingFileRefs())) {
			mappingFileRef.postUpdate();
		}
		if (this.impliedMappingFileRef != null) {
			this.impliedMappingFileRef.postUpdate();
		}
	}
	
	protected PersistenceUnitTransactionType buildSpecifiedTransactionType() {
		return PersistenceUnitTransactionType.fromXmlResourceModel(this.xmlPersistenceUnit.getTransactionType());
	}

	/**
	 * TODO - calculate default
	 * From the JPA spec: "In a Java EE environment, if this element is not
	 * specified, the default is JTA. In a Java SE environment, if this element
	 * is not specified, a default of RESOURCE_LOCAL may be assumed."
	 */
	protected PersistenceUnitTransactionType buildDefaultTransactionType() {
		return null;
	}

	/**
	 * Since this is a *list*, we simply loop through the elements and match
	 * the context to the resource element by index, not by name like we do
	 * with 'impliedClassRefs'.
	 */
	protected void updateJarFileRefs() {
		// make a copy of the XML file refs (to prevent ConcurrentModificationException)
		Iterator<XmlJarFileRef> xmlFileRefs = new CloneIterator<XmlJarFileRef>(this.xmlPersistenceUnit.getJarFiles());

		for (Iterator<JarFileRef> contextFileRefs = this.jarFileRefs(); contextFileRefs.hasNext(); ) {
			JarFileRef contextFileRef = contextFileRefs.next();
			if (xmlFileRefs.hasNext()) {
				contextFileRef.update(xmlFileRefs.next());
			} else {
				this.removeJarFileRef_(contextFileRef);
			}
		}

		while (xmlFileRefs.hasNext()) {
			this.addJarFileRef_(this.buildJarFileRef(xmlFileRefs.next()));
		}
	}

	protected JarFileRef buildJarFileRef(XmlJarFileRef xmlJarFileRef) {
		return this.getJpaFactory().buildJarFileRef(this, xmlJarFileRef);
	}

	/**
	 * Since this is a *list*, we simply loop through the elements and match
	 * the context to the resource element by index, not by name like we do
	 * with 'impliedClassRefs'.
	 */
	protected void updateSpecifiedClassRefs() {
		// make a copy of the XML class refs (to prevent ConcurrentModificationException)
		Iterator<XmlJavaClassRef> xmlClassRefs = new CloneIterator<XmlJavaClassRef>(this.xmlPersistenceUnit.getClasses());

		for (Iterator<ClassRef> contextClassRefs = this.specifiedClassRefs(); contextClassRefs.hasNext(); ) {
			ClassRef contextClassRef = contextClassRefs.next();
			if (xmlClassRefs.hasNext()) {
				contextClassRef.update(xmlClassRefs.next());
			} else {
				this.removeSpecifiedClassRef_(contextClassRef);
			}
		}

		while (xmlClassRefs.hasNext()) {
			this.addSpecifiedClassRef_(this.buildClassRef(xmlClassRefs.next()));
		}
	}

	protected ClassRef buildClassRef(XmlJavaClassRef xmlClassRef) {
		return this.getJpaFactory().buildClassRef(this, xmlClassRef);
	}

	/**
	 * Since this is a *list*, we simply loop through the elements and match
	 * the context to the resource element by index, not by name like we do
	 * with 'impliedClassRefs'.
	 */
	protected void updateMappingFileRefs() {
		// first update the specified mapping file refs...
		// make a copy of the XML file refs (to prevent ConcurrentModificationException)
		Iterator<XmlMappingFileRef> xmlFileRefs = new CloneIterator<XmlMappingFileRef>(this.xmlPersistenceUnit.getMappingFiles());

		for (Iterator<MappingFileRef> contextFileRefs = this.specifiedMappingFileRefs(); contextFileRefs.hasNext(); ) {
			MappingFileRef contextFileRef = contextFileRefs.next();
			if (xmlFileRefs.hasNext()) {
				contextFileRef.update(xmlFileRefs.next());
			} else {
				this.removeSpecifiedMappingFileRef_(contextFileRef);
			}
		}

		while (xmlFileRefs.hasNext()) {
			this.addSpecifiedMappingFileRef_(this.buildSpecifiedMappingFileRef(xmlFileRefs.next()));
		}

		// ...then update the implied mapping file ref
		if (this.impliedMappingFileIsSpecified()) {
			if (this.impliedMappingFileRef != null) {
				this.unsetImpliedMappingFileRef();
			}
		} else {
			if (this.impliedMappingFileExists()) {
				if (this.impliedMappingFileRef == null) {
					this.setImpliedMappingFileRef();
				}
				this.impliedMappingFileRef.update(null);
			} else {
				if (this.impliedMappingFileRef != null) {
					this.unsetImpliedMappingFileRef();
				}
			}
		}
	}

	protected MappingFileRef buildSpecifiedMappingFileRef(XmlMappingFileRef xmlMappingFileRef) {
		return this.getJpaFactory().buildMappingFileRef(this, xmlMappingFileRef);
	}

	protected boolean impliedMappingFileIsSpecified() {
		String impliedMappingFileName = JptCorePlugin.DEFAULT_ORM_XML_FILE_PATH;
		for (Iterator<MappingFileRef> stream = this.specifiedMappingFileRefs(); stream.hasNext(); ) {
			if (impliedMappingFileName.equals(stream.next().getFileName())) {
				return true;
			}
		}
		return false;
	}

	protected boolean impliedMappingFileExists() {
		return getJpaProject().getDefaultOrmXmlResource() != null;
	}

	protected void updateImpliedClassRefs() {
		if (this.excludesUnlistedClasses()) {
			this.clearImpliedClassRefs_();
		} else {
			this.updateImpliedClassRefs_();
		}
	}

	protected void updateImpliedClassRefs_() {
		ArrayList<ClassRef> impliedRefsToRemove = CollectionTools.list(this.impliedClassRefs(), this.impliedClassRefsSize());
		ArrayList<ClassRef> impliedRefsToUpdate = new ArrayList<ClassRef>(this.impliedClassRefsSize());

		for (Iterator<String> annotatedClassNames = this.getJpaProject().annotatedClassNames(); annotatedClassNames.hasNext(); ) {
			String annotatedClassName = annotatedClassNames.next();
			if ( ! this.specifiesPersistentType(annotatedClassName)) {
				boolean match = false;
				for (Iterator<ClassRef> stream = impliedRefsToRemove.iterator(); stream.hasNext(); ) {
					ClassRef classRef = stream.next();
					if (annotatedClassName.equals(classRef.getClassName())) {
						stream.remove();
						impliedRefsToUpdate.add(classRef);
						match = true;
						break;
					}
				}
				if ( ! match) {
					this.addImpliedClassRef(annotatedClassName);
				}
			}
		}
		for (ClassRef classRef : impliedRefsToRemove) {
			this.removeImpliedClassRef(classRef);
		}
		// handle adding and removing implied class refs first, update the
		// remaining implied class refs last; this reduces the churn during "update"
		for (ClassRef classRef : impliedRefsToUpdate) {
			classRef.update(classRef.getClassName());
		}
	}

	protected void clearImpliedClassRefs_() {
		for (Iterator<ClassRef> stream = this.impliedClassRefs(); stream.hasNext(); ) {
			this.removeImpliedClassRef(stream.next());
		}
	}

	/**
	 * Since this is a *list*, we simply loop through the elements and match
	 * the context to the resource element by index, not by name like we do
	 * with 'impliedClassRefs'.
	 */
	protected void updateProperties() {
		Iterator<XmlProperty> xmlProperties = this.xmlProperties();

		for (Iterator<Property> contextProperties = this.properties(); contextProperties.hasNext(); ) {
			Property contextProperty = contextProperties.next();
			if (xmlProperties.hasNext()) {
				contextProperty.update(xmlProperties.next());
			} else {
				this.removeProperty_(contextProperty);
			}
		}

		while (xmlProperties.hasNext()) {
			this.addProperty_(this.buildProperty(xmlProperties.next()));
		}
	}

	protected Iterator<XmlProperty> xmlProperties() {
		XmlProperties xmlProperties = this.xmlPersistenceUnit.getProperties();
		// make a copy of the XML properties (to prevent ConcurrentModificationException)
		return (xmlProperties != null) ? new CloneIterator<XmlProperty>(xmlProperties.getProperties()) : EmptyIterator.<XmlProperty>instance();
	}

	protected void updatePersistenceUnitDefaults() {
		MappingFilePersistenceUnitDefaults defaults = this.getDefaults();
		this.setDefaultAccess(this.buildDefaultAccess(defaults));
		this.setDefaultCatalog(this.buildDefaultCatalog(defaults));
		this.setDefaultSchema(this.buildDefaultSchema(defaults));
		this.setDefaultCascadePersist(this.buildDefaultCascadePersist(defaults));
	}

	/**
	 * return the first persistence unit defaults we encounter in a mapping file
	 */
	protected MappingFilePersistenceUnitDefaults getDefaults() {
		for (Iterator<MappingFileRef> stream = this.mappingFileRefs(); stream.hasNext(); ) {
			MappingFileRef mappingFileRef = stream.next();
			if (mappingFileRef.persistenceUnitDefaultsExists()) {
				return mappingFileRef.getPersistenceUnitDefaults();
			}
		}
		return null;
	}

	protected AccessType buildDefaultAccess(MappingFilePersistenceUnitDefaults defaults) {
		return (defaults == null) ? null : defaults.getAccess();
	}

	protected String buildDefaultCatalog(MappingFilePersistenceUnitDefaults defaults) {
		String catalog = (defaults == null) ? null : defaults.getCatalog();
		return (catalog != null) ? catalog : this.getJpaProject().getDefaultCatalog();
	}

	protected String buildDefaultSchema(MappingFilePersistenceUnitDefaults defaults) {
		String schema = (defaults == null) ? null : defaults.getSchema();
		return (schema != null) ? schema : this.getJpaProject().getDefaultSchema();
	}

	protected boolean buildDefaultCascadePersist(MappingFilePersistenceUnitDefaults defaults) {
		return (defaults == null) ? false : defaults.isCascadePersist();
	}


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

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

	protected void validateMappingFiles(List<IMessage> messages, IReporter reporter) {
		this.checkForMultiplePersistenceUnitDefaults(messages);
		this.checkForDuplicateMappingFiles(messages);
		for (Iterator<MappingFileRef> stream = this.mappingFileRefs(); stream.hasNext();) {
			stream.next().validate(messages, reporter);
		}
	}

	protected void checkForMultiplePersistenceUnitDefaults(List<IMessage> messages) {
		Iterator<MappingFileRef> stream = mappingFileRefs();
		while (stream.hasNext()) {
			if (stream.next().persistenceUnitDefaultsExists()) {
				break;
			}
		}
		while (stream.hasNext()) {
			MappingFileRef mappingFileRef = stream.next();
			if (mappingFileRef.persistenceUnitDefaultsExists()) {
				messages.add(
					DefaultJpaValidationMessages.buildMessage(
						IMessage.NORMAL_SEVERITY,
						JpaValidationMessages.MAPPING_FILE_EXTRANEOUS_PERSISTENCE_UNIT_DEFAULTS,
						new String[] {mappingFileRef.getFileName()},
						mappingFileRef
					)
				);
			}
		}
	}

	protected void checkForDuplicateMappingFiles(List<IMessage> messages) {
		HashBag<String> fileNames = new HashBag<String>();
		CollectionTools.addAll(fileNames, this.mappingFileRefNames());
		for (Iterator<MappingFileRef> stream = this.mappingFileRefs(); stream.hasNext(); ) {
			MappingFileRef mappingFileRef = stream.next();
			String fileName = mappingFileRef.getFileName();
			if (fileNames.count(fileName) > 1) {
				messages.add(
					DefaultJpaValidationMessages.buildMessage(
						IMessage.HIGH_SEVERITY,
						JpaValidationMessages.PERSISTENCE_UNIT_DUPLICATE_MAPPING_FILE,
						new String[] {fileName}, 
						mappingFileRef, 
						mappingFileRef.getValidationTextRange()
					)
				);
			}
		}
	}

	protected Iterator<String> mappingFileRefNames() {
		return new TransformationIterator<MappingFileRef, String>(this.mappingFileRefs()) {
			@Override
			protected String transform(MappingFileRef mappingFileRef) {
				return mappingFileRef.getFileName();
			}
		};
	}

	protected void validateClassRefs(List<IMessage> messages, IReporter reporter) {
		this.checkForDuplicateClasses(messages);
		for (Iterator<ClassRef> stream = this.classRefs(); stream.hasNext(); ) {
			stream.next().validate(messages, reporter);
		}
	}

	protected void checkForDuplicateClasses(List<IMessage> messages) {
		HashBag<String> classNames = new HashBag<String>();
		CollectionTools.addAll(classNames, this.classRefNames());
		for (Iterator<ClassRef> stream = this.classRefs(); stream.hasNext(); ) {
			ClassRef classRef = stream.next();
			String className = classRef.getClassName();
			if ((className != null) && (classNames.count(className) > 1)) {
				messages.add(
					DefaultJpaValidationMessages.buildMessage(
						IMessage.HIGH_SEVERITY,
						JpaValidationMessages.PERSISTENCE_UNIT_DUPLICATE_CLASS,
						new String[] {className}, 
						classRef, 
						classRef.getValidationTextRange()
					)
				);
			}
		}
	}

	protected Iterator<String> classRefNames() {
		return new TransformationIterator<ClassRef, String>(this.classRefs()) {
			@Override
			protected String transform(ClassRef classRef) {
				return classRef.getClassName();
			}
		};
	}


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

	public JpaStructureNode getStructureNode(int textOffset) {
		for (Iterator<JarFileRef> stream = this.jarFileRefs(); stream.hasNext(); ) {
			JarFileRef jarFileRef = stream.next();
			if (jarFileRef.containsOffset(textOffset)) {
				return jarFileRef;
			}
		}
		for (Iterator<MappingFileRef> stream = this.mappingFileRefs(); stream.hasNext(); ) {
			MappingFileRef mappingFileRef = stream.next();
			if (mappingFileRef.containsOffset(textOffset)) {
				return mappingFileRef;
			}
		}
		for (Iterator<ClassRef> stream = this.classRefs(); stream.hasNext(); ) {
			ClassRef classRef = stream.next();
			if (classRef.containsOffset(textOffset)) {
				return classRef;
			}
		}
		return this;
	}
	
	public boolean shouldValidateAgainstDatabase() {
		return connectionProfileIsActive();
	}

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

	public PersistentType getPersistentType(String typeName) {
		for (Iterator<MappingFileRef> stream = this.mappingFileRefs(); stream.hasNext(); ) {
			PersistentType persistentType = stream.next().getPersistentType(typeName);
			if (persistentType != null) {
				return persistentType;
			}
		}
		for (Iterator<ClassRef> stream = this.classRefs(); stream.hasNext(); ) {
			ClassRef classRef = stream.next();
			if (classRef.isFor(typeName)) {
				return classRef.getJavaPersistentType();
			}
		}
		for (Iterator<JarFileRef> stream = this.jarFileRefs(); stream.hasNext(); ) {
			PersistentType persistentType = stream.next().getPersistentType(typeName);
			if (persistentType != null) {
				return persistentType;
			}
		}
		return null;
	}

	public boolean specifiesPersistentType(String className) {
		for (Iterator<ClassRef> stream = this.specifiedClassRefs(); stream.hasNext(); ) {
			if (className.equals(stream.next().getClassName())) {
				return true;
			}
		}
		for (Iterator<MappingFileRef> stream = this.mappingFileRefs(); stream.hasNext(); ) {
			if (stream.next().getPersistentType(className) != null) {
				return true;
			}
		}
		return false;
	}

	public Entity getEntity(String typeName) {
		PersistentType persistentType = this.getPersistentType(typeName);
		if (persistentType == null) {
			return null;
		}
		TypeMapping typeMapping = persistentType.getMapping();
		return (typeMapping instanceof Entity) ? (Entity) typeMapping : null;
	}

	public Embeddable getEmbeddable(String typeName) {
		PersistentType persistentType = this.getPersistentType(typeName);
		if (persistentType == null) {
			return null;
		}
		TypeMapping typeMapping = persistentType.getMapping();
		return (typeMapping instanceof Embeddable) ? (Embeddable) typeMapping : null;
	}

	public boolean containsOffset(int textOffset) {
		return (this.xmlPersistenceUnit != null) && this.xmlPersistenceUnit.containsOffset(textOffset);
	}

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

}
