
<%
/**
 * Copyright (c) 2002-2010 IBM Corporation and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v20.html
 *
 * Contributors:
 *   IBM - Initial API and implementation
 */
%>
<%GenPackage genPackage = (GenPackage)argument; GenModel genModel=genPackage.getGenModel(); /* Trick to import java.util.* without warnings */Iterator.class.getName();%>
<%final boolean isJDK50 = genModel.getComplianceLevel().getValue() >= GenJDKLevel.JDK50;%>
<%@ 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");%>
<%boolean useGenerics = genModel.useGenerics();%>
<%String _ArrayList = genModel.getImportedName(useGenerics ? "java.util.ArrayList<java.lang.Object>" : "java.util.ArrayList");%>
<%String _Collection = genModel.getImportedName(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 -->
<%if (genPackage.hasAPITags()) {%>
 * <%=genPackage.getAPITags(genModel.getIndentation(stringBuffer))%>
<%}%>
 * @generated
 */
<%if (isJDK50 && genPackage.hasAPIDeprecatedTag()) {%>
@Deprecated
<%} else if (isJDK50 && GenModelUtil.hasAPIDeprecatedTag(genPackage.getGenClasses())) {%>
@SuppressWarnings("deprecation")
<%}%>
public class <%=genPackage.getItemProviderAdapterFactoryClassName()%> extends <%=genPackage.getImportedAdapterFactoryClassName()%> implements ComposeableAdapterFactory, IChangeNotifier<%if (genPackage.isDisposableProviderFactory()) {%>, <%=genModel.getImportedName("org.eclipse.emf.edit.provider.IDisposable")%><%}%><%if (genPackage.isExtensibleProviderFactory()) {%>, <%=genModel.getImportedName("org.eclipse.emf.edit.provider.IChildCreationExtender")%><%}%>
{
<%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();

<%}%>
<%if (genPackage.isExtensibleProviderFactory()) {%>
	/**
	 * This helps manage the child creation extenders.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected <%=genModel.getImportedName("org.eclipse.emf.edit.provider.ChildCreationExtenderManager")%> childCreationExtenderManager = new <%=genModel.getImportedName("org.eclipse.emf.edit.provider.ChildCreationExtenderManager")%>(<%=genPackage.getImportedEditPluginClassName()%>.INSTANCE, <%=genPackage.getImportedPackageInterfaceName()%>.eNS_URI);

<%}%>
	/**
	 * 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.getRawQualifiedInterfaceName()%>} instances.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
  <%if (genClass.hasAPITags()) {%>
	 * <%=genClass.getAPITags(genModel.getIndentation(stringBuffer))%>
  <%}%>
	 * @generated
	 */
  <%if (isJDK50 && genClass.hasAPIDeprecatedTag()) {%>
	@Deprecated
  <%}%>
	protected <%=genClass.getProviderClassName()%> <%=genClass.getUncapName()%>ItemProvider;

	/**
	 * This creates an adapter for a {@link <%=genClass.getRawQualifiedInterfaceName()%>}.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
  <%if (genClass.hasAPITags()) {%>
	 * <%=genClass.getAPITags(genModel.getIndentation(stringBuffer))%>
  <%}%>
	 * @generated
	 */
  <%if (isJDK50 && genClass.hasAPIDeprecatedTag()) {%>
	@Deprecated
  <%}%>
  <%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.getRawQualifiedInterfaceName()%>}.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
  <%if (genClass.hasAPITags()) {%>
	 * <%=genClass.getAPITags(genModel.getIndentation(stringBuffer))%>
  <%}%>
	 * @generated
	 */
  <%if (isJDK50 && genClass.hasAPIDeprecatedTag()) {%>
	@Deprecated
  <%}%>
  <%if (genModel.useClassOverrideAnnotation()) {%>
	@Override
  <%}%>
	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 -->
  <%if (genClass.hasAPITags()) {%>
	 * <%=genClass.getAPITags(genModel.getIndentation(stringBuffer))%>
  <%}%>
	 * @generated
	 */
  <%if (isJDK50 && genClass.hasAPIDeprecatedTag()) {%>
	@Deprecated
  <%}%>
	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
	 */
<%if (genModel.useInterfaceOverrideAnnotation()){%>
	@Override
<%}%>
	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
	 */
<%if (genModel.useInterfaceOverrideAnnotation()){%>
	@Override
<%}%>
	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<%if (genModel.useGenerics()) {%><?><%}%>) || <%if (genModel.getRuntimePlatform() == GenRuntimePlatform.GWT) {%><%=genModel.getImportedName("org.eclipse.emf.common.util.Reflect")%>.isInstance((Class<%if (genModel.useGenerics()) {%><?><%}%>)type, adapter)<%} else {%>(((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
	 */
<%if (genModel.useClassOverrideAnnotation()) {%>
	@Override
<%}%>
	protected void associate(Adapter adapter, Notifier target)
	{
		super.associate(adapter, target);
		if (adapter != null)
		{
			disposable.add(adapter);
		}
	}

<%}%>
<%if (genPackage.isExtensibleProviderFactory()) {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public <%=genModel.getImportedName(useGenerics ? "java.util.List<org.eclipse.emf.edit.provider.IChildCreationExtender>" : "java.util.List")%> getChildCreationExtenders()
	{
		return childCreationExtenderManager.getChildCreationExtenders();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public <%=genModel.getImportedName(useGenerics ? "java.util.Collection<?>" : "java.util.Collection")%> getNewChildDescriptors(Object object, <%=genModel.getImportedName("org.eclipse.emf.edit.domain.EditingDomain")%> editingDomain)
	{
		return childCreationExtenderManager.getNewChildDescriptors(object, editingDomain);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public <%=genModel.getImportedName("org.eclipse.emf.common.util.ResourceLocator")%> getResourceLocator()
	{
		return childCreationExtenderManager;
	}

<%}%>
	/**
	 * This adds a listener.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
<%if (genModel.useInterfaceOverrideAnnotation()){%>
	@Override
<%}%>
	public void addListener(INotifyChangedListener notifyChangedListener)
	{
		changeNotifier.addListener(notifyChangedListener);
	}

	/**
	 * This removes a listener.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
<%if (genModel.useInterfaceOverrideAnnotation()){%>
	@Override
<%}%>
	public void removeListener(INotifyChangedListener notifyChangedListener)
	{
		changeNotifier.removeListener(notifyChangedListener);
	}

	/**
	 * This delegates to {@link #changeNotifier} and to {@link #parentAdapterFactory}.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
<%if (genModel.useInterfaceOverrideAnnotation()){%>
	@Override
<%}%>
	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
	 */
<%if (genModel.useInterfaceOverrideAnnotation()){%>
	@Override
<%}%>
	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();
<%}%>
<%}%>
<%}%>
	}

<%}%>
<%if (genPackage.isChildCreationExtenders()) {%>
  <%for (Map.Entry<GenPackage, Map<GenClass, List<GenClass.ChildCreationData>>> packageEntry : genPackage.getExtendedChildCreationData().entrySet()) {%>
	/**
	 * A child creation extender for the {@link <%=packageEntry.getKey().getImportedPackageInterfaceName()%>}.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public static class <%=genPackage.getChildCreationExtenderName(packageEntry.getKey())%> implements <%=genModel.getImportedName("org.eclipse.emf.edit.provider.IChildCreationExtender")%>
	{
		/**
		 * The switch for creating child descriptors specific to each extended class.
		 * <!-- begin-user-doc -->
		 * <!-- end-user-doc -->
		 * @generated
		 */
		protected static class CreationSwitch extends <%=genModel.getImportedName(packageEntry.getKey().getQualifiedSwitchClassName())%><%=useGenerics ? "<Object>" : ""%>
		{
			/**
			 * The child descriptors being populated.
			 * <!-- begin-user-doc -->
			 * <!-- end-user-doc -->
			 * @generated
			 */
			protected <%=genModel.getImportedName(useGenerics ? "java.util.List<Object>" : "java.util.List")%> newChildDescriptors;

			/**
			 * The domain in which to create the children.
			 * <!-- begin-user-doc -->
			 * <!-- end-user-doc -->
			 * @generated
			 */
			protected <%=genModel.getImportedName("org.eclipse.emf.edit.domain.EditingDomain")%> editingDomain;

			/**
			 * Creates the a switch for populating child descriptors in the given domain.
			 * <!-- begin-user-doc -->
			 * <!-- end-user-doc -->
			 * @generated
			 */
			CreationSwitch(<%=genModel.getImportedName(useGenerics ? "java.util.List<Object>" : "java.util.List")%> newChildDescriptors, <%=genModel.getImportedName("org.eclipse.emf.edit.domain.EditingDomain")%> editingDomain) 
			{
				this.newChildDescriptors = newChildDescriptors;
				this.editingDomain = editingDomain;
			}
     <%for (Map.Entry<GenClass, List<GenClass.ChildCreationData>> classEntry : packageEntry.getValue().entrySet()) { GenClass genClass = classEntry.getKey();%>
			/**
			 * <!-- begin-user-doc -->
			 * <!-- end-user-doc -->
			 * @generated
			 */
<%if (genModel.useClassOverrideAnnotation()) {%>
			@Override
<%}%>
			public <%=genClass.getTypeParameters()%>Object case<%=genPackage.getClassUniqueName(genClass)%>(<%=genClass.getImportedInterfaceName()%><%=genClass.getInterfaceTypeArguments()%> object)
			{
     <%for (GenClass.ChildCreationData childCreationData : classEntry.getValue()) { GenFeature createFeature = childCreationData.createFeature; GenFeature delegatedFeature = childCreationData.delegatedFeature; GenClassifier createClassifier = childCreationData.createClassifier;%>
      <%if (createFeature.isFeatureMapType()) {%>
        <%if (delegatedFeature.isReferenceType()) { GenClass createClass = (GenClass)createClassifier;%>
<%@ egf:patternCall patternId="platform:/plugin/org.eclipse.egf.emf.pattern/egf/EMF_Pattern.fcore#LogicalName=org.eclipse.egf.emf.pattern.edit.call.ItemProvider.ItemProvider.newChildDescriptorsReferenceDelegatedFeature.override" args="createClass:createClass,createFeature:createFeature,delegatedFeature:delegatedFeature,createClassifier:createClassifier,childCreationData:childCreationData,genClass:genClass,genPackage:genPackage,genModel:genModel,isJDK50:isJDK50"%><%//ItemProvider/newChildDescriptorsReferenceDelegatedFeature.override.javajetinc%>
        <%} else { GenDataType createDataType = (GenDataType)createClassifier;%>
<%@ egf:patternCall patternId="platform:/plugin/org.eclipse.egf.emf.pattern/egf/EMF_Pattern.fcore#LogicalName=org.eclipse.egf.emf.pattern.edit.call.ItemProvider.ItemProvider.newChildDescriptorsAttributeDelegatedFeature.override" args="createDataType:createDataType,createFeature:createFeature,delegatedFeature:delegatedFeature,createClassifier:createClassifier,childCreationData:childCreationData,genClass:genClass,genPackage:genPackage,genModel:genModel,isJDK50:isJDK50"%><%//ItemProvider/newChildDescriptorsAttributeDelegatedFeature.override.javajetinc%>
        <%}%>
      <%} else if (createFeature.isReferenceType()) { GenClass createClass = (GenClass)createClassifier;%>
<%@ egf:patternCall patternId="platform:/plugin/org.eclipse.egf.emf.pattern/egf/EMF_Pattern.fcore#LogicalName=org.eclipse.egf.emf.pattern.edit.call.ItemProvider.ItemProvider.newChildDescriptorsReferenceFeature.override" args="createClass:createClass,createFeature:createFeature,delegatedFeature:delegatedFeature,createClassifier:createClassifier,childCreationData:childCreationData,genClass:genClass,genPackage:genPackage,genModel:genModel,isJDK50:isJDK50"%><%//ItemProvider/newChildDescriptorsReferenceFeature.override.javajetinc %>
      <%} else { GenDataType createDataType = (GenDataType)createClassifier;%>
<%@ egf:patternCall patternId="platform:/plugin/org.eclipse.egf.emf.pattern/egf/EMF_Pattern.fcore#LogicalName=org.eclipse.egf.emf.pattern.edit.call.ItemProvider.ItemProvider.newChildDescriptorsAttributeFeature.override" args="createDataType:createDataType,createFeature:createFeature,delegatedFeature:delegatedFeature,createClassifier:createClassifier,childCreationData:childCreationData,genClass:genClass,genPackage:genPackage,genModel:genModel,isJDK50:isJDK50"%><%//ItemProvider/newChildDescriptorsAttributeFeature.override.javajetinc%>
      <%}%>

     <%}%>
				return null;
			}
 
     <%}%>
			/**
			 * <!-- begin-user-doc -->
			 * <!-- end-user-doc -->
			 * @generated
			 */
			protected <%=genModel.getImportedName("org.eclipse.emf.edit.command.CommandParameter")%> createChildParameter(Object feature, Object child)
			{
				return new <%=genModel.getImportedName("org.eclipse.emf.edit.command.CommandParameter")%>(null, feature, child);
			}

		}

		/**
		 * <!-- begin-user-doc -->
		 * <!-- end-user-doc -->
		 * @generated
		 */
		public <%=_Collection%> getNewChildDescriptors(Object object, <%=genModel.getImportedName("org.eclipse.emf.edit.domain.EditingDomain")%> editingDomain)
		{
			<%=_ArrayList%> result = new <%=_ArrayList%>();
			new CreationSwitch(result, editingDomain).doSwitch((<%=genModel.getImportedName("org.eclipse.emf.ecore.EObject")%>)object);
			return result;
		}

		/**
		 * <!-- begin-user-doc -->
		 * <!-- end-user-doc -->
		 * @generated
		 */
		public <%=genModel.getImportedName("org.eclipse.emf.common.util.ResourceLocator")%> getResourceLocator()
		{
			return <%=genPackage.getImportedEditPluginClassName()%>.INSTANCE;
		}
	}

  <%}%>
<%}%>
}
<%genModel.emitSortedImports();%>
