
<%
/**
 * <copyright>
 *
 * Copyright (c) 2002-2006 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>
 */
%>
<%final GenPackage genPackage = (GenPackage)((Object[])argument)[0]; final GenModel genModel=genPackage.getGenModel();%>
<%boolean isInterface = Boolean.TRUE.equals(((Object[])argument)[1]); boolean isImplementation = Boolean.TRUE.equals(((Object[])argument)[2]);%>
<%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.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>
 *   <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 -->
 * @generated
 */
<%}%>
<%if (isImplementation) {%>
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.getQualifiedInterfaceName()%> <em><%=genClass.getFormattedName()%></em>}' class.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see <%=genClass.getQualifiedInterfaceName()%>
      <%}%>
    <%} 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()%>()
	 * @generated
	 */
	<%=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 -->
	 * @generated
	 * @ordered
	 */
	<%=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 -->
	 * @generated
	 * @ordered
	 */
	<%=publicStaticFinalFlag%>int <%=genClass.getFeatureCountID()%> = <%=genClass.getFeatureCountValue()%>;

    <%}%>
  <%}%>
<%}%>
<%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 -->
	 * @generated
	 */
	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);

		// Obtain or create and register package
		<%=genPackage.getPackageClassName()%> the<%=genPackage.getBasicPackageName()%> = (<%=genPackage.getPackageClassName()%>)(<%=genModel.getImportedName("org.eclipse.emf.ecore.EPackage")%>.Registry.INSTANCE.get(eNS_URI) instanceof <%=genPackage.getPackageClassName()%> ? <%=genModel.getImportedName("org.eclipse.emf.ecore.EPackage")%>.Registry.INSTANCE.get(eNS_URI) : 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 (GenPackage interdep : genPackage.getPackageInterDependencies()) {%>
		<%=interdep.getImportedPackageClassName()%> <%=genPackage.getPackageInstanceVariable(interdep)%> = (<%=interdep.getImportedPackageClassName()%>)(<%=genModel.getImportedName("org.eclipse.emf.ecore.EPackage")%>.Registry.INSTANCE.getEPackage(<%=interdep.getImportedPackageInterfaceName()%>.eNS_URI) instanceof <%=interdep.getImportedPackageClassName()%> ? <%=genModel.getImportedName("org.eclipse.emf.ecore.EPackage")%>.Registry.INSTANCE.getEPackage(<%=interdep.getImportedPackageInterfaceName()%>.eNS_URI) : <%=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()
			 {
				 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 (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.getQualifiedInterfaceName()%> <em><%=genClass.getFormattedName()%></em>}'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return the meta object for class '<em><%=genClass.getFormattedName()%></em>'.
	 * @see <%=genClass.getQualifiedInterfaceName()%>
      <%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 -->
	 * @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
      <%}}%>
    <%}%>
	 * @generated
	 */
<%} else {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
<%}%>
<%if (isImplementation) {%>
	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.getQualifiedInterfaceName()%><%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.getQualifiedInterfaceName()%><%if (!genClass.isMapEntry() && !genFeature.isSuppressedGetVisibility()) {%>#<%=genFeature.getGetAccessor()%>()<%}%>
	 * @see #get<%=genClass.getClassifierAccessorName()%>()
	 * @generated
	 */
<%} else {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
<%}%>
<%if (isImplementation) {%>
	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 (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) {%>
	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
	 */
	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 (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<?> 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
	 */
	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 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%>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%>addEOperation(<%=genClass.getClassifierInstanceName()%>, <%=genPackage.getPackageInstanceVariable(genOperation.getTypeGenPackage())%>.get<%=genOperation.getTypeClassifierAccessorName()%>(), "<%=genOperation.getName()%>", <%=genOperation.getLowerBound()%>, <%=genOperation.getUpperBound()%>, <%=genOperation.getUniqueFlag()%>, <%=genOperation.getOrderedFlag()%>);<%=genModel.getNonNLS()%>
            <%} else {%>
		<%=prefix%>addEOperation(<%=genClass.getClassifierInstanceName()%>, <%=genPackage.getPackageInstanceVariable(genOperation.getTypeGenPackage())%>.get<%=genOperation.getTypeClassifierAccessorName()%>(), "<%=genOperation.getName()%>", <%=genOperation.getLowerBound()%>, <%=genOperation.getUpperBound()%>);<%=genModel.getNonNLS()%>
            <%}%>
          <%} else {%>
		<%=prefix%>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(eNS_URI);
    <%}%>
    <%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 = 1; for (EObject eContainer = nestedEAnnotation.eContainer(); eContainer != eAnnotation; eContainer = eContainer.eContainer()) { ++depth; } List<GenPackage.AnnotationReferenceData> nestedAnnotationReferenceDataList = genPackage.getReferenceData(nestedEAnnotation);%>
		addAnnotation
		  (<%=genPackage.getAnnotatedModelElementAccessor(eAnnotation)%>, 
		   <%=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>
	 *   <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.getQualifiedInterfaceName()%> <em><%=genClass.getFormattedName()%></em>}' class.
		 * <!-- begin-user-doc -->
		 * <!-- end-user-doc -->
		 * @see <%=genClass.getQualifiedInterfaceName()%>
      <%}%>
    <%} 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()%>()
		 * @generated
		 */
		<%=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 -->
		 * @generated
		 */
		<%=publicStaticFinalFlag%><%=genFeature.getImportedMetaType()%> <%=genClass.getFeatureID(genFeature)%> = eINSTANCE.get<%=genFeature.getFeatureAccessorName()%>();

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

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