| /* |
| * 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.tools.jcasgen; |
| |
| /* |
| * One Jg instance per use. --> GUI instance (if GUI used) which is a JFrame |
| */ |
| |
| import java.awt.event.WindowAdapter; |
| import java.awt.event.WindowEvent; |
| import java.io.File; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.net.MalformedURLException; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.net.URL; |
| import java.text.MessageFormat; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.MissingResourceException; |
| import java.util.Properties; |
| import java.util.ResourceBundle; |
| import java.util.Set; |
| import java.util.TreeMap; |
| import java.util.TreeSet; |
| |
| import javax.swing.UIManager; |
| |
| import org.apache.uima.UIMAFramework; |
| import org.apache.uima.analysis_engine.AnalysisEngineDescription; |
| import org.apache.uima.cas.BuiltinTypeKinds; |
| import org.apache.uima.cas.CAS; |
| import org.apache.uima.cas.Feature; |
| import org.apache.uima.cas.Type; |
| import org.apache.uima.cas.TypeSystem; |
| import org.apache.uima.cas.impl.CASImpl; |
| import org.apache.uima.cas.impl.TypeImpl; |
| import org.apache.uima.cas.impl.TypeImpl_string; |
| import org.apache.uima.cas.impl.TypeSystemImpl; |
| import org.apache.uima.resource.ResourceInitializationException; |
| import org.apache.uima.resource.ResourceManager; |
| 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.TypePriorities; |
| 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.apache.uima.util.XMLizable; |
| |
| |
| /** |
| * Class holds type plugin-wide collections and static methods. Also implements the runnable that is |
| * called to do the processing |
| */ |
| |
| public class Jg { |
| |
| /** |
| * Interface implemeted by JCAS code generation's templates. |
| */ |
| public interface IJCasTypeTemplate { |
| |
| /** |
| * Generate. |
| * |
| * @param argument the argument |
| * @return the string |
| */ |
| public String generate(Object argument); |
| } |
| |
| /** The Constant jControlModel. */ |
| static final String jControlModel = "jMergeCtl.xml"; |
| |
| /** The Constant featureDescriptionArray0. */ |
| static final FeatureDescription[] featureDescriptionArray0 = new FeatureDescription[0]; |
| |
| /** The Constant reservedFeatureNames. */ |
| static final Collection reservedFeatureNames = new ArrayList(); |
| { |
| |
| reservedFeatureNames.add("Address"); |
| reservedFeatureNames.add("CAS"); |
| reservedFeatureNames.add("CASImpl"); |
| reservedFeatureNames.add("Class"); |
| reservedFeatureNames.add("FeatureValue"); |
| reservedFeatureNames.add("FeatureValueAsString"); |
| reservedFeatureNames.add("FeatureValueFromString"); |
| reservedFeatureNames.add("FloatValue"); |
| reservedFeatureNames.add("IntValue"); |
| reservedFeatureNames.add("LowLevelCas"); |
| reservedFeatureNames.add("StringValue"); |
| reservedFeatureNames.add("Type"); |
| reservedFeatureNames.add("View"); |
| reservedFeatureNames.add("TypeIndexID"); |
| } |
| |
| /** |
| * Set of types not generated from the CAS type set because they're already in existence as |
| * builtins in the JCas impl. and if they're generated, the generated forms are wrong. |
| */ |
| static final Set noGenTypes = new HashSet(); |
| |
| /** The Constant casCreateProperties. */ |
| public static final Properties casCreateProperties = new Properties(); |
| static { |
| casCreateProperties.setProperty(UIMAFramework.CAS_INITIAL_HEAP_SIZE, "200"); |
| } |
| |
| /** The Constant extendableBuiltInTypes. */ |
| static final Map extendableBuiltInTypes = new HashMap(); |
| |
| // create a hash map of built-in types, where the |
| // key is the fully-qualified name "uima.tcas.Annotation" |
| // and the value is a Collection of FeatureDescription objects, |
| // representing the features. These will be merged with the |
| // specified features. Supertype features are not included. |
| |
| /** The Constant emptyFds. */ |
| static final FeatureDescription[] emptyFds = new FeatureDescription[0]; |
| |
| /** The built in type system. */ |
| static TypeSystem builtInTypeSystem; |
| |
| static { |
| CAS tcas = null; |
| try { |
| tcas = CasCreationUtils.createCas((TypeSystemDescription) null, null, |
| new FsIndexDescription[0], casCreateProperties); |
| |
| } catch (ResourceInitializationException e1) { |
| // never get here |
| } |
| |
| ((CASImpl) tcas).commitTypeSystem(); |
| builtInTypeSystem = ((CASImpl) tcas).getTypeSystemImpl(); // follow commit because commit may reuse existing type system |
| |
| for (Iterator it = builtInTypeSystem.getTypeIterator(); it.hasNext();) { |
| Type type = (Type) it.next(); |
| if (type.isFeatureFinal()) { |
| noGenTypes.add(type.getName()); |
| continue; // skip if feature final |
| } |
| String typeName = type.getName(); |
| List<Feature> fs = type.getFeatures(); |
| List<Feature> features = new ArrayList<Feature>(fs.size()); |
| // get list of features defined in this type excluding those defined in supertypes |
| for (int i = 0; i < fs.size(); i++) { |
| Feature f = fs.get(i); |
| String fName = f.getName(); |
| String fTypeName = fName.substring(0, fName.indexOf(':')); |
| if (typeName.equals(fTypeName)) |
| features.add(f); |
| } |
| FeatureDescription[] fds = new FeatureDescription[features.size()]; |
| for (int i = 0; i < features.size(); i++) { |
| FeatureDescription fd = UIMAFramework.getResourceSpecifierFactory() |
| .createFeatureDescription(); |
| Feature f = features.get(i); |
| fd.setName(f.getShortName()); |
| fd.setRangeTypeName(f.getRange().getName()); |
| fds[i] = fd; |
| } |
| extendableBuiltInTypes.put(typeName, fds); |
| } |
| } |
| |
| /** The built in types. */ |
| // table builtInTypes initialized inside TypeInfo constructor |
| static Map<String, TypeInfo> builtInTypes = new HashMap<>(); |
| |
| /** |
| * Adds the built in type info. |
| * |
| * @param casName the cas name |
| * @param javaName the java name |
| * @param casElementName the cas element name |
| */ |
| static private void addBuiltInTypeInfo(String casName, String javaName, String casElementName) { |
| TypeInfo ti = new TypeInfo(casName, javaName, casElementName); |
| builtInTypes.put(casName, ti); |
| } |
| |
| /** |
| * Adds the built in type info. |
| * |
| * @param casName the cas name |
| * @param javaName the java name |
| */ |
| static private void addBuiltInTypeInfo(String casName, String javaName) { |
| addBuiltInTypeInfo(casName, javaName, null); |
| } |
| |
| // first type needed by fsArrayType; in hash map will be overwritten, though |
| static { |
| // addBuiltInTypeInfo("uima.cas.TOP", "org.apache.uima.cas.FeatureStructure"); // overridden below |
| addBuiltInTypeInfo("uima.cas.Integer", "int"); |
| addBuiltInTypeInfo("uima.cas.Float", "float"); |
| addBuiltInTypeInfo("uima.cas.String", "String"); |
| addBuiltInTypeInfo("uima.cas.Byte", "byte"); |
| addBuiltInTypeInfo("uima.cas.Short", "short"); |
| addBuiltInTypeInfo("uima.cas.Long", "long"); |
| addBuiltInTypeInfo("uima.cas.Double", "double"); |
| addBuiltInTypeInfo("uima.cas.Boolean", "boolean"); |
| |
| addBuiltInTypeInfo("uima.cas.TOP", "org.apache.uima.jcas.cas.TOP"); |
| addBuiltInTypeInfo("uima.cas.FSArray", "org.apache.uima.jcas.cas.FSArray", "uima.cas.TOP"); |
| addBuiltInTypeInfo("uima.cas.IntegerArray", "org.apache.uima.jcas.cas.IntegerArray", |
| "uima.cas.Integer"); |
| addBuiltInTypeInfo("uima.cas.FloatArray", "org.apache.uima.jcas.cas.FloatArray", |
| "uima.cas.Float"); |
| addBuiltInTypeInfo("uima.cas.StringArray", "org.apache.uima.jcas.cas.StringArray", |
| "uima.cas.String"); |
| addBuiltInTypeInfo("uima.cas.BooleanArray", "org.apache.uima.jcas.cas.BooleanArray", |
| "uima.cas.Boolean"); |
| addBuiltInTypeInfo("uima.cas.ByteArray", "org.apache.uima.jcas.cas.ByteArray", "uima.cas.Byte"); |
| addBuiltInTypeInfo("uima.cas.ShortArray", "org.apache.uima.jcas.cas.ShortArray", |
| "uima.cas.Short"); |
| addBuiltInTypeInfo("uima.cas.LongArray", "org.apache.uima.jcas.cas.LongArray", "uima.cas.Long"); |
| addBuiltInTypeInfo("uima.cas.DoubleArray", "org.apache.uima.jcas.cas.DoubleArray", |
| "uima.cas.Double"); |
| addBuiltInTypeInfo("uima.cas.AnnotationBase", "org.apache.uima.jcas.cas.AnnotationBase"); |
| addBuiltInTypeInfo("uima.tcas.Annotation", "org.apache.uima.jcas.tcas.Annotation"); |
| addBuiltInTypeInfo("uima.tcas.DocumentAnnotation", |
| "org.apache.uima.jcas.tcas.DocumentAnnotation"); |
| addBuiltInTypeInfo("uima.cas.EmptyFloatList", "org.apache.uima.jcas.cas.EmptyFloatList"); |
| addBuiltInTypeInfo("uima.cas.EmptyFSList", "org.apache.uima.jcas.cas.EmptyFSList"); |
| addBuiltInTypeInfo("uima.cas.EmptyIntegerList", "org.apache.uima.jcas.cas.EmptyIntegerList"); |
| addBuiltInTypeInfo("uima.cas.EmptyStringList", "org.apache.uima.jcas.cas.EmptyStringList"); |
| addBuiltInTypeInfo("uima.cas.FloatList", "org.apache.uima.jcas.cas.FloatList"); |
| addBuiltInTypeInfo("uima.cas.FSList", "org.apache.uima.jcas.cas.FSList"); |
| addBuiltInTypeInfo("uima.cas.IntegerList", "org.apache.uima.jcas.cas.IntegerList"); |
| addBuiltInTypeInfo("uima.cas.StringList", "org.apache.uima.jcas.cas.StringList"); |
| addBuiltInTypeInfo("uima.cas.NonEmptyFloatList", "org.apache.uima.jcas.cas.NonEmptyFloatList"); |
| addBuiltInTypeInfo("uima.cas.NonEmptyFSList", "org.apache.uima.jcas.cas.NonEmptyFSList"); |
| addBuiltInTypeInfo("uima.cas.NonEmptyIntegerList", |
| "org.apache.uima.jcas.cas.NonEmptyIntegerList"); |
| addBuiltInTypeInfo("uima.cas.NonEmptyStringList", "org.apache.uima.jcas.cas.NonEmptyStringList"); |
| addBuiltInTypeInfo("uima.cas.Sofa", "org.apache.uima.jcas.cas.Sofa"); |
| // not built-in |
| // addBuiltInTypeInfo("uima.cas.IntegerArrayList", "org.apache.uima.jcas.cas.IntegerArrayList"); |
| // addBuiltInTypeInfo("uima.cas.FSArrayList", "org.apache.uima.jcas.cas.FSArrayList"); |
| // addBuiltInTypeInfo("uima.cas.FSHashSet", "org.apache.uima.jcas.cas.FSHashSet"); |
| } |
| |
| /** The resource bundle. */ |
| // Resource bundle. |
| private static ResourceBundle resourceBundle; |
| static { |
| try { |
| resourceBundle = ResourceBundle |
| .getBundle("org.apache.uima.tools.jcasgen.jcasgenpPluginResources"); |
| } catch (MissingResourceException x) { |
| resourceBundle = null; |
| } |
| } |
| |
| /** The imports. */ |
| // Instance fields |
| final Map imports = new HashMap(); // can't be final - one per instance running |
| |
| /** The imports. */ |
| final Map _imports = new HashMap(); |
| |
| /** The class path. */ |
| String classPath = ""; |
| |
| /** The xml source file name. */ |
| String xmlSourceFileName; |
| |
| /** The cas. */ |
| CAS cas; |
| |
| /** The gui. */ |
| GUI gui; |
| |
| /** The merger. */ |
| IMerge merger; |
| |
| /** The progress monitor. */ |
| IProgressMonitor progressMonitor; |
| |
| /** The error. */ |
| public IError error; // referenced by the plugin |
| |
| /** The waiter. */ |
| Waiter waiter; |
| |
| /** The package name. */ |
| String packageName; |
| |
| /** The simple class name. */ |
| String simpleClassName; |
| |
| /** The type system. */ |
| private TypeSystem typeSystem = null; |
| |
| /** The cas string type. */ |
| private Type casStringType; |
| |
| /** The tcas annotation type. */ |
| private Type tcasAnnotationType; |
| |
| /** The merged types adding features. */ |
| private Map<String, Set<String>> mergedTypesAddingFeatures = new TreeMap<String, Set<String>>(); // a Map of types and the xml files that were merged to create them |
| |
| /** The project path dir. */ |
| private String projectPathDir; |
| |
| /** The limit J cas gen to project scope. */ |
| private boolean limitJCasGenToProjectScope; |
| |
| /** |
| * Instantiates a new jg. |
| */ |
| public Jg() { // default constructor |
| } |
| |
| /** |
| * Returns the string from the plugin's resource bundle, or 'key' if not found. |
| * |
| * @param key the key |
| * @return the resource string |
| */ |
| public String getResourceString(String key) { |
| ResourceBundle bundle = getResourceBundle(); |
| try { |
| return bundle.getString(key); |
| } catch (MissingResourceException e) { |
| return key; |
| } |
| } |
| |
| /** |
| * Gets the string. |
| * |
| * @param key the key |
| * @param substitutions the substitutions |
| * @return the string |
| */ |
| public String getString(String key, Object[] substitutions) { |
| return MessageFormat.format(getResourceString(key), substitutions); |
| } |
| |
| /** |
| * Returns the plugin's resource bundle,. |
| * |
| * @return the resource bundle |
| */ |
| public ResourceBundle getResourceBundle() { |
| return resourceBundle; |
| } |
| |
| /** |
| * The Class ErrorExit. |
| */ |
| public static class ErrorExit extends RuntimeException { |
| |
| /** The Constant serialVersionUID. */ |
| private static final long serialVersionUID = -3314235749649859540L; |
| } |
| |
| // ************ |
| // * driveGui * |
| /** |
| * Drive gui. |
| */ |
| // ************ |
| public void driveGui() { |
| // usingGui = true; |
| try { |
| UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); |
| } catch (Exception e) { |
| System.err.println("Could not set look and feel: " + e.getMessage()); |
| } |
| |
| gui = new GUI(this); |
| gui.addWindowListener(new WindowAdapter() { |
| @Override |
| public void windowClosing(WindowEvent e) { |
| Prefs.set(gui); |
| waiter.finished(); |
| } |
| }); |
| Prefs.get(gui); |
| gui.pnG.taStatus.setLineWrap(true); |
| gui.pnG.taStatus.setWrapStyleWord(true); |
| gui.show(); |
| waiter = new Waiter(); |
| waiter.waitforGUI(); |
| } |
| |
| /** |
| * The main method. |
| * |
| * @param args the arguments |
| */ |
| // exits with -1 if failure |
| public static void main(String[] args) { |
| int rc = (new Jg()).main0(args, null, null, new LogThrowErrorImpl()); |
| System.exit(rc); |
| } |
| |
| /** |
| * Main for cde. |
| * |
| * @param aMerger the a merger |
| * @param aProgressMonitor the a progress monitor |
| * @param aError the a error |
| * @param inputFile the input file |
| * @param outputDirectory the output directory |
| * @param tds the tds |
| * @param aCas the a cas |
| * @throws IOException Signals that an I/O exception has occurred. |
| */ |
| public void mainForCde(IMerge aMerger, IProgressMonitor aProgressMonitor, IError aError, |
| String inputFile, String outputDirectory, TypeDescription[] tds, CASImpl aCas) |
| throws IOException { |
| mainForCde(aMerger, aProgressMonitor, aError, |
| inputFile, outputDirectory, tds, aCas, "", false, null); |
| } |
| |
| /** |
| * Main for cde. |
| * |
| * @param aMerger the a merger |
| * @param aProgressMonitor the a progress monitor |
| * @param aError the a error |
| * @param inputFile the input file |
| * @param outputDirectory the output directory |
| * @param tds the tds |
| * @param aCas the a cas |
| * @param projectPathDir the project path dir |
| * @param limitJCasGenToProjectScope the limit J cas gen to project scope |
| * @param mergedTypesAddingFeatures the merged types adding features |
| * @throws IOException Signals that an I/O exception has occurred. |
| */ |
| public void mainForCde(IMerge aMerger, IProgressMonitor aProgressMonitor, IError aError, |
| String inputFile, String outputDirectory, TypeDescription[] tds, CASImpl aCas, |
| String projectPathDir, boolean limitJCasGenToProjectScope, |
| Map<String, Set<String>> mergedTypesAddingFeatures) |
| throws IOException { |
| try { |
| // Generate type classes by using DEFAULT templates |
| mainGenerateAllTypesFromTemplates(aMerger, aProgressMonitor, aError, inputFile, |
| outputDirectory, tds, aCas, JCasTypeTemplate.class, |
| projectPathDir, limitJCasGenToProjectScope, mergedTypesAddingFeatures); |
| // convert thrown things to IOExceptions to avoid changing API for this |
| // FIXME later |
| } catch (InstantiationException e) { |
| throw new IOException(e.toString()); |
| } catch (IllegalAccessException e) { |
| throw new IOException(e.toString()); |
| } |
| } |
| |
| /** |
| * Main generate all types from templates. |
| * |
| * @param aMerger the a merger |
| * @param aProgressMonitor the a progress monitor |
| * @param aError the a error |
| * @param inputFile the input file |
| * @param outputDirectory the output directory |
| * @param tds the tds |
| * @param aCas the a cas |
| * @param jcasTypeClass the jcas type class |
| * @param jcas_TypeClass the jcas type class |
| * @throws IOException Signals that an I/O exception has occurred. |
| * @throws InstantiationException the instantiation exception |
| * @throws IllegalAccessException the illegal access exception |
| */ |
| // use template classes to generate code |
| public void mainGenerateAllTypesFromTemplates(IMerge aMerger, IProgressMonitor aProgressMonitor, |
| IError aError, String inputFile, String outputDirectory, TypeDescription[] tds, |
| CASImpl aCas, Class jcasTypeClass, // Template class |
| Class jcas_TypeClass) // Template class |
| throws IOException, InstantiationException, IllegalAccessException { |
| mainGenerateAllTypesFromTemplates(aMerger, aProgressMonitor, |
| aError, inputFile, outputDirectory, tds, aCas, |
| jcasTypeClass, "", false, null); |
| } |
| |
| /** |
| * Main generate all types from templates. |
| * |
| * @param aMerger the a merger |
| * @param aProgressMonitor the a progress monitor |
| * @param aError the a error |
| * @param inputFile the input file |
| * @param outputDirectory the output directory |
| * @param tds the tds |
| * @param aCas the a cas |
| * @param jcasTypeClass the jcas type class |
| * @param projectPathDir the project path dir |
| * @param limitJCasGenToProjectScope the limit J cas gen to project scope |
| * @param mergedTypesAddingFeatures the merged types adding features |
| * @throws IOException Signals that an I/O exception has occurred. |
| * @throws InstantiationException the instantiation exception |
| * @throws IllegalAccessException the illegal access exception |
| */ |
| public void mainGenerateAllTypesFromTemplates(IMerge aMerger, IProgressMonitor aProgressMonitor, |
| IError aError, String inputFile, String outputDirectory, TypeDescription[] tds, |
| CASImpl aCas, Class jcasTypeClass, // Template class |
| String projectPathDir, boolean limitJCasGenToProjectScope, |
| Map<String, Set<String>> mergedTypesAddingFeatures) // Template class |
| throws IOException, InstantiationException, IllegalAccessException { |
| this.merger = aMerger; |
| this.error = aError; |
| this.progressMonitor = aProgressMonitor; |
| xmlSourceFileName = inputFile.replaceAll("\\\\", "/"); |
| this.projectPathDir = projectPathDir; |
| this.limitJCasGenToProjectScope = limitJCasGenToProjectScope; |
| this.mergedTypesAddingFeatures = mergedTypesAddingFeatures; |
| |
| // Generate type classes by using SPECIFIED templates |
| generateAllTypesFromTemplates(outputDirectory, tds, aCas, jcasTypeClass); |
| } |
| |
| /** |
| * Main 0. |
| * |
| * @param args the args |
| * @param aMerger the a merger |
| * @param aProgressMonitor the a progress monitor |
| * @param aError the a error |
| * @return the int |
| */ |
| public int main0(String[] args, IMerge aMerger, IProgressMonitor aProgressMonitor, IError aError) { |
| this.merger = aMerger; |
| this.error = aError; |
| this.progressMonitor = aProgressMonitor; |
| boolean foundInput = false; |
| for (int i = 0; i < args.length; i++) { |
| if (args[i].equals("-jcasgeninput")) { |
| if (i == args.length - 1) { |
| driveGui(); |
| return 0; |
| } else { |
| foundInput = true; |
| break; |
| } |
| } |
| } |
| if (foundInput) |
| return main1(args); |
| else { |
| driveGui(); |
| return 0; |
| } |
| } |
| |
| /** |
| * Arguments are: |
| * -jcasgeninput xxxx |
| * -jcasgenoutput xxxx |
| * -jcasgenclasspath xxxx |
| * |
| * |
| * @param arguments the arguments |
| * @return the int |
| */ |
| public int main1(String[] arguments) { |
| boolean hadError = false; |
| try { |
| try { |
| if (null == progressMonitor) { |
| progressMonitor = new UimaLoggerProgressMonitor(); |
| } |
| if (null == error) |
| error = new LogThrowErrorImpl(); |
| |
| String inputFile = null; |
| String outputDirectory = null; |
| |
| TypeSystemDescription typeSystemDescription = null; |
| TypeDescription[] tds = null; |
| |
| projectPathDir = ""; // init to default value |
| limitJCasGenToProjectScope = false; |
| |
| for (int i = 0; i < arguments.length - 1; i++) { |
| if (arguments[i].equalsIgnoreCase("-jcasgeninput")) { |
| inputFile = arguments[++i]; |
| continue; |
| } |
| if (arguments[i].equalsIgnoreCase("-jcasgenoutput")) { |
| outputDirectory = arguments[++i]; |
| continue; |
| } |
| // This is used by the jcasgen maven plugin |
| if (arguments[i].equalsIgnoreCase("=jcasgenclasspath") || // https://issues.apache.org/jira/browse/UIMA-3044 |
| arguments[i].equalsIgnoreCase("-jcasgenclasspath")) { // https://issues.apache.org/jira/browse/UIMA-3044 |
| classPath = arguments[++i]; |
| continue; |
| } |
| if (arguments[i].equalsIgnoreCase("-limitToDirectory")) { |
| projectPathDir = arguments[++i]; |
| limitJCasGenToProjectScope = (projectPathDir.length() > 0); |
| continue; |
| } |
| } |
| |
| xmlSourceFileName = inputFile.replaceAll("\\\\", "/"); |
| URL url; |
| if(inputFile.substring(0, 4).equalsIgnoreCase("jar:")) { |
| // https://issues.apache.org/jira/browse/UIMA-1793 get things out of Jars |
| try { |
| url = new URL(inputFile); |
| // if (null == url) { // is never null from above line |
| // error.newError(IError.ERROR, getString("fileNotFound", new Object[] { inputFile }), null); |
| // } |
| if(null == outputDirectory || outputDirectory.equals("")) { |
| error.newError(IError.ERROR, getString("sourceArgNeedsDirectory", new Object[] { inputFile }), null); |
| } |
| } catch (MalformedURLException e) { |
| error.newError(IError.ERROR, getString("fileNotFound", new Object[] { inputFile }), null); |
| url = null; // never get here, the previous statement throws. Needed, though for java path analysis. |
| } |
| } else { |
| File file = new File(inputFile); |
| if (!file.exists()) { |
| error.newError(IError.ERROR, getString("fileNotFound", new Object[] { inputFile }), null); |
| } |
| if (null == outputDirectory || outputDirectory.equals("")) { |
| File dir = file.getParentFile(); |
| if (null == dir) { |
| error.newError(IError.ERROR, getString("sourceArgNeedsDirectory", |
| new Object[] { inputFile }), null); |
| } |
| outputDirectory = dir.getPath() + File.separator + "JCas" |
| + ((null != merger) ? "" : "New"); |
| } |
| url = file.toURI().toURL(); |
| } |
| |
| progressMonitor.beginTask("", 5); |
| progressMonitor.subTask("Output going to '" + outputDirectory + "'"); |
| progressMonitor.subTask(getString("ReadingDescriptorAndCreatingTypes", |
| new Object[] { inputFile })); |
| // code to read xml and make cas type instance |
| CASImpl casLocal = null; |
| // handle classpath |
| try { |
| XMLInputSource in = new XMLInputSource(url); |
| XMLizable specifier = UIMAFramework.getXMLParser().parse(in); |
| |
| mergedTypesAddingFeatures.clear(); |
| if (specifier instanceof AnalysisEngineDescription) { |
| AnalysisEngineDescription aeSpecifier = (AnalysisEngineDescription) specifier; |
| if (!aeSpecifier.isPrimitive()) |
| typeSystemDescription = CasCreationUtils.mergeDelegateAnalysisEngineTypeSystems( |
| aeSpecifier, createResourceManager(), mergedTypesAddingFeatures); |
| else |
| typeSystemDescription = mergeTypeSystemImports(aeSpecifier |
| .getAnalysisEngineMetaData().getTypeSystem()); |
| |
| } else if (specifier instanceof TypeSystemDescription) |
| typeSystemDescription = mergeTypeSystemImports(((TypeSystemDescription) specifier)); |
| else { |
| error.newError(IError.ERROR, getString("fileDoesntParse", new Object[] { inputFile }), |
| null); |
| } |
| if (mergedTypesAddingFeatures.size() > 0) { |
| error.newError(IError.WARN, getString("typesHaveFeaturesAdded", |
| new Object[] { makeMergeMessage(mergedTypesAddingFeatures) }), null); |
| } |
| TypePriorities typePriorities = null; |
| FsIndexDescription[] fsIndexDescription = null; |
| try { |
| |
| // no ResourceManager, since everything has been |
| // imported/merged by previous actions |
| casLocal = (CASImpl) CasCreationUtils.createCas(typeSystemDescription, typePriorities, |
| fsIndexDescription); |
| } catch (ResourceInitializationException e) { |
| error.newError(IError.WARN, getString("resourceInitializationException", |
| new Object[] { e.getLocalizedMessage() }), e); |
| casLocal = null; // continue with null cas, anyway |
| } |
| |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } catch (InvalidXMLException e) { |
| error.newError(IError.ERROR, getString("invalidXML", new Object[] { inputFile }), e); |
| } catch (ResourceInitializationException e) { |
| error.newError(IError.ERROR, getString("resourceInitializationExceptionError", |
| new Object[] {}), e); |
| } |
| |
| progressMonitor.worked(1); |
| tds = typeSystemDescription.getTypes(); |
| |
| // Generate type classes from DEFAULT templates |
| generateAllTypesFromTemplates(outputDirectory, tds, casLocal, JCasTypeTemplate.class); |
| |
| } catch (IOException e) { |
| error.newError(IError.ERROR, getString("IOException", new Object[] {}), e); |
| } catch (ErrorExit e) { |
| hadError = true; |
| } catch (InstantiationException e) { |
| error.newError(IError.ERROR, getString("InstantiationException", new Object[] {}), e); |
| } catch (IllegalAccessException e) { |
| error.newError(IError.ERROR, getString("IllegalAccessException", new Object[] {}), e); |
| } |
| } finally { |
| progressMonitor.done(); |
| } |
| return (hadError) ? -1 : 0; |
| } |
| |
| /** |
| * Make merge message. |
| * |
| * @param m the m |
| * @return the string |
| */ |
| // message: TypeName = ".....", URLs defining this type = "xxxx", "xxxx", .... |
| private String makeMergeMessage(Map m) { |
| StringBuffer sb = new StringBuffer(); |
| for (Iterator it = m.entrySet().iterator(); it.hasNext();) { |
| Map.Entry entry = (Map.Entry) it.next(); |
| String typeName = (String) entry.getKey(); |
| sb.append("\n "); |
| sb.append("TypeName having merged features = ").append(typeName).append( |
| "\n URLs defining this type ="); |
| Set urls = (Set) entry.getValue(); |
| boolean afterFirst = false; |
| for (Iterator itUrls = urls.iterator(); itUrls.hasNext();) { |
| if (afterFirst) |
| sb.append(",\n "); |
| else |
| sb.append("\n "); |
| afterFirst = true; |
| String url = (String) itUrls.next(); |
| sb.append('"').append(url).append('"'); |
| } |
| } |
| return sb.toString(); |
| } |
| |
| /** |
| * Generate all types from templates. |
| * |
| * @param outputDirectory the output directory |
| * @param tds the tds |
| * @param aCas the a cas |
| * @param jcasTypeClass the jcas type class |
| * @throws IOException Signals that an I/O exception has occurred. |
| * @throws InstantiationException the instantiation exception |
| * @throws IllegalAccessException the illegal access exception |
| */ |
| // This is also the interface for CDE |
| private void generateAllTypesFromTemplates(String outputDirectory, TypeDescription[] tds, |
| CASImpl aCas, Class jcasTypeClass) throws IOException, |
| InstantiationException, IllegalAccessException { |
| |
| // Create instances of Template classes |
| IJCasTypeTemplate jcasTypeInstance = (IJCasTypeTemplate) jcasTypeClass.newInstance(); |
| |
| Set generatedBuiltInTypes = new TreeSet(); |
| |
| this.cas = aCas; |
| this.typeSystem = cas.getTypeSystem(); |
| this.casStringType = typeSystem.getType(CAS.TYPE_NAME_STRING); |
| this.tcasAnnotationType = typeSystem.getType(CAS.TYPE_NAME_ANNOTATION); |
| |
| for (int i = 0; i < tds.length; i++) { |
| TypeDescription td = tds[i]; |
| // System.out.println("Description: " + td.getDescription() ); |
| if (noGenTypes.contains(td.getName())) |
| continue; |
| if (td.getSupertypeName().equals("uima.cas.String")) |
| continue; |
| if (limitJCasGenToProjectScope && |
| isOutOfScope(td, projectPathDir)) { |
| Set<String> mt = mergedTypesAddingFeatures.get(td.getName()); |
| if (null == mt) { |
| continue; |
| } |
| StringBuilder sb = new StringBuilder("\n"); |
| for (String p : mt) { |
| sb.append(" ").append(p).append('\n'); |
| } |
| error.newError(IError.ERROR, getString("limitingButTypeWasExtended", new Object[] { td.getName(), sb.toString()}), null); |
| continue; |
| } |
| |
| // if the type is built-in - augment it with the built-in's features |
| FeatureDescription[] builtInFeatures = (FeatureDescription[]) extendableBuiltInTypes.get(td |
| .getName()); |
| if (null != builtInFeatures) { |
| generatedBuiltInTypes.add(td.getName()); |
| List newFeatures = setDifference(td.getFeatures(), builtInFeatures); |
| int newFeaturesSize = newFeatures.size(); |
| if (newFeaturesSize > 0) { |
| int newSize = builtInFeatures.length + newFeaturesSize; |
| FeatureDescription[] newFds = new FeatureDescription[newSize]; |
| System.arraycopy(builtInFeatures, 0, newFds, 0, builtInFeatures.length); |
| for (int j = builtInFeatures.length, k = 0; k < newFeaturesSize; j++, k++) |
| newFds[j] = (FeatureDescription) newFeatures.get(k); |
| td.setFeatures(newFds); |
| } else { |
| // The only built-in type which is extensible is DocumentAnnotation. |
| // If we get here, the user defined DocumentAnnotation, but did not add any features |
| // In this case, skip generation |
| continue; |
| } |
| } |
| generateClassesFromTemplate(td, outputDirectory, jcasTypeInstance); |
| } |
| |
| /* |
| * This code was supposed to generate extendable built-in types that were not |
| * extended by the input types |
| * But the only extendable built-in type is DocumentAnnotation, and it should |
| * not be generated by default - there's one provided by the framework. |
| * |
| for (Iterator it = extendableBuiltInTypes.entrySet().iterator(); it.hasNext();) { |
| Map.Entry entry = (Map.Entry) it.next(); |
| String typeName = (String) entry.getKey(); |
| if (noGenTypes.contains(typeName) || generatedBuiltInTypes.contains(typeName)) |
| continue; |
| TypeDescription td = createTdFromType(typeName); |
| generateClasses(td, outputDirectory); |
| } |
| */ |
| } |
| |
| /* This code was only called by above commented out section |
| private TypeDescription createTdFromType(String typeName) { |
| TypeDescription td = UIMAFramework.getResourceSpecifierFactory().createTypeDescription(); |
| Type type = builtInTypeSystem.getType(typeName); |
| td.setName(typeName); |
| td.setSupertypeName(builtInTypeSystem.getParent(type).getName()); |
| |
| ArrayList featuresOfType = new ArrayList(); |
| final List vFeatures = type.getFeatures(); |
| for (int i = 0; i < vFeatures.size(); i++) { |
| Feature f = (Feature) vFeatures.get(i); |
| if (f.getDomain().equals(type)) { |
| FeatureDescription fd = UIMAFramework.getResourceSpecifierFactory() |
| .createFeatureDescription(); |
| fd.setName(f.getShortName()); |
| fd.setRangeTypeName(f.getRange().getName()); |
| featuresOfType.add(fd); |
| } |
| } |
| td.setFeatures((FeatureDescription[]) featuresOfType |
| .toArray(new FeatureDescription[featuresOfType.size()])); |
| return td; |
| } |
| */ |
| |
| /** |
| * return true if td is not defined in this project, of |
| * it is defined, but is also in merged and any of the other |
| * merged urls are not defined in this project. |
| * |
| * @param td the td |
| * @param projectDirPath the project dir path |
| * @return true, if is out of scope |
| */ |
| private boolean isOutOfScope(TypeDescription td, String projectDirPath) { |
| URI typeDefinitionUri; |
| try { |
| typeDefinitionUri = new URI (td.getSourceUrlString()); |
| } catch (URISyntaxException e) { |
| return true; // may be overkill - but if td's source can't be parsed ... likely out of project |
| } |
| String tdPath = typeDefinitionUri.getPath(); |
| |
| // Issue UIMA-4080 - If a type system resides in a JAR, then the path is null and it is |
| // certainly out of scope. |
| if (tdPath == null) { |
| return true; |
| } |
| |
| // UIMA-4119 - On windows, the default path representation and the URI path representation |
| // differ: "/C:/..." vs. "C:\...". If the projectDirPath does not start with a /, we can be sure |
| // that it is not an absolute path in URI notation, so we try to resolve it. |
| // In this way, we can handle clients that use the URI notation (e.g. the Eclipse plugin) |
| // as well as clients that use file-system notation (e.g. jcasgen-maven-plugin or a simple |
| // invocation from the command line. |
| String resolvedProjectPath; |
| if (!projectDirPath.startsWith("/")) { |
| resolvedProjectPath = new File(projectDirPath).getAbsoluteFile().toURI().getPath(); |
| } |
| else { |
| resolvedProjectPath = projectDirPath; |
| } |
| |
| // UIMA-4131 - Make sure that paths end in a slash so that "/my/project1" is not considered |
| // to be in the scope of "/my/project" |
| if (!tdPath.endsWith("/")) { |
| tdPath += "/"; |
| } |
| |
| if (!resolvedProjectPath.endsWith("/")) { |
| resolvedProjectPath += "/"; |
| } |
| |
| boolean r = !tdPath.startsWith(resolvedProjectPath); |
| if (r) { |
| return true; |
| } |
| Set<String> mergedPaths = mergedTypesAddingFeatures.get(td.getName()); |
| if (null != mergedPaths) { |
| for (String p : mergedPaths) { |
| URI tempURI; |
| try { |
| tempURI = new URI(p); |
| } catch (URISyntaxException e) { |
| return true; //because a merged path is out of the project |
| } |
| String tempPath = tempURI.getPath(); |
| if (!tempPath.startsWith(resolvedProjectPath)) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Generate type classes from the specified templates. |
| * |
| * @param td TypeDescription object |
| * @param outputDirectory output directory |
| * @param jcasTypeInstance Template instance used to generate class |
| * @return void |
| * @throws IOException - |
| */ |
| private void generateClassesFromTemplate(TypeDescription td, String outputDirectory, |
| IJCasTypeTemplate jcasTypeInstance) |
| throws IOException { |
| simpleClassName = removePkg(getJavaName(td)); |
| generateClass(progressMonitor, outputDirectory, td, jcasTypeInstance.generate(new Object[] { |
| this, td }), getJavaName(td), merger); |
| // simpleClassName = removePkg(getJavaName_Type(td)); |
| // generateClass(progressMonitor, outputDirectory, td, jcas_TypeInstance.generate(new Object[] { |
| // this, td }), getJavaName_Type(td), merger); |
| } |
| |
| /** |
| * Gets the pkg. |
| * |
| * @param td the td |
| * @return the pkg |
| */ |
| String getPkg(TypeDescription td) { |
| return getPkg(td.getName()); |
| } |
| |
| /** |
| * Gets the pkg. |
| * |
| * @param nameWithPkg the name with pkg |
| * @return the pkg |
| */ |
| String getPkg(String nameWithPkg) { |
| int lastDot = nameWithPkg.lastIndexOf('.'); |
| if (lastDot >= 0) |
| return nameWithPkg.substring(0, lastDot); |
| return ""; |
| } |
| |
| /** |
| * Generate class. |
| * |
| * @param progressMonitorGenerateClass the progress monitor generate class |
| * @param outputDirectory the output directory |
| * @param td the td |
| * @param sourceContents the source contents |
| * @param className the class name |
| * @param mergerGenerateClass the merger generate class |
| * @throws IOException Signals that an I/O exception has occurred. |
| */ |
| private void generateClass(IProgressMonitor progressMonitorGenerateClass, String outputDirectory, |
| TypeDescription td, String sourceContents, String className, IMerge mergerGenerateClass) |
| throws IOException { |
| |
| String pkgName = getJavaPkg(td); |
| String qualifiedClassName = (0 != pkgName.length()) ? pkgName + "." + className : className; |
| String targetContainer = outputDirectory + '/' + pkgName.replace('.', '/'); |
| String targetPath = targetContainer + "/" + className + ".java"; |
| File targetFile = new File(targetPath); |
| |
| if (null != mergerGenerateClass) { |
| mergerGenerateClass.doMerge(this, progressMonitorGenerateClass, sourceContents, |
| targetContainer, targetPath, qualifiedClassName, targetFile); |
| } else { |
| if (targetFile.exists()) { |
| progressMonitorGenerateClass.subTask(getString("replacingTarget", |
| new Object[] { qualifiedClassName })); |
| } else |
| progressMonitorGenerateClass.subTask(getString("creatingTarget", |
| new Object[] { qualifiedClassName })); |
| (new File(targetContainer)).mkdirs(); |
| FileWriter fw = new FileWriter(targetPath); |
| try { |
| fw.write(sourceContents); |
| } finally { |
| fw.close(); |
| } |
| } |
| } |
| |
| /** |
| * Removes the pkg. |
| * |
| * @param name the name |
| * @return the string |
| */ |
| public static String removePkg(String name) { |
| int lastDot = name.lastIndexOf('.'); |
| String simpleName = name; |
| if (lastDot >= 0) |
| simpleName = name.substring(lastDot + 1); |
| return simpleName; |
| } |
| |
| // ************************************************** |
| // * sc (jTname) = return word that * |
| // * goes into generated Cas get/set * |
| // ************************************************** |
| |
| /** |
| * Sc. |
| * |
| * @param v the v |
| * @return the string |
| */ |
| String sc(String v) { |
| // return part of word that goes in calls like get<insert>Value |
| // input is Java type spec |
| if (v.equals("int")) |
| return "Int"; |
| if (v.equals("float")) |
| return "Float"; |
| if (v.equals("String")) |
| return "String"; |
| if (v.equals("boolean")) |
| return "Boolean"; |
| if (v.equals("byte")) |
| return "Byte"; |
| if (v.equals("short")) |
| return "Short"; |
| if (v.equals("long")) |
| return "Long"; |
| if (v.equals("double")) |
| return "Double"; |
| return "Feature"; // for user defined features and other built-ins which are FSs |
| } |
| |
| // * Functions that convert between CAS fully-qualified names and Java names. |
| // * Handles both import issues and switching packages for some built-ins. |
| |
| /** |
| * Gets the java pkg. |
| * |
| * @param td the td |
| * @return the java pkg |
| */ |
| String getJavaPkg(TypeDescription td) { |
| TypeInfo bi = Jg.builtInTypes.get(td.getName()); |
| if (null == bi) |
| return getPkg(td); |
| return getPkg(bi.javaNameWithPkg); |
| } |
| |
| /** |
| * Gets the java name with pkg. |
| * |
| * @param casTypeName the cas type name |
| * @return the java name with pkg |
| */ |
| String getJavaNameWithPkg(String casTypeName) { |
| TypeInfo bi = Jg.builtInTypes.get(casTypeName); |
| return (null == bi) ? casTypeName : bi.javaNameWithPkg; |
| } |
| |
| /** |
| * Checks for pkg prefix. |
| * |
| * @param name the name |
| * @return true, if successful |
| */ |
| boolean hasPkgPrefix(String name) { |
| return name.lastIndexOf('.') >= 0; |
| } |
| |
| /** |
| * Gets the java name. |
| * |
| * @param td the td |
| * @return the java name |
| */ |
| String getJavaName(TypeDescription td) { |
| return getJavaName(td.getName()); |
| } |
| |
| /** |
| * Gets the java name type. |
| * |
| * @param td the td |
| * @return the java name type |
| */ |
| String getJavaName_Type(TypeDescription td) { |
| return getJavaName(td) + "_Type"; |
| } |
| |
| /** |
| * Gets the java name. |
| * |
| * @param name the name |
| * @return the java name |
| */ |
| String getJavaName(String name) { |
| |
| if (!hasPkgPrefix(name)) |
| return name; |
| String javaNameWithPkg = getJavaNameWithPkg(name); |
| String simpleName = removePkg(javaNameWithPkg); |
| if (getPkg(javaNameWithPkg).equals(packageName)) |
| return simpleName; |
| if (javaNameWithPkg.equals(imports.get(simpleName))) |
| return simpleName; |
| return javaNameWithPkg; |
| } |
| |
| /** The non importable java names. */ |
| private static ArrayList nonImportableJavaNames = new ArrayList(8); |
| static { |
| nonImportableJavaNames.add("String"); |
| nonImportableJavaNames.add("float"); |
| nonImportableJavaNames.add("int"); |
| nonImportableJavaNames.add("boolean"); |
| nonImportableJavaNames.add("byte"); |
| nonImportableJavaNames.add("short"); |
| nonImportableJavaNames.add("long"); |
| nonImportableJavaNames.add("double"); |
| } |
| |
| /** |
| * Collect import. |
| * |
| * @param casName the cas name |
| * @param _Type the type |
| */ |
| void collectImport(String casName, boolean _Type) { |
| if (!hasPkgPrefix(casName)) |
| return; |
| String javaNameWithPkg = getJavaNameWithPkg(casName); |
| if (nonImportableJavaNames.contains(javaNameWithPkg)) |
| return; |
| String pkg = getPkg(javaNameWithPkg); |
| if (pkg.equals(packageName)) |
| return; |
| if (_Type) |
| javaNameWithPkg += "_Type"; |
| String simpleName = removePkg(javaNameWithPkg); |
| if (simpleName.equals(simpleClassName)) |
| return; |
| if (null == imports.get(simpleName)) { |
| if (_Type) |
| _imports.put(simpleName, javaNameWithPkg); |
| else |
| imports.put(simpleName, javaNameWithPkg); |
| } |
| } |
| |
| /** |
| * Collect imports. |
| * |
| * @param td the td |
| * @param _Type the type |
| * @return the collection |
| */ |
| Collection collectImports(TypeDescription td, boolean _Type) { |
| if (_Type) |
| _imports.clear(); |
| else |
| imports.clear(); |
| collectImport(td.getName(), _Type); |
| collectImport(td.getSupertypeName(), _Type); |
| |
| if (!_Type) { |
| |
| FeatureDescription[] fds = td.getFeatures(); |
| for (int i = 0; i < fds.length; i++) { |
| FeatureDescription fd = fds[i]; |
| if (null != typeSystem) { |
| String rangeTypeNameCAS = fd.getRangeTypeName(); |
| Type rangeCasType = typeSystem.getType(rangeTypeNameCAS); |
| if (typeSystem.subsumes(casStringType, rangeCasType)) |
| continue; |
| } |
| collectImport(fd.getRangeTypeName(), false); |
| if (hasArrayRange(fd)) { |
| collectImport(getJavaRangeArrayElementType(fd), false); |
| } |
| } |
| } |
| return (_Type) ? _imports.values() : imports.values(); |
| } |
| |
| /** |
| * Gets the java range type. |
| * |
| * @param fd the fd |
| * @return the java range type |
| */ |
| String getJavaRangeType(FeatureDescription fd) { |
| String rangeTypeNameCAS = fd.getRangeTypeName(); |
| if (null != typeSystem) { |
| Type rangeCasType = typeSystem.getType(rangeTypeNameCAS); |
| if (rangeCasType instanceof TypeImpl_string) { |
| // type is a subtype of string, make its java type = to string |
| return "String"; |
| } |
| } |
| return getJavaName(rangeTypeNameCAS); |
| } |
| |
| /** |
| * Checks if is sub type of annotation. |
| * |
| * @param td the td |
| * @return true, if is sub type of annotation |
| */ |
| boolean isSubTypeOfAnnotation(TypeDescription td) { |
| if (null == cas) |
| return false; |
| Type type = typeSystem.getType(td.getName()); |
| if (null == type) // happens when type hasn't been defined |
| return false; |
| return typeSystem.subsumes(tcasAnnotationType, type); |
| } |
| |
| /** |
| * Checks for array range. |
| * |
| * @param fd the fd |
| * @return true, if successful |
| */ |
| boolean hasArrayRange(FeatureDescription fd) { |
| TypeInfo bi = Jg.builtInTypes.get(fd.getRangeTypeName()); |
| if (null == bi) |
| return false; |
| return bi.isArray; |
| } |
| |
| /** |
| * Checks if is possible index key. |
| * |
| * @param fd the fd |
| * @return true, if is possible index key |
| */ |
| boolean isPossibleIndexKey(FeatureDescription fd) { |
| String rangeTypeName = fd.getRangeTypeName(); |
| // keys are primitives + string + string subtypes |
| TypeImpl rangeType = (null == typeSystem) ? null : (TypeImpl) typeSystem.getType(rangeTypeName); |
| return (null == typeSystem) || // default is to do checking |
| rangeType.isStringSubtype() || |
| BuiltinTypeKinds.primitiveTypeNames_contains(rangeTypeName); // includes String |
| } |
| |
| /** |
| * Checks if is string subtype. |
| * |
| * @param fd the fd |
| * @return true, if is string subtype |
| */ |
| boolean isStringSubtype(FeatureDescription fd) { |
| if (null != typeSystem) { |
| String rangeTypeName = fd.getRangeTypeName(); |
| TypeImpl rangeType = (TypeImpl) typeSystem.getType(rangeTypeName); |
| return rangeType.getSuperType() == ((TypeSystemImpl)typeSystem).stringType; |
| } |
| return false; |
| } |
| |
| /** |
| * Gets the java range array element type. |
| * |
| * @param fd the fd |
| * @return the java range array element type |
| */ |
| String getJavaRangeArrayElementType(FeatureDescription fd) { |
| String arrayElementCasNameWithNameSpace = fd.getElementType(); |
| TypeInfo bi = Jg.builtInTypes.get(fd.getRangeTypeName()); |
| if (null == bi) { |
| if (null == arrayElementCasNameWithNameSpace) |
| return ""; |
| return getJavaName(arrayElementCasNameWithNameSpace); |
| } |
| if (null != arrayElementCasNameWithNameSpace && !"".equals(arrayElementCasNameWithNameSpace)) { |
| return getJavaName(arrayElementCasNameWithNameSpace); |
| } |
| return getJavaName(bi.arrayElNameWithPkg); |
| } |
| |
| // ************************************************** |
| // * uc1(featurename) make uppercase feature name for use by getters/setters |
| /** |
| * Uc 1. |
| * |
| * @param name the name |
| * @return the string |
| */ |
| // ************************************************** |
| String uc1(String name) { // upper case first letter |
| return name.substring(0, 1).toUpperCase() + name.substring(1); |
| } |
| |
| /** |
| * Gets the date. |
| * |
| * @return the date |
| */ |
| String getDate() { |
| return (new Date()).toString(); |
| } |
| |
| // ******************************* |
| // * castResult * |
| /** |
| * Cast result. |
| * |
| * @param resultType the result type |
| * @param core the core |
| * @return the string |
| */ |
| // ******************************* |
| String castResult(String resultType, String core) { |
| if ("Feature".equals(sc(resultType)) && resultType != null |
| && !resultType.equals("FeatureStructure")) |
| return "(" + resultType + ")(" + core + ")"; |
| return core; |
| } |
| |
| // instance generate get/setRefValue int |
| // get/setIntValue |
| // get/setStringValue String |
| // get/setFloatValue float |
| // range = Feature, String, Float, Int |
| |
| /** |
| * Wrap to get FS. |
| * |
| * @param core string representing the get or set code |
| * @param range Boolean, Byte, Short, Int, Long, Float, Double, String, or Feature |
| * @return - |
| */ |
| String wrapToGetFS(String core, String range) { |
| if (range.equals("Feature")) |
| return "jcasType.ll_cas.ll_getFSForRef(" + core + ")"; |
| return core; |
| } |
| |
| /** |
| * Simple core. |
| * |
| * @param get_set get or set |
| * @param range Boolean, Byte, Short, Int, Long, Float, Double, String, or Feature |
| * @param fname feature name (e.g. "begin" |
| * @return the string |
| */ |
| String simpleCore(String get_set, String range, String fname) { |
| String v = ", v"; |
| // if (get_set.equals("set") && range.equals("Feature")) |
| // v = ", jcasType.ll_cas.ll_getFSRef(v)"; |
| boolean isInInt = ! (range.equals("String") || range.equals("Feature") || range.equals("JavaObject")); |
| String chksfx = getCheckSuffix(get_set, range); |
| String featOrOffset = "_FI_" + fname; |
| return "_" + get_set + range + "Value" + chksfx + "(" + featOrOffset + |
| ((get_set.equals("set")) ? v : "") + ")"; |
| } |
| |
| /** |
| * Simple LL core. |
| * |
| * @param get_set the get set |
| * @param range the range |
| * @param fname the fname |
| * @return the string |
| */ |
| String simpleLLCore(String get_set, String range, String fname) { |
| String v = ", v"; |
| // if (get_set.equals("set") && range.equals("Feature")) |
| // v = ", ll_cas.ll_getFSRef(v)"; |
| return "ll_cas.ll_" + get_set + range + "Value(addr, casFeatCode_" + fname |
| + ((get_set.equals("set")) ? v : "") + ")"; |
| } |
| |
| // return string that starts with FS whose value is not an array object, but |
| // a normal CAS type, one of whose features is the array object |
| /** |
| * Array core. |
| * |
| * @param get_set get or set |
| * @param range the component range: Boolean, Byte, Short, Int, Long, Float, Double, String, Feature |
| * @param arrayRange the array range |
| * @param fname the fname |
| * @return the string |
| */ |
| String arrayCore(String get_set, String range, String arrayRange, String fname) { |
| String v = ", v"; |
| // if (get_set.equals("set") && range.equals("Feature")) |
| // v = ", jcasType.ll_cas.ll_getFSRef(v)"; |
| return |
| "((" + arrayRange + ")(" + simpleCore("get", "Feature", fname) + "))." + get_set + |
| "(i" + ((get_set.equals("set")) ? v : "") + ")"; |
| } |
| |
| /** |
| * Array LL core. |
| * |
| * @param get_set the get set |
| * @param range the range |
| * @param fname the fname |
| * @return the string |
| */ |
| String arrayLLCore(String get_set, String range, String fname) { |
| String v = ", v"; |
| return "ll_cas.ll_" + get_set + range + "ArrayValue(" + simpleLLCore("get", "Feature", fname) |
| + ", i" + ((get_set.equals("set")) ? v : "") + ")"; |
| } |
| |
| /** |
| * Array LL core chk. |
| * |
| * @param get_set the get set |
| * @param range the range |
| * @param fname the fname |
| * @return the string |
| */ |
| String arrayLLCoreChk(String get_set, String range, String fname) { |
| String v = ", v"; |
| return "ll_cas.ll_" + get_set + range + "ArrayValue(" + simpleLLCore("get", "Feature", fname) |
| + ", i" + ((get_set.equals("set")) ? v : "") + ", true)"; |
| } |
| |
| /** |
| * Gets the feature value. |
| * |
| * @param fd the fd |
| * @param td the td |
| * @return the feature value |
| */ |
| String getFeatureValue(FeatureDescription fd, TypeDescription td) { |
| String getSetNamePart = getGetSetNamePart(fd); |
| String core = simpleCore("get", getSetNamePart, fd.getName()); |
| return castResult(getJavaRangeType(fd), core); |
| } |
| |
| /** |
| * Sets the feature value. |
| * |
| * @param fd the fd |
| * @param td the td |
| * @return the string |
| */ |
| String setFeatureValue(FeatureDescription fd, TypeDescription td) { |
| return simpleCore("set", getGetSetNamePart(fd), fd.getName()); |
| } |
| |
| /** |
| * Gets the array feature value. |
| * |
| * @param fd the fd |
| * @param td the td |
| * @return the array feature value |
| */ |
| String getArrayFeatureValue(FeatureDescription fd, TypeDescription td) { |
| String getSetArrayNamePart = getGetSetArrayNamePart(fd); |
| String core = arrayCore("get", getSetArrayNamePart, getJavaRangeType(fd), fd.getName()); |
| return castResult(getJavaRangeArrayElementType(fd), core); |
| } |
| |
| /** |
| * Sets the array feature value. |
| * |
| * @param fd the fd |
| * @param td the td |
| * @return the string |
| */ |
| String setArrayFeatureValue(FeatureDescription fd, TypeDescription td) { |
| return arrayCore("set", getGetSetArrayNamePart(fd), getJavaRangeType(fd), fd.getName()); |
| } |
| |
| /** |
| * Gets the gets the set name part. |
| * |
| * @param fd the fd |
| * @return the gets the set name part |
| */ |
| String getGetSetNamePart(FeatureDescription fd) { |
| return sc(getJavaRangeType(fd)); |
| } |
| |
| /** |
| * Gets the gets the set array name part. |
| * |
| * @param fd the fd |
| * @return the gets the set array name part |
| */ |
| String getGetSetArrayNamePart(FeatureDescription fd) { |
| return sc(getJavaRangeArrayElementType(fd)); |
| } |
| |
| /** |
| * Null blank. |
| * |
| * @param s the s |
| * @return the string |
| */ |
| String nullBlank(String s) { |
| if (null == s) |
| return ""; |
| return s; |
| } |
| |
| /** |
| * Creates the resource manager. |
| * |
| * @return the resource manager |
| */ |
| public ResourceManager createResourceManager() { |
| ResourceManager resourceManager = UIMAFramework.newDefaultResourceManager(); |
| |
| try { |
| resourceManager.setExtensionClassPath(this.getClass().getClassLoader(), classPath, true); |
| } catch (MalformedURLException e1) { |
| error.newError(IError.ERROR, getString("Internal Error", null), e1); |
| } |
| return resourceManager; |
| } |
| |
| /** |
| * Merge type system imports. |
| * |
| * @param tsd the tsd |
| * @return the type system description |
| * @throws ResourceInitializationException the resource initialization exception |
| */ |
| private TypeSystemDescription mergeTypeSystemImports(TypeSystemDescription tsd) |
| throws ResourceInitializationException { |
| Collection tsdc = new ArrayList(1); |
| tsdc.add(tsd.clone()); |
| mergedTypesAddingFeatures.clear(); |
| TypeSystemDescription mergedTsd = CasCreationUtils.mergeTypeSystems(tsdc, |
| createResourceManager(), mergedTypesAddingFeatures); |
| return mergedTsd; |
| } |
| |
| /** |
| * Sets the difference. |
| * |
| * @param newFeatures the new features |
| * @param alreadyDefinedFeatures the already defined features |
| * @return the list |
| */ |
| List setDifference(FeatureDescription[] newFeatures, FeatureDescription[] alreadyDefinedFeatures) { |
| List result = new ArrayList(); |
| outerLoop: for (int i = 0; i < newFeatures.length; i++) { |
| for (int j = 0; j < alreadyDefinedFeatures.length; j++) { |
| if (isSameFeatureDescription(newFeatures[i], alreadyDefinedFeatures[j])) |
| continue outerLoop; |
| } |
| result.add(newFeatures[i]); |
| } |
| return result; |
| } |
| |
| /** |
| * Checks if is same feature description. |
| * |
| * @param f1 the f 1 |
| * @param f2 the f 2 |
| * @return true, if is same feature description |
| */ |
| private boolean isSameFeatureDescription(FeatureDescription f1, FeatureDescription f2) { |
| if (!f2.getName().equals(f1.getName())) |
| return false; |
| if (!f2.getRangeTypeName().equals(f1.getRangeTypeName())) |
| return false; |
| return true; |
| } |
| |
| /** |
| * Gets the check suffix. |
| * |
| * @param get_set the get set |
| * @param range the range |
| * @return the check suffix |
| */ |
| private String getCheckSuffix(String get_set, String range) { |
| if (get_set.equals("get")) return "Nc"; |
| |
| return (range.equals("Feature")) ? "NcWj" : "Nfc"; |
| } |
| |
| } |