
<%
/**
 * <copyright>
 *
 * Copyright (c) 2002-2004 IBM Corporation and others.
 * 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:
 *   IBM - Initial API and implementation
 *
 * </copyright>
 */
%>
<%GenPackage genPackage = (GenPackage)argument; GenModel genModel=genPackage.getGenModel(); if (false) {/* Trick to import java.util.* without warnings */Iterator.class.getName();}%>
<%@ egf:patternCall patternId="platform:/plugin/org.eclipse.egf.emf.pattern.base/egf/EMF_Pattern_Base.fcore#LogicalName=org.eclipse.egf.emf.pattern.base.HeaderJava" args="parameter:argument"%>
package <%=genPackage.getProviderPackageName()%>;

<%genModel.addImport("org.eclipse.emf.common.notify.Adapter");%>
<%genModel.addImport("org.eclipse.emf.common.notify.Notification");%>
<%genModel.addImport("org.eclipse.emf.common.notify.Notifier");%>
<%genModel.addImport("org.eclipse.emf.edit.provider.ChangeNotifier");%>
<%genModel.addImport("org.eclipse.emf.edit.provider.ComposeableAdapterFactory");%>
<%genModel.addImport("org.eclipse.emf.edit.provider.ComposedAdapterFactory");%>
<%genModel.addImport("org.eclipse.emf.edit.provider.IChangeNotifier");%>
<%genModel.addImport("org.eclipse.emf.edit.provider.IEditingDomainItemProvider");%>
<%genModel.addImport("org.eclipse.emf.edit.provider.IItemLabelProvider");%>
<%genModel.addImport("org.eclipse.emf.edit.provider.IItemPropertySource");%>
<%genModel.addImport("org.eclipse.emf.edit.provider.INotifyChangedListener");%>
<%genModel.addImport("org.eclipse.emf.edit.provider.IStructuredItemContentProvider");%>
<%genModel.addImport("org.eclipse.emf.edit.provider.ITreeItemContentProvider");%>
<%String _ArrayList = genModel.getImportedName(genModel.useGenerics() ? "java.util.ArrayList<java.lang.Object>" : "java.util.ArrayList");%>
<%String _Collection = genModel.getImportedName(genModel.useGenerics() ? "java.util.Collection<java.lang.Object>" : "java.util.Collection");%>
<%genModel.markImportLocation(stringBuffer);%>

/**
 * This is the factory that is used to provide the interfaces needed to support Viewers.
 * The adapters generated by this factory convert EMF adapter notifications into calls to {@link #fireNotifyChanged fireNotifyChanged}.
 * The adapters also support Eclipse property sheets.
 * Note that most of the adapters are shared among multiple instances.
 * <!-- begin-user-doc -->
 * <!-- end-user-doc -->
 * @generated
 */
