You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by jo...@apache.org on 2009/05/05 12:52:21 UTC

svn commit: r771663 - in /incubator/uima/uimaj/trunk: uimaj-core/ uimaj-core/src/main/java/org/apache/uima/ecore/ uimaj-ep-runtime/ uimaj-examples/src/main/java/org/apache/uima/examples/xmi/

Author: joern
Date: Tue May  5 10:52:19 2009
New Revision: 771663

URL: http://svn.apache.org/viewvc?rev=771663&view=rev
Log:
UIMA-1326: Moved ecore classes from uimaj-core to uimaj-examples and removed uimaj-examples dependency from uimaj-ep-runtime plugin.

Added:
    incubator/uima/uimaj/trunk/uimaj-examples/src/main/java/org/apache/uima/examples/xmi/Ecore2UimaTypeSystem.java   (with props)
    incubator/uima/uimaj/trunk/uimaj-examples/src/main/java/org/apache/uima/examples/xmi/UimaTypeSystem2Ecore.java   (with props)
Removed:
    incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/ecore/
Modified:
    incubator/uima/uimaj/trunk/uimaj-core/pom.xml
    incubator/uima/uimaj/trunk/uimaj-ep-runtime/pom.xml
    incubator/uima/uimaj/trunk/uimaj-examples/src/main/java/org/apache/uima/examples/xmi/XmiEcoreCasConsumer.java

Modified: incubator/uima/uimaj/trunk/uimaj-core/pom.xml
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-core/pom.xml?rev=771663&r1=771662&r2=771663&view=diff
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-core/pom.xml (original)
+++ incubator/uima/uimaj/trunk/uimaj-core/pom.xml Tue May  5 10:52:19 2009
@@ -51,24 +51,6 @@
 	      <scope>compile</scope>
 	    </dependency>
 		<dependency>
-			<groupId>org.eclipse.emf</groupId>
-			<artifactId>common</artifactId>
-			<version>2.1.0</version>
-			<scope>provided</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.eclipse.emf</groupId>
-			<artifactId>ecore</artifactId>
-			<version>2.1.0</version>
-			<scope>provided</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.eclipse.emf</groupId>
-			<artifactId>ecore-xmi</artifactId>
-			<version>2.1.0</version>
-			<scope>provided</scope>
-		</dependency>
-		<dependency>
 			<groupId>org.apache.uima</groupId>
 			<artifactId>uimaj-test-util</artifactId>
 			<version>${uimaj-release-version}</version>

Modified: incubator/uima/uimaj/trunk/uimaj-ep-runtime/pom.xml
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-ep-runtime/pom.xml?rev=771663&r1=771662&r2=771663&view=diff
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-ep-runtime/pom.xml (original)
+++ incubator/uima/uimaj/trunk/uimaj-ep-runtime/pom.xml Tue May  5 10:52:19 2009
@@ -71,13 +71,6 @@
 
     <dependency>
       <groupId>org.apache.uima</groupId>
-      <artifactId>uimaj-examples</artifactId>
-      <version>${uimaj-release-version}</version>
-      <scope>compile</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>org.apache.uima</groupId>
       <artifactId>uimaj-adapter-vinci</artifactId>
       <version>${uimaj-release-version}</version>
       <scope>compile</scope>
@@ -128,7 +121,6 @@
                  alternative to the jars - but might have a
                  versioning / control issue -->
             <_exportcontents>
-               example,
                org.apache.uima,
                org.apache.uima.adapter.vinci,
                org.apache.uima.adapter.vinci.util,
@@ -167,14 +159,6 @@
                org.apache.uima.collection.impl.metadata,
                org.apache.uima.collection.impl.metadata.cpe,
                org.apache.uima.collection.metadata,
-               org.apache.uima.ecore,
-               org.apache.uima.examples,
-               org.apache.uima.examples.cas,
-               org.apache.uima.examples.casMultiplier,
-               org.apache.uima.examples.cpe,
-               org.apache.uima.examples.flow,
-               org.apache.uima.examples.tokenizer,
-               org.apache.uima.examples.xmi,
                org.apache.uima.flow,
                org.apache.uima.flow.impl,
                org.apache.uima.impl,
@@ -209,13 +193,6 @@
                org.apache.uima.tools.util.gui,
                org.apache.uima.tools.util.htmlview,
                org.apache.uima.tools.viewer,
-               org.apache.uima.tutorial,
-               org.apache.uima.tutorial.ex1,
-               org.apache.uima.tutorial.ex2,
-               org.apache.uima.tutorial.ex3,
-               org.apache.uima.tutorial.ex4,
-               org.apache.uima.tutorial.ex5,
-               org.apache.uima.tutorial.ex6,
                org.apache.uima.uimacpp,
                org.apache.uima.util,
                org.apache.uima.util.impl,

