
<%
/**
 * <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");%>
  <%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()%>

	/**
	 * 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.  Simple
	 * dependencies are satisfied by calling this method on all
	 * dependent packages before doing anything else.  This method drives
	 * initialization for interdependent packages directly, in parallel
	 * with this package, itself.
	 * <p>Of this package and its interdependencies, all packages which
	 * have not yet been registered by their URI values are first created
	 * and registered.  The packages are then initialized in two steps:
	 * meta-model objects for all of the packages are created before any
	 * are initialized, since one package's meta-model objects may refer to
	 * those of another.
	 * <p>Invocation of this method will not affect any packages that have
	 * already been initialized.
	 * <!-- 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.getPackageInterfaceName()%> = (<%=genPackage.getPackageClassName()%>)(<%=genModel.getImportedName("org.eclipse.emf.ecore.EPackage")%>.Registry.INSTANCE.getEPackage(eNS_URI) instanceof <%=genPackage.getPackageClassName()%> ? <%=genModel.getImportedName("org.eclipse.emf.ecore.EPackage")%>.Registry.INSTANCE.getEPackage(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.getPackageInterfaceName()%>.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.getPackageInterfaceName()%>.createPackageContents();
    <%}%>
    <%for (GenPackage interdep : genPackage.getPackageBuildInterDependencies()) {%>
		<%=genPackage.getPackageInstanceVariable(interdep)%>.createPackageContents();
    <%}%>

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

  <%}%>
  <%if (genPackage.isLoadedInitialization() || !genPackage.getPackageLoadInterDependencies().isEmpty()) {%>
		// Fix loaded packages
    <%if (genPackage.isLoadedInitialization()) {%>
		the<%=genPackage.getPackageInterfaceName()%>.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.getPackageInterfaceName()%>, 
			 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.getPackageInterfaceName()%>.freeze();

  <%}%>
		return the<%=genPackage.getPackageInterfaceName()%>;
	}

<%}%>
<%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.getFactoryInterfaceName()%>()
	{
		return (<%=genPackage.getImportedFactoryInterfaceName()%>)getEFactoryInstance();
	}
<%} else {%>
	<%=genPackage.getFactoryInterfaceName()%> get<%=genPackage.getFactoryInterfaceName()%>();
<%}%>

<%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()) {%>	
        <%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)%>
          <%}%>
		   });
        <%}%>
        <%for (EAnnotation nestedEAnnotation : genPackage.getAllNestedAnnotations(eAnnotation)) {String nestedAnnotationSource = nestedEAnnotation.getSource(); int depth = 1; for (EObject eContainer = nestedEAnnotation.eContainer(); eContainer != eAnnotation; eContainer = eContainer.eContainer()) { ++depth; }%>
		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)%>
          <%}%>
		   });
        <%}%>
        <%for (EAnnotation nestedEAnnotation : genPackage.getAllNestedAnnotations(eAnnotation)) {String nestedAnnotationSource = nestedEAnnotation.getSource(); int depth = 1; for (EObject eContainer = nestedEAnnotation.eContainer(); eContainer != eAnnotation; eContainer = eContainer.eContainer()) { ++depth; }%>
		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)%>
          <%}%>
		   });
        <%}%>
      <%}%>
	}

    <%}%>
  <%} 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();%>