public class <%=genPackage.getItemProviderAdapterFactoryClassName()%> extends <%=genPackage.getImportedAdapterFactoryClassName()%> implements ComposeableAdapterFactory, IChangeNotifier<%if (genPackage.isDisposableProviderFactory()) {%>, <%=genModel.getImportedName("org.eclipse.emf.edit.provider.IDisposable")%><%}%>
{
<%if (genModel.hasCopyrightField()) {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public static final <%=genModel.getImportedName("java.lang.String")%> copyright = <%=genModel.getCopyrightFieldLiteral()%>;<%=genModel.getNonNLS()%>

<%}%>
	/**
	 * This keeps track of the root adapter factory that delegates to this adapter factory.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected ComposedAdapterFactory parentAdapterFactory;

	/**
	 * This is used to implement {@link org.eclipse.emf.edit.provider.IChangeNotifier}.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected IChangeNotifier changeNotifier = new ChangeNotifier();

<%if (genPackage.isDisposableProviderFactory() && genPackage.hasStatefulProvider()) {%>
	/**
	 * This keeps track of all the item providers created, so that they can be {@link #dispose disposed}.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected <%=genModel.getImportedName("org.eclipse.emf.edit.provider.Disposable")%> disposable = new Disposable();

<%}%>
	/**
	 * This keeps track of all the supported types checked by {@link #isFactoryForType isFactoryForType}.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected <%=_Collection%> supportedTypes = new <%=_ArrayList%>();

	/**
	 * This constructs an instance.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public <%=genPackage.getItemProviderAdapterFactoryClassName()%>()
	{
<%for (String name : genPackage.getProviderSupportedTypes()) {%>
		supportedTypes.add(<%=genModel.getImportedName(name)%>.class);
<%}%>
	}

<%for (GenPackage genDelegate : genPackage.getAdapterDelegatePackages()) {%>
	/**
	 * This keeps track of the factory to which to delegate adapter creation for objects from that package.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected <%=genDelegate.getImportedAdapterFactoryClassName()%> <%=genPackage.getUncapAdapterFactoryDelegateName(genDelegate)%> = null;

	/**
	 * This determines the delegate factory for the package.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected <%=genDelegate.getImportedAdapterFactoryClassName()%> get<%=genPackage.getAdapterFactoryDelegateName(genDelegate)%>()
	{
		if (<%=genPackage.getUncapAdapterFactoryDelegateName(genDelegate)%> == null)
		{
			<%=genModel.getImportedName("org.eclipse.emf.common.notify.AdapterFactory")%> rootAdapterFactory = getRootAdapterFactory();
			if (rootAdapterFactory instanceof ComposedAdapterFactory)
			{
				<%=genModel.getImportedName("org.eclipse.emf.common.notify.AdapterFactory")%> delegateAdapterFactory =
					((ComposedAdapterFactory)rootAdapterFactory).getFactoryForType(<%=genDelegate.getImportedAdapterFactoryClassName()%>.getPackage());
				if (delegateAdapterFactory instanceof <%=genDelegate.getImportedAdapterFactoryClassName()%>)
				{
					<%=genPackage.getUncapAdapterFactoryDelegateName(genDelegate)%> = (<%=genDelegate.getImportedAdapterFactoryClassName()%>)delegateAdapterFactory;
				}
			}
		}
		return <%=genPackage.getUncapAdapterFactoryDelegateName(genDelegate)%>;
	}

<%}%>
<%for (GenClass genClass : genPackage.getGenClasses()) {%>
<%if (!genClass.isAbstract() && genClass.getProvider() != GenProviderKind.NONE_LITERAL) {%>
<%if (genClass.isProviderSingleton()) {%>
	/**
	 * This keeps track of the one adapter used for all {@link <%=genClass.getQualifiedInterfaceName()%>} instances.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected <%=genClass.getProviderClassName()%> <%=genClass.getUncapName()%>ItemProvider;

	/**
	 * This creates an adapter for a {@link <%=genClass.getQualifiedInterfaceName()%>}.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
<%if (genModel.useClassOverrideAnnotation()) {%>
	@Override
<%}%>
	public Adapter create<%=genClass.getName()%>Adapter()
	{
		if (<%=genClass.getUncapName()%>ItemProvider == null)
		{
			<%=genClass.getUncapName()%>ItemProvider = new <%=genClass.getProviderClassName()%>(this);
		}

		return <%=genClass.getUncapName()%>ItemProvider;
	}

<%} else {%>
	/**
	 * This creates an adapter for a {@link <%=genClass.getQualifiedInterfaceName()%>}.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public Adapter create<%=genClass.getName()%>Adapter()
	{
		return new <%=genClass.getProviderClassName()%>(this);
	}

<%}%>
<%}%>
<%}%>
<%for (GenClass genClass : genPackage.getAdapterDelegateSuperClasses()) {%>
	/**
	 * <%=genClass.getName()%> of <%=genClass.getItemProviderAdapterFactoryClassName()%>
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public Adapter create<%=genClass.getName()%>Adapter()
	{
		return
			get<%=genClass.getItemProviderAdapterFactoryClassName()%>() == null ?
				null :
				get<%=genClass.getItemProviderAdapterFactoryClassName()%>().create<%=genClass.getName()%>Adapter();
	}

<%}%>
	/**
	 * This returns the root adapter factory that contains this factory.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public ComposeableAdapterFactory getRootAdapterFactory()
	{
		return parentAdapterFactory == null ? this : parentAdapterFactory.getRootAdapterFactory();
	}

	/**
	 * This sets the composed adapter factory that contains this factory.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setParentAdapterFactory(ComposedAdapterFactory parentAdapterFactory)
	{
		this.parentAdapterFactory = parentAdapterFactory;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
<%if (genModel.useClassOverrideAnnotation()) {%>
	@Override
<%}%>
	public boolean isFactoryForType(Object type)
	{
		return supportedTypes.contains(type) || super.isFactoryForType(type);
	}

	/**
	 * This implementation substitutes the factory itself as the key for the adapter.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
<%if (genModel.useClassOverrideAnnotation()) {%>
	@Override
<%}%>
	public Adapter adapt(Notifier notifier, Object type)
	{
		return super.adapt(notifier, this);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
<%if (genModel.useClassOverrideAnnotation()) {%>
	@Override
<%}%>
	public Object adapt(Object object, Object type)
	{
		if (isFactoryForType(type))
		{
			Object adapter = super.adapt(object, type);
			if (!(type instanceof Class) || (((Class<%if (genModel.useGenerics()) {%><?><%}%>)type).isInstance(adapter)))
			{
				return adapter;
			}
		}

		return null;
	}

<%if (genPackage.isDisposableProviderFactory() && genPackage.hasStatefulProvider()) {%>
	/**
	 * Associates an adapter with a notifier via the base implementation, then records it to ensure it will be disposed.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected void associate(Adapter adapter, Notifier target)
	{
		super.associate(adapter, target);
		if (adapter != null)
		{
			disposable.add(adapter);
		}
	}

<%}%>
	/**
	 * This adds a listener.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void addListener(INotifyChangedListener notifyChangedListener)
	{
		changeNotifier.addListener(notifyChangedListener);
	}

	/**
	 * This removes a listener.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void removeListener(INotifyChangedListener notifyChangedListener)
	{
		changeNotifier.removeListener(notifyChangedListener);
	}

	/**
	 * This delegates to {@link #changeNotifier} and to {@link #parentAdapterFactory}.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void fireNotifyChanged(Notification notification)
	{
		changeNotifier.fireNotifyChanged(notification);

		if (parentAdapterFactory != null)
		{
			parentAdapterFactory.fireNotifyChanged(notification);
		}
	}

<%if (genPackage.isDisposableProviderFactory()) {%>
	/**
	 * This disposes all of the item providers created by this factory. 
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void dispose()
	{
<%if (genPackage.hasStatefulProvider()) {%>
		disposable.dispose();
<%} else {%>
<%for (GenClass genClass : genPackage.getGenClasses()) {%>
<%if (!genClass.isAbstract() && genClass.isProviderSingleton()) {%>
		if (<%=genClass.getUncapName()%>ItemProvider != null) <%=genClass.getUncapName()%>ItemProvider.dispose();
<%}%>
<%}%>
<%}%>
	}

<%}%>
}
<%genModel.emitSortedImports();%>
