
<%
/**
 * <copyright>
 *
 * Copyright (c) 2002-2005 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>
 */
%>
<%GenModel genModel = (GenModel)argument;%>
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>

<%@ egf:patternCall patternId="platform:/plugin/org.eclipse.egf.emf.pattern.base/egf/EMF_Pattern_Base.fcore#LogicalName=org.eclipse.egf.emf.pattern.base.HeaderXml" args="parameter:argument"%>

<%if (genModel.isBundleManifest()) {%>
<plugin>
<%} else {%>
<plugin
      name="%pluginName"
      id="<%=genModel.getEditPluginID()%>"
      version="1.0.0"
      provider-name="%providerName"
      class="<%=genModel.getQualifiedEditPluginClassName()%>$Implementation">

   <requires>
  <%for (String pluginID : genModel.getEditRequiredPlugins()) {%>
      <import plugin="<%=pluginID%>"<%if (!pluginID.startsWith("org.eclipse.core.runtime")) {%> export="true"<%}%>/>
  <%}%>
   </requires>

   <runtime>
  <%if (genModel.isRuntimeJar()) {%>
      <library name="<%=genModel.getEditPluginID()%>.jar">
  <%} else {%>
      <library name=".">
  <%}%>
         <export name="*"/>
      </library>
   </runtime>
<%}%>
<%for (GenPackage genPackage : genModel.getAllGenPackagesWithClassifiers()) {%>
  <%if (!genPackage.getGenClasses().isEmpty()) {%>

   <extension point="org.eclipse.emf.edit.itemProviderAdapterFactories">
      <factory
            uri="<%=genPackage.getNSURI()%>"
            class="<%=genPackage.getQualifiedItemProviderAdapterFactoryClassName()%>"
            supportedTypes=
    <%for (ListIterator<?> j = genPackage.getProviderSupportedTypes().listIterator(); j.hasNext(); ) {%>
              <%=j.hasPrevious() ? " " : "\""%><%=j.next()%><%if (!j.hasNext()) {%>"/><%}%>
    <%}%>
   </extension>
    <%if (genPackage.isChildCreationExtenders()) { Map<GenPackage, Map<GenClass, List<GenClass.ChildCreationData>>> extendedChildCreationData = genPackage.getExtendedChildCreationData();%>
      <%if (!extendedChildCreationData.isEmpty()) {%>

   <extension point="org.eclipse.emf.edit.childCreationExtenders">
        <%for (Map.Entry<GenPackage, Map<GenClass, List<GenClass.ChildCreationData>>> entry : extendedChildCreationData.entrySet()) {%>
      <extender
            uri="<%=entry.getKey().getNSURI()%>"
            class="<%=genPackage.getQualifiedItemProviderAdapterFactoryClassName()%>$<%=genPackage.getChildCreationExtenderName(entry.getKey())%>"/>
        <%}%>
   </extension>
      <%}%>
    <%}%>
  <%}%>
<%}%>
<%if (genModel.sameModelEditProject()) {%>
  <%for (GenPackage genPackage : genModel.getAllGenPackagesWithClassifiers()) {%>

   <extension point="org.eclipse.emf.ecore.generated_package">
      <package
            uri="<%=genPackage.getNSURI()%>"
    <%if (genModel.hasLocalGenModel()) {%>
            class="<%=genPackage.getQualifiedPackageInterfaceName()%>"
            genModel="<%=genModel.getRelativeGenModelLocation()%>"/>
    <%} else {%>
            class="<%=genPackage.getQualifiedPackageInterfaceName()%>"/>
    <%}%>
   </extension>
    <%if (genPackage.isContentType()) {%>

   <extension point="org.eclipse.emf.ecore.content_parser">
      <parser
            contentTypeIdentifier="<%=genPackage.getContentTypeIdentifier()%>"
            class="<%=genPackage.getQualifiedEffectiveResourceFactoryClassName()%>"/>
   </extension>

   <extension point="org.eclipse.core.contenttype.contentTypes">
      <content-type
            base-type="<%=genPackage.isXMIResource() ? "org.eclipse.emf.ecore.xmi" : "org.eclipse.core.runtime.xml"%>"
            file-extensions="<%=genPackage.getFileExtensions()%>"
            id="<%=genPackage.getContentTypeIdentifier()%>"
            name="%_UI_<%=genPackage.getPrefix()%>_content_type"
            priority="normal">
         <describer class="org.eclipse.emf.ecore.xmi.impl.RootXMLContentHandlerImpl$Describer">
      <%if (genPackage.hasTargetNamespace()) {%>
            <parameter name="namespace" value="<%=genPackage.getNSURI()%>"/>
      <%}%>
      <%if (genPackage.isXMIResource()) {%>
            <parameter name="kind" value="xmi"/>
      <%}%>
         </describer>
      </content-type>
   </extension>
    <%} else if (genPackage.getResource() != GenResourceKind.NONE_LITERAL) {%>

   <extension point="org.eclipse.emf.ecore.extension_parser">
      <parser
            type="<%=genPackage.getFileExtension()%>"
            class="<%=genPackage.getQualifiedResourceFactoryClassName()%>"/>
   </extension>
    <%}%>
  <%}%>
<%}%>

</plugin>