Added: incubator/uima/uimaj/trunk/uimaj-examples/src/main/java/org/apache/uima/examples/xmi/Ecore2UimaTypeSystem.java
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-examples/src/main/java/org/apache/uima/examples/xmi/Ecore2UimaTypeSystem.java?rev=771663&view=auto
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-examples/src/main/java/org/apache/uima/examples/xmi/Ecore2UimaTypeSystem.java (added)
+++ incubator/uima/uimaj/trunk/uimaj-examples/src/main/java/org/apache/uima/examples/xmi/Ecore2UimaTypeSystem.java Tue May  5 10:52:19 2009
@@ -0,0 +1,526 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.uima.examples.xmi;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.uima.ResourceSpecifierFactory;
+import org.apache.uima.UIMAFramework;
+import org.apache.uima.UIMARuntimeException;
+import org.apache.uima.cas.CAS;
+import org.apache.uima.cas.impl.XmiCasSerializer;
+import org.apache.uima.resource.metadata.AllowedValue;
+import org.apache.uima.resource.metadata.FeatureDescription;
+import org.apache.uima.resource.metadata.FsIndexDescription;
+import org.apache.uima.resource.metadata.TypeDescription;
+import org.apache.uima.resource.metadata.TypeSystemDescription;
+import org.apache.uima.util.CasCreationUtils;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EAnnotation;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EEnum;
+import org.eclipse.emf.ecore.EEnumLiteral;
+import org.eclipse.emf.ecore.ENamedElement;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EcorePackage;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
+
+/**
+ * Converts an Ecore model to a UIMA TypeSystemDescription.
+ */
+public class Ecore2UimaTypeSystem {
+  /**
+   * Configures the handling of multi-valued properties in the Ecore model. If set to Boolean.FALSE
+   * (the default), UIMA array types (e.g. FSArray) will be generated. If set to Boolean.TRUE, UIMA
+   * list types (e.g. FSList) will be generated. Note that for primitive types that have no
+   * corresponding list type (Byte, Short, Long, Double, and Boolean), array types will always be
+   * used.
+   */
+  public static final String OPTION_GENERATE_UIMA_LIST_TYPES = "OPTION_GENERATE_UIMA_LIST_TYPES";
+
+  /**
+   * Configures the assignment of supertypes to EClasses that have no declared supertype. If set to
+   * Boolean.TRUE (the default), if such an EClass has "begin" and "end" properties of type EInt,
+   * the superclass will be set to uima.tcas.Annotation. If set to Boolean.FALSE, all EClasses with
+   * no declared supertype will have their supertype set to uima.cas.TOP.
+   */
+  public static final String OPTION_CREATE_ANNOTATION_SUBTYPES = "OPTION_CREATE_ANNOTATION_SUBTYPES";
+
+  private static ResourceSpecifierFactory uimaFactory = UIMAFramework.getResourceSpecifierFactory();
+
+  /**
+   * Converts an Ecore model to a UIMA TypeSytemDescription.
+   * 
+   * @param aEcoreFilePath
+   *          file path to a .ecore model file
+   * @param aOptions
+   *          a Map defining options for the conversion. Valid keys for this map are defined as
+   *          constants on this class.
+   * 
+   * @return The UIMA TypeSystemDescription corresponding to the Ecore model
+   * @throws URISyntaxException
+   *           if there is a problem finding or reading the .ecore file
+   */
+  public static TypeSystemDescription ecore2UimaTypeSystem(String aEcoreFilePath, Map aOptions)
+          throws URISyntaxException {
+    // register default resource factory
+    Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("*",
+            new XMIResourceFactoryImpl());
+    // create resource set to hold the resource we're loading and its dependent resources
+    ResourceSet resourceSet = new ResourceSetImpl();
+    // convert file path to absolute path -- seems to be required for propery proxy resolution
+    File inputFile = new File(aEcoreFilePath);
+    URI absoluteInputURI = URI.createFileURI(inputFile.getAbsolutePath());
+    // load the resource
+    Resource resource = resourceSet.getResource(absoluteInputURI, true);
+    // convert to UIMA TypeSystem
+    return ecore2UimaTypeSystem(resource, aOptions);
+  }
+
+  /**
+   * Converts an Ecore model to a UIMA TypeSytemDescription.
+   * 
+   * @param aEcoreResource
+   *          An EMF Resource containing the Ecore model
+   * @param aOptions
+   *          a Map defining options for the conversion. Valid keys for this map are defined as
+   *          constants on this class.
+   * 
+   * @return The UIMA TypeSystemDescription corresponding to the Ecore model
+   * @throws URISyntaxException
+   *           if there is a problem reading from the resource
+   */
+  public static TypeSystemDescription ecore2UimaTypeSystem(Resource aEcoreResource, Map aOptions)
+          throws URISyntaxException {
+    if (aOptions == null) {
+      aOptions = Collections.EMPTY_MAP;
+    }
+
+    TypeSystemDescription tsDesc = uimaFactory.createTypeSystemDescription();
+
+    // try to get descriptive info from EAnnotation with NS "http://uima.apache.org",
+    // on the first EPackage in the Resource
+    EPackage ePackage = (EPackage) aEcoreResource.getContents().get(0);
+    EAnnotation eannot = ePackage.getEAnnotation("http://uima.apache.org");
+    if (eannot != null) {
+      tsDesc.setName((String) eannot.getDetails().get("name"));
+      tsDesc.setDescription((String) eannot.getDetails().get("description"));
+      tsDesc.setVendor((String) eannot.getDetails().get("vendor"));
+      tsDesc.setVersion((String) eannot.getDetails().get("version"));
+    }
+
+    // convert types
+    List types = new ArrayList();
+    Iterator iter = aEcoreResource.getContents().iterator();
+    while (iter.hasNext()) {
+      Object obj = iter.next();
+      if (obj instanceof EPackage) {
+        ePackage2UimaTypes((EPackage) obj, types, aOptions);
+      }
+    }
+    TypeDescription[] typeArr = new TypeDescription[types.size()];
+    types.toArray(typeArr);
+    tsDesc.setTypes(typeArr);
+    return tsDesc;
+  }
+
+  private static void ePackage2UimaTypes(EPackage aEPackage, List aResultTypes, Map aOptions)
+          throws URISyntaxException {
+    String nsUri = aEPackage.getNsURI();
+    String uimaNamespace = namespaceUri2UimaNamespace(nsUri);
+    // skip the uima.cas package, since it contains only feature-final built-ins
+    if ("uima.cas".equals(uimaNamespace)) {
+      return;
+    }
+
+    Iterator iter = aEPackage.getEClassifiers().iterator();
+    while (iter.hasNext()) {
+      Object classifier = iter.next();
+      if (classifier instanceof EClass) {
+        EClass eclass = (EClass) classifier;
+        TypeDescription type = eclass2UimaType(eclass, uimaNamespace, aOptions);
+        // skip uima.tcas.Annotation, since it is feature-final
+        if (!"uima.tcas.Annotation".equals(type.getName())) {
+          aResultTypes.add(type);
+        }
+      } else if (classifier instanceof EEnum) {
+        EEnum eenum = (EEnum) classifier;
+        TypeDescription type = eenum2UimaType(eenum, uimaNamespace, aOptions);
+        aResultTypes.add(type);
+      }
+    }
+    // now process nested subpckages
+    iter = aEPackage.getESubpackages().iterator();
+    while (iter.hasNext()) {
+      ePackage2UimaTypes((EPackage) iter.next(), aResultTypes, aOptions);
+    }
+  }
+
+  private static TypeDescription eclass2UimaType(EClass aEClass, String aUimaNamespace, Map aOptions)
+          throws URISyntaxException {
+    TypeDescription type = uimaFactory.createTypeDescription();
+    // set name
+    if (aUimaNamespace != null) {
+      type.setName(aUimaNamespace + "." + aEClass.getName());
+    } else {
+      type.setName(aEClass.getName());
+    }
+    // try to get desecription from EAnnotation
+    EAnnotation eannot = aEClass.getEAnnotation("http://uima.apache.org");
+    if (eannot != null) {
+      type.setDescription((String) eannot.getDetails().get("description"));
+    }
+    // set supertype
+    EList supertypes = aEClass.getESuperTypes();
+    if (supertypes.isEmpty()) // supertype not defined in the Ecore model
+    {
+      if (aOptions.get(OPTION_CREATE_ANNOTATION_SUBTYPES) == Boolean.FALSE) {
+        type.setSupertypeName(CAS.TYPE_NAME_TOP);
+      } else {
+        // if this class has "begin" and "end" attributes of type EInt, make it a subtype of
+        // annotation
+        EStructuralFeature begin = aEClass.getEStructuralFeature("begin");
+        EStructuralFeature end = aEClass.getEStructuralFeature("end");
+        if (begin != null && end != null && begin.getEType() == EcorePackage.eINSTANCE.getEInt()
+                && end.getEType() == EcorePackage.eINSTANCE.getEInt()) {
+          type.setSupertypeName(CAS.TYPE_NAME_ANNOTATION);
+        } else {
+          type.setSupertypeName(CAS.TYPE_NAME_TOP);
+        }
+      }
+    } else {
+      EClass supertype = (EClass) supertypes.get(0);
+      // if the supertype is EObject, translate that to uima.cas.TOP
+      if (supertype.equals(EcorePackage.eINSTANCE.getEObject())) {
+        type.setSupertypeName(CAS.TYPE_NAME_TOP);
+      }
+      // otherwise translate the name according to our conventions
+      String uimaSupertypeName = getUimaTypeName(supertype, false, aOptions);
+      type.setSupertypeName(uimaSupertypeName);
+
+      // if there are multiple supertypes, the first one is arbitrarily chosen
+      // as the single supertype for the UIMA type. Other features are copied-down.
+      if (supertypes.size() > 1) {
+        System.err.println("Warning: EClass " + aEClass.getName()
+                + " defines multiple supertypes. " + "The UIMA supertype will be "
+                + type.getSupertypeName()
+                + "; features inherited from other supertypes will be copied down.");
+      }
+    }
+    // set features
+    EList eFeatures = aEClass.getEStructuralFeatures();
+    Iterator iter = eFeatures.iterator();
+    List uimaFeatures = new ArrayList();
+    while (iter.hasNext()) {
+      EStructuralFeature eFeat = (EStructuralFeature) iter.next();
+      FeatureDescription uimaFeat = eStructuralFeature2UimaFeature(eFeat, aOptions);
+      uimaFeatures.add(uimaFeat);
+    }
+    // copy down features from additional supertypes
+    for (int i = 1; i < supertypes.size(); i++) {
+      EClass copyFrom = (EClass) supertypes.get(i);
+      EList copyFeatures = copyFrom.getEStructuralFeatures();
+      Iterator iter2 = copyFeatures.iterator();
+      while (iter2.hasNext()) {
+        EStructuralFeature eFeat = (EStructuralFeature) iter2.next();
+        // do not copy if this feature is a duplicate of one defined on the class
+        // or inherited from its primary supertype
+        EList locallyDefinedFeatures = aEClass.getEStructuralFeatures();
+        EList firstSupertypesFeatures = ((EClass) supertypes.get(0)).getEAllStructuralFeatures();
+        if (!containsNamedElement(locallyDefinedFeatures, eFeat.getName())
+                && !containsNamedElement(firstSupertypesFeatures, eFeat.getName())) {
+          FeatureDescription uimaFeat = eStructuralFeature2UimaFeature(eFeat, aOptions);
+          uimaFeatures.add(uimaFeat);
+        }
+      }
+    }
+
+    FeatureDescription[] featureArr = new FeatureDescription[uimaFeatures.size()];
+    uimaFeatures.toArray(featureArr);
+    type.setFeatures(featureArr);
+    return type;
+  }
+
+  private static boolean containsNamedElement(EList locallyDefinedFeatures, String name) {
+    Iterator iter = locallyDefinedFeatures.iterator();
+    while (iter.hasNext()) {
+      Object obj = iter.next();
+      if (obj instanceof ENamedElement) {
+        if (name.equals(((ENamedElement) obj).getName())) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  private static TypeDescription eenum2UimaType(EEnum aEEnum, String aUimaNamespace, Map aOptions)
+          throws URISyntaxException {
+    TypeDescription type = uimaFactory.createTypeDescription();
+    // set name
+    if (aUimaNamespace != null) {
+      type.setName(aUimaNamespace + "." + aEEnum.getName());
+    } else {
+      type.setName(aEEnum.getName());
+    }
+    // set supetype to String
+    type.setSupertypeName(CAS.TYPE_NAME_STRING);
+    // try to get desecription from EAnnotation
+    EAnnotation eannot = aEEnum.getEAnnotation("http://uima.apache.org");
+    if (eannot != null) {
+      type.setDescription((String) eannot.getDetails().get("description"));
+    }
+    // set allowed values
+    EList literals = aEEnum.getELiterals();
+    AllowedValue[] vals = new AllowedValue[literals.size()];
+    for (int i = 0; i < literals.size(); i++) {
+      EEnumLiteral literal = (EEnumLiteral) literals.get(i);
+      vals[i] = uimaFactory.createAllowedValue();
+      vals[i].setString(literal.getName());
+      EAnnotation literalAnnot = literal.getEAnnotation("http://uima.apache.org");
+      if (literalAnnot != null) {
+        vals[i].setDescription((String) literalAnnot.getDetails().get("description"));
+      }
+    }
+    type.setAllowedValues(vals);
+    return type;
+  }
+
+  /**
+   * @param attr
+   * @return
+   */
+  private static FeatureDescription eStructuralFeature2UimaFeature(
+          EStructuralFeature aStructuralFeature, Map aOptions) throws URISyntaxException {
+    FeatureDescription feat = uimaFactory.createFeatureDescription();
+    feat.setName(aStructuralFeature.getName());
+    String rangeTypeName = null;
+    String elementTypeName = null;
+    EAnnotation eannot = aStructuralFeature.getEAnnotation("http://uima.apache.org");
+    if (eannot != null) {
+      feat.setDescription((String) eannot.getDetails().get("description"));
+      // the UIMA type name to use may be recorded as an EAnnotation; this is
+      // particularly important for arrays and lists, since Ecore doesn't distinguish between
+      // these two possible implementations for a multi-valued property
+      rangeTypeName = (String) eannot.getDetails().get("uimaType");
+      // the elemnt type may also be specified as an EAnnotation; this is
+      // used for the case where an FSArray or FSList is NOT represented
+      // as a multi-valued property
+      elementTypeName = (String) eannot.getDetails().get("elementType");
+    }
+    EClassifier attrRangeType = aStructuralFeature.getEType();
+
+    // if range type wasn't specified in an EAnnotation, compute it ourselves
+    if (rangeTypeName == null) {
+      rangeTypeName = getUimaTypeName(attrRangeType, aStructuralFeature.isMany(), aOptions);
+    }
+    feat.setRangeTypeName(rangeTypeName);
+
+    if (aStructuralFeature.isMany()) {
+      // set the element type of the array/list to the EType of the structural feature
+      // (except primitive, or TOP, which are assumed)
+      String uimaElementType = getUimaTypeName(attrRangeType, false, aOptions);
+      if (!CAS.TYPE_NAME_INTEGER.equals(uimaElementType)
+              && !CAS.TYPE_NAME_FLOAT.equals(uimaElementType)
+              && !CAS.TYPE_NAME_STRING.equals(uimaElementType)
+              && !CAS.TYPE_NAME_TOP.equals(uimaElementType)
+              && !CAS.TYPE_NAME_BYTE.equals(uimaElementType)
+              && !CAS.TYPE_NAME_SHORT.equals(uimaElementType)
+              && !CAS.TYPE_NAME_LONG.equals(uimaElementType)
+              && !CAS.TYPE_NAME_DOUBLE.equals(uimaElementType)
+              && !CAS.TYPE_NAME_BOOLEAN.equals(uimaElementType)) {
+        feat.setElementType(uimaElementType);
+      }
+    } else if (!aStructuralFeature.getEType().equals(EcorePackage.eINSTANCE.getEByteArray())) {
+      // if in Ecore we have a single-valued property whose range type is an array or list,
+      // we need to set "multiple references allowed" to true in the UIMA type system
+      // (exception: don't do this for the EByteArray data type, which is implicilty a
+      // multi-valued type)
+      if (isArrayOrList(rangeTypeName)) {
+        feat.setMultipleReferencesAllowed(Boolean.TRUE);
+        // also, set element type if one was contained in the EAnnotation
+        feat.setElementType(elementTypeName);
+      }
+    }
+    return feat;
+  }
+
+  private static boolean isArrayOrList(String rangeTypeName) {
+    return CAS.TYPE_NAME_FS_LIST.equals(rangeTypeName)
+            || CAS.TYPE_NAME_INTEGER_LIST.equals(rangeTypeName)
+            || CAS.TYPE_NAME_FLOAT_LIST.equals(rangeTypeName)
+            || CAS.TYPE_NAME_STRING_LIST.equals(rangeTypeName)
+            || CAS.TYPE_NAME_FS_ARRAY.equals(rangeTypeName)
+            || CAS.TYPE_NAME_INTEGER_ARRAY.equals(rangeTypeName)
+            || CAS.TYPE_NAME_FLOAT_ARRAY.equals(rangeTypeName)
+            || CAS.TYPE_NAME_STRING_ARRAY.equals(rangeTypeName)
+            || CAS.TYPE_NAME_BYTE_ARRAY.equals(rangeTypeName)
+            || CAS.TYPE_NAME_SHORT_ARRAY.equals(rangeTypeName)
+            || CAS.TYPE_NAME_LONG_ARRAY.equals(rangeTypeName)
+            || CAS.TYPE_NAME_DOUBLE_ARRAY.equals(rangeTypeName)
+            || CAS.TYPE_NAME_BOOLEAN_ARRAY.equals(rangeTypeName);
+
+  }
+
+  private static String getUimaTypeName(EClassifier aEcoreType, boolean aMultiValued, Map aOptions)
+          throws URISyntaxException {
+    boolean useUimaLists = Boolean.TRUE.equals(aOptions.get(OPTION_GENERATE_UIMA_LIST_TYPES));
+
+    if (aEcoreType.eIsProxy()) {
+      // try to resolve
+      aEcoreType = (EClassifier) EcoreUtil.resolve(aEcoreType, aEcoreType);
+      if (aEcoreType.eIsProxy()) {
+        throw new UIMARuntimeException(UIMARuntimeException.ECORE_UNRESOLVED_PROXY,
+                new Object[] { aEcoreType.toString() });
+      }
+    }
+
+    if (aEcoreType instanceof EClass || aEcoreType instanceof EEnum) {
+      // maps to non-primitive UIMA type
+      if (aMultiValued) {
+        // UIMA doesn't have typed arrays or lists of nonprimitives
+        return useUimaLists ? CAS.TYPE_NAME_FS_LIST : CAS.TYPE_NAME_FS_ARRAY;
+      }
+
+      // Derive type name from package name
+      EPackage epackage = aEcoreType.getEPackage();
+      if (epackage != null) {
+        String uimaNamespace = namespaceUri2UimaNamespace(epackage.getNsURI());
+        if (uimaNamespace != null)
+          return uimaNamespace + '.' + aEcoreType.getName();
+        else
+          return aEcoreType.getName();
+      } else {
+        return aEcoreType.getName();
+      }
+    } else // primitive type
+    {
+      if (aEcoreType.equals(EcorePackage.eINSTANCE.getEInt())) {
+        return aMultiValued ? (useUimaLists ? CAS.TYPE_NAME_INTEGER_LIST
+                : CAS.TYPE_NAME_INTEGER_ARRAY) : CAS.TYPE_NAME_INTEGER;
+      } else if (aEcoreType.equals(EcorePackage.eINSTANCE.getEShort())) {
+        return aMultiValued ? CAS.TYPE_NAME_SHORT_ARRAY : CAS.TYPE_NAME_SHORT;
+      } else if (aEcoreType.equals(EcorePackage.eINSTANCE.getELong())) {
+        return aMultiValued ? CAS.TYPE_NAME_LONG_ARRAY : CAS.TYPE_NAME_LONG;
+      } else if (aEcoreType.equals(EcorePackage.eINSTANCE.getEByte())) {
+        return aMultiValued ? CAS.TYPE_NAME_BYTE_ARRAY : CAS.TYPE_NAME_BYTE;
+      } else if (aEcoreType.equals(EcorePackage.eINSTANCE.getEFloat())) {
+        return aMultiValued ? (useUimaLists ? CAS.TYPE_NAME_FLOAT_LIST : CAS.TYPE_NAME_FLOAT_ARRAY)
+                : CAS.TYPE_NAME_FLOAT;
+      } else if (aEcoreType.equals(EcorePackage.eINSTANCE.getEDouble())) {
+        return aMultiValued ? CAS.TYPE_NAME_DOUBLE_ARRAY : CAS.TYPE_NAME_DOUBLE;
+      } else if (aEcoreType.equals(EcorePackage.eINSTANCE.getEBoolean())) {
+        return aMultiValued ? CAS.TYPE_NAME_BOOLEAN_ARRAY : CAS.TYPE_NAME_BOOLEAN;
+      }
+      // Ecore has a special type EByteArray that we use instead of a
+      // multi-valued EByte property. This gives a slightly more efficient
+      // serialization
+      else if (aEcoreType.equals(EcorePackage.eINSTANCE.getEByteArray())) {
+        return CAS.TYPE_NAME_BYTE_ARRAY;
+      } else // any other datatype maps to String
+      {
+        if (!aEcoreType.equals(EcorePackage.eINSTANCE.getEString())) {
+          System.err.println("Warning: unknown EDataType " + aEcoreType.getName()
+                  + " being mapped to uima.cas.String.");
+        }
+        return aMultiValued ? (useUimaLists ? CAS.TYPE_NAME_STRING_LIST
+                : CAS.TYPE_NAME_STRING_ARRAY) : CAS.TYPE_NAME_STRING;
+      }
+    }
+  }
+
+  private static String namespaceUri2UimaNamespace(String nsUri) throws URISyntaxException {
+    // Check for the special "no namespace URI", which maps to the null UIMA namespace
+    if (XmiCasSerializer.DEFAULT_NAMESPACE_URI.equals(nsUri)) {
+      return null;
+    }
+    // Our convention is that the UIMA namespace is the URI path, with leading slashes
+    // removed, trailing ".ecore" removed, and internal slashes converted to dots
+    java.net.URI uri = new java.net.URI(nsUri);
+    String uimaNs = uri.getPath();
+    if (uimaNs == null) {
+      // The URI is a URN
+      uimaNs = uri.getSchemeSpecificPart();
+      uimaNs = uimaNs.replace(':', '.');
+    } else {
+      // The URI is a URL
+      while (uimaNs.startsWith("/")) {
+	uimaNs = uimaNs.substring(1);
+      }
+      if (uimaNs.endsWith(".ecore")) {
+	uimaNs = uimaNs.substring(0, uimaNs.length() - 6);
+      }
+      uimaNs = uimaNs.replace('/', '.');
+    }
+    uimaNs = uimaNs.replace('-', '_');
+    return uimaNs;
+  }
+
+  /**
+   * Main program. Takes two arguments: the filename of an input .ecore file and the filename of the
+   * UIMA TypeSystem file to generate.
+   */
+  public static void main(String[] args) throws Exception {
+    if (args.length != 2) {
+      System.err.println("Usage: java " + Ecore2UimaTypeSystem.class.getName()
+              + " <ecore filename> <filename of UIMA TypeSystem file to generate>");
+      return;
+    }
+    if (!new File(args[0]).exists()) {
+      System.err.println("File " + args[0] + " does not exist");
+      return;
+    }
+
+    Map options = new HashMap();
+    // options.put(OPTION_GENERATE_UIMA_LIST_TYPES, Boolean.TRUE);
+    TypeSystemDescription tsDesc = ecore2UimaTypeSystem(args[0], options);
+
+    FileOutputStream os = new FileOutputStream(args[1]);
+    try {
+      tsDesc.toXML(os);
+    } finally {
+      os.close();
+    }
+
+    // test creating a CAS
+    try {
+      CasCreationUtils.createCas(tsDesc, null, new FsIndexDescription[0]);
+    } catch (Exception e) {
+      System.err
+              .println("Warning: CAS could not be created from the output type system.  The following problem occurred:");
+      System.err.println(e.getMessage());
+    }
+  }
+}

Propchange: incubator/uima/uimaj/trunk/uimaj-examples/src/main/java/org/apache/uima/examples/xmi/Ecore2UimaTypeSystem.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: incubator/uima/uimaj/trunk/uimaj-examples/src/main/java/org/apache/uima/examples/xmi/UimaTypeSystem2Ecore.java
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-examples/src/main/java/org/apache/uima/examples/xmi/UimaTypeSystem2Ecore.java?rev=771663&view=auto
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-examples/src/main/java/org/apache/uima/examples/xmi/UimaTypeSystem2Ecore.java (added)
+++ incubator/uima/uimaj/trunk/uimaj-examples/src/main/java/org/apache/uima/examples/xmi/UimaTypeSystem2Ecore.java Tue May  5 10:52:19 2009
@@ -0,0 +1,503 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.uima.examples.xmi;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.uima.UIMAFramework;
+import org.apache.uima.UIMARuntimeException;
+import org.apache.uima.cas.CAS;
+import org.apache.uima.cas.impl.XmiCasSerializer;
+import org.apache.uima.resource.ResourceInitializationException;
+import org.apache.uima.resource.metadata.AllowedValue;
+import org.apache.uima.resource.metadata.FeatureDescription;
+import org.apache.uima.resource.metadata.TypeDescription;
+import org.apache.uima.resource.metadata.TypeSystemDescription;
+import org.apache.uima.util.CasCreationUtils;
+import org.apache.uima.util.InvalidXMLException;
+import org.apache.uima.util.XMLInputSource;
+import org.eclipse.emf.common.util.TreeIterator;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EAnnotation;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EEnum;
+import org.eclipse.emf.ecore.EEnumLiteral;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EcoreFactory;
+import org.eclipse.emf.ecore.EcorePackage;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
+
+/**
+ * Converts a UIMA TypeSystemDescription to an Ecore model.
+ */
+public class UimaTypeSystem2Ecore {
+  /**
+   * Converts a UIMA TypeSystem descriptor to an Ecore model
+   * 
+   * @param aUimaTypeSystemFilePath
+   *          file path to UIMA TypeSystem descritpor
+   * @param aOutputResource
+   *          An EMF Resource to be populated with the Ecore model
+   * @param aOptions
+   *          a Map defining options for the conversion. Valid keys for this map are defined as
+   *          constants on this class.
+   * 
+   * @throws InvalidXMLException
+   *           if the TypeSystem descriptor, or one of its imports, is not valid or if there are
+   *           duplicate, inconsistent definitions of the same type.
+   * @throws IOException
+   *           if an failure occur while reading the descriptor file
+   */
+  public static void uimaTypeSystem2Ecore(String aUimaTypeSystemFilePath, Resource aOutputResource,
+          Map aOptions) throws InvalidXMLException, IOException {
+    TypeSystemDescription tsDesc = UIMAFramework.getXMLParser().parseTypeSystemDescription(
+            new XMLInputSource(aUimaTypeSystemFilePath));
+    uimaTypeSystem2Ecore(tsDesc, aOutputResource, aOptions);
+  }
+
+  /**
+   * Converts a UIMA TypeSystemDescription to an Ecore model
+   * 
+   * @param aTypeSystem
+   *          UIMA TypeSystemDescription object to convert
+   * @param aOutputResource
+   *          An EMF Resource to be populated with the Ecore model
+   * @param aOptions
+   *          a Map defining options for the conversion. Valid keys for this map are defined as
+   *          constants on this class.
+   * 
+   * @throws InvalidXMLException
+   *           if the TypeSystem descriptor imports another descriptor that could not be
+   *           successfully parsed, or if there are duplicate, inconsistent definitions of the same
+   *           type.
+   */
+  public static void uimaTypeSystem2Ecore(TypeSystemDescription aTypeSystem,
+          Resource aOutputResource, Map aOptions) throws InvalidXMLException {
+    uimaTypeSystem2Ecore(aTypeSystem, aOutputResource, aOptions, null);
+  }
+
+  /**
+   * Converts a UIMA TypeSystemDescription to an Ecore model
+   * 
+   * @param aTypeSystem
+   *          UIMA TypeSystemDescription object to convert
+   * @param aOutputResource
+   *          An EMF Resource to be populated with the Ecore model
+   * @param aOptions
+   *          a Map defining options for the conversion. Valid keys for this map are defined as
+   *          constants on this class.
+   * @param aSchemaLocationMap
+   *          optional parameter - if non-null, this map will be populated with (Namespace URI,
+   *          Schema Location) pairs, suitable for inclusion in the "schemaLocation" attribute of
+   *          XMI instance documents.
+   */
+  public static void uimaTypeSystem2Ecore(TypeSystemDescription aTypeSystem,
+          Resource aOutputResource, Map aOptions, Map aSchemaLocationMap)
+          throws InvalidXMLException {
+    // Add the default definition of uima.tcas.DocumentAnnotation. If the
+    // user also defines this type (with additional features), it will be merged
+    // with this. First clone the aTypeSystem object so user won't notice
+    // we have added a new type definition to their TypeSystemDescription.
+    aTypeSystem = (TypeSystemDescription) aTypeSystem.clone();
+    TypeDescription docAnnotType = aTypeSystem.addType("uima.tcas.DocumentAnnotation", "",
+            "uima.tcas.Annotation");
+    docAnnotType.addFeature("language", "", "uima.cas.String");
+
+    // resolve imports
+    aTypeSystem.resolveImports();
+
+    // merge, to eliminate duplicate type definitions
+    try {
+      aTypeSystem = CasCreationUtils.mergeTypeSystems(Arrays.asList(new Object[] { aTypeSystem }));
+    } catch (ResourceInitializationException e) {
+      throw new InvalidXMLException(e);
+    }
+
+    if (aOptions == null) {
+      aOptions = Collections.EMPTY_MAP;
+    }
+
+    // load Ecore model for the UIMA Built-in types
+    ResourceSet resSet = aOutputResource.getResourceSet();
+    if (resSet == null) {
+      resSet = new ResourceSetImpl();
+      resSet.getResources().add(aOutputResource);
+    }
+    loadUimaBuiltinsEcore(resSet, aSchemaLocationMap);
+
+    // Do this in two passes. First pass creates EPackages, EClasses, and EEnums (for string
+    // subtypes)
+    // Second pass sets supertypes and creates EStructuralFeatures
+    TypeDescription[] types = aTypeSystem.getTypes();
+    EPackage firstPackage = null;
+    for (int i = 0; i < types.length; i++) {
+      TypeDescription type = types[i];
+      EClassifier eclassifier = uimaType2EClassifier(type, aOptions);
+      // EPackages may also have been created. Add the root EPackage to the resource.
+      EPackage rootPackage = eclassifier.getEPackage();
+      while (rootPackage.getESuperPackage() != null)
+        rootPackage = rootPackage.getESuperPackage();
+      aOutputResource.getContents().add(rootPackage);
+      if (aSchemaLocationMap != null) {
+        String schemaLoc = aOutputResource.getURI() + "#"
+                + aOutputResource.getURIFragment(eclassifier.getEPackage());
+        aSchemaLocationMap.put(eclassifier.getEPackage().getNsURI(), schemaLoc);
+      }
+      if (firstPackage == null) {
+        firstPackage = eclassifier.getEPackage();
+      }
+    }
+
+    // Now make second pass to set supertype and create feautres
+    for (int i = 0; i < types.length; i++) {
+      TypeDescription type = types[i];
+      EClassifier eclassifier = lookupEClassifierForType(type.getName());
+      if (eclassifier instanceof EClass) {
+        EClass eclass = (EClass) eclassifier;
+        // set supertype
+        String supertypeName = type.getSupertypeName();
+        EClassifier superclass = lookupEClassifierForType(supertypeName); // creates EClass if not
+        // already existing
+        eclass.getESuperTypes().add(superclass);
+
+        // set features
+        FeatureDescription[] features = type.getFeatures();
+        for (int j = 0; j < features.length; j++) {
+          eclass.getEStructuralFeatures()
+                  .add(uimaFeature2EStructuralFeature(features[j], aOptions));
+        }
+      }
+    }
+
+    // add descriptive type system attributes as EAnnotations on first package
+    EAnnotation eannot = EcoreFactory.eINSTANCE.createEAnnotation();
+    eannot.setSource("http://uima.apache.org");
+    if (aTypeSystem.getName() != null && aTypeSystem.getName().length() > 0)
+      eannot.getDetails().put("name", aTypeSystem.getName());
+    if (aTypeSystem.getDescription() != null && aTypeSystem.getDescription().length() > 0)
+      eannot.getDetails().put("description", aTypeSystem.getDescription());
+    if (aTypeSystem.getVersion() != null && aTypeSystem.getVersion().length() > 0)
+      eannot.getDetails().put("version", aTypeSystem.getVersion());
+    if (aTypeSystem.getVendor() != null && aTypeSystem.getVendor().length() > 0)
+      eannot.getDetails().put("vendor", aTypeSystem.getVendor());
+    firstPackage.getEAnnotations().add(eannot);
+  }
+
+  private static Resource loadUimaBuiltinsEcore(ResourceSet resourceSet, Map aSchemaLocationMap) {
+    // load Ecore model for UIMA built-in types (use classloader to locate)
+    URL uimaEcoreUrl = UimaTypeSystem2Ecore.class.getResource("/uima.ecore");
+    if (uimaEcoreUrl == null) {
+      throw new UIMARuntimeException(UIMARuntimeException.UIMA_ECORE_NOT_FOUND, new Object[0]);
+    }
+    Resource uimaEcoreResource = resourceSet.getResource(URI.createURI(uimaEcoreUrl.toString()),
+            true);
+    // register core UIMA packages (I'm surprised I need to do this manually)
+    TreeIterator iter = uimaEcoreResource.getAllContents();
+    while (iter.hasNext()) {
+      Object current = iter.next();
+      if (current instanceof EPackage) {
+        EPackage pkg = (EPackage) current;
+        EPackage.Registry.INSTANCE.put(pkg.getNsURI(), pkg);
+        if (aSchemaLocationMap != null) {
+          String schemaLoc = uimaEcoreResource.getURI() + "#"
+                  + uimaEcoreResource.getURIFragment(pkg);
+          aSchemaLocationMap.put(pkg.getNsURI(), schemaLoc);
+        }
+      }
+    }
+    return uimaEcoreResource;
+  }
+
+  private static EClassifier uimaType2EClassifier(TypeDescription aType, Map aOptions) {
+    // separate name into package name and class name
+    String fullTypeName = aType.getName();
+    String uimaNamespace, shortTypeName;
+    int lastDot = fullTypeName.lastIndexOf('.');
+    if (lastDot <= 0) {
+      uimaNamespace = null;
+      shortTypeName = fullTypeName;
+    } else {
+      uimaNamespace = fullTypeName.substring(0, lastDot);
+      shortTypeName = fullTypeName.substring(lastDot + 1);
+    }
+
+    // does EPackage already exist for this URI?
+    EPackage ePackage = uimaNamespace2EPackage(uimaNamespace);
+
+    EClassifier eclassifier;
+    // if aType is a "subtype" of uima.cas.String, create an EEnum for it
+    if (CAS.TYPE_NAME_STRING.equals(aType.getSupertypeName())) {
+      eclassifier = EcoreFactory.eINSTANCE.createEEnum();
+      AllowedValue[] vals = aType.getAllowedValues();
+      for (int i = 0; i < vals.length; i++) {
+        EEnumLiteral literal = EcoreFactory.eINSTANCE.createEEnumLiteral();
+        literal.setValue(i);
+        literal.setName(vals[i].getString());
+        if (vals[i].getDescription() != null && vals[i].getDescription().length() > 0) {
+          EAnnotation eannot = EcoreFactory.eINSTANCE.createEAnnotation();
+          eannot.setSource("http://uima.apache.org");
+          eannot.getDetails().put("description", vals[i].getDescription());
+          literal.getEAnnotations().add(eannot);
+        }
+        ((EEnum) eclassifier).getELiterals().add(literal);
+      }
+    } else {
+      // create EClass
+      eclassifier = EcoreFactory.eINSTANCE.createEClass();
+    }
+
+    // set name of EClassifier
+    eclassifier.setName(shortTypeName);
+    // add to package
+    ePackage.getEClassifiers().add(eclassifier);
+    // set description as EAnnotation
+    if (aType.getDescription() != null && aType.getDescription().length() > 0) {
+      EAnnotation eannot = EcoreFactory.eINSTANCE.createEAnnotation();
+      eannot.setSource("http://uima.apache.org");
+      eannot.getDetails().put("description", aType.getDescription());
+      eclassifier.getEAnnotations().add(eannot);
+    }
+    return eclassifier;
+  }
+
+  private static EStructuralFeature uimaFeature2EStructuralFeature(FeatureDescription aFeature,
+          Map aOptions) {
+    String range = aFeature.getRangeTypeName();
+    boolean multiRefAllowed = aFeature.getMultipleReferencesAllowed() == null ? false : aFeature
+            .getMultipleReferencesAllowed().booleanValue();
+    EStructuralFeature efeat;
+    // map primitive types to EAttributes
+    if (CAS.TYPE_NAME_STRING.equals(range)) {
+      efeat = EcoreFactory.eINSTANCE.createEAttribute();
+      efeat.setEType(EcorePackage.eINSTANCE.getEString());
+    } else if (CAS.TYPE_NAME_INTEGER.equals(range)) {
+      efeat = EcoreFactory.eINSTANCE.createEAttribute();
+      efeat.setEType(EcorePackage.eINSTANCE.getEInt());
+    } else if (CAS.TYPE_NAME_FLOAT.equals(range)) {
+      efeat = EcoreFactory.eINSTANCE.createEAttribute();
+      efeat.setEType(EcorePackage.eINSTANCE.getEFloat());
+    } else if (CAS.TYPE_NAME_BYTE.equals(range)) {
+      efeat = EcoreFactory.eINSTANCE.createEAttribute();
+      efeat.setEType(EcorePackage.eINSTANCE.getEByte());
+    } else if (CAS.TYPE_NAME_SHORT.equals(range)) {
+      efeat = EcoreFactory.eINSTANCE.createEAttribute();
+      efeat.setEType(EcorePackage.eINSTANCE.getEShort());
+    } else if (CAS.TYPE_NAME_LONG.equals(range)) {
+      efeat = EcoreFactory.eINSTANCE.createEAttribute();
+      efeat.setEType(EcorePackage.eINSTANCE.getELong());
+    } else if (CAS.TYPE_NAME_DOUBLE.equals(range)) {
+      efeat = EcoreFactory.eINSTANCE.createEAttribute();
+      efeat.setEType(EcorePackage.eINSTANCE.getEDouble());
+    } else if (CAS.TYPE_NAME_BOOLEAN.equals(range)) {
+      efeat = EcoreFactory.eINSTANCE.createEAttribute();
+      efeat.setEType(EcorePackage.eINSTANCE.getEBoolean());
+    }
+    // map arrays and lists to multivalued EAttributes if multiple references not allowed
+    else if ((CAS.TYPE_NAME_STRING_ARRAY.equals(range) || CAS.TYPE_NAME_STRING_LIST.equals(range))
+            && !multiRefAllowed) {
+      efeat = EcoreFactory.eINSTANCE.createEAttribute();
+      efeat.setEType(EcorePackage.eINSTANCE.getEString());
+      efeat.setUpperBound(-1);
+    } else if ((CAS.TYPE_NAME_INTEGER_ARRAY.equals(range) || CAS.TYPE_NAME_INTEGER_LIST
+            .equals(range))
+            && !multiRefAllowed) {
+      efeat = EcoreFactory.eINSTANCE.createEAttribute();
+      efeat.setEType(EcorePackage.eINSTANCE.getEInt());
+      efeat.setUpperBound(-1);
+    } else if ((CAS.TYPE_NAME_FLOAT_ARRAY.equals(range) || CAS.TYPE_NAME_FLOAT_LIST.equals(range))
+            && !multiRefAllowed) {
+      efeat = EcoreFactory.eINSTANCE.createEAttribute();
+      efeat.setEType(EcorePackage.eINSTANCE.getEFloat());
+      efeat.setUpperBound(-1);
+    } else if (CAS.TYPE_NAME_SHORT_ARRAY.equals(range) && !multiRefAllowed) {
+      efeat = EcoreFactory.eINSTANCE.createEAttribute();
+      efeat.setEType(EcorePackage.eINSTANCE.getEShort());
+      efeat.setUpperBound(-1);
+    } else if (CAS.TYPE_NAME_LONG_ARRAY.equals(range) && !multiRefAllowed) {
+      efeat = EcoreFactory.eINSTANCE.createEAttribute();
+      efeat.setEType(EcorePackage.eINSTANCE.getELong());
+      efeat.setUpperBound(-1);
+    } else if (CAS.TYPE_NAME_DOUBLE_ARRAY.equals(range) && !multiRefAllowed) {
+      efeat = EcoreFactory.eINSTANCE.createEAttribute();
+      efeat.setEType(EcorePackage.eINSTANCE.getEDouble());
+      efeat.setUpperBound(-1);
+    } else if (CAS.TYPE_NAME_BOOLEAN_ARRAY.equals(range) && !multiRefAllowed) {
+      efeat = EcoreFactory.eINSTANCE.createEAttribute();
+      efeat.setEType(EcorePackage.eINSTANCE.getEBoolean());
+      efeat.setUpperBound(-1);
+    }
+    // Ecore has a special type EByteArray that we use instead of a
+    // multi-valued EByte property. This gives a slightly more efficient
+    // serialization.
+    else if (CAS.TYPE_NAME_BYTE_ARRAY.equals(range) && !multiRefAllowed) {
+      efeat = EcoreFactory.eINSTANCE.createEAttribute();
+      efeat.setEType(EcorePackage.eINSTANCE.getEByteArray());
+    }
+    // FSArrays and FSLists map to multivalued references if multiple references not allowed
+    else if ((CAS.TYPE_NAME_FS_ARRAY.equals(range) || CAS.TYPE_NAME_FS_LIST.equals(range))
+            && !multiRefAllowed) {
+      efeat = EcoreFactory.eINSTANCE.createEReference();
+      String elementType = aFeature.getElementType();
+      if (elementType == null) {
+        elementType = CAS.TYPE_NAME_TOP;
+      }
+      efeat.setEType(lookupEClassifierForType(elementType));
+      efeat.setUpperBound(-1);
+    } else // non-primitive, non-array, non-list type.
+    // map to EAttribute if it's an EEnum, otherwise map to EReference
+    {
+      EClassifier etype = lookupEClassifierForType(range);
+      if (etype instanceof EEnum) {
+        efeat = EcoreFactory.eINSTANCE.createEAttribute();
+      } else {
+        efeat = EcoreFactory.eINSTANCE.createEReference();
+      }
+      efeat.setEType(etype);
+    }
+
+    efeat.setName(aFeature.getName());
+
+    // use EAnnotation to record:
+    // - the description of the feature
+    // - for multi-valued properties, the name of the UIMA type used to
+    // implement it (to distinguish between array and list)
+    // - for FSList or FSArray that are NOT represented by multi-valued
+    // properties, the element type
+    if ((aFeature.getDescription() != null && aFeature.getDescription().length() > 0)
+            || efeat.isMany() || aFeature.getElementType() != null) {
+      EAnnotation eannot = EcoreFactory.eINSTANCE.createEAnnotation();
+      eannot.setSource("http://uima.apache.org");
+      if (aFeature.getDescription() != null && aFeature.getDescription().length() > 0) {
+        eannot.getDetails().put("description", aFeature.getDescription());
+      }
+      if (efeat.isMany()) {
+        eannot.getDetails().put("uimaType", aFeature.getRangeTypeName());
+      }
+      if (!efeat.isMany() && aFeature.getElementType() != null) {
+        eannot.getDetails().put("elementType", aFeature.getElementType());
+      }
+      efeat.getEAnnotations().add(eannot);
+    }
+    return efeat;
+  }
+
+  private static EClassifier lookupEClassifierForType(String aFullTypeName) {
+    // separate name into package name and class name
+    String uimaNamespace, shortTypeName;
+    int lastDot = aFullTypeName.lastIndexOf('.');
+    if (lastDot <= 0) {
+      uimaNamespace = null;
+      shortTypeName = aFullTypeName;
+    } else {
+      uimaNamespace = aFullTypeName.substring(0, lastDot);
+      shortTypeName = aFullTypeName.substring(lastDot + 1);
+    }
+    String nsUri = uimaNamespace2NamespaceUri(uimaNamespace);
+
+    // does EPackage already exist for this URI?
+    EPackage ePackage = EPackage.Registry.INSTANCE.getEPackage(nsUri);
+    if (ePackage == null) {
+      return null;
+    }
+    return ePackage.getEClassifier(shortTypeName);
+  }
+
+  /**
+   * Gets or creates an EPackage for a UIMA namespace. Actually will create a whole chain of nested
+   * EPackages, one for each component of the UIMA namespace, but only the leaf node of the chain
+   * will be returned.
+   * 
+   * @param uimaNamespace
+   *          UIMA namespace
+   * @return EPackage corresponding to this namespace.
+   */
+  private static EPackage uimaNamespace2EPackage(String uimaNamespace) {
+    // convert UIMA namespace (dotted string) to namespace URI
+    String nsUri = uimaNamespace2NamespaceUri(uimaNamespace);
+    // see if package already exists for this URI
+    EPackage ePackage = EPackage.Registry.INSTANCE.getEPackage(nsUri);
+    if (ePackage == null) {
+      // package name is last component of namespace.
+      // all other components form the parent namespace
+      String parentNamespace = null;
+      String packageName;
+      if (uimaNamespace != null) {
+        int lastDot = uimaNamespace.lastIndexOf('.');
+        packageName = uimaNamespace.substring(lastDot + 1);
+        if (lastDot > 0) {
+          parentNamespace = uimaNamespace.substring(0, lastDot);
+        }
+      } else {
+        packageName = "noNamespace";
+      }
+
+      // create Package
+      ePackage = EcoreFactory.eINSTANCE.createEPackage();
+      ePackage.setNsURI(nsUri);
+      ePackage.setName(packageName);
+      EPackage.Registry.INSTANCE.put(nsUri, ePackage);
+
+      // get or create SuperPackage if any
+      if (parentNamespace != null) {
+        EPackage superPackage = uimaNamespace2EPackage(parentNamespace);
+        superPackage.getESubpackages().add(ePackage);
+      }
+    }
+    return ePackage;
+  }
+
+  private static String uimaNamespace2NamespaceUri(String uimaNamespace) {
+    if (uimaNamespace == null || uimaNamespace.length() == 0) {
+      return XmiCasSerializer.DEFAULT_NAMESPACE_URI;
+    }
+    // Our convention is that the Namespace URI is "http:///", followed by the UIMA namespace, with
+    // dots converted to slashes, and with ".ecore" appended. (This is EMF's convention for
+    // constructing a namespace URI from a Java package name.)
+    return "http:///" + uimaNamespace.replace('.', '/') + ".ecore";
+  }
+
+  /**
+   * Main program. Takes two arguments: the filename of an input TypeSystem descriptor file and the
+   * filename of the Ecore/XMI file to generate.
+   */
+  public static void main(String[] args) throws Exception {
+    // register default resource factory
+    Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("*",
+            new XMIResourceFactoryImpl());
+
+    ResourceSet resourceSet = new ResourceSetImpl();
+    URI outputURI = URI.createFileURI(args[1]);
+    Resource outputResource = resourceSet.createResource(outputURI);
+    Map options = new HashMap();
+    // options.put(OPTION_PRESERVE_UIMA_LIST_TYPES, Boolean.TRUE);
+    uimaTypeSystem2Ecore(args[0], outputResource, options);
+    outputResource.save(null);
+  }
+}

Propchange: incubator/uima/uimaj/trunk/uimaj-examples/src/main/java/org/apache/uima/examples/xmi/UimaTypeSystem2Ecore.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: incubator/uima/uimaj/trunk/uimaj-examples/src/main/java/org/apache/uima/examples/xmi/XmiEcoreCasConsumer.java
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-examples/src/main/java/org/apache/uima/examples/xmi/XmiEcoreCasConsumer.java?rev=771663&r1=771662&r2=771663&view=diff
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-examples/src/main/java/org/apache/uima/examples/xmi/XmiEcoreCasConsumer.java (original)
+++ incubator/uima/uimaj/trunk/uimaj-examples/src/main/java/org/apache/uima/examples/xmi/XmiEcoreCasConsumer.java Tue May  5 10:52:19 2009
@@ -33,7 +33,6 @@
 import org.apache.uima.cas.FSIterator;
 import org.apache.uima.cas.impl.XmiCasSerializer;
 import org.apache.uima.collection.CasConsumer_ImplBase;
-import org.apache.uima.ecore.UimaTypeSystem2Ecore;
 import org.apache.uima.examples.SourceDocumentInformation;
 import org.apache.uima.jcas.JCas;
 import org.apache.uima.resource.ResourceInitializationException;
@@ -82,6 +81,7 @@
 
   private Map schemaLocationMap = null;
 
+  @Override
   public void initialize() throws ResourceInitializationException {
     mDocNum = 0;
     mOutputDir = new File((String) getConfigParameterValue(PARAM_OUTPUTDIR));