/*******************************************************************************
 * Copyright (c) 2007, 2008 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.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.Set;

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.Entity;
import org.eclipse.jpt.core.context.Generator;
import org.eclipse.jpt.core.context.MappingFile;
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.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.context.persistence.Property;
import org.eclipse.jpt.core.internal.context.AbstractXmlContextNode;
import org.eclipse.jpt.core.internal.resource.orm.OrmResourceModelProvider;
import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
import org.eclipse.jpt.core.resource.orm.OrmResource;
import org.eclipse.jpt.core.resource.persistence.PersistenceFactory;
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.FilteringIterator;
import org.eclipse.jpt.utility.internal.iterators.ReadOnlyCompositeListIterator;
import org.eclipse.jpt.utility.internal.iterators.TransformationIterator;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;

public 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 List<MappingFileRef> specifiedMappingFileRefs = new ArrayList<MappingFileRef>();
	
	protected MappingFileRef impliedMappingFileRef;
	
	protected final List<String> jarFiles = new ArrayList<String>();
	
	protected final List<ClassRef> specifiedClassRefs = new ArrayList<ClassRef>();
	
	protected final List<ClassRef> impliedClassRefs = new ArrayList<ClassRef>();
	
	protected Boolean specifiedExcludeUnlistedClasses;
	
	protected boolean defaultExcludeUnlistedClasses = false;
	
	protected final List<Property> properties = new ArrayList<Property>();
	
	/* global generator definitions, defined elsewhere in model */
	protected final List<Generator> generators = new ArrayList<Generator>();
	
	/* global query definitions, defined elsewhere in model */
	protected final List<Query> queries = new ArrayList<Query>();
	
	
	protected AccessType defaultAccess;
	protected String defaultCatalog;
	protected String defaultSchema;
	protected boolean defaultCascadePersist;
	
	public AbstractPersistenceUnit(Persistence parent) {
		super(parent);
	}
	
	@Override
	protected void addNonUpdateAspectNamesTo(Set<String> nonUpdateAspectNames) {
		super.addNonUpdateAspectNamesTo(nonUpdateAspectNames);
		nonUpdateAspectNames.add(GENERATORS_LIST);
		nonUpdateAspectNames.add(QUERIES_LIST);
	}
	
	public String getId() {
		return PersistenceStructureNodes.PERSISTENCE_UNIT_ID;
	}

	@Override
	public PersistenceUnit getPersistenceUnit() {
		return this;
	}
	
	
	// **************** parent *************************************************
	
	@Override
	public Persistence getParent() {
		return (Persistence) super.getParent();
	}
	
	
	// **************** name ***************************************************
	
	public String getName() {
		return this.name;
	}
	
	public void setName(String newName) {
		String oldName = this.name;
		this.name = newName;
		this.xmlPersistenceUnit.setName(newName);
		firePropertyChanged(NAME_PROPERTY, oldName, newName);
	}
	
	
	// **************** transaction type ***************************************
	
	public PersistenceUnitTransactionType getTransactionType() {
		return (isTransactionTypeDefault()) ?
			getDefaultTransactionType() : getSpecifiedTransactionType();
	}
	
	public PersistenceUnitTransactionType getSpecifiedTransactionType() {
		return this.specifiedTransactionType;
	}
	
	public void setSpecifiedTransactionType(PersistenceUnitTransactionType newTransactionType) {
		PersistenceUnitTransactionType oldTransactionType = this.specifiedTransactionType;
		this.specifiedTransactionType = newTransactionType;		
		this.xmlPersistenceUnit.setTransactionType(PersistenceUnitTransactionType.toXmlResourceModel(newTransactionType));		
		firePropertyChanged(SPECIFIED_TRANSACTION_TYPE_PROPERTY, oldTransactionType, newTransactionType);
	}
	
	public boolean isTransactionTypeDefault() {
		return this.specifiedTransactionType == null;
	}
	
	public PersistenceUnitTransactionType getDefaultTransactionType() {
		return this.defaultTransactionType;
	}
	
	protected void setDefaultTransactionType(PersistenceUnitTransactionType newTransactionType) {
		PersistenceUnitTransactionType oldTransactionType = this.defaultTransactionType;
		this.defaultTransactionType = newTransactionType;		
		firePropertyChanged(DEFAULT_TRANSACTION_TYPE_PROPERTY, oldTransactionType, newTransactionType);
	}
	
	// **************** description ********************************************
	
	public String getDescription() {
		return this.description;
	}
	
	public void setDescription(String newDescription) {
		String oldDescription = this.description;
		this.description = newDescription;
		this.xmlPersistenceUnit.setDescription(newDescription);
		firePropertyChanged(DESCRIPTION_PROPERTY, oldDescription, newDescription);
	}
	
	
	// **************** provider ***********************************************
	
	public String getProvider() {
		return this.provider;
	}
	
	public void setProvider(String newProvider) {
		String oldProvider = this.provider;
		this.provider = newProvider;
		this.xmlPersistenceUnit.setProvider(newProvider);
		firePropertyChanged(PROVIDER_PROPERTY, oldProvider, newProvider);
	}
	
	
	// **************** jta data source ****************************************
	
	public String getJtaDataSource() {
		return this.jtaDataSource;
	}
	
	public void setJtaDataSource(String newJtaDataSource) {
		String oldJtaDataSource = this.jtaDataSource;
		this.jtaDataSource = newJtaDataSource;
		this.xmlPersistenceUnit.setJtaDataSource(newJtaDataSource);
		firePropertyChanged(JTA_DATA_SOURCE_PROPERTY, oldJtaDataSource, newJtaDataSource);
	}
	
	
	// **************** non-jta data source ************************************
	
	public String getNonJtaDataSource() {
		return this.nonJtaDataSource;
	}
	
	public void setNonJtaDataSource(String newNonJtaDataSource) {
		String oldNonJtaDataSource = this.nonJtaDataSource;
		this.nonJtaDataSource = newNonJtaDataSource;
		this.xmlPersistenceUnit.setNonJtaDataSource(newNonJtaDataSource);
		firePropertyChanged(NON_JTA_DATA_SOURCE_PROPERTY, oldNonJtaDataSource, newNonJtaDataSource);
	}
	
	
	// **************** mapping file refs **************************************
	
	public ListIterator<MappingFileRef> mappingFileRefs() {
		if (impliedMappingFileRef == null) {
			return specifiedMappingFileRefs();
		}
		return new ReadOnlyCompositeListIterator<MappingFileRef>(
			specifiedMappingFileRefs(), impliedMappingFileRef);
	}
	
	public int mappingFileRefsSize() {
		if (impliedMappingFileRef == null) {
			return specifiedMappingFileRefsSize();
		}
		return 1 + specifiedMappingFileRefsSize();
	}

	// **************** specified mapping file refs ****************************
	
	public ListIterator<MappingFileRef> specifiedMappingFileRefs() {
		return new CloneListIterator<MappingFileRef>(specifiedMappingFileRefs);
	}
	
	public int specifiedMappingFileRefsSize() {
		return specifiedMappingFileRefs.size();
	}
	
	public MappingFileRef addSpecifiedMappingFileRef() {
		return addSpecifiedMappingFileRef(specifiedMappingFileRefs.size());
	}
	
	public MappingFileRef addSpecifiedMappingFileRef(int index) {
		XmlMappingFileRef xmlMappingFileRef = PersistenceFactory.eINSTANCE.createXmlMappingFileRef();
		MappingFileRef mappingFileRef = buildMappingFileRef(xmlMappingFileRef);
		specifiedMappingFileRefs.add(index, mappingFileRef);
		this.xmlPersistenceUnit.getMappingFiles().add(index, xmlMappingFileRef);
		fireItemAdded(SPECIFIED_MAPPING_FILE_REFS_LIST, index, mappingFileRef);
		return mappingFileRef;
	}
	
	public void removeSpecifiedMappingFileRef(MappingFileRef mappingFileRef) {
		removeSpecifiedMappingFileRef(specifiedMappingFileRefs.indexOf(mappingFileRef));
	}
	
	public void removeSpecifiedMappingFileRef(int index) {
		MappingFileRef mappingFileRefRemoved = specifiedMappingFileRefs.remove(index);
		mappingFileRefRemoved.dispose();
		this.xmlPersistenceUnit.getMappingFiles().remove(index);
		fireItemRemoved(SPECIFIED_MAPPING_FILE_REFS_LIST, index, mappingFileRefRemoved);
	}
	
	protected void addSpecifiedMappingFileRef_(MappingFileRef mappingFileRef) {
		addSpecifiedMappingFileRef_(specifiedMappingFileRefs.size(), mappingFileRef);
	}
	
	protected void addSpecifiedMappingFileRef_(int index, MappingFileRef mappingFileRef) {
		addItemToList(index, mappingFileRef, 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 impliedMappingFileRef;
	}
	
	protected MappingFileRef setImpliedMappingFileRef() {
		if (impliedMappingFileRef != null) {
			throw new IllegalStateException("The implied mapping file ref is already set."); //$NON-NLS-1$
		}
		MappingFileRef mappingFileRef = buildMappingFileRef(null);
		impliedMappingFileRef = mappingFileRef;
		firePropertyChanged(IMPLIED_MAPPING_FILE_REF_PROPERTY, null, mappingFileRef);
		return mappingFileRef;
	}
	
	protected void unsetImpliedMappingFileRef() {
		if (impliedMappingFileRef == null) {
			throw new IllegalStateException("The implied mapping file ref is already unset."); //$NON-NLS-1$
		}
		MappingFileRef mappingFileRef = impliedMappingFileRef;
		impliedMappingFileRef.dispose();
		impliedMappingFileRef = null;
		firePropertyChanged(IMPLIED_MAPPING_FILE_REF_PROPERTY, mappingFileRef, null);
	}
	
	
	// **************** jar files ***********************************
	
	public ListIterator<String> jarFiles() {
		return new CloneListIterator<String>(this.jarFiles);
	}
	
	public int jarFilesSize() {
		return this.jarFiles.size();
	}
	
	public void addJarFile(String jarFile) {
		this.addJarFile(this.jarFiles.size(), jarFile);
	}
	
	public void addJarFile(int index, String jarFile) {
		this.jarFiles.add(index, jarFile);
		this.xmlPersistenceUnit.getJarFiles().add(index, jarFile);
		this.fireItemAdded(JAR_FILES_LIST, index, jarFile);
	}

	public void removeJarFile(String jarFile) {
		this.removeJarFile(this.jarFiles.indexOf(jarFile));
	}
	
	public void removeJarFile(int index) {
		String jarFile = this.jarFiles.remove(index);
		this.xmlPersistenceUnit.getJarFiles().remove(index);
		this.fireItemRemoved(JAR_FILES_LIST, index, jarFile);
	}
	
	protected void addJarFile_(String jarFile) {
		this.addJarFile_(this.jarFiles.size(), jarFile);
	}
	
	protected void addJarFile_(int index, String jarFile) {
		this.addItemToList(index, jarFile, this.jarFiles, JAR_FILES_LIST);
	}
	
	protected void removeJarFile_(String jarFile) {
		this.removeItemFromList(jarFile, this.jarFiles, JAR_FILES_LIST);
	}

	protected void removeJarFile_(int index) {
		this.removeItemFromList(index, this.jarFiles, JAR_FILES_LIST);
	}

	protected void setJarFile_(int index, String jarFile) {
		this.setItemInList(index, jarFile, this.jarFiles, JAR_FILES_LIST);
	}
	
	public void moveJarFile(int targetIndex, int sourceIndex) {
		CollectionTools.move(this.jarFiles, targetIndex, sourceIndex);
		this.xmlPersistenceUnit.getJarFiles().move(targetIndex, sourceIndex);
		this.fireItemMoved(JAR_FILES_LIST, targetIndex, sourceIndex);		
	}

	
	// **************** class refs *********************************************
	
	@SuppressWarnings("unchecked")
	public ListIterator<ClassRef> classRefs() {
		return new ReadOnlyCompositeListIterator<ClassRef>(
			specifiedClassRefs(), impliedClassRefs());
	}
	
	public int classRefsSize() {
		return specifiedClassRefsSize() + impliedClassRefsSize();
	}
	
	// **************** specified class refs ***********************************
	
	public ListIterator<ClassRef> specifiedClassRefs() {
		return new CloneListIterator<ClassRef>(this.specifiedClassRefs);
	}
	
	public int specifiedClassRefsSize() {
		return specifiedClassRefs.size();
	}
	
	public ClassRef addSpecifiedClassRef() {
		return addSpecifiedClassRef(this.specifiedClassRefsSize());
	}
	
	public ClassRef addSpecifiedClassRef(int index) {
		XmlJavaClassRef xmlClassRef = PersistenceFactory.eINSTANCE.createXmlJavaClassRef();
		ClassRef classRef = buildClassRef(xmlClassRef);
		this.specifiedClassRefs.add(index, classRef);
		this.xmlPersistenceUnit.getClasses().add(index, xmlClassRef);
		fireItemAdded(SPECIFIED_CLASS_REFS_LIST, index, classRef);
		return classRef;
	}

	public void removeSpecifiedClassRef(ClassRef classRef) {
		removeSpecifiedClassRef(this.specifiedClassRefs.indexOf(classRef));
	}
	
	public void removeSpecifiedClassRef(int index) {
		ClassRef classRefRemoved = this.specifiedClassRefs.remove(index);
		classRefRemoved.dispose();
		this.xmlPersistenceUnit.getClasses().remove(index);
		fireItemRemoved(SPECIFIED_CLASS_REFS_LIST, index, classRefRemoved);
	}
	
	protected void addSpecifiedClassRef_(ClassRef classRef) {
		addSpecifiedClassRef_(this.specifiedClassRefs.size(), classRef);
	}
	
	protected void addSpecifiedClassRef_(int index, ClassRef classRef) {
		addItemToList(index, 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 ListIterator<ClassRef> impliedClassRefs() {
		return new CloneListIterator<ClassRef>(impliedClassRefs);
	}
	
	public int impliedClassRefsSize() {
		return impliedClassRefs.size();
	}
	
	protected ClassRef addImpliedClassRef(String className) {
		return this.addImpliedClassRef(this.impliedClassRefs.size(), className);
	}
	
	protected ClassRef addImpliedClassRef(int index, String className) {
		ClassRef classRef = buildClassRef(className);
		addItemToList(index, classRef, this.impliedClassRefs, IMPLIED_CLASS_REFS_LIST);
		return classRef;
	}
	
	protected void removeImpliedClassRef(ClassRef classRef) {
		classRef.dispose();
		this.removeItemFromList(classRef, this.impliedClassRefs, IMPLIED_CLASS_REFS_LIST);
	}
	
	
	// **************** exclude unlisted classes *******************************
	
	public boolean isExcludeUnlistedClasses() {
		return getSpecifiedExcludeUnlistedClasses() == null ? getDefaultExcludeUnlistedClasses() : getSpecifiedExcludeUnlistedClasses().booleanValue();
	}
	
	public Boolean getSpecifiedExcludeUnlistedClasses() {
		return this.specifiedExcludeUnlistedClasses;
	}
	
	public void setSpecifiedExcludeUnlistedClasses(Boolean newExcludeUnlistedClasses) {
		Boolean oldExcludeUnlistedClasses = this.specifiedExcludeUnlistedClasses;
		this.specifiedExcludeUnlistedClasses = newExcludeUnlistedClasses;
		
		this.xmlPersistenceUnit.setExcludeUnlistedClasses(this.specifiedExcludeUnlistedClasses);
		
		firePropertyChanged(SPECIFIED_EXCLUDE_UNLISTED_CLASSES_PROPERTY, oldExcludeUnlistedClasses, newExcludeUnlistedClasses);
	}

	public boolean getDefaultExcludeUnlistedClasses() {
		// TODO - calculate default
		//  This is determined from the project
		return this.defaultExcludeUnlistedClasses;
	}


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

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

	public Property getProperty(String key) {
		if (key == null) {
			throw new IllegalStateException("Cannot getProperty: key is null."); //$NON-NLS-1$
		}
		for(Property property : this.properties) {
			if(key.equals(property.getName())) {
				return property;
			}
		}
		return null;
	}

	public ListIterator<Property> propertiesWithPrefix(String keyPrefix) {
		if (keyPrefix == null) {
			throw new IllegalStateException("Cannot find propertiesWithPrefix: keyPrefix is null."); //$NON-NLS-1$
		}
		List<Property> result = new ArrayList<Property>();
		
		for(Property property : this.properties) {
			if(property.getName() != null && property.getName().startsWith(keyPrefix)) {
				result.add( property);
			}
		}
		return result.listIterator();
	}
	
	public Property getProperty(String key, String value) {
		if (key == null || value == null) {
			throw new IllegalStateException("Cannot getProperty: key or value is null."); //$NON-NLS-1$
		}
		for(Property property : this.properties) {
			if(key.equals(property.getName())) {
				if(value.equals(property.getValue())) {
						return property;
				}
			}
		}
		return null;
	}
	
	protected Property getProperty(int index) {
		return this.properties.get(index);
	}

	protected XmlProperty getXmlProperty(String propertyName, String value) {
		if (this.xmlPersistenceUnit.getProperties() == null) {
			XmlProperties xmlProperties = PersistenceFactory.eINSTANCE.createXmlProperties();
			this.xmlPersistenceUnit.setProperties(xmlProperties);
		}
		for(XmlProperty xmlProperty : this.xmlPersistenceUnit.getProperties().getProperties()) {
			if(propertyName.equals(xmlProperty.getName()) && value.equals(xmlProperty.getValue())) {
				return xmlProperty;
			}
		}
		return null;
	}

	/**
	 * Adds or Changes Property with the given key and value.
	 */
	public void putProperty(String key, String value, boolean allowDuplicates) {
		if( ! allowDuplicates && this.containsProperty(key)) {
			this.putXmlProperty(key, value, this.getProperty(key).getValue());
			return;
		}
		if( value != null) {
			XmlProperty xmlProperty = PersistenceFactory.eINSTANCE.createXmlProperty();
			xmlProperty.setName(key);
			xmlProperty.setValue(value);
			
			this.addXmlProperty(xmlProperty, propertiesSize());
			return;
		}
	}
	
	public void replacePropertyValue(String key, String oldValue, String newValue) {
		
		this.putXmlProperty(key, newValue, oldValue);
	}
	
	protected void putXmlProperty(String key, String value, String oldValue) {
		if( value == null) {
			this.removeProperty(key);
			return;
		}

		XmlProperty xmlProperty = this.getXmlProperty(key, oldValue);
		if(xmlProperty == null) {
			throw new NoSuchElementException("Missing Property name: " + key + ", value: " + oldValue); //$NON-NLS-1$ //$NON-NLS-2$
		}
		xmlProperty.setValue(value);
	}	
	
	public boolean containsProperty(String key) {
		return (this.getProperty(key) != null);
	}

	public Property addProperty() {
		return addProperty(propertiesSize());
	}
	
	public Property addProperty(int index) {
		return this.addXmlProperty(PersistenceFactory.eINSTANCE.createXmlProperty(), index);
	}
	
	protected Property addXmlProperty(XmlProperty xmlProperty, int index) {

		Property property = buildProperty(xmlProperty);
		
		if (this.xmlPersistenceUnit.getProperties() == null) {
			XmlProperties xmlProperties = PersistenceFactory.eINSTANCE.createXmlProperties();
			this.xmlPersistenceUnit.setProperties(xmlProperties);
		}
		
		this.properties.add(index, property);
		this.xmlPersistenceUnit.getProperties().getProperties().add(index, xmlProperty);
		this.fireItemAdded(PROPERTIES_LIST, index, property);
		return property;
	}
	
	public void removeProperty(String key) {
		this.removeProperty(this.getProperty(key));
	}
	
	public void removeProperty(String key, String value) {
		this.removeProperty(this.getProperty(key, value));
	}
	
	public void removeProperty(Property property) {
		if (property != null) {
			this.removeProperty(this.properties.indexOf(property));
		}
	}
	
	protected void removeProperty(int index) {
		Property propertyRemoved = this.properties.remove(index);
		this.xmlPersistenceUnit.getProperties().getProperties().remove(index);
		
		if (this.xmlPersistenceUnit.getProperties().getProperties().isEmpty()) {
			this.xmlPersistenceUnit.setProperties(null);
		}
		
		fireItemRemoved(PROPERTIES_LIST, index, propertyRemoved);
	}
	
	protected void addProperty_(Property property) {
		addProperty_(this.properties.size(), property);
	}
	
	protected void addProperty_(int index, Property property) {
		addItemToList(index, property, this.properties, PROPERTIES_LIST);
	}
	
	protected void removeProperty_(Property property) {
		this.removeItemFromList(property, this.properties, PROPERTIES_LIST);
	}
	
	
	// **************** Persistence Unit Defaults *********************************************
	
	//TODO validation for multiple persistenceUnitDefaults.
	
	//Take the first MappingFilePersistenceUnitDefaults found in a mapping file and use
	//this for the defaults of the PersistenceUnit.
	protected MappingFilePersistenceUnitDefaults getPersistenceUnitDefaults() {
		for (Iterator<MappingFileRef> stream= this.mappingFileRefs(); stream.hasNext(); ) {
			MappingFilePersistenceUnitDefaults defaults = stream.next().getPersistenceUnitDefaults();
			if (defaults != null) {
				return defaults;
			}
		}
		return null;
	}

	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);
	}	
	
	public String getDefaultCatalog() {
		return this.defaultCatalog;
	}
	
	protected void setDefaultCatalog(String catalog) {
		String old = this.defaultCatalog;
		this.defaultCatalog = catalog;
		this.firePropertyChanged(DEFAULT_CATALOG_PROPERTY, old, catalog);
	}
	
	public String getDefaultSchema() {
		return this.defaultSchema;
	}
	
	protected void setDefaultSchema(String schema) {
		String old = this.defaultSchema;
		this.defaultSchema = schema;
		this.firePropertyChanged(DEFAULT_SCHEMA_PROPERTY, old, schema);
	}
	
	public boolean getDefaultCascadePersist() {
		return this.defaultCascadePersist;
	}
	
	protected void setDefaultCascadePersist(boolean cascadePersist) {
		boolean old = this.defaultCascadePersist;
		this.defaultCascadePersist = cascadePersist;
		this.firePropertyChanged(DEFAULT_CASCADE_PERSIST_PROPERTY, old, cascadePersist);
	}
	
	
	// **************** generators *********************
	
	public void addGenerator(Generator generator) {
		this.generators.add(generator);
	}
	
	public ListIterator<Generator> allGenerators() {
		return new CloneListIterator<Generator>(this.generators);
	}

	protected Iterator<String> allGeneratorNames() {
		return new TransformationIterator<Generator, String>(this.allGenerators()) {
			@Override
			protected String transform(Generator generator) {
				return generator.getName();
			}
		};
	}
	
	protected Iterator<String> allNonNullGeneratorNames() {
		return new FilteringIterator<String, String>(this.allGeneratorNames()) {
			@Override
			protected boolean accept(String generatorName) {
				return generatorName != null;
			}
		};
	}
	
	public String[] uniqueGeneratorNames() {
		HashSet<String> names = CollectionTools.set(this.allNonNullGeneratorNames());
		return names.toArray(new String[names.size()]);
	}

	
	// **************** queries *********************
	
	public void addQuery(Query query) {
		this.queries.add(query);
	}
	
	public ListIterator<Query> allQueries() {
		return new CloneListIterator<Query>(this.queries);
	}
	
	
	// **************** updating ***********************************************
	
	/**
	 * Concrete subclass must call this in the constructor, not called here
	 */
	//be careful changing the order of this method, bug 258701 is one reason.
	protected void initialize(XmlPersistenceUnit xpu) {
		this.xmlPersistenceUnit = xpu;
		this.name = xpu.getName();
		this.specifiedExcludeUnlistedClasses = xpu.getExcludeUnlistedClasses();
		this.specifiedTransactionType = specifiedTransactionType(xpu);
		this.defaultTransactionType = defaultTransacationType();
		this.description = xpu.getDescription();
		this.provider = xpu.getProvider();
		this.jtaDataSource = xpu.getJtaDataSource();
		this.nonJtaDataSource = xpu.getNonJtaDataSource();
		this.specifiedExcludeUnlistedClasses = xpu.getExcludeUnlistedClasses();
		this.initializeJarFiles();
		initializeProperties(xpu);
		
		//initialize specified classRefs before mappingFileRefs because of 
		//JpaFile rootStructureNode, we want the mapping file to "win",
		//as it would in a Jpa runtime implementation
		initializeSpecifiedClassRefs(xpu);
		initializeMappingFileRefs(xpu);
		//initialize implied classRefs last since they depend on both
		//specified classRefs and mappingFileRefs
		initializeImpliedClassRefs(xpu);
		initializePersistenceUnitDefaults();
	}
	
	protected void initializeMappingFileRefs(XmlPersistenceUnit xpu) {
		for (XmlMappingFileRef xmlMappingFileRef : xpu.getMappingFiles()) {
			specifiedMappingFileRefs.add(buildMappingFileRef(xmlMappingFileRef));
		}
		if (! impliedMappingFileIsSpecified() && impliedMappingFileExists()) {
			impliedMappingFileRef = buildMappingFileRef(null);
		}
	}
	
	protected void initializeJarFiles() {
		for (String jarFile : this.xmlPersistenceUnit.getJarFiles()) {
			this.jarFiles.add(jarFile);
		}
	}
	
	protected void initializeSpecifiedClassRefs(XmlPersistenceUnit xpu) {
		for (XmlJavaClassRef xmlJavaClassRef : xpu.getClasses()) {
			specifiedClassRefs.add(buildClassRef(xmlJavaClassRef));
		}
	}
	
	protected void initializeImpliedClassRefs(XmlPersistenceUnit xpu) {
		if (getJpaProject().discoversAnnotatedClasses() && ! isExcludeUnlistedClasses()) {
			for (String typeName : CollectionTools.iterable(this.getJpaProject().annotatedClassNames())) {
				if ( ! classIsSpecified(typeName)) {
					impliedClassRefs.add(buildClassRef(typeName));
				}
			}
		}
	}
	
	protected void initializeProperties(XmlPersistenceUnit xpu) {
		XmlProperties xmlProperties = xpu.getProperties();
		if (xmlProperties == null) {
			return;
		}
		for (XmlProperty xmlProperty : xmlProperties.getProperties()) {
			this.properties.add(buildProperty(xmlProperty));
		}
	}
	
	protected void initializePersistenceUnitDefaults() {
		MappingFilePersistenceUnitDefaults defaults = this.getPersistenceUnitDefaults();
		this.defaultAccess = this.buildDefaultAccess(defaults);
		this.defaultCatalog = this.buildDefaultCatalog(defaults);
		this.defaultSchema = this.buildDefaultSchema(defaults);
		this.defaultCascadePersist = this.buildDefaultCascadePersist(defaults);
	}

	public void update(XmlPersistenceUnit persistenceUnit) {
		this.xmlPersistenceUnit = persistenceUnit;
		this.generators.clear();
		this.queries.clear();
		updateName(persistenceUnit);
		updateSpecifiedTransactionType(persistenceUnit);
		updateDefaultTransactionType();
		updateDescription(persistenceUnit);
		updateProvider(persistenceUnit);
		updateJtaDataSource(persistenceUnit);
		updateNonJtaDataSource(persistenceUnit);
		updateJarFiles(persistenceUnit);
		//update specified classRefs before mappingFileRefs because of 
		//JpaFile rootStructureNode, we want the mapping file to "win",
		//as it would in a Jpa runtime implementation
		updateSpecifiedClassRefs(persistenceUnit);
		updateMappingFileRefs(persistenceUnit);
		//update implied classRefs last since they depend on both
		//specified classRefs and mappingFileRefs
		updateImpliedClassRefs();
		updateExcludeUnlistedClasses(persistenceUnit);
		updateProperties(persistenceUnit);
		updatePersistenceUnitDefaults();
		generatorRepositoryUpdated();
		queryRepositoryUpdated();
	}
	
	protected void updateName(XmlPersistenceUnit persistenceUnit) {
		setName(persistenceUnit.getName());
	}
	
	protected void updateSpecifiedTransactionType(XmlPersistenceUnit persistenceUnit) {
		setSpecifiedTransactionType(specifiedTransactionType(persistenceUnit));
	}
	
	protected PersistenceUnitTransactionType specifiedTransactionType(XmlPersistenceUnit persistenceUnit) {
		return PersistenceUnitTransactionType.fromXmlResourceModel(persistenceUnit.getTransactionType());
	}
	
	protected void updateDefaultTransactionType() {
		setDefaultTransactionType(defaultTransacationType());
	}
	
	protected PersistenceUnitTransactionType defaultTransacationType() {
		// 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."
		return null;
	}
	
	protected void updateDescription(XmlPersistenceUnit persistenceUnit) {
		setDescription(persistenceUnit.getDescription());
	}
	
	protected void updateProvider(XmlPersistenceUnit persistenceUnit) {
		setProvider(persistenceUnit.getProvider());
	}
	
	protected void updateJtaDataSource(XmlPersistenceUnit persistenceUnit) {
		setJtaDataSource(persistenceUnit.getJtaDataSource());
	}
	
	protected void updateNonJtaDataSource(XmlPersistenceUnit persistenceUnit) {
		setNonJtaDataSource(persistenceUnit.getNonJtaDataSource());
	}
	
	protected void updateMappingFileRefs(XmlPersistenceUnit persistenceUnit) {
		Iterator<MappingFileRef> stream = specifiedMappingFileRefs();
		Iterator<XmlMappingFileRef> stream2 = new CloneIterator<XmlMappingFileRef>(persistenceUnit.getMappingFiles());//prevent ConcurrentModificiationException
		
		while (stream.hasNext()) {
			MappingFileRef mappingFileRef = stream.next();
			if (stream2.hasNext()) {
				mappingFileRef.update(stream2.next());
			}
			else {
				removeSpecifiedMappingFileRef_(mappingFileRef);
			}
		}
		
		while (stream2.hasNext()) {
			addSpecifiedMappingFileRef_(buildMappingFileRef(stream2.next()));
		}
		
		if (impliedMappingFileIsSpecified()) {
			if (impliedMappingFileRef != null) {
				unsetImpliedMappingFileRef();
			}
		}
		else {
			if (impliedMappingFileExists()) {
				if (impliedMappingFileRef == null) {
					setImpliedMappingFileRef();
				}
				getImpliedMappingFileRef().update(null);
			}
			else {
				if (impliedMappingFileRef != null) {
					unsetImpliedMappingFileRef();
				}
			}
		}
	}
	
	protected boolean impliedMappingFileIsSpecified() {
		String impliedMappingFile = JptCorePlugin.DEFAULT_ORM_XML_FILE_PATH;
		for (MappingFileRef each : specifiedMappingFileRefs) {
			if (impliedMappingFile.equals(each.getFileName())) {
				return true;
			}
		}
		return false;
	}
	
	protected boolean impliedMappingFileExists() {
		OrmResourceModelProvider modelProvider = 
			OrmResourceModelProvider.getDefaultModelProvider(getJpaProject().getProject());
		OrmResource resource = modelProvider.getResource();
		return resource != null && resource.exists();
	}
	
	protected MappingFileRef buildMappingFileRef(XmlMappingFileRef xmlMappingFileRef) {
		return getJpaFactory().buildMappingFileRef(this, xmlMappingFileRef);
	}
	
	protected void updateJarFiles(XmlPersistenceUnit persistenceUnit) {
		int index = 0;
		for (String xmlJarFile : persistenceUnit.getJarFiles()) {
			if (this.jarFiles.size() > index) {
				if ( ! this.jarFiles.get(index).equals(xmlJarFile)) {
					this.setJarFile_(index, xmlJarFile);
				}
			} else {
				this.setJarFile_(index, xmlJarFile);			
			}
			index++;
		}
		
		while (index < this.jarFiles.size()) {
			this.removeJarFile_(index);
		}
	}
	
	//this is not being changed to match updateImpliedClassRefs.  In the xml,
	//changing the class name does not imply that a new object needs to be created.
	//If anything we should be matching ClassRefs with the corresponding XmlJavaClassRef
	//and if there is not one the ClassRef would be removed.  We would not want to 
	//do a name match as is done for the implied class refs.
	protected void updateSpecifiedClassRefs(XmlPersistenceUnit persistenceUnit) {
		Iterator<ClassRef> contextClassRefs = specifiedClassRefs();
		Iterator<XmlJavaClassRef> resourceClassRefs = new CloneIterator<XmlJavaClassRef>(persistenceUnit.getClasses());//prevent ConcurrentModificiationException
		
		while (contextClassRefs.hasNext()) {
			ClassRef contextClassRef = contextClassRefs.next();
			if (resourceClassRefs.hasNext()) {
				contextClassRef.update(resourceClassRefs.next());
			}
			else {
				removeSpecifiedClassRef_(contextClassRef);
			}
		}
		
		while (resourceClassRefs.hasNext()) {
			addSpecifiedClassRef_(buildClassRef(resourceClassRefs.next()));
		}
	}
	
	protected void updateImpliedClassRefs() {
		if (isExcludeUnlistedClasses()) {
			for (ClassRef classRef : CollectionTools.iterable(impliedClassRefs())) {
				removeImpliedClassRef(classRef);
			}
			return;
		}
		
		Iterator<String> annotatedClassNames = getJpaProject().annotatedClassNames();
		Collection<ClassRef> impliedRefsToRemove = CollectionTools.collection(impliedClassRefs());
		Collection<ClassRef> impliedRefsToUpdate = new ArrayList<ClassRef>();
		
		while (annotatedClassNames.hasNext()) {
			String annotatedClassName = annotatedClassNames.next();
			boolean impliedRefFound = false;
			if (!classIsSpecified(annotatedClassName)) {
				for (ClassRef classRef : impliedRefsToRemove) {
					if (annotatedClassName.equals(classRef.getClassName())) {
						impliedRefsToRemove.remove(classRef);
						impliedRefsToUpdate.add(classRef);
						impliedRefFound = true;
						break;
					}
				}
				if (!impliedRefFound) {
					addImpliedClassRef(annotatedClassName);
				}
			}
		}
		for (ClassRef classRef : impliedRefsToRemove) {
			removeImpliedClassRef(classRef);
		}
		//first handle adding/removing of the implied class refs, then update the others last, 
		//this causes less churn in the update process
		for (ClassRef classRef : impliedRefsToUpdate) {
			classRef.update(classRef.getClassName());
		}
	}
	
	protected ClassRef buildClassRef(XmlJavaClassRef xmlClassRef) {
		return getJpaFactory().buildClassRef(this, xmlClassRef);
	}
	
	protected ClassRef buildClassRef(String className) {
		return getJpaFactory().buildClassRef(this, className);
	}
	
	/**
	 * Return true if the class is specified either as a class
	 * or listed in a mapping file
	 */
	protected boolean classIsSpecified(String className) {
		for (ClassRef specifiedClassRef : CollectionTools.iterable(specifiedClassRefs())) {
			if (className.equals(specifiedClassRef.getClassName())) {
				return true;
			}
		}
		for (Iterator<MappingFileRef> stream = this.mappingFileRefs(); stream.hasNext(); ) {
			if (stream.next().getPersistentType(className) != null) {
				return true;
			}
		}
		return false;
	}
	
	protected void updateExcludeUnlistedClasses(XmlPersistenceUnit persistenceUnit) {
		setSpecifiedExcludeUnlistedClasses(persistenceUnit.getExcludeUnlistedClasses());
	}

	protected void updateProperties(XmlPersistenceUnit persistenceUnit) {
		List<XmlProperty> xmlProperties = 	this.buildXmlProperties(persistenceUnit);
		
		Iterator<Property> stream = this.properties();
		while (stream.hasNext()) {
			Property property = stream.next();
			XmlProperty xmlProperty = this.getXmlPropertyNamed(property.getName(), xmlProperties);
			if (xmlProperty != null) {
				property.update(xmlProperty);
				
				xmlProperties.remove(xmlProperty);
			}
			else {
				this.removeProperty_(property);
			}
		}

		for (XmlProperty xmlProperty : xmlProperties) {
			this.addProperty_(this.buildProperty(xmlProperty));
		}
	}
	
	protected Property buildProperty(XmlProperty xmlProperty) {
		return getJpaFactory().buildProperty(this, xmlProperty);
	}

	protected List<XmlProperty> buildXmlProperties(XmlPersistenceUnit persistenceUnit) {
		if (persistenceUnit.getProperties() == null) {
			return new ArrayList<XmlProperty>();
		}
		return CollectionTools.list(persistenceUnit.getProperties().getProperties());
	}
	
	protected XmlProperty getXmlPropertyNamed(String name, List<XmlProperty> xmlProperties) {
		for(XmlProperty xmlProperty : xmlProperties) {
			String xmlPropertyName = xmlProperty.getName();
			if(xmlPropertyName == name || xmlPropertyName.equals(name)) {
				return xmlProperty;
			};
		}
		return null;
	}
		
	protected void updatePersistenceUnitDefaults() {
		MappingFilePersistenceUnitDefaults defaults = getPersistenceUnitDefaults();
		this.setDefaultAccess(this.buildDefaultAccess(defaults));
		this.setDefaultCatalog(this.buildDefaultCatalog(defaults));
		this.setDefaultSchema(this.buildDefaultSchema(defaults));
		this.setDefaultCascadePersist(this.buildDefaultCascadePersist(defaults));
	}

	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();
	}
	
	// This is called after the persistence unit has been updated to ensure
	// we catch all added generators
	protected void generatorRepositoryUpdated() {
		fireListChanged(GENERATORS_LIST);
	}
	
	// This is called after the persistence unit has been updated to ensure
	// we catch all added queries
	protected void queryRepositoryUpdated() {
		fireListChanged(QUERIES_LIST);
	}
	
	
	// ********** Validation ***********************************************
	
	@Override
	public void validate(List<IMessage> messages) {
		super.validate(messages);
		this.validateMappingFiles(messages);	
		this.validateClassRefs(messages);
	}
	
	protected void validateMappingFiles(List<IMessage> messages) {
		this.checkForMultiplePersistenceUnitDefaults(messages);
		this.checkForDuplicateMappingFiles(messages);
		for (Iterator<MappingFileRef> stream = this.mappingFileRefs(); stream.hasNext();) {
			stream.next().validate(messages);
		}
	}
	
	protected void checkForMultiplePersistenceUnitDefaults(List<IMessage> messages) {
		boolean foundDefaultsToUse = false;
		Iterator<MappingFileRef> stream = mappingFileRefs();
		while (stream.hasNext() && ! foundDefaultsToUse) {
			MappingFileRef mappingFileRef = stream.next();
			MappingFile mappingFile = mappingFileRef.getMappingFile();
			if (mappingFile != null 
					&& mappingFile.getRoot() != null 
					&& mappingFile.getRoot().getPersistenceUnitDefaults() != null
					&& mappingFile.getRoot().getPersistenceUnitDefaults().resourceExists()) {
				foundDefaultsToUse = true;
			}
		}
		while (stream.hasNext()) {
			MappingFileRef mappingFileRef = stream.next();
			MappingFile mappingFile = mappingFileRef.getMappingFile();
			if (mappingFile != null 
				&& mappingFile.getRoot() != null 
				&& mappingFile.getRoot().getPersistenceUnitDefaults() != null
				&& mappingFile.getRoot().getPersistenceUnitDefaults().resourceExists()) {
				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 (MappingFileRef mappingFileRef : CollectionTools.iterable(this.mappingFileRefs())) {
			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) {
		this.checkForDuplicateClasses(messages);
		for (Iterator<ClassRef> stream = this.classRefs(); stream.hasNext(); ) {
			stream.next().validate(messages);
		}
	}

	protected void checkForDuplicateClasses(List<IMessage> messages) {
		HashBag<String> classNames = new HashBag<String>();
		CollectionTools.addAll(classNames, this.classRefNames());
		for (ClassRef classRef : CollectionTools.iterable(this.classRefs())) {
			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();
			}
		};
	}

	protected Collection<MappingFile> buildMappingFiles() {
		ArrayList<MappingFile> result = new ArrayList<MappingFile>();
		for (Iterator<MappingFileRef> stream = this.mappingFileRefs(); stream.hasNext(); ) {
			MappingFile mappingFile = stream.next().getMappingFile();
			if (mappingFile != null) {
				result.add(mappingFile);
			}
		}
		return result;
	}
	
	//*************************************
	
	public PersistentType getPersistentType(String fullyQualifiedTypeName) {
		for (Iterator<MappingFileRef> stream = this.mappingFileRefs(); stream.hasNext(); ) {
			PersistentType persistentType = stream.next().getPersistentType(fullyQualifiedTypeName);
			if (persistentType != null) {
				return persistentType;
			}
		}
		for (ClassRef classRef : CollectionTools.iterable(classRefs())) {
			if (classRef.isFor(fullyQualifiedTypeName)) {
				return classRef.getJavaPersistentType();
			}
		}
		return null;
	}
	
	public Entity getEntity(String fullyQualifiedTypeName) {
		PersistentType persistentType = this.getPersistentType(fullyQualifiedTypeName);
		if (persistentType == null) {
			return null;
		}
		TypeMapping typeMapping = persistentType.getMapping();
		return (typeMapping instanceof Entity) ? (Entity) typeMapping : null;
	}
	
	public JpaStructureNode getStructureNode(int textOffset) {
		for (MappingFileRef mappingFileRef : CollectionTools.iterable(mappingFileRefs())) {
			if (mappingFileRef.containsOffset(textOffset)) {
				return mappingFileRef;
			}
		}
		for (ClassRef classRef : CollectionTools.iterable(classRefs())) {
			if (classRef.containsOffset(textOffset)) {
				return classRef;
			}
		}
		return this;
	}
	
	public boolean containsOffset(int textOffset) {
		if (xmlPersistenceUnit == null) {
			return false;
		}
		return xmlPersistenceUnit.containsOffset(textOffset);
	}
	
	public TextRange getSelectionTextRange() {
		return xmlPersistenceUnit.getSelectionTextRange();
	}
	
	public TextRange getValidationTextRange() {
		return xmlPersistenceUnit.getValidationTextRange();
	}
	
	@Override
	public void toString(StringBuilder sb) {
		super.toString(sb);
		sb.append(getName());
	}
	
	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();
		}
	}
}
