/* | |
* 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.ruta; | |
import static org.apache.uima.util.Level.SEVERE; | |
import java.io.IOException; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import java.util.HashMap; | |
import java.util.HashSet; | |
import java.util.Iterator; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Map.Entry; | |
import java.util.Set; | |
import java.util.logging.Level; | |
import java.util.logging.Logger; | |
import org.antlr.runtime.CommonToken; | |
import org.apache.commons.lang3.StringUtils; | |
import org.apache.commons.lang3.tuple.ImmutableTriple; | |
import org.apache.commons.lang3.tuple.Triple; | |
import org.apache.uima.UIMAFramework; | |
import org.apache.uima.UimaContext; | |
import org.apache.uima.cas.CAS; | |
import org.apache.uima.cas.CASException; | |
import org.apache.uima.cas.Type; | |
import org.apache.uima.cas.TypeSystem; | |
import org.apache.uima.cas.text.AnnotationFS; | |
import org.apache.uima.fit.factory.TypeSystemDescriptionFactory; | |
import org.apache.uima.fit.internal.ResourceManagerFactory; | |
import org.apache.uima.resource.ResourceAccessException; | |
import org.apache.uima.resource.ResourceInitializationException; | |
import org.apache.uima.resource.ResourceManager; | |
import org.apache.uima.resource.metadata.TypeDescription; | |
import org.apache.uima.resource.metadata.TypeSystemDescription; | |
import org.apache.uima.ruta.action.AbstractRutaAction; | |
import org.apache.uima.ruta.block.RutaBlock; | |
import org.apache.uima.ruta.condition.AbstractRutaCondition; | |
import org.apache.uima.ruta.engine.RutaEngine; | |
import org.apache.uima.ruta.expression.IRutaExpression; | |
import org.apache.uima.ruta.expression.annotation.IAnnotationExpression; | |
import org.apache.uima.ruta.expression.bool.IBooleanExpression; | |
import org.apache.uima.ruta.expression.bool.SimpleBooleanListExpression; | |
import org.apache.uima.ruta.expression.list.ListExpression; | |
import org.apache.uima.ruta.expression.number.INumberExpression; | |
import org.apache.uima.ruta.expression.number.SimpleNumberListExpression; | |
import org.apache.uima.ruta.expression.resource.LiteralWordListExpression; | |
import org.apache.uima.ruta.expression.resource.LiteralWordTableExpression; | |
import org.apache.uima.ruta.expression.resource.StringWordListExpression; | |
import org.apache.uima.ruta.expression.resource.StringWordTableExpression; | |
import org.apache.uima.ruta.expression.resource.WordListExpression; | |
import org.apache.uima.ruta.expression.resource.WordTableExpression; | |
import org.apache.uima.ruta.expression.string.IStringExpression; | |
import org.apache.uima.ruta.expression.string.SimpleStringListExpression; | |
import org.apache.uima.ruta.expression.type.ITypeExpression; | |
import org.apache.uima.ruta.expression.type.SimpleTypeExpression; | |
import org.apache.uima.ruta.expression.type.SimpleTypeListExpression; | |
import org.apache.uima.ruta.resource.CSVTable; | |
import org.apache.uima.ruta.resource.MultiTreeWordList; | |
import org.apache.uima.ruta.resource.RutaResourceLoader; | |
import org.apache.uima.ruta.resource.RutaTable; | |
import org.apache.uima.ruta.resource.RutaWordList; | |
import org.apache.uima.ruta.resource.TreeWordList; | |
import org.apache.uima.ruta.rule.MatchContext; | |
import org.apache.uima.ruta.rule.RuleElement; | |
import org.apache.uima.ruta.rule.RuleMatch; | |
import org.apache.uima.ruta.verbalize.RutaVerbalizer; | |
import org.apache.uima.util.InvalidXMLException; | |
import org.springframework.core.io.Resource; | |
import org.springframework.core.io.ResourceLoader; | |
public class RutaEnvironment { | |
private static final String DOCUMENT = "Document"; | |
private final Object annotationTypeDummy = new Object(); | |
private Map<String, Type> types; | |
private Map<String, RutaWordList> wordLists; | |
private Map<String, RutaTable> tables; | |
private RutaBlock owner; | |
/** | |
* Mapping from short type name (e.g. {@code W}) to their disambiguated long type names (e.g. | |
* {@code org.apache.uima.ruta.type.W}). | |
*/ | |
private Map<String, String> namespaces; | |
/** | |
* Mapping from ambiguous short type names to all their possible long type names. | |
*/ | |
private Map<String, Set<String>> ambiguousTypeAlias; | |
/** | |
* Set of imported typesystems. | |
*/ | |
private Set<String> typesystems; | |
/** | |
* Set of imported scripts. | |
*/ | |
private Set<String> scripts; | |
/** | |
* An alias from a long to a short name. | |
*/ | |
private static class Alias { | |
final String longName; | |
final String shortName; | |
Alias(String longName, String shortName) { | |
this.longName = longName; | |
this.shortName = shortName; | |
} | |
} | |
/** | |
* Types that are imported in the environment. Keys are type system descriptors and values are | |
* aliased types. | |
*/ | |
private Map<String, List<Alias>> typeImports; | |
/** | |
* Packages that are imported in the environment without a typesystem specification. | |
* | |
* Keys are package names and values are aliases. An empty string as alias means that all types | |
* from the package should be imported in the default namespace. | |
*/ | |
private Map<String, List<String>> packageImports; | |
/** | |
* Set of types that are declared in the script. | |
*/ | |
private Set<String> declaredAnnotationTypes; | |
private Map<String, Object> variableValues; | |
private Map<String, Object> tempVariableValues; | |
private Map<String, Class<?>> variableTypes; | |
private Map<String, Class<?>> availableTypes; | |
private Map<String, Class<?>> variableGenericTypes; | |
private Map<String, Class<?>> availableListTypes; | |
private Map<String, Triple<Map<String, String>, List<AbstractRutaCondition>, Set<String>>> macroConditions; | |
private Map<String, Triple<Map<String, String>, List<AbstractRutaAction>, Set<String>>> macroActions; | |
private String[] resourcePaths = null; | |
private CAS cas; | |
private Map<String, Object> initializedVariables; | |
private ResourceManager resourceManager; | |
private Map<String, String> variableAliases; | |
private RutaVerbalizer verbalizer = new RutaVerbalizer(); | |
public RutaEnvironment(RutaBlock owner) { | |
super(); | |
this.owner = owner; | |
types = new HashMap<>(); | |
namespaces = new HashMap<>(); | |
ambiguousTypeAlias = new HashMap<>(); | |
typesystems = new HashSet<>(); | |
scripts = new HashSet<>(); | |
typeImports = new HashMap<>(); | |
packageImports = new HashMap<>(); | |
declaredAnnotationTypes = new HashSet<>(); | |
wordLists = new HashMap<>(); | |
tables = new HashMap<>(); | |
variableValues = new HashMap<>(); | |
tempVariableValues = new HashMap<>(); | |
variableTypes = new HashMap<>(); | |
variableGenericTypes = new HashMap<>(); | |
macroConditions = new HashMap<>(); | |
macroActions = new HashMap<>(); | |
availableTypes = new HashMap<>(); | |
availableTypes.put(RutaConstants.RUTA_VARIABLE_ANNOTATION, AnnotationFS.class); | |
availableTypes.put("INT", Integer.class); | |
availableTypes.put("STRING", String.class); | |
availableTypes.put("DOUBLE", Double.class); | |
availableTypes.put("FLOAT", Float.class); | |
availableTypes.put("BOOLEAN", Boolean.class); | |
availableTypes.put("TYPE", Type.class); | |
availableTypes.put("CONDITION", AbstractRutaCondition.class); | |
availableTypes.put("ACTION", AbstractRutaAction.class); | |
availableTypes.put("WORDLIST", RutaWordList.class); | |
availableTypes.put("WORDTABLE", RutaTable.class); | |
availableTypes.put(RutaConstants.RUTA_VARIABLE_ANNOTATION_LIST, List.class); | |
availableTypes.put("BOOLEANLIST", List.class); | |
availableTypes.put("INTLIST", List.class); | |
availableTypes.put("DOUBLELIST", List.class); | |
availableTypes.put("FLOATLIST", List.class); | |
availableTypes.put("STRINGLIST", List.class); | |
availableTypes.put(RutaConstants.RUTA_VARIABLE_TYPE_LIST, List.class); | |
availableListTypes = new HashMap<>(); | |
availableListTypes.put(RutaConstants.RUTA_VARIABLE_ANNOTATION_LIST, AnnotationFS.class); | |
availableListTypes.put("BOOLEANLIST", Boolean.class); | |
availableListTypes.put("INTLIST", Integer.class); | |
availableListTypes.put("DOUBLELIST", Double.class); | |
availableListTypes.put("FLOATLIST", Float.class); | |
availableListTypes.put("STRINGLIST", String.class); | |
availableListTypes.put(RutaConstants.RUTA_VARIABLE_TYPE_LIST, Type.class); | |
resourcePaths = getResourcePaths(); | |
initializedVariables = new HashMap<>(); | |
variableAliases = new HashMap<>(); | |
// Always import BasicTypeSystem | |
addTypeSystem("org.apache.uima.ruta.engine.BasicTypeSystem"); | |
} | |
/** | |
* Import short type names. | |
* | |
* @param cas | |
* Cas to initialize the types for. | |
* @param strictImport | |
* Specify whether all types should be imported (false) or only types | |
*/ | |
public void initializeTypes(CAS cas, boolean strictImport) { | |
this.cas = cas; | |
try { | |
if (strictImport) { | |
importDeclaredTypes(cas.getTypeSystem()); | |
importDeclaredTypesystems(cas.getTypeSystem()); | |
importTypeAliases(cas.getTypeSystem()); | |
importPackageAliases(cas.getTypeSystem()); | |
importDeclaredScripts(cas.getTypeSystem()); | |
} else { | |
// import all types known to the cas | |
importAllTypes(cas.getTypeSystem()); | |
importTypeAliases(cas.getTypeSystem()); | |
importPackageAliases(cas.getTypeSystem()); | |
} | |
ambiguousTypeAlias.remove(DOCUMENT); | |
namespaces.remove(DOCUMENT); | |
Type documentType = cas.getTypeSystem().getType(CAS.TYPE_NAME_DOCUMENT_ANNOTATION); | |
addType(DOCUMENT, documentType); | |
addType(documentType.getShortName(), documentType); | |
Type annotationType = cas.getJCas().getCasType(org.apache.uima.jcas.tcas.Annotation.type); | |
addType("Annotation", annotationType); | |
} catch (CASException e) { | |
UIMAFramework.getLogger(getClass()).log(SEVERE, "Cannot initialize types.", e); | |
} catch (InvalidXMLException e) { | |
UIMAFramework.getLogger(getClass()).log(SEVERE, "Cannot initialize types.", e); | |
} | |
} | |
/** | |
* Imports all types that are known to a type system. | |
* | |
* @param ts | |
* Type system to import. | |
* @throws CASException | |
*/ | |
private void importAllTypes(TypeSystem ts) throws CASException { | |
Type topType = ts.getTopType(); | |
if (topType != null) { | |
List<Type> list = ts.getProperlySubsumedTypes(topType); | |
for (Type type : list) { | |
addType(type); | |
} | |
} | |
} | |
/** | |
* Import all types that are declared by the script. | |
* | |
* @param casTS | |
* Type system containing all known types. | |
* @throws InvalidXMLException | |
* When import cannot be resolved. | |
*/ | |
private void importDeclaredTypes(TypeSystem casTS) throws InvalidXMLException { | |
for (String name : declaredAnnotationTypes) { | |
Type type = casTS.getType(name); | |
if (type != null) { | |
addType(type); | |
} else { | |
throw new RuntimeException("Type '" + name + "' not found"); | |
} | |
} | |
} | |
/** | |
* Import all typesystems that are imported in the script. | |
* | |
* @param casTS | |
* Type system containing all known types. | |
* @throws InvalidXMLException | |
* When import cannot be resolved. | |
*/ | |
private void importDeclaredTypesystems(TypeSystem casTS) throws InvalidXMLException { | |
String[] descriptors = typesystems.toArray(new String[typesystems.size()]); | |
TypeSystemDescription ts = TypeSystemDescriptionFactory | |
.createTypeSystemDescription(descriptors); | |
ts.resolveImports(getResourceManager()); | |
for (TypeDescription td : ts.getTypes()) { | |
Type type = casTS.getType(td.getName()); | |
if (type != null) { | |
addType(type); | |
} else { | |
throw new RuntimeException("Type '" + td.getName() + "' not found"); | |
} | |
} | |
} | |
/** | |
* Import all already initialized types of imported scripts. | |
* | |
* @param casTS | |
* Type system containing all known types. | |
* @throws InvalidXMLException | |
* When import cannot be resolved. | |
*/ | |
private void importDeclaredScripts(TypeSystem casTS) throws InvalidXMLException { | |
RutaModule script = owner.getScript(); | |
for (String eachImportedScript : scripts) { | |
RutaModule importedModule = script.getScript(eachImportedScript); | |
RutaEnvironment importedEnvironment = importedModule.getRootBlock().getEnvironment(); | |
Map<String, Type> importedTypeMap = importedEnvironment.getTypes(); | |
Map<String, String> importedNamespaces = importedEnvironment.getNamespaces(); | |
Set<Entry<String, String>> entrySet = importedNamespaces.entrySet(); | |
for (Entry<String, String> entry : entrySet) { | |
if (!ownsType(entry.getValue()) && !StringUtils.equals(entry.getKey(), DOCUMENT)) { | |
Type type = importedTypeMap.get(entry.getValue()); | |
addType(entry.getKey(), type); | |
} | |
} | |
// TODO import also wordlists and variables? | |
} | |
} | |
/** | |
* Imports all type aliases. | |
* | |
* @param casTS | |
* Cas type system. | |
*/ | |
private void importTypeAliases(TypeSystem casTS) { | |
for (List<Alias> aliases : typeImports.values()) { | |
for (Alias alias : aliases) { | |
Type type = casTS.getType(alias.longName); | |
if (type == null) { | |
throw new RuntimeException("Type '" + alias.longName + "' not found"); | |
} | |
addType(alias.shortName, casTS.getType(alias.longName)); | |
} | |
} | |
} | |
/** | |
* Import all packages that are imported by the script. | |
* | |
* @param casTS | |
* Type system containing all known types. | |
*/ | |
private void importPackageAliases(TypeSystem casTS) { | |
Iterator<Type> iter = casTS.getTypeIterator(); | |
while (iter.hasNext()) { | |
Type type = iter.next(); | |
String name = type.getName(); | |
String pkg = name.substring(0, Math.max(name.lastIndexOf('.'), 0)); | |
List<String> aliases = packageImports.get(pkg); | |
if (aliases != null) { | |
for (String alias : aliases) { | |
if (alias.isEmpty()) { | |
addType(type); | |
} else { | |
addType(alias + "." + type.getShortName(), type); | |
} | |
} | |
} | |
} | |
} | |
public String[] getResourcePaths() { | |
if (resourcePaths == null) { | |
RutaBlock parent = owner.getParent(); | |
if (parent != null) { | |
return parent.getEnvironment().getResourcePaths(); | |
} | |
} | |
return resourcePaths; | |
} | |
public void setResourcePaths(String[] resourcePaths) { | |
this.resourcePaths = resourcePaths; | |
} | |
public boolean ownsType(String match) { | |
match = expand(match); | |
return types.keySet().contains(match); | |
} | |
private String expand(String string) { | |
String complete = namespaces.get(string); | |
if (complete == null) { | |
if (!string.contains(".")) { | |
complete = namespaces.get(string); | |
if (complete == null) { | |
complete = string; | |
} | |
} else { | |
complete = string; | |
} | |
} | |
return complete; | |
} | |
/** | |
* Resolves an annotation type. | |
* | |
* @param match | |
* Annotation type to resolve. | |
* @return Resolved annotation type or null if match is unknown. | |
* @throws IllegalArgumentException | |
* When {@code match} is ambiguous. | |
*/ | |
public Type getType(String match) { | |
// make sure that match is not ambiguous | |
Set<String> ambiguousTargets = ambiguousTypeAlias.get(match); | |
if (ambiguousTargets != null) { | |
StringBuilder message = new StringBuilder(match); | |
message.append(" is ambiguous, use one of the following instead : "); | |
for (String target : ambiguousTargets) { | |
message.append(target).append(' '); | |
} | |
throw new IllegalArgumentException(message.toString()); | |
} | |
// try to resolve match | |
String expanded = expand(match); | |
Type type = types.get(expanded); | |
if (type == null) { | |
RutaBlock parent = owner.getParent(); | |
if (parent != null) { | |
type = parent.getEnvironment().getType(match); | |
} | |
} | |
return type; | |
} | |
public void addType(String string, Type type) { | |
importType(type.getName(), string); | |
types.put(type.getName(), type); | |
} | |
public void addType(Type type) { | |
addType(type.getShortName(), type); | |
} | |
public void declareType(String name) { | |
declaredAnnotationTypes.add(name); | |
} | |
/** | |
* Add a typesystem to the script. | |
* | |
* @param descriptor | |
* Type system's descriptor path. | |
*/ | |
public void addTypeSystem(String descriptor) { | |
typesystems.add(descriptor); | |
} | |
/** | |
* Add a script to the script. | |
* | |
* @param script | |
* the script's full name. | |
*/ | |
public void addScript(String script) { | |
scripts.add(script); | |
} | |
/** | |
* Import a type in the current namespace. | |
* | |
* @param longName | |
* Complete type name. | |
* @param shortName | |
* Short type name (without namespace). | |
*/ | |
private void importType(String longName, String shortName) { | |
Set<String> targets = ambiguousTypeAlias.get(shortName); | |
if (targets != null) { | |
// shortName is already ambiguous, add longName to its list of | |
// possible targets | |
targets.add(longName); | |
} else { | |
String existing = namespaces.put(shortName, longName); | |
if (existing != null && !existing.equals(longName)) { | |
// shortName can now be resolved to "existing" or "longName" | |
targets = new HashSet<>(2); | |
targets.add(existing); | |
targets.add(longName); | |
// add existing mapping and longName to its list of possible | |
// targets | |
ambiguousTypeAlias.put(shortName, targets); | |
// remove shortName from the namespace because it is ambiguous | |
namespaces.remove(shortName); | |
} | |
} | |
} | |
/** | |
* Import a type from a type system. | |
* | |
* @param typesystem | |
* Typesystem from which to import the type or null. | |
* @param longName | |
* Type to import. | |
* @param shortName | |
* Short name to use for this type. | |
*/ | |
public void importTypeFromTypeSystem(String typesystem, String longName, String shortName) { | |
String key = typesystem != null ? typesystem : ""; | |
List<Alias> aliases = typeImports.get(key); | |
if (aliases == null) { | |
aliases = new ArrayList<>(); | |
typeImports.put(key, aliases); | |
} | |
aliases.add(new Alias(longName, shortName)); | |
} | |
/** | |
* Import a type from a type system. | |
* | |
* The type is aliased by its unqualified name. | |
* | |
* @param typesystem | |
* Typesystem from which to import the type or null. | |
* @param longName | |
* Type to import. | |
*/ | |
public void importTypeFromTypeSystem(String typesystem, String longName) { | |
importTypeFromTypeSystem(typesystem, longName, | |
longName.substring(longName.lastIndexOf('.') + 1)); | |
} | |
/** | |
* Import all the types from a package. | |
* | |
* @param typesystem | |
* Type system describing the package to load. | |
* @param packageName | |
* Package to load or null to load all packages. | |
* @param alias | |
* Alias of the package. Null or empty string to use no alias. | |
*/ | |
public void importPackageFromTypeSystem(String typesystem, String packageName, String alias) { | |
TypeSystemDescription tsd = TypeSystemDescriptionFactory | |
.createTypeSystemDescription(typesystem); | |
try { | |
tsd.resolveImports(getResourceManager()); | |
} catch (InvalidXMLException e) { | |
throw new RuntimeException("Cannot resolve imports in " + typesystem, e); | |
} | |
for (TypeDescription td : tsd.getTypes()) { | |
String qname = td.getName(); | |
if (packageName == null || (qname.startsWith(packageName) | |
&& qname.indexOf('.', packageName.length() + 1) == -1)) { | |
// td is in packageName | |
if (alias != null) { | |
String shortName = alias + "." + qname.substring(qname.lastIndexOf('.') + 1); | |
importTypeFromTypeSystem(typesystem, qname, shortName); | |
} else { | |
importTypeFromTypeSystem(typesystem, qname); | |
} | |
} | |
} | |
} | |
/** | |
* Imports all the packages from the specified type system. | |
* | |
* @param typesystem | |
* Typesystem to load. | |
* @param alias | |
* Alias for all the packages. | |
*/ | |
public void importAllPackagesFromTypeSystem(String typesystem, String alias) { | |
importPackageFromTypeSystem(typesystem, null, alias); | |
} | |
/** | |
* Import all the types from a package that are available at runtime. | |
* | |
* @param packageName | |
* Package to load. | |
* @param alias | |
* Alias of the package. Null or empty string to use no alias. | |
*/ | |
public void importPackage(String packageName, String alias) { | |
List<String> aliases = packageImports.get(packageName); | |
if (aliases == null) { | |
aliases = new ArrayList<>(1); | |
packageImports.put(packageName, aliases); | |
} | |
aliases.add(alias == null ? "" : alias); | |
} | |
public RutaWordList getWordList(String list) { | |
if (list == null) { | |
return null; | |
} | |
RutaWordList result = wordLists.get(list); | |
UimaContext context = owner.getContext(); | |
Boolean dictRemoveWS = false; | |
if (context != null) { | |
dictRemoveWS = (Boolean) context.getConfigParameterValue(RutaEngine.PARAM_DICT_REMOVE_WS); | |
if (dictRemoveWS == null) { | |
dictRemoveWS = false; | |
} | |
} | |
if (result == null) { | |
if (list.endsWith("txt") || list.endsWith("twl") || list.endsWith("mtwl")) { | |
ResourceLoader resourceLoader = new RutaResourceLoader(getResourcePaths(), | |
getResourceManager().getExtensionClassLoader()); | |
Resource resource = resourceLoader.getResource(list); | |
if (resource.exists()) { | |
try { | |
if (list.endsWith("mtwl")) { | |
wordLists.put(list, new MultiTreeWordList(resource)); | |
} else { | |
wordLists.put(list, new TreeWordList(resource, dictRemoveWS)); | |
} | |
} catch (IOException e) { | |
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, | |
"Error reading word list" + list, e); | |
} | |
} else { | |
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Can't find " + list + "!"); | |
} | |
} else { | |
try { | |
RutaWordList rutaList = (RutaWordList) context.getResourceObject(list); | |
if (rutaList != null) { | |
wordLists.put(list, rutaList); | |
} else { | |
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, | |
"Can't find external resource list" + list); | |
} | |
} catch (ResourceAccessException e) { | |
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, | |
"Can't find external resource list" + list, e); | |
} | |
} | |
} | |
return wordLists.get(list); | |
} | |
public RutaTable getWordTable(String table) { | |
UimaContext context = owner.getContext(); | |
RutaTable result = tables.get(table); | |
if (result == null) { | |
if (table.endsWith("csv") || table.endsWith("txt") || table.endsWith("tsv")) { | |
ResourceLoader resourceLoader = new RutaResourceLoader(getResourcePaths(), | |
getResourceManager().getExtensionClassLoader()); | |
Resource resource = resourceLoader.getResource(table); | |
if (resource.exists()) { | |
try { | |
tables.put(table, new CSVTable(resource, getCsvSeparator(context))); | |
} catch (IOException e) { | |
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, | |
"Error reading csv table " + table, e); | |
} | |
} else { | |
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, | |
"Can't find " + table + "!"); | |
} | |
} else { | |
try { | |
RutaTable rutaTable = (RutaTable) context.getResourceObject(table); | |
tables.put(table, rutaTable); | |
} catch (ResourceAccessException e) { | |
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, | |
"Can't find external resource table" + table, e); | |
} | |
} | |
} | |
return tables.get(table); | |
} | |
private String getCsvSeparator(UimaContext context) { | |
if (context != null) { | |
String cvsSeparator = (String) context | |
.getConfigParameterValue(RutaEngine.PARAM_CSV_SEPARATOR); | |
if (cvsSeparator != null) { | |
return cvsSeparator; | |
} | |
} | |
return CSVTable.DEFAULT_CSV_SEPARATOR; | |
} | |
private void addVariable(String name, Class<?> type, Class<?> generic) { | |
variableTypes.put(name, type); | |
if (generic != null) { | |
variableGenericTypes.put(name, generic); | |
} | |
variableValues.put(name, getInitialValue(name, type)); | |
} | |
@SuppressWarnings("unchecked") | |
private Object getInitialValue(String name, Class<?> type) { | |
Object init = initializedVariables.get(name); | |
if (init != null) { | |
if (init instanceof List) { | |
ArrayList<Object> list = new ArrayList<>(); | |
list.addAll((Collection<? extends Object>) init); | |
return list; | |
} | |
return init; | |
} | |
if (Integer.class.equals(type)) { | |
return 0; | |
} else if (Double.class.equals(type)) { | |
return 0d; | |
} else if (Float.class.equals(type)) { | |
return 0f; | |
} else if (String.class.equals(type)) { | |
return null; | |
} else if (Boolean.class.equals(type)) { | |
return false; | |
} else if (Type.class.equals(type)) { | |
return null; | |
} else if (List.class.equals(type)) { | |
return new ArrayList<>(); | |
} | |
return null; | |
} | |
public void addVariable(String name, String type) { | |
addVariable(name, availableTypes.get(type), availableListTypes.get(type)); | |
} | |
public void removeVariable(String name) { | |
variableTypes.remove(name); | |
variableGenericTypes.remove(name); | |
variableValues.remove(name); | |
tempVariableValues.remove(name); | |
} | |
public boolean ownsVariable(String name) { | |
return variableTypes.containsKey(name); | |
} | |
public boolean ownsVariableOfType(String name, String type) { | |
if (variableAliases.containsKey(name)) { | |
name = variableAliases.get(name); | |
} | |
Class<?> varclass = variableTypes.get(name); | |
Class<?> aclass = availableTypes.get(type); | |
boolean list = true; | |
if (aclass.equals(List.class)) { | |
Class<?> vt = variableGenericTypes.get(name); | |
Class<?> at = availableListTypes.get(type); | |
list = vt != null && vt.equals(at); | |
} | |
return list && varclass != null && varclass.equals(aclass); | |
} | |
public boolean isVariable(String name) { | |
if (variableAliases.containsKey(name)) { | |
name = variableAliases.get(name); | |
} | |
if (ownsVariable(name)) { | |
return true; | |
} | |
if (owner != null && owner.getParent() != null) { | |
return owner.getParent().getEnvironment().isVariable(name); | |
} | |
return false; | |
} | |
public boolean isVariableOfType(String name, String type) { | |
return ownsVariableOfType(name, type) || (owner.getParent() != null | |
&& owner.getParent().getEnvironment().isVariableOfType(name, type)); | |
} | |
public Class<?> getVariableType(String name) { | |
if (variableAliases.containsKey(name)) { | |
name = variableAliases.get(name); | |
} | |
Class<?> result = variableTypes.get(name); | |
if (result != null) { | |
return result; | |
} else if (owner.getParent() != null) { | |
return owner.getParent().getEnvironment().getVariableType(name); | |
} | |
return null; | |
} | |
public Class<?> getVariableGenericType(String name) { | |
Class<?> result = variableGenericTypes.get(name); | |
if (result != null) { | |
return result; | |
} else if (owner.getParent() != null) { | |
return owner.getParent().getEnvironment().getVariableGenericType(name); | |
} | |
return null; | |
} | |
public <T> T getVariableValue(String name, Class<T> type, RutaStream stream) { | |
if (variableAliases.containsKey(name)) { | |
name = variableAliases.get(name); | |
} | |
Object result = null; | |
boolean containsKey = variableValues.containsKey(name); | |
result = tempVariableValues.get(name); | |
if (result == null) { | |
result = variableValues.get(name); | |
} | |
if (result instanceof String && type.equals(Type.class)) { | |
// "cast" string to type, because initial values were set when there | |
// was no cas/type system | |
// yet | |
String stringValue = (String) result; | |
result = types.get(stringValue); | |
if (result == null) { | |
// try to resolve short names | |
result = getType(stringValue); | |
} | |
} | |
if (containsKey && result == null) { | |
// TODO find the problem with the null values! | |
// this might now work for word lists in another env. | |
Object initialValue = getInitialValue(name, type); | |
if (initialValue instanceof Type) { | |
return type.cast(initialValue); | |
} else if (initialValue != null) { | |
throw new IllegalArgumentException("Variable " + name + " of type " + type | |
+ " is not correctly initialized! It is not a Type, but " + initialValue); | |
} | |
} | |
if (result == annotationTypeDummy) { | |
return type.cast(cas.getAnnotationType()); | |
} | |
if (result != null) { | |
MatchContext context = new MatchContext(owner); | |
if (RutaWordList.class.isAssignableFrom(type) && result instanceof WordListExpression) { | |
WordListExpression wle = (WordListExpression) result; | |
RutaWordList list = wle.getList(context, stream); | |
return type.cast(list); | |
} else if (RutaTable.class.isAssignableFrom(type) && result instanceof WordTableExpression) { | |
WordTableExpression wte = (WordTableExpression) result; | |
RutaTable table = wte.getTable(context, stream); | |
return type.cast(table); | |
} else { | |
return type.cast(result); | |
} | |
} else if (owner.getParent() != null) { | |
return owner.getParent().getEnvironment().getVariableValue(name, type, stream); | |
} | |
return null; | |
} | |
public Object getVariableValue(String name, RutaStream stream) { | |
return getVariableValue(name, Object.class, stream); | |
} | |
@SuppressWarnings("rawtypes") | |
public Object getLiteralValue(String var, Object value) { | |
if (ownsVariable(var)) { | |
MatchContext context = new MatchContext(owner); | |
Class<?> clazz = variableTypes.get(var); | |
if (value instanceof INumberExpression) { | |
INumberExpression ne = (INumberExpression) value; | |
if (clazz.equals(Integer.class)) { | |
return ne.getIntegerValue(context, null); | |
} else if (clazz.equals(Double.class)) { | |
return ne.getDoubleValue(context, null); | |
} else if (clazz.equals(Float.class)) { | |
return ne.getFloatValue(context, null); | |
} else if (clazz.equals(String.class)) { | |
return ne.getStringValue(context, null); | |
} | |
} else if (clazz.equals(String.class) && value instanceof IStringExpression) { | |
IStringExpression se = (IStringExpression) value; | |
return se.getStringValue(context, null); | |
} else if (clazz.equals(Boolean.class) && value instanceof IBooleanExpression) { | |
IBooleanExpression be = (IBooleanExpression) value; | |
return be.getBooleanValue(context, null); | |
} | |
if (clazz.equals(RutaWordList.class) && value instanceof LiteralWordListExpression) { | |
return value; | |
} else if (clazz.equals(RutaWordList.class) && value instanceof StringWordListExpression) { | |
return value; | |
} else if (clazz.equals(RutaWordList.class) && value instanceof String) { | |
return value; | |
} else if (clazz.equals(RutaTable.class) && value instanceof LiteralWordTableExpression) { | |
return value; | |
} else if (clazz.equals(RutaTable.class) && value instanceof StringWordTableExpression) { | |
return value; | |
} else if (clazz.equals(RutaTable.class) && value instanceof String) { | |
return value; | |
} else if (clazz.equals(List.class) && value instanceof ListExpression) { | |
List list = getList((ListExpression) value); | |
return list; | |
} else if (clazz.equals(Type.class) && value instanceof CommonToken) { | |
String typeName = ((CommonToken) value).getText(); | |
return typeName; | |
} else if (clazz.equals(Type.class) && value instanceof SimpleTypeExpression) { | |
String typeName = ((SimpleTypeExpression) value).getTypeString(); | |
return typeName; | |
} | |
return null; | |
} else { | |
return owner.getParent().getEnvironment().getLiteralValue(var, value); | |
} | |
} | |
@SuppressWarnings("unchecked") | |
public void setInitialVariableValue(String var, Object value) { | |
if (ownsVariable(var)) { | |
if (value instanceof List) { | |
List<Object> initValue = new ArrayList<>(); | |
initValue.addAll((Collection<? extends Object>) value); | |
initializedVariables.put(var, initValue); | |
} else { | |
initializedVariables.put(var, value); | |
} | |
setVariableValue(var, value); | |
} else if (owner.getParent() != null) { | |
owner.getParent().getEnvironment().setInitialVariableValue(var, value); | |
} | |
} | |
public void setVariableValue(String name, Object value) { | |
if (variableAliases.containsKey(name)) { | |
name = variableAliases.get(name); | |
} | |
if (ownsVariable(name)) { | |
Class<?> clazz = variableTypes.get(name); | |
if (value == null) { | |
value = getInitialValue(name, clazz); | |
} | |
variableValues.put(name, value); | |
} else if (owner.getParent() != null) { | |
owner.getParent().getEnvironment().setVariableValue(name, value); | |
} | |
} | |
public void setTempVariableValue(String name, Object value) { | |
if (variableAliases.containsKey(name)) { | |
name = variableAliases.get(name); | |
} | |
tempVariableValues.put(name, value); | |
} | |
@SuppressWarnings("rawtypes") | |
private List getList(ListExpression value) { | |
if (value instanceof SimpleBooleanListExpression) { | |
SimpleBooleanListExpression e = (SimpleBooleanListExpression) value; | |
return e.getList(); | |
} else if (value instanceof SimpleNumberListExpression) { | |
SimpleNumberListExpression e = (SimpleNumberListExpression) value; | |
return e.getList(); | |
} else if (value instanceof SimpleStringListExpression) { | |
SimpleStringListExpression e = (SimpleStringListExpression) value; | |
return e.getList(); | |
} else if (value instanceof SimpleTypeListExpression) { | |
SimpleTypeListExpression e = (SimpleTypeListExpression) value; | |
return e.getList(); | |
} | |
return null; | |
} | |
public void reset(CAS cas) { | |
this.cas = cas; | |
Set<Entry<String, Object>> entrySet = variableValues.entrySet(); | |
for (Entry<String, Object> entry : entrySet) { | |
String key = entry.getKey(); | |
Class<?> variableType = variableTypes.get(key); | |
Object initialValue = getInitialValue(key, variableTypes.get(key)); | |
if ((!variableType.equals(RutaTable.class) && !variableType.equals(RutaWordList.class)) | |
|| initialValue != null) { | |
// not for word lists | |
entry.setValue(initialValue); | |
} | |
} | |
} | |
public ResourceManager getResourceManager() { | |
if (resourceManager != null) { | |
return resourceManager; | |
} else { | |
RutaBlock parent = owner.getParent(); | |
if (parent != null) { | |
return parent.getEnvironment().getResourceManager(); | |
} | |
} | |
// at least return default resource manager | |
try { | |
resourceManager = ResourceManagerFactory.newResourceManager(); | |
return resourceManager; | |
} catch (ResourceInitializationException e) { | |
UIMAFramework.getLogger(getClass()).log(SEVERE, | |
"Failed to initialize fallback ResourceManager.", e); | |
} | |
return UIMAFramework.newDefaultResourceManager(); | |
} | |
public void setResourceManager(ResourceManager resourceManager) { | |
this.resourceManager = resourceManager; | |
} | |
public void addMacroAction(String name, Map<String, String> def, Set<String> vars, | |
List<AbstractRutaAction> actions) { | |
macroActions.put(name, new ImmutableTriple<>(def, actions, vars)); | |
} | |
public void addMacroCondition(String name, Map<String, String> def, Set<String> vars, | |
List<AbstractRutaCondition> conditions) { | |
macroConditions.put(name, new ImmutableTriple<>(def, conditions, vars)); | |
} | |
public boolean isMacroAction(String name) { | |
boolean isDefined = macroActions.keySet().contains(name); | |
if (isDefined) { | |
return true; | |
} else if (owner != null && owner.getParent() != null) { | |
return owner.getParent().getEnvironment().isMacroAction(name); | |
} | |
return false; | |
} | |
public boolean isMacroCondition(String name) { | |
boolean isDefined = macroConditions.keySet().contains(name); | |
if (isDefined) { | |
return true; | |
} else if (owner != null && owner.getParent() != null) { | |
return owner.getParent().getEnvironment().isMacroCondition(name); | |
} | |
return false; | |
} | |
public Triple<Map<String, String>, List<AbstractRutaAction>, Set<String>> getMacroAction( | |
String name) { | |
Triple<Map<String, String>, List<AbstractRutaAction>, Set<String>> definition = macroActions | |
.get(name); | |
if (definition != null) { | |
return definition; | |
} else if (owner != null && owner.getParent() != null) { | |
return owner.getParent().getEnvironment().getMacroAction(name); | |
} | |
return null; | |
} | |
public Triple<Map<String, String>, List<AbstractRutaCondition>, Set<String>> getMacroCondition( | |
String name) { | |
Triple<Map<String, String>, List<AbstractRutaCondition>, Set<String>> definition = macroConditions | |
.get(name); | |
if (definition != null) { | |
return definition; | |
} else if (owner != null && owner.getParent() != null) { | |
return owner.getParent().getEnvironment().getMacroCondition(name); | |
} | |
return null; | |
} | |
public void addAliasVariable(String name, String var) { | |
variableAliases.put(name, var); | |
} | |
public void removeAliasVariable(String name) { | |
variableAliases.remove(name); | |
} | |
public String getVariableNameOfExpression(IRutaExpression expression) { | |
String verbalize = verbalizer.verbalize(expression); | |
return verbalize; | |
} | |
public Map<String, Type> getTypes() { | |
return types; | |
} | |
public Set<String> getDeclaredAnnotationTypes() { | |
return declaredAnnotationTypes; | |
} | |
public Set<String> getTypesystems() { | |
return typesystems; | |
} | |
public Map<String, String> getNamespaces() { | |
return namespaces; | |
} | |
public void addMatchToVariable(RuleMatch ruleMatch, RuleElement element, MatchContext context, | |
RutaStream stream) { | |
String var = element.getLabel(); | |
if (StringUtils.isBlank(var)) { | |
return; | |
} | |
List<AnnotationFS> annotations = ruleMatch.getMatchedAnnotationsOfElement(element); | |
addAnnotationsToVariable(annotations, var, context); | |
} | |
public void removeVariableValue(String var, MatchContext context) { | |
if (StringUtils.isBlank(var)) { | |
return; | |
} | |
setTempVariableValue(var, null); | |
} | |
public void addAnnotationsToVariable(List<AnnotationFS> annotations, String var, | |
MatchContext context) { | |
if (StringUtils.isBlank(var)) { | |
return; | |
} | |
Class<?> variableType = getVariableType(var); | |
if (List.class.equals(variableType) && AnnotationFS.class.equals(getVariableGenericType(var))) { | |
setTempVariableValue(var, annotations); | |
} else if (AnnotationFS.class.equals(variableType)) { | |
if (context.getDirection()) { | |
AnnotationFS annotation = null; | |
if (annotations != null) { | |
if (context.getDirection()) { | |
annotation = annotations.get(annotations.size() - 1); | |
} else { | |
annotation = annotations.get(0); | |
} | |
} | |
setTempVariableValue(var, annotation); | |
} | |
} | |
} | |
public void acceptTempVariableValues(Collection<String> localVariables) { | |
for (String variableName : localVariables) { | |
if (tempVariableValues.containsKey(variableName)) { | |
Object value = tempVariableValues.get(variableName); | |
setVariableValue(variableName, value); | |
} | |
} | |
clearTempVariables(localVariables); | |
} | |
public void clearTempVariables(Collection<String> localVariables) { | |
for (String variableName : localVariables) { | |
tempVariableValues.remove(variableName); | |
} | |
} | |
public void ensureMaterializedInitialValues(MatchContext matchContext, RutaStream stream) { | |
for (Entry<String, Object> entry : new ArrayList<>(initializedVariables.entrySet())) { | |
String var = entry.getKey(); | |
Object value = entry.getValue(); | |
if (value instanceof IAnnotationExpression || value instanceof IBooleanExpression | |
|| value instanceof INumberExpression || value instanceof IStringExpression | |
|| value instanceof ITypeExpression) { | |
Class<?> clazz = variableTypes.get(var); | |
Object expressionValue = stream.getExpressionValue(clazz, (IRutaExpression) value, | |
matchContext); | |
initializedVariables.put(var, expressionValue); | |
variableValues.put(var, expressionValue); | |
} else if (value instanceof List) { | |
List<?> list = (List<?>) value; | |
List<Object> newList = new ArrayList<>(list.size()); | |
Class<?> clazz = variableGenericTypes.get(var); | |
for (Object each : list) { | |
if (each instanceof IAnnotationExpression || each instanceof IBooleanExpression | |
|| each instanceof INumberExpression || each instanceof IStringExpression | |
|| each instanceof ITypeExpression) { | |
Object expressionValue = stream.getExpressionValue(clazz, (IRutaExpression) each, | |
matchContext); | |
newList.add(expressionValue); | |
} else { | |
newList.add(each); | |
} | |
} | |
initializedVariables.put(var, newList); | |
variableValues.put(var, new ArrayList<>(newList)); | |
} | |
} | |
} | |
} |