
<%
/**
 * 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
 */
%>
<%final GenPackage genPackage = (GenPackage)((Object[])argument)[0]; final GenModel genModel=genPackage.getGenModel();%>
<%final boolean isJDK50 = genModel.getComplianceLevel().getValue() >= GenJDKLevel.JDK50;%>
<%boolean isInterface = Boolean.TRUE.equals(((Object[])argument)[1]); boolean isImplementation = Boolean.TRUE.equals(((Object[])argument)[2]);  boolean useInterfaceOverrideAnnotation = genModel.useInterfaceOverrideAnnotation() && !(isInterface && isImplementation);%>
<%boolean packageNeedsSuppressDeprecation = isJDK50 && GenModelUtil.hasAPIDeprecatedTag(genPackage.getOrderedGenClassifiers()) && !genPackage.hasAPIDeprecatedTag() && !genModel.isSuppressEMFMetaData();%>
<%String publicStaticFinalFlag = isImplementation ? "public static final " : "";%>
<%boolean needsAddEOperation = false;%>
<%boolean needsAddEParameter = false;%>
<%@ 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"%>
<%if (isImplementation && !genModel.isSuppressInterfaces()) {%>
package <%=genPackage.getClassPackageName()%>;
<%} else {%>
package <%=genPackage.getReflectionPackageName()%>;
<%}%>

