/*******************************************************************************
 * Copyright (c) 2007, 2016 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0, which accompanies this distribution
 * and is available at https://www.eclipse.org/legal/epl-2.0/.
 *
 * Contributors:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.jpa.core.internal.context;

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.Vector;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jpt.common.core.JptResourceType;
import org.eclipse.jpt.common.core.internal.utility.ValidationMessageTools;
import org.eclipse.jpt.common.core.utility.TextRange;
import org.eclipse.jpt.common.core.utility.ValidationMessage;
import org.eclipse.jpt.common.utility.internal.ObjectTools;
import org.eclipse.jpt.common.utility.internal.collection.CollectionTools;
import org.eclipse.jpt.common.utility.internal.iterator.IteratorTools;
import org.eclipse.jpt.common.utility.iterable.ListIterable;
import org.eclipse.jpt.jpa.core.JpaModel;
import org.eclipse.jpt.jpa.core.context.JpaContextModel;
import org.eclipse.jpt.jpa.core.context.MappingFile;
import org.eclipse.jpt.jpa.core.context.persistence.PersistenceUnit;
import org.eclipse.jpt.jpa.core.internal.AbstractJpaModel;
import org.eclipse.jpt.jpa.db.Catalog;
import org.eclipse.jpt.jpa.db.Schema;
import org.eclipse.jpt.jpa.db.SchemaContainer;
import org.eclipse.jst.j2ee.model.internal.validation.ValidationCancelledException;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;

public abstract class AbstractJpaContextModel<P extends JpaContextModel>
	extends AbstractJpaModel<P>
	implements JpaContextModel
{
	protected AbstractJpaContextModel(P parent) {
		super(parent);
	}


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

	public void synchronizeWithResourceModel(IProgressMonitor monitor) {
		if (monitor.isCanceled()) {
			throw new OperationCanceledException();
		}
	}

	/**
	 * convenience method
	 */
	protected void synchronizeModelsWithResourceModel(Iterable<? extends JpaContextModel> models, IProgressMonitor monitor) {
		for (JpaContextModel model : models) {
			model.synchronizeWithResourceModel(monitor);
		}
	}

	public void update(IProgressMonitor monitor) {
		if (monitor.isCanceled()) {
			throw new OperationCanceledException();
		}
	}

	/**
	 * convenience method
	 */
	protected void updateModels(Iterable<? extends JpaContextModel> models, IProgressMonitor monitor) {
		for (JpaContextModel model : models) {
			model.update(monitor);
		}
	}


	// ********** containment hierarchy **********

	/**
	 * Overridden in:<ul>
	 * <li>{@link org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaContextModel#getResourceType() AbstractJavaJpaContextModel}
	 * <li>{@link org.eclipse.jpt.jpa.core.internal.jpa1.context.java.GenericJarFile#getResourceType() GenericJarFile}
	 * <li>{@link org.eclipse.jpt.jpa.core.internal.jpa1.context.orm.GenericOrmXml#getResourceType() GenericOrmXml}
	 * <li>{@link org.eclipse.jpt.jpa.core.internal.jpa1.context.persistence.GenericPersistenceXml#getResourceType() GenericPersistenceXml}
	 * </ul>
	 */
	public JptResourceType getResourceType() {
		return this.parent.getResourceType();
	}

	/**
	 * Overridden in:<ul>
	 * <li>{@link org.eclipse.jpt.jpa.core.internal.context.persistence.AbstractPersistenceUnit#getPersistenceUnit() AbstractPersistenceUnit}
	 * to return itself
	 * <li>{@link org.eclipse.jpt.jpa.core.internal.jpa1.context.GenericContextRoot#getPersistenceUnit() GenericContextModelRoot}
	 * to return <code>null</code>
	 * </ul>
	 */
	public PersistenceUnit getPersistenceUnit() {
		return this.parent.getPersistenceUnit();
	}

	/**
	 * Overridden in:<ul>
	 * <li>{@link org.eclipse.jpt.jpa.core.internal.context.orm.AbstractEntityMappings#getMappingFileRoot() AbstractEntityMappings}
	 * to return itself
	 * <li>{@link org.eclipse.jpt.jpa.core.internal.jpa1.context.GenericContextRoot#getMappingFileRoot() GenericContextModelRoot}
	 * to return <code>null</code>
	 * </ul>
	 */
	public MappingFile.Root getMappingFileRoot() {
		return this.parent.getMappingFileRoot();
	}


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

	/**
	 * All subclass implementations should be
	 * preceded by a "super" call to this method.
	 */
	public void validate(List<IMessage> messages, IReporter reporter) {
		if (reporter.isCancelled()) {
			throw new ValidationCancelledException();
		}
	}

	/**
	 * Return the specified text range if it is not <code>null</code>; if it is
	 * <code>null</code>, return the model's validation text range.
	 * Typically, the specified text range is for one of the model's children.
	 */
	protected TextRange getValidationTextRange(TextRange textRange) {
		return (textRange != null) ? textRange : this.getValidationTextRange();
	}

	/**
	 * Validate the specified model if it is not <code>null</code>.
	 */
	protected void validateModel(JpaContextModel model, List<IMessage> messages, IReporter reporter) {
		if (model != null) {
			model.validate(messages, reporter);
		}
	}

	/**
	 * Validate the specified models.
	 */
	protected void validateModels(Iterable<? extends JpaContextModel> models, List<IMessage> messages, IReporter reporter) {
		for (JpaContextModel model : models) {
			model.validate(messages, reporter);
		}
	}

	/**
	 * @see #buildValidationMessage(JpaModel, ValidationMessage)
	 * @see IMessage#HIGH_SEVERITY
	 */
	protected IMessage buildValidationMessage(ValidationMessage message) {
		return this.buildValidationMessage(this, message);
	}

	/**
	 * @see ValidationMessageTools#buildValidationMessage(IResource, ValidationMessage)
	 * @see IMessage#HIGH_SEVERITY
	 */
	protected IMessage buildValidationMessage(JpaModel target, ValidationMessage message) {
		return ValidationMessageTools.buildValidationMessage(target.getResource(), message);
	}

	/**
	 * @see #buildValidationMessage(JpaModel, ValidationMessage, Object[])
	 * @see IMessage#HIGH_SEVERITY
	 */
	protected IMessage buildValidationMessage(ValidationMessage message, Object... args) {
		return this.buildValidationMessage(this, message, args);
	}

	/**
	 * @see ValidationMessageTools#buildValidationMessage(IResource, ValidationMessage, Object[])
	 * @see IMessage#HIGH_SEVERITY
	 */
	protected IMessage buildValidationMessage(JpaModel target, ValidationMessage message, Object... args) {
		return ValidationMessageTools.buildValidationMessage(target.getResource(), message, args);
	}

	/**
	 * @see #buildValidationMessage(JpaModel, TextRange, ValidationMessage)
	 * @see IMessage#HIGH_SEVERITY
	 */
	protected IMessage buildValidationMessage(TextRange textRange, ValidationMessage message) {
		return this.buildValidationMessage(this, textRange, message);
	}

	/**
	 * @see ValidationMessageTools#buildValidationMessage(IResource, TextRange, ValidationMessage)
	 * @see IMessage#HIGH_SEVERITY
	 */
	protected IMessage buildValidationMessage(JpaModel target, TextRange textRange, ValidationMessage message) {
		return ValidationMessageTools.buildValidationMessage(target.getResource(), textRange, message);
	}

	/**
	 * @see #buildValidationMessage(JpaModel, TextRange, ValidationMessage, Object[])
	 * @see IMessage#HIGH_SEVERITY
	 */
	protected IMessage buildValidationMessage(TextRange textRange, ValidationMessage message, Object... args) {
		return this.buildValidationMessage(this, textRange, message, args);
	}

	/**
	 * @see ValidationMessageTools#buildValidationMessage(IResource, TextRange, ValidationMessage, Object[])
	 * @see IMessage#HIGH_SEVERITY
	 */
	protected IMessage buildValidationMessage(JpaModel target, TextRange textRange, ValidationMessage message, Object... args) {
		return ValidationMessageTools.buildValidationMessage(target.getResource(), textRange, message, args);
	}


	// *********** completion proposals ***********

	public Iterable<String> getCompletionProposals(int pos) {
		if (this.connectionProfileIsActive()) {
			Iterable<String> result = this.getConnectedCompletionProposals(pos);
			if (result != null) {
				return result;
			}
		}
		return null;
	}

	/**
	 * This method is called if the database is connected, allowing us to
	 * get candidates from the various database tables etc.
	 * This method should <em>not</em> be cascaded to "child" objects; it should
	 * only return candidates for the current object. The cascading is
	 * handled by {@link #getCompletionProposals(int)}.
	 */
	@SuppressWarnings("unused")
	protected Iterable<String> getConnectedCompletionProposals(int pos) {
		return null;
	}


	// ********** database stuff **********

	public Schema getContextDefaultDbSchema() {
		SchemaContainer dbSchemaContainer = this.getContextDefaultDbSchemaContainer();
		return (dbSchemaContainer == null) ? null : dbSchemaContainer.getSchemaForIdentifier(this.getContextDefaultSchema());
	}

	protected String getContextDefaultSchema() {
		MappingFile.Root mfr = this.getMappingFileRoot();
		return (mfr != null) ? mfr.getSchema() : this.getPersistenceUnit().getDefaultSchema();
	}

	/**
	 * If we don't have a catalog (i.e. we don't even have a <em>default</em> catalog),
	 * then the database probably does not support catalogs; and we need to
	 * get the schema directly from the database.
	 */
	public SchemaContainer getContextDefaultDbSchemaContainer() {
		String catalog = this.getContextDefaultCatalog();
		return (catalog != null) ? this.resolveDbCatalog(catalog) : this.getDatabase();
	}

	/**
	 * If we don't have a catalog (i.e. we don't even have a <em>default</em>
	 * catalog), then the database probably does not support catalogs.
	 */
	public Catalog getContextDefaultDbCatalog() {
		String catalog = this.getContextDefaultCatalog();
		return (catalog == null) ? null : this.resolveDbCatalog(catalog);
	}

	protected String getContextDefaultCatalog() {
		MappingFile.Root mfr = this.getMappingFileRoot();
		return (mfr != null) ? mfr.getCatalog() : this.getPersistenceUnit().getDefaultCatalog();
	}


	// ********** containers **********

	/**
	 * Adapter used to synchronize a collection of context models with the
	 * corresponding collection of resource models.
	 * @param <C> the type of context elements
	 * @param <R> the type of resource elements
	 */
	public static abstract class Container<C, R>
		implements ListIterable<C>
	{
		/**
		 * "Context" elements.
		 */
		protected final Vector<C> elements = new Vector<>();

		/**
		 * Aspect name used for event notification when the
		 * container's contents change.
		 */
		protected final String aspectName;

		protected final Adapter<C, R> adapter;


		protected Container(String aspectName, Adapter<C, R> adapter) {
			super();
			this.aspectName = aspectName;
			this.adapter = adapter;
		}

		/**
		 * Subclasses call this as necessary.
		 */
		protected void initialize() {
			for (R resourceElement : this.adapter.getResourceElements()) {
				this.elements.add(this.adapter.buildContextElement(resourceElement));
			}
		}

		public C get(int index) {
			return this.elements.get(index);
		}

		public ListIterator<C> iterator() {
			return IteratorTools.clone(this.elements);
		}

		/**
		 * Return the size of the context elements collection
		 */
		public int size() {
			return this.elements.size();
		}

		/**
		 * Add a context element for the specified resource element at the
		 * specified index.
		 */
		public C addContextElement(int index, R resourceElement) {
			return this.add(index, this.adapter.buildContextElement(resourceElement));
		}

		/**
		 * Add the specified context element to the container at the specified
		 * index.
		 */
		protected abstract C add(int index, C element);

		/**
		 * Add context elements for the specified resource elements at the
		 * specified index.
		 */
		public Iterable<C> addContextElements(int index, Iterable<R> resourceElements) {
			ArrayList<C> contextElements = new ArrayList<>();
			for (R resourceElement : resourceElements) {
				contextElements.add(this.adapter.buildContextElement(resourceElement));
			}
			return this.addAll(index, contextElements);
		}

		/**
		 * Add the specified context elements to the collection.
		 */
		protected abstract Iterable<C> addAll(int index, Iterable<C> contextElements);

		/**
		 * Remove the specified context element from the container.
		 */
		public abstract void remove(C element);

		/**
		 * Remove the specified context elements from the container.
		 */
		public abstract void removeAll(Iterable<C> contextElements);

		protected abstract void move(int index, C element);

		@Override
		public String toString() {
			return this.elements.toString();
		}

		/**
		 * Adapter used by the container to convert resource and context
		 * elements.
		 */
		public interface Adapter<C, R> {
			/**
			 * Return the current list of resource elements.
			 * The context elements are synchronized with this list.
			 */
			Iterable<R> getResourceElements();

			/**
			 * Return the specified context element's resource element.
			 * @see #buildContextElement(Object)
			 */
			R extractResourceElement(C contextElement);

			/**
			 * Build a context element for the specified resource element.
			 * @see #extractResourceElement(Object)
			 */
			C buildContextElement(R resourceElement);
		}
	}

	public abstract class AbstractContainerAdapter<C, R>
		implements Container.Adapter<C, R>
	{
		@Override
		public String toString() {
			return ObjectTools.toString(this);
		}
	}


	/**
	 * Adapter used to synchronize a collection of context models with the
	 * corresponding collection of resource models.
	 * @param <C> the type of context elements
	 * @param <R> the type of resource elements
	 */
	public abstract class ContextContainer<C extends JpaContextModel, R>
		extends Container<C, R>
	{
		protected ContextContainer(String aspectName, Container.Adapter<C, R> adapter) {
			super(aspectName, adapter);
		}

		/**
		 * Synchronize the context container with its
		 * corresponding resource container: moving, removing, and adding elements
		 * as necessary.
		 * <p>
		 * We can do this because:<ul>
		 * <li>the XML translators will <em>move</em> the EMF elements when
		 * appropriate (as opposed to simply rebuilding them in place).
		 * <li>the Java resource model will re-use existing annotations when
		 * appropriate (as opposed to simply rebuilding them in place).
		 * </ul>
		 */
		public void synchronizeWithResourceModel(IProgressMonitor monitor) {
			this.sync(true, monitor);  // true = sync
		}

		/**
		 * @see #synchronizeWithResourceModel(IProgressMonitor)
		 */
		public void update(IProgressMonitor monitor) {
			this.sync(false, monitor);  // false = update
		}

		/**
		 * The specified <code>sync</code> flag controls whether any surviving
		 * context nodes are either <em>synchronized</em> (<code>true</code>) or
		 * <em>updated</em> (<code>false</code>).
		 */
		protected void sync(boolean sync, IProgressMonitor monitor) {
			@SuppressWarnings("unchecked")
			HashSet<C> contextElements = (HashSet<C>) CollectionTools.hashSet(this.elements.toArray());
			ArrayList<C> contextElementsToSync = new ArrayList<>(contextElements.size());
			int resourceIndex = 0;

			for (R resourceElement : this.adapter.getResourceElements()) {
				boolean match = false;
				for (Iterator<C> stream = contextElements.iterator(); stream.hasNext(); ) {
					C contextElement = stream.next();
					if (ObjectTools.equals(this.adapter.extractResourceElement(contextElement), resourceElement)) {
						// we don't know the source index because the element has been moved by previously moved elements
						this.move(resourceIndex, contextElement);
						stream.remove();
						// TODO perform update here someday...
						contextElementsToSync.add(contextElement);
						match = true;
						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.addContextElement(resourceIndex, resourceElement);
				}
				resourceIndex++;
			}
			// remove any leftover context elements
			for (C contextElement : contextElements) {
				this.remove(contextElement);
			}
			// TODO bjv
			// take care of the structural changes before sync'ing the remaining elements;
			// we might be able to do this inline once we get rid of the "list change" events
			// and go with only add, remove, etc. list events
			// (these syncs will trigger "list change" events with list aspect adapters, which
			// trigger refreshes of UI adapters (e.g. TableModelAdapter) which will prematurely
			// discover any structural changes... :( )
			// see ItemAspectListValueModelAdapter.itemAspectChanged(EventObject)
			for (C contextElement : contextElementsToSync) {
				if (sync) {
					contextElement.synchronizeWithResourceModel(monitor);
				} else {
					contextElement.update(monitor);
				}
			}
		}
	}


	/**
	 * Adapter used to synchronize a <em>collection</em> of context models with the
	 * corresponding <em>collection</em> of resource models.
	 * @param <C> the type of context elements
	 * @param <R> the type of resource elements
	 */
	public abstract class ContextCollectionContainer<C extends JpaContextModel, R>
		extends ContextContainer<C, R>
	{
		protected ContextCollectionContainer(String aspectName, Container.Adapter<C, R> adapter) {
			super(aspectName, adapter);
		}

		@Override
		protected C add(int index, C element) {
			// ignore the index - not a list
			AbstractJpaContextModel.this.addItemToCollection(element, this.elements, this.aspectName);
			return element;
		}

		@Override
		protected Iterable<C> addAll(int index, Iterable<C> contextElements) {
			// ignore the index - not a list
			AbstractJpaContextModel.this.addItemsToCollection(contextElements, this.elements, this.aspectName);
			return contextElements;
		}

		@Override
		public void remove(C element) {
			AbstractJpaContextModel.this.removeItemFromCollection(element, this.elements, this.aspectName);
		}

		@Override
		public void removeAll(Iterable<C> contextElements) {
			AbstractJpaContextModel.this.removeItemsFromCollection(contextElements, this.elements, this.aspectName);
		}

		@Override
		protected void move(int index, C element) {
			// NOP - not a list
		}
	}

	// open up accessibility to container classes
	@Override
	protected <E> boolean addItemToCollection(E item, Collection<E> collection, String collectionName) {
		return super.addItemToCollection(item, collection, collectionName);
	}
	@Override
	protected <E> boolean addItemsToCollection(Iterable<? extends E> items, Collection<E> collection, String collectionName) {
		return super.addItemsToCollection(items, collection, collectionName);
	}
	@Override
	protected boolean removeItemFromCollection(Object item, Collection<?> collection, String collectionName) {
		return super.removeItemFromCollection(item, collection, collectionName);
	}
	@Override
	protected boolean removeItemsFromCollection(Iterable<?> items, Collection<?> collection, String collectionName) {
		return super.removeItemsFromCollection(items, collection, collectionName);
	}


	/**
	 * Use this container for a collection of <em>specified</em> elements.
	 * The container is initialized from the resource model upon construction.
	 * @see AbstractJpaContextModel.SpecifiedContextListContainer
	 * @see #buildSpecifiedContextCollectionContainer(String, AbstractJpaContextModel.Container.Adapter)
	 */
	public class SpecifiedContextCollectionContainer<C extends JpaContextModel, R>
		extends ContextCollectionContainer<C, R>
	{
		public SpecifiedContextCollectionContainer(String aspectName, Container.Adapter<C, R> adapter) {
			super(aspectName, adapter);
			this.initialize();
		}
	}

	protected <C extends JpaContextModel, R> SpecifiedContextCollectionContainer<C, R> buildSpecifiedContextCollectionContainer(String aspectName, Container.Adapter<C, R> adapter) {
		return new SpecifiedContextCollectionContainer<>(aspectName, adapter);
	}


	/**
	 * Use this container for a collection of <em>virtual</em> elements
	 * (e.g. default elements).
	 * The container is <em>not</em> initialized from the resource model upon
	 * construction (i.e. the container will effectively be initialized with the
	 * first <em>update</em>).
	 * @see AbstractJpaContextModel.VirtualContextListContainer
	 * @see #buildVirtualContextCollectionContainer(String, AbstractJpaContextModel.Container.Adapter)
	 */
	public class VirtualContextCollectionContainer<C extends JpaContextModel, R>
		extends ContextCollectionContainer<C, R>
	{
		public VirtualContextCollectionContainer(String aspectName, Container.Adapter<C, R> adapter) {
			super(aspectName, adapter);
			// NO initialization
		}
	}

	protected <C extends JpaContextModel, R> VirtualContextCollectionContainer<C, R> buildVirtualContextCollectionContainer(String aspectName, Container.Adapter<C, R> adapter) {
		return new VirtualContextCollectionContainer<>(aspectName, adapter);
	}


	/**
	 * Adapter used to synchronize a <em>list</em> of context models with the
	 * corresponding <em>list</em> of resource models.
	 * @param <C> the type of context elements
	 * @param <R> the type of resource elements
	 */
	public abstract class ContextListContainer<C extends JpaContextModel, R>
		extends ContextContainer<C, R>
	{
		protected ContextListContainer(String aspectName, Container.Adapter<C, R> adapter) {
			super(aspectName, adapter);
		}

		/**
		 * Return the index of the specified context element.
		 */
		public int indexOf(C element) {
			return this.elements.indexOf(element);
		}

		@Override
		protected C add(int index, C element) {
			AbstractJpaContextModel.this.addItemToList(index, element, this.elements, this.aspectName);
			return element;
		}

		@Override
		public Iterable<C> addAll(int index, Iterable<C> contextElements) {
			AbstractJpaContextModel.this.addItemsToList(index, contextElements, this.elements, this.aspectName);
			return contextElements;
		}

		/**
		 * Move the context element at the specified source index to the
		 * specified target index.
		 */
		public void move(int targetIndex, int sourceIndex) {
			AbstractJpaContextModel.this.moveItemInList(targetIndex, sourceIndex, this.elements, this.aspectName);
		}

		@Override
		public void move(int index, C element) {
			AbstractJpaContextModel.this.moveItemInList(index, element, this.elements, this.aspectName);
		}

		/**
		 * Clear the container.
		 */
		public void clear() {
			AbstractJpaContextModel.this.clearList(this.elements, this.aspectName);
		}

		/**
		 * Remove the context element at the specified index from the container.
		 */
		public C remove(int index) {
			return AbstractJpaContextModel.this.removeItemFromList(index, this.elements, this.aspectName);
		}

		@Override
		public void remove(C element) {
			AbstractJpaContextModel.this.removeItemFromList(element, this.elements, this.aspectName);
		}

		@Override
		public void removeAll(Iterable<C> contextElements) {
			AbstractJpaContextModel.this.removeItemsFromList(contextElements, this.elements, this.aspectName);
		}
	}

	// open up accessibility to container classes
	@Override
	protected <E> void addItemToList(int index, E item, List<E> list, String listName) {
		super.addItemToList(index, item, list, listName);
	}
	@Override
	protected <E> boolean addItemsToList(int index, Iterable<? extends E> items, List<E> list, String listName) {
		return super.addItemsToList(index, items, list, listName);
	}
	@Override
	protected <E> void moveItemInList(int targetIndex, int sourceIndex, List<E> list, String listName) {
		super.moveItemInList(targetIndex, sourceIndex, list, listName);
	}
	@Override
	protected <E> void moveItemInList(int targetIndex, E item, List<E> list, String listName) {
		super.moveItemInList(targetIndex, item, list, listName);
	}
	@Override
	protected boolean clearList(List<?> list, String listName) {
		return super.clearList(list, listName);
	}
	@Override
	protected <E> E removeItemFromList(int index, List<E> list, String listName) {
		return super.removeItemFromList(index, list, listName);
	}
	@Override
	protected boolean removeItemFromList(Object item, List<?> list, String listName) {
		return super.removeItemFromList(item, list, listName);
	}
	@Override
	protected boolean removeItemsFromList(Iterable<?> items, List<?> list, String listName) {
		return super.removeItemsFromList(items, list, listName);
	}


	/**
	 * @see AbstractJpaContextModel.SpecifiedContextCollectionContainer
	 * @see #buildSpecifiedContextListContainer(String, AbstractJpaContextModel.Container.Adapter)
	 */
	public class SpecifiedContextListContainer<C extends JpaContextModel, R>
		extends ContextListContainer<C, R>
	{
		public SpecifiedContextListContainer(String aspectName, Container.Adapter<C, R> adapter) {
			super(aspectName, adapter);
			this.initialize();
		}
	}

	protected <C extends JpaContextModel, R> SpecifiedContextListContainer<C, R> buildSpecifiedContextListContainer(String aspectName, Container.Adapter<C, R> adapter) {
		return new SpecifiedContextListContainer<>(aspectName, adapter);
	}


	/**
	 * @see AbstractJpaContextModel.VirtualContextCollectionContainer
	 * @see #buildVirtualContextListContainer(String, AbstractJpaContextModel.Container.Adapter)
	 */
	public class VirtualContextListContainer<C extends JpaContextModel, R>
		extends ContextListContainer<C, R>
	{
		public VirtualContextListContainer(String aspectName, Container.Adapter<C, R> adapter) {
			super(aspectName, adapter);
			// NO initialization
		}
	}

	protected <C extends JpaContextModel, R> VirtualContextListContainer<C, R> buildVirtualContextListContainer(String aspectName, Container.Adapter<C, R> adapter) {
		return new VirtualContextListContainer<>(aspectName, adapter);
	}


	/**
	 * Adapter used to synchronize a <em>list</em> of context values with the
	 * corresponding list of resource values. The assumption is the values are
	 * equal in each model (e.g. {@link String}s).
	 * @param <E> the type of context elements
	 */
	public abstract class ValueListContainer<E>
		extends Container<E, E>
	{
		protected ValueListContainer(String aspectName, Container.Adapter<E, E> adapter) {
			super(aspectName, adapter);
		}

		/**
		 * Return the index of the specified context element.
		 */
		public int indexOf(E element) {
			return this.elements.indexOf(element);
		}

		@Override
		protected E add(int index, E element) {
			AbstractJpaContextModel.this.addItemToList(index, element, this.elements, this.aspectName);
			return element;
		}

		@Override
		protected Iterable<E> addAll(int index, Iterable<E> contextElements) {
			AbstractJpaContextModel.this.addItemsToList(index, contextElements, this.elements, this.aspectName);
			return contextElements;
		}

		/**
		 * Move the context element at the specified source index to the
		 * specified target index.
		 */
		public void move(int targetIndex, int sourceIndex) {
			AbstractJpaContextModel.this.moveItemInList(targetIndex, sourceIndex, this.elements, this.aspectName);
		}

		@Override
		public void move(int index, E element) {
			AbstractJpaContextModel.this.moveItemInList(index, element, this.elements, this.aspectName);
		}

		@Override
		public void remove(E element) {
			AbstractJpaContextModel.this.removeItemFromList(element, this.elements, this.aspectName);
		}

		/**
		 * Remove the context element at the specified index from the container.
		 */
		public E remove(int index) {
			return AbstractJpaContextModel.this.removeItemFromList(index, this.elements, this.aspectName);
		}

		@Override
		public void removeAll(Iterable<E> contextElements) {
			AbstractJpaContextModel.this.removeItemsFromList(contextElements, this.elements, this.aspectName);
		}

		public void synchronizeWithResourceModel() {
			int resourceIndex = 0;
			// TODO we don't look for any moves, just simple adds and removes
			for (E resourceElement : this.adapter.getResourceElements()) {
				if (this.size() > resourceIndex) {
					E contextElement = this.get(resourceIndex);
					if (ObjectTools.notEquals(this.adapter.extractResourceElement(contextElement), resourceElement)) {
						this.addContextElement(resourceIndex, resourceElement);
					}
				} else {
					this.addContextElement(resourceIndex, resourceElement);
				}
				resourceIndex++;
			}

			while (resourceIndex < this.size()) {
				this.remove(resourceIndex++);
			}
		}
	}
}