<%genModel.markImportLocation(stringBuffer, genPackage);%>
<%if (isImplementation) {%>
<%genModel.addPseudoImport("org.eclipse.emf.ecore.EPackage.Registry");%>
<%genModel.addPseudoImport("org.eclipse.emf.ecore.EPackage.Descriptor");%>
<%genModel.addPseudoImport("org.eclipse.emf.ecore.impl.EPackageImpl.EBasicWhiteList");%>
<%genModel.addPseudoImport("org.eclipse.emf.ecore.impl.MinimalEObjectImpl.Container");%>
<%genModel.addPseudoImport("org.eclipse.emf.ecore.impl.MinimalEObjectImpl.Container.Dynamic");%>
  <%if (genPackage.isLiteralsInterface()) {%>
<%genModel.addPseudoImport(genPackage.getQualifiedPackageInterfaceName() + ".Literals");%>
  <%}%>
<%for (GenClassifier genClassifier : genPackage.getOrderedGenClassifiers()) genModel.addPseudoImport(genPackage.getQualifiedPackageInterfaceName() + "." + genPackage.getClassifierID(genClassifier));%>
<%}%>
<%if (isInterface) {%>

/**
 * <!-- begin-user-doc -->
 * The <b>Package</b> for the model.
 * It contains accessors for the meta objects to represent
 * <ul>
 *   <li>each class,</li>
 *   <li>each feature of each class,</li>
  <%if (genModel.isOperationReflection()) {%>
 *   <li>each operation of each class,</li>
  <%}%>
 *   <li>each enum,</li>
 *   <li>and each data type</li>
 * </ul>
 * <!-- end-user-doc -->
<%if (genPackage.hasDocumentation()) {%>
 * <!-- begin-model-doc -->
 * <%=genPackage.getDocumentation(genModel.getIndentation(stringBuffer))%>
 * <!-- end-model-doc -->
<%}%>
 * @see <%=genPackage.getQualifiedFactoryInterfaceName()%>
  <%if (!genModel.isSuppressEMFModelTags()) { boolean first = true; for (StringTokenizer stringTokenizer = new StringTokenizer(genPackage.getModelInfo(), "\n\r"); stringTokenizer.hasMoreTokens(); ) { String modelInfo = stringTokenizer.nextToken(); if (first) { first = false;%>
 * @model <%=modelInfo%>
  <%} else {%>
 *        <%=modelInfo%>
  <%}} if (first) {%>
 * @model
  <%}}%>
 * @generated
 */
<%} else {%>

/**
 * <!-- begin-user-doc -->
 * An implementation of the model <b>Package</b>.
 * <!-- end-user-doc -->
<%if (genPackage.hasAPITags()) {%>
 * <%=genPackage.getAPITags(genModel.getIndentation(stringBuffer))%>
<%}%>
 * @generated
 */
<%}%>
<%if (isJDK50 && genPackage.hasAPIDeprecatedTag()) {%>
@Deprecated
<%}%>
<%if (isImplementation) {%>
  <%if (packageNeedsSuppressDeprecation) {%>
@SuppressWarnings("deprecation")
  <%}%>
public class <%=genPackage.getPackageClassName()%> extends <%=genModel.getImportedName("org.eclipse.emf.ecore.impl.EPackageImpl")%><%if (!isInterface){%> implements <%=genPackage.getImportedPackageInterfaceName()%><%}%>
<%} else {%>
public interface <%=genPackage.getPackageInterfaceName()%> extends <%=genModel.getImportedName("org.eclipse.emf.ecore.EPackage")%>
<%}%>
{
<%if (genModel.hasCopyrightField()) {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	<%=publicStaticFinalFlag%><%=genModel.getImportedName("java.lang.String")%> copyright = <%=genModel.getCopyrightFieldLiteral()%>;<%=genModel.getNonNLS()%>

<%}%>
<%if (isInterface) {%>
	/**
	 * The package name.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	<%=publicStaticFinalFlag%><%=genModel.getImportedName("java.lang.String")%> eNAME = "<%=genPackage.getPackageName()%>";<%=genModel.getNonNLS()%>

	/**
	 * The package namespace URI.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	<%=publicStaticFinalFlag%><%=genModel.getImportedName("java.lang.String")%> eNS_URI = "<%=genPackage.getNSURI()%>";<%=genModel.getNonNLS()%>

	/**
	 * The package namespace name.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	<%=publicStaticFinalFlag%><%=genModel.getImportedName("java.lang.String")%> eNS_PREFIX = "<%=genPackage.getNSName()%>";<%=genModel.getNonNLS()%>
  <%if (genPackage.isContentType()) {%>

	/**
	 * The package content type ID.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	<%=publicStaticFinalFlag%><%=genModel.getImportedName("java.lang.String")%> eCONTENT_TYPE = "<%=genPackage.getContentTypeIdentifier()%>";<%=genModel.getNonNLS()%>
  <%}%>

	/**
	 * The singleton instance of the package.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	<%=publicStaticFinalFlag%><%=genPackage.getPackageInterfaceName()%> eINSTANCE = <%=genPackage.getQualifiedPackageClassName()%>.init();

  <%for (GenClassifier genClassifier : genPackage.getOrderedGenClassifiers()) {%>
	/**
    <%if (genClassifier instanceof GenClass) { GenClass genClass = (GenClass)genClassifier;%>
      <%if (!genClass.isInterface()) {%>
	 * The meta object id for the '{@link <%=genClass.getQualifiedClassName()%> <em><%=genClass.getFormattedName()%></em>}' class.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see <%=genClass.getQualifiedClassName()%>
      <%} else {%>
	 * The meta object id for the '{@link <%=genClass.getRawQualifiedInterfaceName()%> <em><%=genClass.getFormattedName()%></em>}' class.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see <%=genClass.getRawQualifiedInterfaceName()%>
      <%}%>
    <%} else if (genClassifier instanceof GenEnum) { GenEnum genEnum = (GenEnum)genClassifier;%>
	 * The meta object id for the '{@link <%=genEnum.getQualifiedName()%> <em><%=genEnum.getFormattedName()%></em>}' enum.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see <%=genEnum.getQualifiedName()%>
    <%} else if (genClassifier instanceof GenDataType) { GenDataType genDataType = (GenDataType)genClassifier;%>
	 * The meta object id for the '<em><%=genDataType.getFormattedName()%></em>' data type.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
      <%if (!genDataType.isPrimitiveType() && !genDataType.isArrayType()) {%>
	 * @see <%=genDataType.getRawInstanceClassName()%>
      <%}%>
    <%}%>
	 * @see <%=genPackage.getQualifiedPackageClassName()%>#get<%=genClassifier.getClassifierAccessorName()%>()
  <%if (genClassifier.hasAPITags()) {%>
	 * <%=genClassifier.getAPITags(genModel.getIndentation(stringBuffer))%>
  <%}%>
	 * @generated
	 */
  <%if (isJDK50 && genClassifier.hasAPIDeprecatedTag()) {%>
	@Deprecated
  <%}%>
	<%=publicStaticFinalFlag%>int <%=genPackage.getClassifierID(genClassifier)%> = <%=genPackage.getClassifierValue(genClassifier)%>;

    <%if (genClassifier instanceof GenClass) { GenClass genClass = (GenClass)genClassifier;%>
      <%for (GenFeature genFeature : genClass.getAllGenFeatures()) {%>
	/**
	 * The feature id for the '<em><b><%=genFeature.getFormattedName()%></b></em>' <%=genFeature.getFeatureKind()%>.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
    <%if (genFeature.hasImplicitAPITags()) {%>
	 * <%=genFeature.getImplicitAPITags(genModel.getIndentation(stringBuffer))%>
    <%}%>
	 * @generated
	 * @ordered
	 */
  <%if (isJDK50 && genFeature.hasImplicitAPIDeprecatedTag()) {%>
	@Deprecated
  <%}%>
	<%=publicStaticFinalFlag%>int <%=genClass.getFeatureID(genFeature)%> = <%=genClass.getFeatureValue(genFeature)%>;

      <%}%>
	/**
	 * The number of structural features of the '<em><%=genClass.getFormattedName()%></em>' class.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
    <%if (genClass.hasAPITags()) {%>
	 * <%=genClass.getAPITags(genModel.getIndentation(stringBuffer))%>
    <%}%>
	 * @generated
	 * @ordered
	 */
  <%if (isJDK50 && genClass.hasAPIDeprecatedTag()) {%>
	@Deprecated
  <%}%>
	<%=publicStaticFinalFlag%>int <%=genClass.getFeatureCountID()%> = <%=genClass.getFeatureCountValue()%>;

      <%if (genModel.isOperationReflection()) {%>
        <%for (GenOperation genOperation : genClass.getAllGenOperations(false)) {%>
          <%if (genClass.getOverrideGenOperation(genOperation) == null) {%>
	/**
	 * The operation id for the '<em><%=genOperation.getFormattedName()%></em>' operation.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
    <%if (genOperation.hasImplicitAPITags()) {%>
	 * <%=genOperation.getImplicitAPITags(genModel.getIndentation(stringBuffer))%>
    <%}%>
	 * @generated
	 * @ordered
	 */
  <%if (isJDK50 && genOperation.hasImplicitAPIDeprecatedTag()) {%>
	@Deprecated
  <%}%>
	<%=publicStaticFinalFlag%>int <%=genClass.getOperationID(genOperation, false)%> = <%=genClass.getOperationValue(genOperation)%>;

          <%}%>
        <%}%>
	/**
	 * The number of operations of the '<em><%=genClass.getFormattedName()%></em>' class.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
    <%if (genClass.hasAPITags()) {%>
	 * <%=genClass.getAPITags(genModel.getIndentation(stringBuffer))%>
    <%}%>
	 * @generated
	 * @ordered
	 */
  <%if (isJDK50 && genClass.hasAPIDeprecatedTag()) {%>
	@Deprecated
  <%}%>
	<%=publicStaticFinalFlag%>int <%=genClass.getOperationCountID()%> = <%=genClass.getOperationCountValue()%>;

      <%}%>
    <%}%>
  <%}%>
<%}%>
<%if (isImplementation) {%>
  <%if (genPackage.isLoadingInitialization()) {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected String packageFilename = "<%=genPackage.getSerializedPackageFilename()%>";<%=genModel.getNonNLS()%>

  <%}%>
  <%for (GenClassifier genClassifier : genPackage.getGenClassifiers()) {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
    <%if (genClassifier.hasAPITags(true)) {%>
	 * <%=genClassifier.getAPITags(genModel.getIndentation(stringBuffer), true)%>
    <%}%>
	 * @generated
	 */
  <%if (isJDK50 && genClassifier.hasAPIDeprecatedTag()) {%>
	@Deprecated
  <%}%>
	private <%=genClassifier.getImportedMetaType()%> <%=genClassifier.getClassifierInstanceName()%> = null;

  <%}%>
	/**
	 * Creates an instance of the model <b>Package</b>, registered with
	 * {@link org.eclipse.emf.ecore.EPackage.Registry EPackage.Registry} by the package
	 * package URI value.
	 * <p>Note: the correct way to create the package is via the static
	 * factory method {@link #init init()}, which also performs
	 * initialization of the package, or returns the registered package,
	 * if one already exists.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see org.eclipse.emf.ecore.EPackage.Registry
	 * @see <%=genPackage.getQualifiedPackageInterfaceName()%>#eNS_URI
	 * @see #init()
	 * @generated
	 */
	private <%=genPackage.getPackageClassName()%>()
	{
		super(eNS_URI, <%=genPackage.getQualifiedEFactoryInstanceAccessor()%>);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	private static boolean isInited = false;

	/**
	 * Creates, registers, and initializes the <b>Package</b> for this model, and for any others upon which it depends.
	 *
	 * <p>This method is used to initialize {@link <%=genPackage.getImportedPackageInterfaceName()%>#eINSTANCE} when that field is accessed.
	 * Clients should not invoke it directly. Instead, they should simply access that field to obtain the package.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #eNS_URI
  <%if (!genPackage.isLoadedInitialization()) {%>
	 * @see #createPackageContents()
	 * @see #initializePackageContents()
  <%}%>
	 * @generated
	 */
	public static <%=genPackage.getImportedPackageInterfaceName()%> init()
	{
		if (isInited) return (<%=genPackage.getImportedPackageInterfaceName()%>)<%=genModel.getImportedName("org.eclipse.emf.ecore.EPackage")%>.Registry.INSTANCE.getEPackage(<%=genPackage.getImportedPackageInterfaceName()%>.eNS_URI);

    <%if (genModel.getRuntimePlatform() == GenRuntimePlatform.GWT) {%>
		initializeRegistryHelpers();

    <%}%>
		// Obtain or create and register package
		Object registered<%=genPackage.getBasicPackageName()%> = <%=genModel.getImportedName("org.eclipse.emf.ecore.EPackage")%>.Registry.INSTANCE.get(eNS_URI);
		<%=genPackage.getPackageClassName()%> the<%=genPackage.getBasicPackageName()%> = registered<%=genPackage.getBasicPackageName()%> instanceof <%=genPackage.getPackageClassName()%> ? (<%=genPackage.getPackageClassName()%>)registered<%=genPackage.getBasicPackageName()%> : new <%=genPackage.getPackageClassName()%>();

		isInited = true;

    <%if (!genPackage.getPackageSimpleDependencies().isEmpty()) {%>
		// Initialize simple dependencies
    <%for (GenPackage dep : genPackage.getPackageSimpleDependencies()) {%>
		<%=dep.getImportedPackageInterfaceName()%>.eINSTANCE.eClass();
    <%}%>

  <%}%>
  <%if (!genPackage.getPackageInterDependencies().isEmpty()) {%>
		// Obtain or create and register interdependencies
    <%for (ListIterator<GenPackage> i = genPackage.getPackageInterDependencies().listIterator(); i.hasNext(); ) { GenPackage interdep = i.next(); %>
		<%if (i.previousIndex() == 0) {%>Object <%}%>registeredPackage = <%=genModel.getImportedName("org.eclipse.emf.ecore.EPackage")%>.Registry.INSTANCE.getEPackage(<%=interdep.getImportedPackageInterfaceName()%>.eNS_URI);
		<%=interdep.getImportedPackageClassName()%> <%=genPackage.getPackageInstanceVariable(interdep)%> = (<%=interdep.getImportedPackageClassName()%>)(registeredPackage instanceof <%=interdep.getImportedPackageClassName()%> ? registeredPackage : <%=interdep.getImportedPackageInterfaceName()%>.eINSTANCE);
    <%}%>

  <%}%>
  <%if (genPackage.isLoadedInitialization() || !genPackage.getPackageLoadInterDependencies().isEmpty()) {%>
		// Load packages
    <%if (genPackage.isLoadingInitialization()) {%>
		the<%=genPackage.getBasicPackageName()%>.loadPackage();
    <%}%>
    <%for (GenPackage interdep : genPackage.getPackageLoadInterDependencies()) {%>
      <%if (interdep.isLoadingInitialization()) {%>
		<%=genPackage.getPackageInstanceVariable(interdep)%>.loadPackage();
      <%}%>
    <%}%>

  <%}%>
  <%if (!genPackage.isLoadedInitialization() || !genPackage.getPackageBuildInterDependencies().isEmpty()) {%>
		// Create package meta-data objects
    <%if (!genPackage.isLoadedInitialization()) {%>
		the<%=genPackage.getBasicPackageName()%>.createPackageContents();
    <%}%>
    <%for (GenPackage interdep : genPackage.getPackageBuildInterDependencies()) {%>
		<%=genPackage.getPackageInstanceVariable(interdep)%>.createPackageContents();
    <%}%>

		// Initialize created meta-data
    <%if (!genPackage.isLoadedInitialization()) {%>
		the<%=genPackage.getBasicPackageName()%>.initializePackageContents();
    <%}%>
    <%for (GenPackage interdep : genPackage.getPackageBuildInterDependencies()) {%>
		<%=genPackage.getPackageInstanceVariable(interdep)%>.initializePackageContents();
    <%}%>

  <%}%>
  <%if (genPackage.isLoadedInitialization() || !genPackage.getPackageLoadInterDependencies().isEmpty()) {%>
		// Fix loaded packages
    <%if (genPackage.isLoadedInitialization()) {%>
		the<%=genPackage.getBasicPackageName()%>.fixPackageContents();
    <%}%>
    <%for (GenPackage interdep : genPackage.getPackageLoadInterDependencies()) {%>
		<%=genPackage.getPackageInstanceVariable(interdep)%>.fixPackageContents();
    <%}%>

  <%}%>
  <%if (genPackage.hasConstraints()) {%>
		// Register package validator
		<%=genModel.getImportedName("org.eclipse.emf.ecore.EValidator")%>.Registry.INSTANCE.put
			(the<%=genPackage.getBasicPackageName()%>,
			 new <%=genModel.getImportedName("org.eclipse.emf.ecore.EValidator")%>.Descriptor()
			 {
 <%if (genModel.useInterfaceOverrideAnnotation()) {%>
				 @Override
 <%}%>
				 public <%=genModel.getImportedName("org.eclipse.emf.ecore.EValidator")%> getEValidator()
				 {
					 return <%=genPackage.getImportedValidatorClassName()%>.INSTANCE;
				 }
			 });

  <%}%>
  <%if (!genPackage.isEcorePackage()) {%>
		// Mark meta-data to indicate it can't be changed
		the<%=genPackage.getBasicPackageName()%>.freeze();

  <%}%>
		// Update the registry and return the package
		<%=genModel.getImportedName("org.eclipse.emf.ecore.EPackage")%>.Registry.INSTANCE.put(<%=genPackage.getImportedPackageInterfaceName()%>.eNS_URI, the<%=genPackage.getBasicPackageName()%>);
		return the<%=genPackage.getBasicPackageName()%>;
	}
  <%if (genModel.getRuntimePlatform() == GenRuntimePlatform.GWT) {%>

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public static void initializeRegistryHelpers()
	{
    <%Set<String> helpers = new HashSet<String>(); for (GenClassifier genClassifier : genPackage.getGenClassifiers()) {%>
      <%if (genClassifier instanceof GenClass) { GenClass genClass = (GenClass)genClassifier;%>
        <%if (!genClass.isDynamic()) { String theClass = genClass.isMapEntry() ? genClass.getImportedClassName() : genClass.getRawImportedInterfaceName(); if (helpers.add(theClass)) {%>
		<%=genModel.getImportedName("org.eclipse.emf.common.util.Reflect")%>.register
			(<%=theClass%>.class,
			 new <%=genModel.getImportedName("org.eclipse.emf.common.util.Reflect")%>.Helper()
			 {
				 public boolean isInstance(Object instance)
				 {
					 return instance instanceof <%=genClass.isMapEntry() ? genClass.getImportedClassName() : genClass.getRawImportedInterfaceName() + genClass.getInterfaceWildTypeArguments()%>;
				 }

				 public Object newArrayInstance(int size)
				 {
					 return new <%=theClass%>[size];
				 }
			 });
        <%}}%>
      <%} else if (genClassifier instanceof GenDataType) { GenDataType genDataType = (GenDataType)genClassifier;%>
        <%if (!genDataType.isPrimitiveType() && !genDataType.isObjectType()) { String theClass = genDataType.getRawImportedInstanceClassName(); if (helpers.add(theClass)) { %>
		<%=genModel.getImportedName("org.eclipse.emf.common.util.Reflect")%>.register
			(<%=theClass%>.class,
			 new <%=genModel.getImportedName("org.eclipse.emf.common.util.Reflect")%>.Helper()
			 {
				 public boolean isInstance(Object instance)
				 {
					 return instance instanceof <%=theClass%>;
				 }

				 public Object newArrayInstance(int size)
				 {
        <%if (genDataType.isArrayType()) { String componentType = theClass; String indices = ""; while(componentType.endsWith("[]")) { componentType = componentType.substring(0, componentType.length() - 2); indices += "[]";}%>
					 return new <%=componentType%>[size]<%=indices%>;
        <%} else {%>
					 return new <%=theClass%>[size];
        <%}%>
				 }
		});
        <%}}%>
      <%}%>
    <%}%>
	}


	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public static class WhiteList implements <%=genModel.getImportedName("com.google.gwt.user.client.rpc.IsSerializable")%>, EBasicWhiteList
	{
    <%for (GenClassifier genClassifier : genPackage.getGenClassifiers()) {%>
      <%if (genClassifier instanceof GenClass) { GenClass genClass = (GenClass)genClassifier;%>
        <%if (!genClass.isDynamic()) {%>
		/**
		 * <!-- begin-user-doc -->
		 * <!-- end-user-doc -->
		 * @generated
		 */
		protected <%=genClass.isMapEntry() ? genClass.getImportedClassName() : genClass.getImportedWildcardInstanceClassName()%> <%=genClass.getSafeUncapName()%>;

        <%}%>
      <%} else if (genClassifier instanceof GenDataType) { GenDataType genDataType = (GenDataType)genClassifier;%>
        <%if (!genDataType.isObjectType() && genDataType.isSerializable()) {%>
		/**
		 * <!-- begin-user-doc -->
		 * <!-- end-user-doc -->
		 * @generated
		 */
		protected <%=genDataType.getImportedWildcardInstanceClassName()%> <%=genDataType.getSafeUncapName()%>;

        <%}%>
      <%}%>
    <%}%>
	}
  <%}%>

<%}%>
<%if (isInterface) { // TODO REMOVE THIS BOGUS EMPTY LINE%>

<%}%>
  <%for (GenClassifier genClassifier : genPackage.getGenClassifiers()) {%>
<%if (isInterface) {%>
	/**
    <%if (genClassifier instanceof GenClass) { GenClass genClass = (GenClass)genClassifier;%>
	 * Returns the meta object for class '{@link <%=genClass.getRawQualifiedInterfaceName()%> <em><%=genClass.getFormattedName()%></em>}'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return the meta object for class '<em><%=genClass.getFormattedName()%></em>'.
	 * @see <%=genClass.getRawQualifiedInterfaceName()%>
      <%if (!genModel.isSuppressEMFModelTags() && (genClass.isExternalInterface() || genClass.isDynamic())) { boolean first = true; for (StringTokenizer stringTokenizer = new StringTokenizer(genClass.getModelInfo(), "\n\r"); stringTokenizer.hasMoreTokens(); ) { String modelInfo = stringTokenizer.nextToken(); if (first) { first = false;%>
	 * @model <%=modelInfo%>
        <%} else {%>
	 *        <%=modelInfo%>
        <%}} if (first) {%>
	 * @model
      <%}}%>
    <%} else if (genClassifier instanceof GenEnum) { GenEnum genEnum = (GenEnum)genClassifier;%>
	 * Returns the meta object for enum '{@link <%=genEnum.getQualifiedName()%> <em><%=genEnum.getFormattedName()%></em>}'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return the meta object for enum '<em><%=genEnum.getFormattedName()%></em>'.
	 * @see <%=genEnum.getQualifiedName()%>
    <%} else if (genClassifier instanceof GenDataType) { GenDataType genDataType = (GenDataType)genClassifier;%>
      <%if (genDataType.isPrimitiveType() || genDataType.isArrayType()) {%>
	 * Returns the meta object for data type '<em><%=genDataType.getFormattedName()%></em>'.
      <%} else {%>
	 * Returns the meta object for data type '{@link <%=genDataType.getRawInstanceClassName()%> <em><%=genDataType.getFormattedName()%></em>}'.
      <%}%>
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
      <%if (genDataType.hasDocumentation()) {%>
     * <!-- begin-model-doc -->
     * <%=genDataType.getDocumentation(genModel.getIndentation(stringBuffer))%>
     * <!-- end-model-doc -->
      <%}%>
	 * @return the meta object for data type '<em><%=genDataType.getFormattedName()%></em>'.
      <%if (!genDataType.isPrimitiveType() && !genDataType.isArrayType()) {%>
	 * @see <%=genDataType.getRawInstanceClassName()%>
      <%}%>
      <%if (!genModel.isSuppressEMFModelTags()) {boolean first = true; for (StringTokenizer stringTokenizer = new StringTokenizer(genDataType.getModelInfo(), "\n\r"); stringTokenizer.hasMoreTokens(); ) { String modelInfo = stringTokenizer.nextToken(); if (first) { first = false;%>
	 * @model <%=modelInfo%>
      <%} else {%>
	 *        <%=modelInfo%>
      <%}} if (first) {%>
	 * @model
      <%}}%>
    <%}%>
  <%if ((genClassifier instanceof GenClass || genClassifier instanceof GenEnum) && genClassifier.hasAPITags()) {%>
	 * <%=genClassifier.getAPITags(genModel.getIndentation(stringBuffer))%>
  <%}%>
	 * @generated
	 */
<%} else {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
  <%if (genClassifier.hasAPITags()) {%>
	 * <%=genClassifier.getAPITags(genModel.getIndentation(stringBuffer))%>
  <%}%>
	 * @generated
	 */
<%}%>
  <%if (isJDK50 && genClassifier.hasAPIDeprecatedTag()) {%>
	@Deprecated
  <%}%>
<%if (isImplementation) {%>
 <%if (useInterfaceOverrideAnnotation) {%>
	@Override
 <%}%>
	public <%=genClassifier.getImportedMetaType()%> get<%=genClassifier.getClassifierAccessorName()%>()
	{
    <%if (genPackage.isLoadedInitialization()) {%>
		if (<%=genClassifier.getClassifierInstanceName()%> == null)
		{
			<%=genClassifier.getClassifierInstanceName()%> = (<%=genClassifier.getImportedMetaType()%>)<%=genModel.getImportedName("org.eclipse.emf.ecore.EPackage")%>.Registry.INSTANCE.getEPackage(<%=genPackage.getImportedPackageInterfaceName()%>.eNS_URI).getEClassifiers().get(<%=genPackage.getLocalClassifierIndex(genClassifier)%>);
		}
    <%}%>
		return <%=genClassifier.getClassifierInstanceName()%>;
	}

<%} else {%>
	<%=genClassifier.getImportedMetaType()%> get<%=genClassifier.getClassifierAccessorName()%>();

<%}%>
    <%if (genClassifier instanceof GenClass) { GenClass genClass = (GenClass)genClassifier;%>
      <%for (GenFeature genFeature : genClass.getGenFeatures()) {%>
<%if (isInterface) {%>
	/**
	 * Returns the meta object for the <%=genFeature.getFeatureKind()%> '{@link <%=genClass.getRawQualifiedInterfaceName()%><%if (!genClass.isMapEntry() && !genFeature.isSuppressedGetVisibility()) {%>#<%=genFeature.getGetAccessor()%><%}%> <em><%=genFeature.getFormattedName()%></em>}'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return the meta object for the <%=genFeature.getFeatureKind()%> '<em><%=genFeature.getFormattedName()%></em>'.
	 * @see <%=genClass.getRawQualifiedInterfaceName()%><%if (!genClass.isMapEntry() && !genFeature.isSuppressedGetVisibility()) {%>#<%=genFeature.getGetAccessor()%>()<%}%>
	 * @see #get<%=genClass.getClassifierAccessorName()%>()
    <%if (genFeature.hasImplicitAPITags()) {%>
	 * <%=genFeature.getImplicitAPITags(genModel.getIndentation(stringBuffer))%>
    <%}%>
	 * @generated
	 */
<%} else {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
    <%if (genFeature.hasImplicitAPITags()) {%>
	 * <%=genFeature.getImplicitAPITags(genModel.getIndentation(stringBuffer))%>
    <%}%>
	 * @generated
	 */
<%}%>
<%if (isJDK50 && genFeature.hasImplicitAPIDeprecatedTag()) {%>
	@Deprecated
<%}%>
<%if (isImplementation) {%>
   <%if (useInterfaceOverrideAnnotation) {%>
	@Override
   <%}%>
	public <%=genFeature.getImportedMetaType()%> get<%=genFeature.getFeatureAccessorName()%>()
	{
        <%if (!genPackage.isLoadedInitialization()) {%>
		return (<%=genFeature.getImportedMetaType()%>)<%=genClass.getClassifierInstanceName()%>.getEStructuralFeatures().get(<%=genClass.getLocalFeatureIndex(genFeature)%>);
        <%} else {%>
        return (<%=genFeature.getImportedMetaType()%>)get<%=genClassifier.getClassifierAccessorName()%>().getEStructuralFeatures().get(<%=genClass.getLocalFeatureIndex(genFeature)%>);
        <%}%>
	}
<%} else {%>
	<%=genFeature.getImportedMetaType()%> get<%=genFeature.getFeatureAccessorName()%>();
<%}%>

      <%}%>
      <%if (genModel.isOperationReflection()) {%>
        <%for (GenOperation genOperation : genClass.getGenOperations()) {%>
<%if (isInterface) {%>
	/**
	 * Returns the meta object for the '{@link <%=genClass.getRawQualifiedInterfaceName()%>#<%=genOperation.getName()%>(<%=genOperation.getParameterTypes(", ")%>) <em><%=genOperation.getFormattedName()%></em>}' operation.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return the meta object for the '<em><%=genOperation.getFormattedName()%></em>' operation.
	 * @see <%=genClass.getRawQualifiedInterfaceName()%>#<%=genOperation.getName()%>(<%=genOperation.getParameterTypes(", ")%>)
    <%if (genOperation.hasImplicitAPITags()) {%>
	 * <%=genOperation.getImplicitAPITags(genModel.getIndentation(stringBuffer))%>
    <%}%>
	 * @generated
	 */
<%} else {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
    <%if (genOperation.hasImplicitAPITags()) {%>
	 * <%=genOperation.getImplicitAPITags(genModel.getIndentation(stringBuffer))%>
    <%}%>
	 * @generated
	 */
<%}%>
<%if (isJDK50 && genOperation.hasImplicitAPIDeprecatedTag()) {%>
	@Deprecated
<%}%>
<%if (isImplementation) {%>
   <%if (useInterfaceOverrideAnnotation) {%>
	@Override
   <%}%>
	public <%=genOperation.getImportedMetaType()%> get<%=genOperation.getOperationAccessorName()%>()
	{
        <%if (!genPackage.isLoadedInitialization()) {%>
		return <%=genClass.getClassifierInstanceName()%>.getEOperations().get(<%=genClass.getLocalOperationIndex(genOperation)%>);
        <%} else {%>
        return get<%=genClassifier.getClassifierAccessorName()%>().getEOperations().get(<%=genClass.getLocalOperationIndex(genOperation)%>);
        <%}%>
	}
<%} else {%>
	<%=genOperation.getImportedMetaType()%> get<%=genOperation.getOperationAccessorName()%>();
<%}%>

        <%}%>
      <%}%>
    <%}%>
  <%}%>
<%if (isInterface) {%>
	/**
	 * Returns the factory that creates the instances of the model.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return the factory that creates the instances of the model.
	 * @generated
	 */
<%} else {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
<%}%>
<%if (isImplementation) {%>
   <%if (useInterfaceOverrideAnnotation) {%>
	@Override
   <%}%>
	public <%=genPackage.getImportedFactoryInterfaceName()%> get<%=genPackage.getFactoryName()%>()
	{
		return (<%=genPackage.getImportedFactoryInterfaceName()%>)getEFactoryInstance();
	}
<%} else {%>
	<%=genPackage.getFactoryInterfaceName()%> get<%=genPackage.getFactoryName()%>();
<%}%>

<%if (isImplementation) {%>
  <%if (!genPackage.isLoadedInitialization()) {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	private boolean isCreated = false;

	/**
	 * Creates the meta-model objects for the package.  This method is
	 * guarded to have no affect on any invocation but its first.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
    <%{boolean needsSuppressDeprecation = false; if (!packageNeedsSuppressDeprecation && isJDK50 && !genModel.isSuppressEMFMetaData()) { LOOP: for (GenClass genClass : genPackage.getGenClasses()) { for (GenFeature genFeature : genClass.getGenFeatures()) { if (genFeature.hasAPIDeprecatedTag()) { needsSuppressDeprecation = true; break LOOP; }}
      for (GenOperation genOperation : genClass.getGenOperations()) { if (genOperation.hasAPIDeprecatedTag()) { needsSuppressDeprecation = true; break LOOP; }}} if (needsSuppressDeprecation) {%>
	@SuppressWarnings("deprecation")
    <%}}}%>
	public void createPackageContents()
	{
		if (isCreated) return;
		isCreated = true;
    <%if (!genPackage.getGenClasses().isEmpty()) {%>

		// Create classes and their features
      <%for (Iterator<GenClass> c=genPackage.getGenClasses().iterator(); c.hasNext();) { GenClass genClass = c.next();%>
		<%=genClass.getClassifierInstanceName()%> = create<%=genClass.getMetaType()%>(<%=genClass.getClassifierID()%>);
        <%for (GenFeature genFeature : genClass.getGenFeatures()) {%>
		create<%=genFeature.getMetaType()%>(<%=genClass.getClassifierInstanceName()%>, <%=genClass.getFeatureID(genFeature)%>);
        <%}%>
        <%if (genModel.isOperationReflection()) {%>
          <%for (GenOperation genOperation : genClass.getGenOperations()) {%>
		createEOperation(<%=genClass.getClassifierInstanceName()%>, <%=genClass.getOperationID(genOperation, false)%>);
          <%}%>
        <%}%>
        <%if (c.hasNext()) {%>

        <%}%>
      <%}%>
    <%}%>
    <%if (!genPackage.getGenEnums().isEmpty()) {%>

		// Create enums
      <%for (GenEnum genEnum : genPackage.getGenEnums()) {%>
		<%=genEnum.getClassifierInstanceName()%> = createEEnum(<%=genEnum.getClassifierID()%>);
      <%}%>
    <%}%>
    <%if (!genPackage.getGenDataTypes().isEmpty()) {%>

		// Create data types
      <%for (GenDataType genDataType : genPackage.getGenDataTypes()) {%>
		<%=genDataType.getClassifierInstanceName()%> = createEDataType(<%=genDataType.getClassifierID()%>);
      <%}%>
    <%}%>
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	private boolean isInitialized = false;

<%
///////////////////////
class Information
{
  @SuppressWarnings("unused")
  EGenericType eGenericType;
  int depth;
  String type;
  String accessor;
}

class InformationIterator
{
  Iterator<Object> iterator;
  InformationIterator(EGenericType eGenericType)
  {
    iterator = EcoreUtil.getAllContents(Collections.singleton(eGenericType));
  }

  boolean hasNext()
  {
    return iterator.hasNext();
  }

  Information next()
  {
    Information information = new Information();
    EGenericType eGenericType = information.eGenericType = (EGenericType)iterator.next();
    for (EObject container = eGenericType.eContainer(); container instanceof EGenericType; container = container.eContainer())
    {
      ++information.depth;
    }
    if (eGenericType.getEClassifier() != null )
    {
      GenClassifier genClassifier = genModel.findGenClassifier(eGenericType.getEClassifier());
      information.type = genPackage.getPackageInstanceVariable(genClassifier.getGenPackage()) + ".get" + genClassifier.getClassifierAccessorName() + "()";
    }
    else if (eGenericType.getETypeParameter() != null)
    {
      ETypeParameter eTypeParameter = eGenericType.getETypeParameter();
      if (eTypeParameter.eContainer() instanceof EClass)
      {
        information.type = genModel.findGenClassifier((EClass)eTypeParameter.eContainer()).getClassifierInstanceName() + "_" + eGenericType.getETypeParameter().getName();
      }
      else
      {
        information.type = "t" + (((EOperation)eTypeParameter.eContainer()).getETypeParameters().indexOf(eTypeParameter) + 1);
      }
    }
    else
    {
      information.type ="";
    }
    if (information.depth > 0)
    {
      if (eGenericType.eContainmentFeature().isMany())
      {
        information.accessor = "getE" + eGenericType.eContainmentFeature().getName().substring(1) + "().add";
      }
      else
      {
        information.accessor = "setE" + eGenericType.eContainmentFeature().getName().substring(1);
      }
    }
    return information;
  }
}
///////////////////////
int maxGenericTypeAssignment = 0;
%>
	/**
	 * Complete the initialization of the package and its meta-model.  This
	 * method is guarded to have no affect on any invocation but its first.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
    <%{boolean needsSuppressDeprecation = false; if (!packageNeedsSuppressDeprecation && isJDK50) { LOOP: for (GenEnum genEnum : genPackage.getGenEnums()) { for (GenEnumLiteral genEnumLiteral : genEnum.getGenEnumLiterals()) { if (genEnumLiteral.hasAPIDeprecatedTag()) { needsSuppressDeprecation = true; break LOOP; }}} if (needsSuppressDeprecation) {%>
	@SuppressWarnings("deprecation")
    <%}}}%>
	public void initializePackageContents()
	{
		if (isInitialized) return;
		isInitialized = true;

		// Initialize package
		setName(eNAME);
		setNsPrefix(eNS_PREFIX);
		setNsURI(eNS_URI);
    <%if (!genPackage.getPackageInitializationDependencies().isEmpty()) {%>

		// Obtain other dependent packages
      <%for (GenPackage dep : genPackage.getPackageInitializationDependencies()) {%>
		<%=dep.getImportedPackageInterfaceName()%> <%=genPackage.getPackageInstanceVariable(dep)%> = (<%=dep.getImportedPackageInterfaceName()%>)<%=genModel.getImportedName("org.eclipse.emf.ecore.EPackage")%>.Registry.INSTANCE.getEPackage(<%=dep.getImportedPackageInterfaceName()%>.eNS_URI);
      <%}%>
    <%}%>
    <%if (!genPackage.getSubGenPackages().isEmpty()) {%>

		// Add subpackages
      <%for (GenPackage sub : genPackage.getSubGenPackages()) {%>
		getESubpackages().add(<%=genPackage.getPackageInstanceVariable(sub)%>);
      <%}%>
    <%}%>
    <%if (!genPackage.getGenClasses().isEmpty()) { boolean firstOperationAssignment = true; int maxTypeParameterAssignment = 0;%>
      <%if (genModel.useGenerics()) {%>

		// Create type parameters
        <%for (GenClassifier genClassifier : genPackage.getGenClassifiers()) {%>
          <%for (GenTypeParameter genTypeParameter : genClassifier.getGenTypeParameters()) {%>
            <%if (!genTypeParameter.getEcoreTypeParameter().getEBounds().isEmpty() || genTypeParameter.isUsed()) {%>
		<%=genModel.getImportedName("org.eclipse.emf.ecore.ETypeParameter")%> <%=genClassifier.getClassifierInstanceName()%>_<%=genTypeParameter.getName()%> = addETypeParameter(<%=genClassifier.getClassifierInstanceName()%>, "<%=genTypeParameter.getName()%>");<%=genModel.getNonNLS()%>
            <%} else {%>
		addETypeParameter(<%=genClassifier.getClassifierInstanceName()%>, "<%=genTypeParameter.getName()%>");<%=genModel.getNonNLS()%>
            <%}%>
          <%}%>
        <%}%>
      <%}%>
      <%if (genModel.useGenerics()) {%>

		// Set bounds for type parameters
        <%for (GenClassifier genClassifier : genPackage.getGenClassifiers()) {%>
          <%for (GenTypeParameter genTypeParameter : genClassifier.getGenTypeParameters()) {%>
            <%for (EGenericType bound : genTypeParameter.getEcoreTypeParameter().getEBounds()) {%>
              <%for (InformationIterator i=new InformationIterator(bound); i.hasNext(); ) { Information info = i.next(); String prefix = ""; if (maxGenericTypeAssignment <= info.depth) { ++maxGenericTypeAssignment; prefix = genModel.getImportedName("org.eclipse.emf.ecore.EGenericType") + " "; }%>
		<%=prefix%>g<%=info.depth + 1%> = createEGenericType(<%=info.type%>);
                <%if (info.depth > 0) {%>
		g<%=info.depth%>.<%=info.accessor%>(g<%=info.depth + 1%>);
                <%}%>
              <%}%>
		<%=genClassifier.getClassifierInstanceName()%>_<%=genTypeParameter.getName()%>.getEBounds().add(g1);
            <%}%>
          <%}%>
        <%}%>
      <%}%>

		// Add supertypes to classes
      <%for (GenClass genClass : genPackage.getGenClasses()) {%>
        <%if (!genClass.hasGenericSuperTypes()) {%>
          <%for (GenClass baseGenClass : genClass.getBaseGenClasses()) {%>
		<%=genClass.getClassifierInstanceName()%>.getESuperTypes().add(<%=genPackage.getPackageInstanceVariable(baseGenClass.getGenPackage())%>.get<%=baseGenClass.getClassifierAccessorName()%>());
          <%}%>
        <%} else {%>
          <%for (EGenericType superType : genClass.getEcoreClass().getEGenericSuperTypes()) {%>
            <%for (InformationIterator i=new InformationIterator(superType); i.hasNext(); ) { Information info = i.next(); String prefix = ""; if (maxGenericTypeAssignment <= info.depth) { ++maxGenericTypeAssignment; prefix = genModel.getImportedName("org.eclipse.emf.ecore.EGenericType") + " "; }%>
		<%=prefix%>g<%=info.depth + 1%> = createEGenericType(<%=info.type%>);
              <%if (info.depth > 0) {%>
		g<%=info.depth%>.<%=info.accessor%>(g<%=info.depth + 1%>);
              <%}%>
            <%}%>
		<%=genClass.getClassifierInstanceName()%>.getEGenericSuperTypes().add(g1);
          <%}%>
        <%}%>
      <%}%>

		// Initialize classes<%if (genModel.isOperationReflection()) {%>, features, and operations; add parameters<%} else {%> and features; add operations and parameters<%}%>
      <%for (Iterator<GenClass> c=genPackage.getGenClasses().iterator(); c.hasNext();) { GenClass genClass = c.next(); boolean hasInstanceTypeName = genModel.useGenerics() && genClass.getEcoreClass().getInstanceTypeName() != null && genClass.getEcoreClass().getInstanceTypeName().contains("<");%>
		initEClass(<%=genClass.getClassifierInstanceName()%>, <%if (genClass.isDynamic()) {%>null<%} else {%><%=genClass.getRawImportedInterfaceName()%>.class<%}%>, "<%=genClass.getName()%>", <%=genClass.getAbstractFlag()%>, <%=genClass.getInterfaceFlag()%>, <%=genClass.getGeneratedInstanceClassFlag()%><%if (hasInstanceTypeName) {%>, "<%=genClass.getEcoreClass().getInstanceTypeName()%>"<%}%>);<%=genModel.getNonNLS()%><%if (hasInstanceTypeName) {%><%=genModel.getNonNLS(2)%><%}%>
        <%for (GenFeature genFeature : genClass.getGenFeatures()) {%>
          <%if (genFeature.hasGenericType()) {%>
            <%for (InformationIterator i=new InformationIterator(genFeature.getEcoreFeature().getEGenericType()); i.hasNext(); ) { Information info = i.next(); String prefix = ""; if (maxGenericTypeAssignment <= info.depth) { ++maxGenericTypeAssignment; prefix = genModel.getImportedName("org.eclipse.emf.ecore.EGenericType") + " "; }%>
		<%=prefix%>g<%=info.depth + 1%> = createEGenericType(<%=info.type%>);
              <%if (info.depth > 0) {%>
		g<%=info.depth%>.<%=info.accessor%>(g<%=info.depth + 1%>);
              <%}%>
            <%}%>
          <%}%>
          <%if (genFeature.isReferenceType()) { GenFeature reverseGenFeature = genFeature.getReverse();%>
          <%String reverse = reverseGenFeature == null ? "null" : genPackage.getPackageInstanceVariable(reverseGenFeature.getGenPackage()) + ".get" + reverseGenFeature.getFeatureAccessorName() + "()";%>
		initEReference(get<%=genFeature.getFeatureAccessorName()%>(), <%if (genFeature.hasGenericType()) {%>g1<%} else {%><%=genPackage.getPackageInstanceVariable(genFeature.getTypeGenPackage())%>.get<%=genFeature.getTypeClassifierAccessorName()%>()<%}%>, <%=reverse%>, "<%=genFeature.getName()%>", <%=genFeature.getDefaultValue()%>, <%=genFeature.getLowerBound()%>, <%=genFeature.getUpperBound()%>, <%=genFeature.getContainerClass()%>, <%=genFeature.getTransientFlag()%>, <%=genFeature.getVolatileFlag()%>, <%=genFeature.getChangeableFlag()%>, <%=genFeature.getContainmentFlag()%>, <%=genFeature.getResolveProxiesFlag()%>, <%=genFeature.getUnsettableFlag()%>, <%=genFeature.getUniqueFlag()%>, <%=genFeature.getDerivedFlag()%>, <%=genFeature.getOrderedFlag()%>);<%=genModel.getNonNLS()%><%=genModel.getNonNLS(genFeature.getDefaultValue(), 2)%>
            <%for (GenFeature keyFeature : genFeature.getKeys()) {%>
		get<%=genFeature.getFeatureAccessorName()%>().getEKeys().add(<%=genPackage.getPackageInstanceVariable(keyFeature.getGenPackage())%>.get<%=keyFeature.getFeatureAccessorName()%>());
            <%}%>
          <%} else {%>
		initEAttribute(get<%=genFeature.getFeatureAccessorName()%>(), <%if (genFeature.hasGenericType()) {%>g1<%} else {%><%=genPackage.getPackageInstanceVariable(genFeature.getTypeGenPackage())%>.get<%=genFeature.getTypeClassifierAccessorName()%>()<%}%>, "<%=genFeature.getName()%>", <%=genFeature.getDefaultValue()%>, <%=genFeature.getLowerBound()%>, <%=genFeature.getUpperBound()%>, <%=genFeature.getContainerClass()%>, <%=genFeature.getTransientFlag()%>, <%=genFeature.getVolatileFlag()%>, <%=genFeature.getChangeableFlag()%>, <%=genFeature.getUnsettableFlag()%>, <%=genFeature.getIDFlag()%>, <%=genFeature.getUniqueFlag()%>, <%=genFeature.getDerivedFlag()%>, <%=genFeature.getOrderedFlag()%>);<%=genModel.getNonNLS()%><%=genModel.getNonNLS(genFeature.getDefaultValue(), 2)%>
          <%}%>
        <%}%>
        <%for (GenOperation genOperation : genClass.getGenOperations()) {String prefix = ""; if (genOperation.hasGenericType() || !genOperation.getGenParameters().isEmpty() || !genOperation.getGenExceptions().isEmpty() || !genOperation.getGenTypeParameters().isEmpty()) { if (firstOperationAssignment) { firstOperationAssignment = false; prefix = genModel.getImportedName("org.eclipse.emf.ecore.EOperation") + " op = "; } else { prefix = "op = "; }} %>

          <%if (genModel.useGenerics()) {%>
		<%=prefix%><%if (genModel.isOperationReflection()) {%>initEOperation(get<%=genOperation.getOperationAccessorName()%>()<%} else {%>addEOperation(<%=genClass.getClassifierInstanceName()%><%}%>, <%if (genOperation.isVoid() || genOperation.hasGenericType()) {%>null<%} else {%><%=genPackage.getPackageInstanceVariable(genOperation.getTypeGenPackage())%>.get<%=genOperation.getTypeClassifierAccessorName()%>()<%}%>, "<%=genOperation.getName()%>", <%=genOperation.getLowerBound()%>, <%=genOperation.getUpperBound()%>, <%=genOperation.getUniqueFlag()%>, <%=genOperation.getOrderedFlag()%>);<%=genModel.getNonNLS()%>
          <%} else if (!genOperation.isVoid()) {%>
            <%if (!genOperation.getEcoreOperation().isOrdered() || !genOperation.getEcoreOperation().isUnique()) { needsAddEOperation = true;%>
		<%=prefix%><%if (genModel.isOperationReflection()) {%>initEOperation(get<%=genOperation.getOperationAccessorName()%>()<%} else {%>addEOperation(<%=genClass.getClassifierInstanceName()%><%}%>, <%=genPackage.getPackageInstanceVariable(genOperation.getTypeGenPackage())%>.get<%=genOperation.getTypeClassifierAccessorName()%>(), "<%=genOperation.getName()%>", <%=genOperation.getLowerBound()%>, <%=genOperation.getUpperBound()%>, <%=genOperation.getUniqueFlag()%>, <%=genOperation.getOrderedFlag()%>);<%=genModel.getNonNLS()%>
            <%} else {%>
		<%=prefix%><%if (genModel.isOperationReflection()) {%>initEOperation(get<%=genOperation.getOperationAccessorName()%>()<%} else {%>addEOperation(<%=genClass.getClassifierInstanceName()%><%}%>, <%=genPackage.getPackageInstanceVariable(genOperation.getTypeGenPackage())%>.get<%=genOperation.getTypeClassifierAccessorName()%>(), "<%=genOperation.getName()%>", <%=genOperation.getLowerBound()%>, <%=genOperation.getUpperBound()%>);<%=genModel.getNonNLS()%>
            <%}%>
          <%} else {%>
		<%=prefix%><%if (genModel.isOperationReflection()) {%>initEOperation(get<%=genOperation.getOperationAccessorName()%>()<%} else {%>addEOperation(<%=genClass.getClassifierInstanceName()%><%}%>, null, "<%=genOperation.getName()%>");<%=genModel.getNonNLS()%>
          <%}%>
          <%if (genModel.useGenerics()) {%>
            <%for (ListIterator<GenTypeParameter> t=genOperation.getGenTypeParameters().listIterator(); t.hasNext(); ) { GenTypeParameter genTypeParameter = t.next(); String typeParameterVariable = ""; if (!genTypeParameter.getEcoreTypeParameter().getEBounds().isEmpty() || genTypeParameter.isUsed()) { if (maxTypeParameterAssignment <= t.previousIndex()) { ++maxTypeParameterAssignment; typeParameterVariable = genModel.getImportedName("org.eclipse.emf.ecore.ETypeParameter") + " t" + t.nextIndex() + " = "; } else { typeParameterVariable = "t" + t.nextIndex() + " = "; }} %>
		<%=typeParameterVariable%>addETypeParameter(op, "<%=genTypeParameter.getName()%>");<%=genModel.getNonNLS()%>
              <%for (EGenericType typeParameter : genTypeParameter.getEcoreTypeParameter().getEBounds()) {%>
                <%for (InformationIterator i=new InformationIterator(typeParameter); i.hasNext(); ) { Information info = i.next(); String typePrefix = ""; if (maxGenericTypeAssignment <= info.depth) { ++maxGenericTypeAssignment; typePrefix = genModel.getImportedName("org.eclipse.emf.ecore.EGenericType") + " "; }%>
		<%=typePrefix%>g<%=info.depth + 1%> = createEGenericType(<%=info.type%>);
                  <%if (info.depth > 0) {%>
		g<%=info.depth%>.<%=info.accessor%>(g<%=info.depth + 1%>);
                  <%}%>
                <%}%>
		t<%=t.nextIndex()%>.getEBounds().add(g1);
              <%}%>
            <%}%>
          <%}%>
          <%for (GenParameter genParameter : genOperation.getGenParameters()) {%>
            <%if (genParameter.hasGenericType()) {%>
              <%for (InformationIterator i=new InformationIterator(genParameter.getEcoreParameter().getEGenericType()); i.hasNext(); ) { Information info = i.next(); String typePrefix = ""; if (maxGenericTypeAssignment <= info.depth) { ++maxGenericTypeAssignment; typePrefix = genModel.getImportedName("org.eclipse.emf.ecore.EGenericType") + " "; }%>
		<%=typePrefix%>g<%=info.depth + 1%> = createEGenericType(<%=info.type%>);
                <%if (info.depth > 0) {%>
		g<%=info.depth%>.<%=info.accessor%>(g<%=info.depth + 1%>);
                <%}%>
              <%}%>
            <%}%>
            <%if (genModel.useGenerics()) {%>
		addEParameter(op, <%if (genParameter.hasGenericType()){%>g1<%} else {%><%=genPackage.getPackageInstanceVariable(genParameter.getTypeGenPackage())%>.get<%=genParameter.getTypeClassifierAccessorName()%>()<%}%>, "<%=genParameter.getName()%>", <%=genParameter.getLowerBound()%>, <%=genParameter.getUpperBound()%>, <%=genParameter.getUniqueFlag()%>, <%=genParameter.getOrderedFlag()%>);<%=genModel.getNonNLS()%>
            <%} else if (!genParameter.getEcoreParameter().isOrdered() || !genParameter.getEcoreParameter().isUnique()) { needsAddEParameter = true;%>
		addEParameter(op, <%if (genParameter.hasGenericType()){%>g1<%} else {%><%=genPackage.getPackageInstanceVariable(genParameter.getTypeGenPackage())%>.get<%=genParameter.getTypeClassifierAccessorName()%>()<%}%>, "<%=genParameter.getName()%>", <%=genParameter.getLowerBound()%>, <%=genParameter.getUpperBound()%>, <%=genParameter.getUniqueFlag()%>, <%=genParameter.getOrderedFlag()%>);<%=genModel.getNonNLS()%>
            <%} else {%>
		addEParameter(op, <%if (genParameter.hasGenericType()){%>g1<%} else {%><%=genPackage.getPackageInstanceVariable(genParameter.getTypeGenPackage())%>.get<%=genParameter.getTypeClassifierAccessorName()%>()<%}%>, "<%=genParameter.getName()%>", <%=genParameter.getLowerBound()%>, <%=genParameter.getUpperBound()%>);<%=genModel.getNonNLS()%>
            <%}%>
          <%}%>
          <%if (genOperation.hasGenericExceptions()) {%>
              <%for (EGenericType genericExceptions : genOperation.getEcoreOperation().getEGenericExceptions()) {%>
                <%for (InformationIterator i=new InformationIterator(genericExceptions); i.hasNext(); ) { Information info = i.next(); String typePrefix = ""; if (maxGenericTypeAssignment <= info.depth) { ++maxGenericTypeAssignment; typePrefix = genModel.getImportedName("org.eclipse.emf.ecore.EGenericType") + " "; }%>
		<%=typePrefix%>g<%=info.depth + 1%> = createEGenericType(<%=info.type%>);
                  <%if (info.depth > 0) {%>
		g<%=info.depth%>.<%=info.accessor%>(g<%=info.depth + 1%>);
                  <%}%>
		addEException(op, g<%=info.depth + 1%>);
                <%}%>
              <%}%>
          <%} else {%>
            <%for (GenClassifier genException : genOperation.getGenExceptions()) {%>
		addEException(op, <%=genPackage.getPackageInstanceVariable(genException.getGenPackage())%>.get<%=genException.getClassifierAccessorName()%>());
            <%}%>
          <%}%>
          <%if (!genOperation.isVoid() && genOperation.hasGenericType()) {%>
            <%for (InformationIterator i=new InformationIterator(genOperation.getEcoreOperation().getEGenericType()); i.hasNext(); ) { Information info = i.next(); String typePrefix = ""; if (maxGenericTypeAssignment <= info.depth) { ++maxGenericTypeAssignment; typePrefix = genModel.getImportedName("org.eclipse.emf.ecore.EGenericType") + " "; }%>
		<%=typePrefix%>g<%=info.depth + 1%> = createEGenericType(<%=info.type%>);
              <%if (info.depth > 0) {%>
		g<%=info.depth%>.<%=info.accessor%>(g<%=info.depth + 1%>);
              <%}%>
            <%}%>
		initEOperation(op, g1);
          <%}%>
        <%}%>
        <%if (c.hasNext()) {%>

        <%}%>
      <%}%>
    <%}%>
    <%if (!genPackage.getGenEnums().isEmpty()) {%>

		// Initialize enums and add enum literals
      <%for (Iterator<GenEnum> e=genPackage.getGenEnums().iterator(); e.hasNext();) { GenEnum genEnum = e.next();%>
		initEEnum(<%=genEnum.getClassifierInstanceName()%>, <%=genEnum.getImportedName()%>.class, "<%=genEnum.getName()%>");<%=genModel.getNonNLS()%>
        <%for (GenEnumLiteral genEnumLiteral : genEnum.getGenEnumLiterals()) {%>
		addEEnumLiteral(<%=genEnum.getClassifierInstanceName()%>, <%=genEnum.getImportedName().equals(genEnum.getClassifierID()) ? genEnum.getQualifiedName() : genEnum.getImportedName()%>.<%=genEnumLiteral.getEnumLiteralInstanceConstantName()%>);
        <%}%>
        <%if (e.hasNext()) {%>

        <%}%>
      <%}%>
    <%}%>
    <%if (!genPackage.getGenDataTypes().isEmpty()) {%>

		// Initialize data types
      <%for (GenDataType genDataType : genPackage.getGenDataTypes()) {boolean hasInstanceTypeName = genModel.useGenerics() && genDataType.getEcoreDataType().getInstanceTypeName() != null && genDataType.getEcoreDataType().getInstanceTypeName().contains("<");%>
		initEDataType(<%=genDataType.getClassifierInstanceName()%>, <%=genDataType.getRawImportedInstanceClassName()%>.class, "<%=genDataType.getName()%>", <%=genDataType.getSerializableFlag()%>, <%=genDataType.getGeneratedInstanceClassFlag()%><%if (hasInstanceTypeName) {%>, "<%=genDataType.getEcoreDataType().getInstanceTypeName()%>"<%}%>);<%=genModel.getNonNLS()%><%if (hasInstanceTypeName) {%><%=genModel.getNonNLS(2)%><%}%>
      <%}%>
    <%}%>
    <%if (genPackage.getSuperGenPackage() == null) {%>

		// Create resource
		createResource(<%=genPackage.getSchemaLocation()%>);
    <%}%>
    <%if (!genPackage.isEcorePackage() && !genPackage.getAnnotationSources().isEmpty()) {%>

		// Create annotations
      <%for (String annotationSource : genPackage.getAnnotationSources()) {%>
		// <%=annotationSource%>
		create<%=genPackage.getAnnotationSourceIdentifier(annotationSource)%>Annotations();
      <%}%>
    <%}%>
	}

    <%for (String annotationSource : genPackage.getAnnotationSources()) {%>
	/**
	 * Initializes the annotations for <b><%=annotationSource%></b>.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected void create<%=genPackage.getAnnotationSourceIdentifier(annotationSource)%>Annotations()
	{
		String source = <%if (annotationSource == null) {%>null;<%} else {%>"<%=annotationSource%>";<%=genModel.getNonNLS()%><%}%>
      <%for (EAnnotation eAnnotation : genPackage.getAllAnnotations()) { List<GenPackage.AnnotationReferenceData> annotationReferenceDataList = genPackage.getReferenceData(eAnnotation);%>
        <%if (annotationSource == null ? eAnnotation.getSource() == null : annotationSource.equals(eAnnotation.getSource())) {%>
		addAnnotation
		  (<%=genPackage.getAnnotatedModelElementAccessor(eAnnotation)%>,
		   source,
		   new String[]
		   {
          <%for (Iterator<Map.Entry<String, String>> k = eAnnotation.getDetails().iterator(); k.hasNext();) { Map.Entry<String, String> detail = k.next(); String key = Literals.toStringLiteral(detail.getKey(), genModel); String value = Literals.toStringLiteral(detail.getValue(), genModel);%>
			   <%=key%>, <%=value%><%=k.hasNext() ? "," : ""%><%=genModel.getNonNLS(key + value)%>
          <%}%>
		   }<%if (annotationReferenceDataList.isEmpty()) {%>);<%} else {%>,<%}%>
          <%if (!annotationReferenceDataList.isEmpty()) {%>
		   new <%=genModel.getImportedName("org.eclipse.emf.common.util.URI")%>[]
		   {
            <%for (Iterator<GenPackage.AnnotationReferenceData> k = annotationReferenceDataList.iterator(); k.hasNext();) { GenPackage.AnnotationReferenceData annotationReferenceData = k.next();%>
			 <%=genModel.getImportedName("org.eclipse.emf.common.util.URI")%>.createURI(<%if (annotationReferenceData.containingGenPackage != genPackage) {%><%=annotationReferenceData.containingGenPackage.getImportedPackageInterfaceName()%>.<%}%>eNS_URI).appendFragment("<%=annotationReferenceData.uriFragment%>")<%if (k.hasNext()) {%>,<%}%><%=genModel.getNonNLS()%>
            <%}%>
		   });
          <%}%>
          <%for (EAnnotation nestedEAnnotation : genPackage.getAllNestedAnnotations(eAnnotation)) {String nestedAnnotationSource = nestedEAnnotation.getSource();  int depth = 0; boolean nonContentAnnotation = false; StringBuilder path = new StringBuilder();  for (EObject eContainer = nestedEAnnotation.eContainer(), child = nestedEAnnotation; child != eAnnotation; child = eContainer, eContainer = eContainer.eContainer())  {  boolean nonContentChild = child.eContainmentFeature() != EcorePackage.Literals.EANNOTATION__CONTENTS; if (path.length() != 0) { path.insert(0, ", ");  } path.insert(0, nonContentChild); if (nonContentChild) { nonContentAnnotation = true; } ++depth;  } List<GenPackage.AnnotationReferenceData> nestedAnnotationReferenceDataList = genPackage.getReferenceData(nestedEAnnotation);%>
		addAnnotation
		  (<%=genPackage.getAnnotatedModelElementAccessor(eAnnotation)%>,
		   <%if (nonContentAnnotation && genModel.getRuntimeVersion().getValue() >= GenRuntimeVersion.EMF210_VALUE) {%>new boolean[] { <%=path.toString()%> }<%} else {%><%=depth%><%}%>,
		   <%if (nestedAnnotationSource == null) {%>null,<%} else {%>"<%=nestedAnnotationSource%>",<%=genModel.getNonNLS()%><%}%>
		   new String[]
		   {
            <%for (Iterator<Map.Entry<String, String>> l = nestedEAnnotation.getDetails().iterator(); l.hasNext();) { Map.Entry<String, String> detail = l.next(); String key = Literals.toStringLiteral(detail.getKey(), genModel); String value = Literals.toStringLiteral(detail.getValue(), genModel);%>
			   <%=key%>, <%=value%><%=l.hasNext() ? "," : ""%><%=genModel.getNonNLS(key + value)%>
            <%}%>
		   }<%if (nestedAnnotationReferenceDataList.isEmpty()) {%>);<%} else {%>,<%}%>
            <%if (!nestedAnnotationReferenceDataList.isEmpty()) {%>
		   new <%=genModel.getImportedName("org.eclipse.emf.common.util.URI")%>[]
		   {
            <%for (Iterator<GenPackage.AnnotationReferenceData> l = nestedAnnotationReferenceDataList.iterator(); l.hasNext();) { GenPackage.AnnotationReferenceData annotationReferenceData = l.next();%>
			 <%=genModel.getImportedName("org.eclipse.emf.common.util.URI")%>.createURI(<%if (annotationReferenceData.containingGenPackage != genPackage) {%><%=annotationReferenceData.containingGenPackage.getImportedPackageInterfaceName()%>.<%}%>eNS_URI).appendFragment("<%=annotationReferenceData.uriFragment%>")<%if (l.hasNext()) {%>,<%}%><%=genModel.getNonNLS()%>
            <%}%>
		   });
            <%}%>
          <%}%>
        <%}%>
      <%}%>
	}

    <%}%>
  <%} else {%>
    <%if (genPackage.isLoadingInitialization()) {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	private boolean isLoaded = false;

	/**
	 * Laods the package and any sub-packages from their serialized form.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void loadPackage()
	{
		if (isLoaded) return;
		isLoaded = true;

		<%=genModel.getImportedName("java.net.URL")%> url = getClass().getResource(packageFilename);
		if (url == null)
		{
			throw new RuntimeException("Missing serialized package: " + packageFilename);<%=genModel.getNonNLS()%>
		}
		<%=genModel.getImportedName("org.eclipse.emf.common.util.URI")%> uri = <%=genModel.getImportedName("org.eclipse.emf.common.util.URI")%>.createURI(url.toString());
		<%=genModel.getImportedName("org.eclipse.emf.ecore.resource.Resource")%> resource = new <%=genModel.getImportedName("org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl")%>().createResource(uri);
		try
		{
			resource.load(null);
		}
		catch (<%=genModel.getImportedName("java.io.IOException")%> exception)
		{
			throw new <%=genModel.getImportedName("org.eclipse.emf.common.util.WrappedException")%>(exception);
		}
		initializeFromLoadedEPackage(this, (<%=genModel.getImportedName("org.eclipse.emf.ecore.EPackage")%>)resource.getContents().get(0));
		createResource(eNS_URI);
	}

    <%}%>

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	private boolean isFixed = false;

	/**
	 * Fixes up the loaded package, to make it appear as if it had been programmatically built.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void fixPackageContents()
	{
		if (isFixed) return;
		isFixed = true;
		fixEClassifiers();
	}

	/**
	 * Sets the instance class on the given classifier.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
    <%if (genModel.useClassOverrideAnnotation()) {%>
	@Override
    <%}%>
	protected void fixInstanceClass(<%=genModel.getImportedName("org.eclipse.emf.ecore.EClassifier")%> eClassifier)
	{
		if (eClassifier.getInstanceClassName() == null)
		{
    <%ArrayList<GenClass> dynamicGenClasses = new ArrayList<GenClass>(); for (GenClass genClass : genPackage.getGenClasses()) { if (genClass.isDynamic()) { dynamicGenClasses.add(genClass); } }%>
    <%if (dynamicGenClasses.isEmpty()) {%>
			eClassifier.setInstanceClassName("<%=genPackage.getInterfacePackageName()%>." + eClassifier.getName());<%=genModel.getNonNLS()%>
			setGeneratedClassName(eClassifier);
    <%} else {%>
			switch (eClassifier.getClassifierID())
			{
      <%for (GenClass genClass : dynamicGenClasses) {%>
        <%if (genClass.isDynamic()) {%>
				case <%=genPackage.getClassifierID(genClass)%>:
        <%}%>
      <%}%>
				{
					break;
				}
				default:
				{
					eClassifier.setInstanceClassName("<%=genPackage.getInterfacePackageName()%>." + eClassifier.getName());<%=genModel.getNonNLS()%>
					setGeneratedClassName(eClassifier);
					break;
				}
			}
    <%}%>
		}
	}

  <%}%>
  <%if (needsAddEOperation) {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected <%=genModel.getImportedName("org.eclipse.emf.ecore.EOperation")%> addEOperation(<%=genModel.getImportedName("org.eclipse.emf.ecore.EClass")%> owner, <%=genModel.getImportedName("org.eclipse.emf.ecore.EClassifier")%> type, String name, int lowerBound, int upperBound, boolean isUnique, boolean isOrdered)
	{
		<%=genModel.getImportedName("org.eclipse.emf.ecore.EOperation")%> o = addEOperation(owner, type, name, lowerBound, upperBound);
		o.setUnique(isUnique);
		o.setOrdered(isOrdered);
		return o;
	}

  <%}%>
  <%if (needsAddEParameter) {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected <%=genModel.getImportedName("org.eclipse.emf.ecore.EParameter")%> addEParameter(<%=genModel.getImportedName("org.eclipse.emf.ecore.EOperation")%> owner, <%=genModel.getImportedName("org.eclipse.emf.ecore.EClassifier")%> type, String name, int lowerBound, int upperBound, boolean isUnique, boolean isOrdered)
	{
		<%=genModel.getImportedName("org.eclipse.emf.ecore.EParameter")%> p = ecoreFactory.createEParameter();
		p.setEType(type);
		p.setName(name);
		p.setLowerBound(lowerBound);
		p.setUpperBound(upperBound);
		p.setUnique(isUnique);
		p.setOrdered(isOrdered);
		owner.getEParameters().add(p);
		return p;
	}

  <%}%>
<%}%>
<%if (isInterface && genPackage.isLiteralsInterface()) {%>
	/**
	 * <!-- begin-user-doc -->
	 * Defines literals for the meta objects that represent
	 * <ul>
	 *   <li>each class,</li>
	 *   <li>each feature of each class,</li>
  <%if (genModel.isOperationReflection()) {%>
	 *   <li>each operation of each class,</li>
  <%}%>
	 *   <li>each enum,</li>
	 *   <li>and each data type</li>
	 * </ul>
	 * <!-- end-user-doc -->
	 * @generated
	 */
	<%if (isImplementation) {%>public <%}%>interface Literals
	{
  <%for (GenClassifier genClassifier : genPackage.getGenClassifiers()) {%>
		/**
    <%if (genClassifier instanceof GenClass) { GenClass genClass = (GenClass)genClassifier;%>
      <%if (!genClass.isInterface()) {%>
		 * The meta object literal for the '{@link <%=genClass.getQualifiedClassName()%> <em><%=genClass.getFormattedName()%></em>}' class.
		 * <!-- begin-user-doc -->
		 * <!-- end-user-doc -->
		 * @see <%=genClass.getQualifiedClassName()%>
      <%} else {%>
		 * The meta object literal for the '{@link <%=genClass.getRawQualifiedInterfaceName()%> <em><%=genClass.getFormattedName()%></em>}' class.
		 * <!-- begin-user-doc -->
		 * <!-- end-user-doc -->
		 * @see <%=genClass.getRawQualifiedInterfaceName()%>
      <%}%>
    <%} else if (genClassifier instanceof GenEnum) { GenEnum genEnum = (GenEnum)genClassifier;%>
		 * The meta object literal for the '{@link <%=genEnum.getQualifiedName()%> <em><%=genEnum.getFormattedName()%></em>}' enum.
		 * <!-- begin-user-doc -->
		 * <!-- end-user-doc -->
		 * @see <%=genEnum.getQualifiedName()%>
    <%} else if (genClassifier instanceof GenDataType) { GenDataType genDataType = (GenDataType)genClassifier;%>
		 * The meta object literal for the '<em><%=genDataType.getFormattedName()%></em>' data type.
		 * <!-- begin-user-doc -->
		 * <!-- end-user-doc -->
      <%if (!genDataType.isPrimitiveType() && !genDataType.isArrayType()) {%>
		 * @see <%=genDataType.getRawInstanceClassName()%>
      <%}%>
    <%}%>
		 * @see <%=genPackage.getQualifiedPackageClassName()%>#get<%=genClassifier.getClassifierAccessorName()%>()
    <%if (genClassifier.hasAPITags()) {%>
		 * <%=genClassifier.getAPITags(genModel.getIndentation(stringBuffer))%>
    <%}%>
		 * @generated
		 */
  <%if (isJDK50 && genClassifier.hasAPIDeprecatedTag()) {%>
		@Deprecated
  <%}%>
		<%=publicStaticFinalFlag%><%=genClassifier.getImportedMetaType()%> <%=genPackage.getClassifierID(genClassifier)%> = eINSTANCE.get<%=genClassifier.getClassifierAccessorName()%>();

    <%if (genClassifier instanceof GenClass) { GenClass genClass = (GenClass)genClassifier;%>
      <%for (GenFeature genFeature : genClass.getGenFeatures()) {%>
		/**
		 * The meta object literal for the '<em><b><%=genFeature.getFormattedName()%></b></em>' <%=genFeature.getFeatureKind()%> feature.
		 * <!-- begin-user-doc -->
		 * <!-- end-user-doc -->
        <%if (genFeature.hasImplicitAPITags()) {%>
		 * <%=genFeature.getImplicitAPITags(genModel.getIndentation(stringBuffer))%>
        <%}%>
		 * @generated
		 */
        <%if (isJDK50 && genFeature.hasImplicitAPIDeprecatedTag()) {%>
		@Deprecated
        <%}%>
		<%=publicStaticFinalFlag%><%=genFeature.getImportedMetaType()%> <%=genClass.getFeatureID(genFeature)%> = eINSTANCE.get<%=genFeature.getFeatureAccessorName()%>();

      <%}%>
      <%if (genModel.isOperationReflection()) {%>
        <%for (GenOperation genOperation : genClass.getGenOperations()) {%>
		/**
		 * The meta object literal for the '<em><b><%=genOperation.getFormattedName()%></b></em>' operation.
		 * <!-- begin-user-doc -->
		 * <!-- end-user-doc -->
          <%if (genOperation.hasImplicitAPITags()) {%>
		 * <%=genOperation.getImplicitAPITags(genModel.getIndentation(stringBuffer))%>
          <%}%>
		 * @generated
		 */
        <%if (isJDK50 && genOperation.hasImplicitAPIDeprecatedTag()) {%>
		@Deprecated
        <%}%>
		<%=publicStaticFinalFlag%><%=genOperation.getImportedMetaType()%> <%=genClass.getOperationID(genOperation, false)%> = eINSTANCE.get<%=genOperation.getOperationAccessorName()%>();

        <%}%>
      <%}%>
    <%}%>
  <%}%>
	}

<%}%>
} //<%=isInterface ? genPackage.getPackageInterfaceName() : genPackage.getPackageClassName()%>
<%genModel.emitSortedImports();%>
