blob: 0bfec221ce23a97ac1617a8f129931b7ad83e46e [file] [log] [blame]
/*
* 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.ide.validator;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
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.Stack;
import java.util.TreeMap;
import org.antlr.runtime.Token;
import org.apache.commons.lang3.StringUtils;
import org.apache.uima.UIMAFramework;
import org.apache.uima.cas.CAS;
import org.apache.uima.resource.ResourceManager;
import org.apache.uima.resource.impl.ResourceManager_impl;
import org.apache.uima.resource.metadata.FeatureDescription;
import org.apache.uima.resource.metadata.TypeDescription;
import org.apache.uima.resource.metadata.TypeSystemDescription;
import org.apache.uima.resource.metadata.impl.FeatureDescription_impl;
import org.apache.uima.ruta.ide.RutaIdeUIPlugin;
import org.apache.uima.ruta.ide.core.IRutaKeywords;
import org.apache.uima.ruta.ide.core.RutaCorePreferences;
import org.apache.uima.ruta.ide.core.RutaExtensionManager;
import org.apache.uima.ruta.ide.core.RutaKeywordsManager;
import org.apache.uima.ruta.ide.core.builder.RutaProjectUtils;
import org.apache.uima.ruta.ide.core.extensions.IIDEActionExtension;
import org.apache.uima.ruta.ide.core.extensions.IIDEBlockExtension;
import org.apache.uima.ruta.ide.core.extensions.IIDEBooleanFunctionExtension;
import org.apache.uima.ruta.ide.core.extensions.IIDEConditionExtension;
import org.apache.uima.ruta.ide.core.extensions.IIDENumberFunctionExtension;
import org.apache.uima.ruta.ide.core.extensions.IIDEStringFunctionExtension;
import org.apache.uima.ruta.ide.core.extensions.IIDETypeFunctionExtension;
import org.apache.uima.ruta.ide.core.extensions.IRutaExtension;
import org.apache.uima.ruta.ide.parser.ast.FeatureMatchExpression;
import org.apache.uima.ruta.ide.parser.ast.ForEachBlock;
import org.apache.uima.ruta.ide.parser.ast.NullExpression;
import org.apache.uima.ruta.ide.parser.ast.RutaAction;
import org.apache.uima.ruta.ide.parser.ast.RutaBlock;
import org.apache.uima.ruta.ide.parser.ast.RutaCondition;
import org.apache.uima.ruta.ide.parser.ast.RutaDeclareDeclarationsStatement;
import org.apache.uima.ruta.ide.parser.ast.RutaExpression;
import org.apache.uima.ruta.ide.parser.ast.RutaFeatureDeclaration;
import org.apache.uima.ruta.ide.parser.ast.RutaFunction;
import org.apache.uima.ruta.ide.parser.ast.RutaImportStatement;
import org.apache.uima.ruta.ide.parser.ast.RutaImportTypesStatement;
import org.apache.uima.ruta.ide.parser.ast.RutaListExpression;
import org.apache.uima.ruta.ide.parser.ast.RutaMacroDeclaration;
import org.apache.uima.ruta.ide.parser.ast.RutaPackageDeclaration;
import org.apache.uima.ruta.ide.parser.ast.RutaRegExpRule;
import org.apache.uima.ruta.ide.parser.ast.RutaRule;
import org.apache.uima.ruta.ide.parser.ast.RutaRuleElement;
import org.apache.uima.ruta.ide.parser.ast.RutaStatementConstants;
import org.apache.uima.ruta.ide.parser.ast.RutaStringExpression;
import org.apache.uima.ruta.ide.parser.ast.RutaStructureAction;
import org.apache.uima.ruta.ide.parser.ast.RutaTypeConstants;
import org.apache.uima.ruta.ide.parser.ast.RutaTypeDeclaration;
import org.apache.uima.ruta.ide.parser.ast.RutaVariableDeclaration;
import org.apache.uima.ruta.ide.parser.ast.RutaVariableReference;
import org.apache.uima.util.InvalidXMLException;
import org.apache.uima.util.XMLInputSource;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.dltk.ast.ASTListNode;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.ASTVisitor;
import org.eclipse.dltk.ast.declarations.MethodDeclaration;
import org.eclipse.dltk.ast.expressions.Expression;
import org.eclipse.dltk.ast.expressions.NumericLiteral;
import org.eclipse.dltk.ast.expressions.StringLiteral;
import org.eclipse.dltk.ast.references.SimpleReference;
import org.eclipse.dltk.ast.statements.Statement;
import org.eclipse.dltk.compiler.problem.IProblem;
import org.eclipse.dltk.compiler.problem.IProblemReporter;
import org.eclipse.dltk.compiler.problem.ProblemSeverity;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.builder.ISourceLineTracker;
import org.eclipse.jface.preference.IPreferenceStore;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
public class LanguageCheckerVisitor extends ASTVisitor {
private IProblemReporter pr;
private ISourceLineTracker linetracker;
private ISourceModule sourceModule;
private Map<String, IIDEConditionExtension> conditionExtensions;
private Map<String, IIDEActionExtension> actionExtensions;
private Map<String, IIDENumberFunctionExtension> numberFunctionExtensions;
private Map<String, IIDEBooleanFunctionExtension> booleanFunctionExtensions;
private Map<String, IIDEStringFunctionExtension> stringFunctionExtensions;
private Map<String, IIDETypeFunctionExtension> typeFunctionExtensions;
private Map<String, IIDEBlockExtension> blockExtensions;
/**
* 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;
/**
* Known variables for each block environment
*/
private final Stack<Map<String, Integer>> knownLocalVariables;
/**
* Name of each block
*/
private final Stack<String> blocks;
/**
* each (inlined) rules
*/
private final Stack<RutaRule> rules;
/**
* Caching the matched type of a rule element
*/
private String matchedType;
/**
* Caching the declared package of the script
*/
private String packageName = "";
/**
* Mapping all long type names of the type system to their type description
*/
private Map<String, TypeDescription> typeDescriptionMap;
/**
* Mapping all long type names of all declared feature description
*/
private Map<String, Set<FeatureDescription>> featureDescriptionMap;
/**
* The type system description of the script file
*/
private TypeSystemDescription typeSystemDescription;
private final String implicitString = "Implicit";
private Set<String> finalTypes;
private boolean reportWarningOnShortNames;
private RutaCheckerProblemFactory problemFactory;
private ResourceManager resourceManager;
private Set<String> allLongTypeNames;
private String parentTypeInDeclaration;
private ClassLoader classLoader;
private String packagePathString;
private boolean packageChecked = false;
private Collection<String> currentLabels = new HashSet<>();
public LanguageCheckerVisitor(IProblemReporter problemReporter, ISourceLineTracker linetracker,
ISourceModule sourceModule, ClassLoader classLoader) {
super();
this.pr = problemReporter;
this.linetracker = linetracker;
this.sourceModule = sourceModule;
this.classLoader = classLoader;
this.problemFactory = new RutaCheckerProblemFactory(sourceModule.getElementName(), linetracker);
namespaces = new TreeMap<String, String>();
ambiguousTypeAlias = new TreeMap<String, Set<String>>();
allLongTypeNames = new HashSet<String>();
knownLocalVariables = new Stack<Map<String, Integer>>();
knownLocalVariables.push(new HashMap<String, Integer>());
blocks = new Stack<String>();
rules = new Stack<RutaRule>();
packagePathString = "";
initializePredefinedInformation();
initializeExtensionInformation();
IProject project = sourceModule.getScriptProject().getProject();
IPath location = sourceModule.getResource().getLocation();
try {
IPath packagePath = RutaProjectUtils.getPackagePath(location, project);
if (packagePath != null) {
packagePathString = packagePath.toPortableString().replaceAll("/", ".");
}
} catch (CoreException e) {
RutaIdeUIPlugin.error(e);
}
IPreferenceStore store = RutaIdeUIPlugin.getDefault().getPreferenceStore();
reportWarningOnShortNames = !store
.getBoolean(RutaCorePreferences.BUILDER_IGNORE_DUPLICATE_SHORTNAMES);
}
@Override
public boolean visit(Statement s) throws Exception {
if (s instanceof RutaPackageDeclaration) {
this.packageName = ((RutaPackageDeclaration) s).getName();
checkPackage(s);
return false;
}
if (s instanceof RutaMacroDeclaration) {
RutaMacroDeclaration decl = (RutaMacroDeclaration) s;
Map<Token, Token> definition = decl.getDefinition();
String name = decl.getName();
int kind = decl.getKind();
if (kind == RutaTypeConstants.RUTA_TYPE_A) {
actionExtensions.put(name, null);
} else if (kind == RutaTypeConstants.RUTA_TYPE_C) {
conditionExtensions.put(name, null);
}
Set<Entry<Token, Token>> entrySet = definition.entrySet();
Map<String, Integer> map = new HashMap<>();
for (Entry<Token, Token> entry : entrySet) {
String varName = entry.getKey().getText();
String varType = entry.getValue().getText();
int vt = getType(varType);
map.put(varName, vt);
}
knownLocalVariables.push(map);
}
if (s instanceof RutaImportTypesStatement) {
RutaImportTypesStatement stmt = (RutaImportTypesStatement) s;
SimpleReference tsExpr = (SimpleReference) stmt.getExpression();
Token typeToken = stmt.getTypeToken();
Token pkgToken = stmt.getPkgToken();
Token aliasToken = stmt.getAliasToken();
if (tsExpr != null) {
String localPath = tsExpr.getName();
processCompleteTypeSystemImport(tsExpr, localPath, typeToken, pkgToken, aliasToken);
} else {
// TODO package import not supported in Workbench
}
} else if (s instanceof RutaImportStatement) {
// handle type system imports
if (((RutaImportStatement) s).getType() == RutaStatementConstants.S_IMPORT_TYPESYSTEM) {
SimpleReference sRef = (SimpleReference) ((RutaImportStatement) s).getExpression();
String localPath = sRef.getName();
processCompleteTypeSystemImport(sRef, localPath);
return false;
}
// handle script-imports
if (((RutaImportStatement) s).getType() == RutaStatementConstants.S_IMPORT_SCRIPT) {
SimpleReference sRef = (SimpleReference) ((RutaImportStatement) s).getExpression();
String localPath = sRef.getName();
// HOTFIX Peter add also the imported types of the imported type system!
try {
URL url = null;
IFile file = RutaCheckerUtils.checkScriptImport(localPath,
sourceModule.getScriptProject());
if (file == null) {
String typesystemSuffix = RutaProjectUtils
.getTypeSystemSuffix(sourceModule.getScriptProject().getProject());
url = RutaCheckerUtils.checkImportExistence(localPath + typesystemSuffix, "xml",
classLoader);
}
if (file == null && url == null) {
pr.reportProblem(problemFactory.createFileNotFoundProblem(sRef, localPath));
} else {
IProject referredProject = sourceModule.getScriptProject().getProject();
if (file != null) {
// script in other project? use that if the file was found in the workspace
referredProject = file.getProject();
IPath typeSystemDescriptorPath = RutaProjectUtils.getTypeSystemDescriptorPath(
file.getLocation(), referredProject, classLoader);
TypeSystemDescription tsDesc = importCompleteTypeSystem(typeSystemDescriptorPath,
url);
List<String> checkDuplicateShortNames = checkOnAmbiguousShortNames(tsDesc);
if (!checkDuplicateShortNames.isEmpty()) {
pr.reportProblem(problemFactory.createDuplicateShortNameInImported(sRef, localPath,
checkDuplicateShortNames, ProblemSeverity.WARNING));
}
}
}
} catch (IOException e) {
pr.reportProblem(problemFactory.createFileNotFoundProblem(sRef, localPath));
}
return false;
}
}
if (s instanceof RutaDeclareDeclarationsStatement) {
RutaDeclareDeclarationsStatement dds = (RutaDeclareDeclarationsStatement) s;
ASTNode parent = dds.getParent();
if (parent != null && parent instanceof RutaVariableReference) {
RutaVariableReference p = (RutaVariableReference) parent;
String name = p.getName();
name = expand(name);
parentTypeInDeclaration = name;
// TODO remember name for new types and their features!
if (finalTypes.contains(name)) {
IProblem problem = problemFactory.createInheritenceFinalProblem(p);
pr.reportProblem(problem);
}
}
return true;
}
if (s instanceof RutaTypeDeclaration) {
RutaTypeDeclaration newType = (RutaTypeDeclaration) s;
String shortName = newType.getName();
String longName = getLongNameOfNewType(shortName);
if (namespaces.values().contains(longName)) {
IProblem problem = problemFactory.createIdConflictsWithTypeProblem(newType);
pr.reportProblem(problem);
return false;
}
if (reportWarningOnShortNames && namespaces.containsKey(shortName)) {
IProblem problem = problemFactory.createDuplicateShortName(newType,
ProblemSeverity.WARNING);
pr.reportProblem(problem);
return false;
}
if (knowsVariable(shortName)) {
IProblem problem = problemFactory.createIdConflictsWithVariableProblem(newType);
pr.reportProblem(problem);
return false;
}
List<RutaFeatureDeclaration> features = newType.getFeatures();
Set<FeatureDescription> feats = new HashSet<FeatureDescription>();
if (parentTypeInDeclaration != null) {
Set<FeatureDescription> set = featureDescriptionMap.get(parentTypeInDeclaration);
if (set != null) {
feats.addAll(set);
}
}
if (features != null) {
for (RutaFeatureDeclaration each : features) {
// TODO create correct feature description! Works right now because the type is not
// checked
String type = each.getType();
type = translate(type);
type = expand(type);
FeatureDescription f = new FeatureDescription_impl(each.getName(), "", type);
feats.add(f);
if (type.equals("INT") || type.equals("STRING") || type.equals("DOUBLE")
|| type.equals("FLOAT") || type.equals("BOOLEAN")) {
continue;
}
if (!namespaces.keySet().contains(type) && !namespaces.values().contains(type)) {
IProblem problem = problemFactory.createUnknownFeatureTypeProblem(each);
pr.reportProblem(problem);
}
}
featureDescriptionMap.put(longName, feats);
}
addDeclaredType(shortName);
return false;
}
if (s instanceof RutaVariableDeclaration) {
RutaVariableDeclaration newVar = (RutaVariableDeclaration) s;
if (knowsVariable(newVar.getName())) {
IProblem problem = problemFactory.createIdConflictsWithVariableProblem(newVar);
pr.reportProblem(problem);
return false;
}
if (namespaces.containsKey(newVar.getName())) {
IProblem problem = problemFactory.createIdConflictsWithTypeProblem(newVar);
pr.reportProblem(problem);
return false;
}
knownLocalVariables.peek().put(newVar.getName(), newVar.getKind());
return false;
}
if (s instanceof RutaRegExpRule) {
RutaRegExpRule rule = (RutaRegExpRule) s;
Map<Expression, Map<Expression, Expression>> faMap = rule.getFeats();
Set<Entry<Expression, Map<Expression, Expression>>> typeEntrySet = faMap.entrySet();
for (Entry<Expression, Map<Expression, Expression>> entry : typeEntrySet) {
Expression struct = entry.getKey();
String structure = "";
if (struct != null) {
structure = sourceModule.getSource().substring(struct.sourceStart(), struct.sourceEnd());
structure = expand(structure);
}
Map<Expression, Expression> fmap = entry.getValue();
Set<Expression> keySet = fmap.keySet();
for (Expression fkey : keySet) {
if (fkey instanceof RutaExpression && fkey.getKind() == RutaTypeConstants.RUTA_TYPE_S) {
String feat = fkey.toString();
feat = getFeatureName(fkey, feat);
boolean findFeature = findFeature(structure, feat, -1);
if (!findFeature) {
IProblem problem = problemFactory.createUnknownFeatureProblem(fkey, structure);
pr.reportProblem(problem);
}
}
}
}
}
if (s instanceof RutaRule) {
if (rules.isEmpty()) {
collectAllLabels((RutaRule) s);
}
rules.push((RutaRule) s);
}
return true;
}
private void collectAllLabels(RutaRule rule) {
try {
RuleElementLabelVisitor visitor = new RuleElementLabelVisitor();
rule.traverse(visitor);
currentLabels = visitor.getLabels();
} catch (Exception e) {
RutaIdeUIPlugin.error(e);
}
}
private void checkPackage(ASTNode node) {
if (!StringUtils.equals(packageName, packagePathString) && !packageChecked) {
pr.reportProblem(problemFactory.createWrongPackageProblem(node));
}
packageChecked = true;
}
private void processCompleteTypeSystemImport(SimpleReference sRef, String localPath)
throws CoreException {
processCompleteTypeSystemImport(sRef, localPath, null, null, null);
}
private void processCompleteTypeSystemImport(SimpleReference sRef, String localPath,
Token typeToken, Token pkgToken, Token aliasToken) throws CoreException {
try {
URL url = null;
IFile file = RutaCheckerUtils.checkTypeSystemImport(localPath,
sourceModule.getScriptProject());
if (file == null) {
url = RutaCheckerUtils.checkImportExistence(localPath, "xml", classLoader);
}
if (file == null && url == null) {
pr.reportProblem(problemFactory.createFileNotFoundProblem(sRef, localPath));
} else {
IPath path = file == null ? null : file.getLocation();
TypeSystemDescription tsDesc = importTypeSystem(path, url, typeToken, pkgToken, aliasToken);
if (reportWarningOnShortNames) {
List<String> checkDuplicateShortNames = checkOnAmbiguousShortNames(tsDesc);
if (!checkDuplicateShortNames.isEmpty()) {
pr.reportProblem(problemFactory.createDuplicateShortNameInImported(sRef, localPath,
checkDuplicateShortNames, ProblemSeverity.WARNING));
}
}
}
} catch (IOException e) {
pr.reportProblem(problemFactory.createFileNotFoundProblem(sRef, localPath));
} catch (InvalidXMLException e) {
pr.reportProblem(problemFactory.createXMLProblem(sRef, localPath));
}
}
private List<String> checkOnAmbiguousShortNames(TypeSystemDescription tsDesc) {
List<String> checkDuplicateShortNames = new ArrayList<String>();
for (TypeDescription each : tsDesc.getTypes()) {
String longName = each.getName();
String shortName = getShortName(longName);
Set<String> set = ambiguousTypeAlias.get(shortName);
if (set != null && set.size() > 1) {
checkDuplicateShortNames.addAll(set);
}
}
return checkDuplicateShortNames;
}
private TypeSystemDescription importTypeSystem(IPath path, URL url, Token typeToken,
Token pkgToken, Token aliasToken)
throws InvalidXMLException, IOException, MalformedURLException, CoreException {
TypeSystemDescription tsDesc = null;
if (path != null) {
tsDesc = UIMAFramework.getXMLParser()
.parseTypeSystemDescription(new XMLInputSource(path.toFile()));
} else {
tsDesc = UIMAFramework.getXMLParser().parseTypeSystemDescription(new XMLInputSource(url));
}
ResourceManager resMgr = getResourceManager(classLoader);
tsDesc.resolveImports(resMgr);
for (TypeDescription each : tsDesc.getTypes()) {
String longName = each.getName();
String shortName = getShortName(longName);
if (pkgToken != null) {
String pkg = pkgToken.getText();
if (!longName.startsWith(pkg + ".")) {
continue;
}
}
if (typeToken != null) {
String type = typeToken.getText();
if (!longName.equals(type)) {
continue;
}
}
if (aliasToken != null) {
String alias = aliasToken.getText();
if (typeToken == null) {
shortName = alias + "." + shortName;
} else {
shortName = alias;
}
}
importType(longName, shortName);
}
return tsDesc;
}
private ResourceManager getResourceManager(ClassLoader classloader)
throws MalformedURLException, CoreException {
if (resourceManager == null) {
resourceManager = new ResourceManager_impl(classloader);
List<IFolder> folders = RutaProjectUtils
.getAllDescriptorFolders(sourceModule.getScriptProject().getProject());
StringBuilder sb = new StringBuilder();
Iterator<IFolder> iterator = folders.iterator();
while (iterator.hasNext()) {
IFolder iFolder = iterator.next();
sb.append(iFolder.getLocation().toPortableString());
if (iterator.hasNext()) {
sb.append(System.getProperty("path.separator"));
}
}
resourceManager.setDataPath(sb.toString());
}
return resourceManager;
}
@Override
public boolean visit(Expression s) throws Exception {
if (s instanceof RutaRuleElement) {
RutaRuleElement re = (RutaRuleElement) s;
Expression head = re.getHead();
if (head instanceof FeatureMatchExpression) {
FeatureMatchExpression fme = (FeatureMatchExpression) head;
String text = fme.getFeature().getText();
int lastIndexOf = text.lastIndexOf('.');
String twf = text.substring(0, lastIndexOf);
Integer variableType = getVariableType(twf);
if (variableType != null && variableType == RutaTypeConstants.RUTA_TYPE_AT) {
matchedType = twf;
} else {
twf = expand(twf);
matchedType = isFeatureMatch(twf);
}
} else if (head != null) {
matchedType = sourceModule.getSource().substring(head.sourceStart(), head.sourceEnd());
}
// cache long name
matchedType = expand(matchedType);
if (matchedType == null) {
matchedType = "uima.tcas.Annotation";
}
}
if (s instanceof FeatureMatchExpression) {
FeatureMatchExpression fme = (FeatureMatchExpression) s;
String featText = fme.getFeature().getText();
// HOTFIX: parser creates wrong AST element
if (allLongTypeNames.contains(featText)) {
return true;
}
if (namespaces.keySet().contains(featText)) {
// wrong ast elements, alias interpreted as feature expression
return false;
}
checkTypeOfFeatureMatch(featText, fme);
return true;
}
if (s instanceof RutaVariableReference) {
if (s instanceof NullExpression) {
return false;
}
RutaVariableReference ref = (RutaVariableReference) s;
if (ref.getType() == RutaTypeConstants.RUTA_TYPE_WT
|| ref.getType() == RutaTypeConstants.RUTA_TYPE_WL) {
if (StringUtils.isBlank(ref.getName())) {
// declaration with a string expression: do not check
return false;
}
}
if ((ref.getType() & RutaTypeConstants.RUTA_TYPE_AT) != 0) {
// types
String name = ref.getName();
if (name.equals("Document")) {
return false;
}
Set<String> set = ambiguousTypeAlias.get(name);
if (set != null && !set.isEmpty()) {
pr.reportProblem(
problemFactory.createAmbiguousShortName(ref, set, ProblemSeverity.ERROR));
return false;
}
if (namespaces.keySet().contains(name) || namespaces.values().contains(name)
|| allLongTypeNames.contains(name)) {
return false;
}
Integer variableType = getVariableType(name);
if (variableType != null && (variableType == RutaTypeConstants.RUTA_TYPE_AT
|| variableType == RutaTypeConstants.RUTA_TYPE_UA
|| variableType == RutaTypeConstants.RUTA_TYPE_UAL)) {
return false;
}
if (isFeatureMatch(name) != null) {
return false;
}
if (isLabel(name)) {
return false;
}
if (name.indexOf(".") != -1) {
String[] split = name.split("[.]");
if (StringUtils.equals(split[split.length - 1], "ct")
|| StringUtils.equals(split[split.length - 1], "coveredText")) {
return false;
}
Integer prefixType = getVariableType(split[0]);
if (prefixType == RutaTypeConstants.RUTA_TYPE_UA
|| prefixType == RutaTypeConstants.RUTA_TYPE_UAL) {
return false;
}
}
pr.reportProblem(problemFactory.createTypeProblem(ref, sourceModule));
return false;
}
if (!isVariableDeclared(ref)) {
return false;
}
checkTypeOfVariable(ref);
return false;
}
// check assign types
if (s instanceof RutaAction) {
RutaAction tma = (RutaAction) s;
String actionName = sourceModule.getSource().substring(tma.getNameStart(), tma.getNameEnd());
String[] keywords = RutaKeywordsManager.getKeywords(IRutaKeywords.ACTION);
List<String> asList = Arrays.asList(keywords);
if (!StringUtils.isEmpty(actionName) && !"-".equals(actionName)
&& !asList.contains(actionName) && !implicitString.equals(tma.getName())
&& !actionExtensions.keySet().contains(actionName)) {
IProblem problem = problemFactory.createUnknownActionProblem(tma);
pr.reportProblem(problem);
}
IRutaExtension extension = actionExtensions.get(actionName);
if (extension != null) {
extension.checkSyntax(tma, problemFactory, pr);
}
if (tma.getName().equals("GETFEATURE") || tma.getName().equals("SETFEATURE")) {
List<?> childs = tma.getChilds();
RutaStringExpression stringExpr = (RutaStringExpression) childs.get(0);
String feat = stringExpr.toString();
feat = getFeatureName(stringExpr, feat);
boolean featureFound = findFeature(matchedType, feat, -1);
if (!featureFound) {
IProblem problem = problemFactory.createUnknownFeatureProblem(stringExpr, matchedType);
pr.reportProblem(problem);
}
}
if (s instanceof RutaStructureAction) {
RutaStructureAction sa = (RutaStructureAction) s;
Expression struct = sa.getStructure();
String structure = null;
if (struct != null) {
structure = sourceModule.getSource().substring(struct.sourceStart(), struct.sourceEnd());
structure = expand(structure);
}
Map<Expression, Expression> assignments = sa.getAssignments();
// hotfix... correct name in ast
String action = sourceModule.getSource().substring(sa.getNameStart(), sa.getNameEnd());
if (assignments != null && !action.equals("TRIE")) {
for (Expression each : assignments.keySet()) {
// TODO refactor to visitor?
String feat = each.toString();
// List<?> childs = each.getChilds();
feat = getFeatureName(each, feat);
boolean featureFound = findFeature(structure, feat, -1);
if (!featureFound) {
IProblem problem = problemFactory.createUnknownFeatureProblem(each, structure);
pr.reportProblem(problem);
}
}
} else if (assignments != null && action.equals("TRIE")) {
for (Expression each : assignments.values()) {
if (each instanceof RutaListExpression) {
RutaListExpression rle = (RutaListExpression) each;
List<?> childs = rle.getExprs().getChilds();
if (childs.size() != 2 && childs.size() != 3) {
IProblem problem = problemFactory.createWrongNumberOfArgumentsProblem(actionName,
rle, 2);
pr.reportProblem(problem);
}
Object arg1 = childs.get(0);
if (arg1 instanceof RutaExpression) {
RutaExpression e1 = (RutaExpression) arg1;
if (e1.getKind() != RutaTypeConstants.RUTA_TYPE_AT) {
IProblem problem = problemFactory.createWrongArgumentTypeProblem(e1, "Type");
pr.reportProblem(problem);
}
}
Object arg2 = childs.get(1);
if (arg2 instanceof RutaExpression) {
RutaExpression e2 = (RutaExpression) arg2;
if (e2.getKind() != RutaTypeConstants.RUTA_TYPE_S) {
IProblem problem = problemFactory.createWrongArgumentTypeProblem(e2, "String");
pr.reportProblem(problem);
}
}
}
}
}
}
}
if (s instanceof RutaCondition) {
RutaCondition cond = (RutaCondition) s;
String conditionName = sourceModule.getSource().substring(cond.getNameStart(),
cond.getNameEnd());
String[] keywords = RutaKeywordsManager.getKeywords(IRutaKeywords.CONDITION);
List<String> asList = Arrays.asList(keywords);
if (!StringUtils.isEmpty(conditionName) && !"-".equals(conditionName)
&& !asList.contains(conditionName) && !implicitString.equals(cond.getName())
&& !conditionExtensions.keySet().contains(conditionName)) {
IProblem problem = problemFactory.createUnknownConditionProblem(cond);
pr.reportProblem(problem);
}
IRutaExtension extension = conditionExtensions.get(conditionName);
if (extension != null) {
// boolean checkSyntax =
extension.checkSyntax(cond, problemFactory, pr);
}
if (conditionName.equals("FEATURE")) {
if (matchedType != null) {
List<?> args = cond.getChilds();
RutaStringExpression se = (RutaStringExpression) args.get(0);
String feat = se.toString();
feat = getFeatureName(se, feat);
boolean featureFound = findFeature(matchedType, feat, -1);
if (!featureFound) {
String featureMatch = isFeatureMatch(matchedType);
if (featureMatch != null) {
featureFound = findFeature(featureMatch, feat, -1);
}
}
if (!featureFound) {
IProblem problem = problemFactory.createUnknownFeatureProblem(se, matchedType);
pr.reportProblem(problem);
}
}
}
if (conditionName.equals("CONTAINS")) {
List<?> args = cond.getChilds();
boolean valid = checkContainsArguments(args);
if (!valid) {
IProblem problem = problemFactory.createWrongArgumentTypeProblem(cond,
"different combination of arguments.");
pr.reportProblem(problem);
}
}
}
if (s instanceof RutaFunction) {
RutaFunction f = (RutaFunction) s;
String name = f.getName();
if (s.getKind() == RutaTypeConstants.RUTA_TYPE_AT) {
IRutaExtension extension = typeFunctionExtensions.get(name);
if (extension != null) {
extension.checkSyntax(s, problemFactory, pr);
}
} else if (s.getKind() == RutaTypeConstants.RUTA_TYPE_B) {
IRutaExtension extension = booleanFunctionExtensions.get(name);
if (extension != null) {
extension.checkSyntax(s, problemFactory, pr);
}
} else if (s.getKind() == RutaTypeConstants.RUTA_TYPE_N) {
IRutaExtension extension = numberFunctionExtensions.get(name);
if (extension != null) {
extension.checkSyntax(s, problemFactory, pr);
}
} else if (s.getKind() == RutaTypeConstants.RUTA_TYPE_S) {
IRutaExtension extension = stringFunctionExtensions.get(name);
if (extension != null) {
extension.checkSyntax(s, problemFactory, pr);
}
}
}
return true;
}
@SuppressWarnings("unused")
private boolean checkContainsArguments(List<?> args) {
if (args.size() == 1) {
Object arg = args.get(0);
// if (arg instanceof ITypeExpression) {
return true;
// }
} else if (args.size() == 2) {
Object arg1 = args.get(0);
Object arg2 = args.get(1);
// if (arg1 instanceof ListExpression) {
return true;
// }
} else if (args.size() == 3) {
Object arg1 = args.get(0);
Object arg2 = args.get(1);
Object arg3 = args.get(2);
// if (arg1 instanceof ITypeExpression && arg2 instanceof INumberExpression
// && arg3 instanceof INumberExpression) {
return true;
// }
} else if (args.size() == 4) {
Object arg1 = args.get(0);
Object arg2 = args.get(1);
Object arg3 = args.get(2);
Object arg4 = args.get(3);
// if (arg1 instanceof ITypeExpression && arg2 instanceof INumberExpression
// && arg3 instanceof INumberExpression && arg4 instanceof IBooleanExpression) {
return true;
// }
} else if (args.size() == 5) {
Object arg1 = args.get(0);
Object arg2 = args.get(1);
Object arg3 = args.get(2);
Object arg4 = args.get(3);
Object arg5 = args.get(3);
// if (arg1 instanceof ListExpression && arg3 instanceof INumberExpression
// && arg4 instanceof INumberExpression && arg5 instanceof IBooleanExpression) {
return true;
// }
}
return false;
}
private boolean isLabel(String name) {
if (currentLabels.contains(name)) {
return true;
}
if (name.contains(".")) {
String[] split = name.split("[.]");
if (split.length > 0) {
return currentLabels.contains(split[0]);
}
}
return false;
}
private String expand(String shortName) {
if (shortName == null) {
return null;
}
String longName = shortName;
String string = namespaces.get(shortName);
if (string != null) {
longName = string;
}
return longName;
}
private void checkTypeOfFeatureMatch(String featText, FeatureMatchExpression fme) {
int lastIndexOf = featText.lastIndexOf(".");
int firstIndexOf = featText.indexOf(".");
if (lastIndexOf == -1) {
return;
}
String bref = featText.substring(0, firstIndexOf);
String aref = featText.substring(0, lastIndexOf);
String fref = featText.substring(lastIndexOf + 1, featText.length());
if (currentLabels.contains(aref) || currentLabels.contains(bref)) {
return;
}
String match = isFeatureMatch(aref);
Integer variableType1 = getVariableType(aref);
Integer variableType2 = getVariableType(bref);
if (match == null && variableType1 != null && variableType2 != null
&& (variableType1 == RutaTypeConstants.RUTA_TYPE_AT
|| variableType2 == RutaTypeConstants.RUTA_TYPE_AT
|| variableType1 == RutaTypeConstants.RUTA_TYPE_UA)) {
// do not check on variables!
return;
}
// match expression against local annotation variables cannot be checked
if (variableType2 == RutaTypeConstants.RUTA_TYPE_UA
|| variableType2 == RutaTypeConstants.RUTA_TYPE_UAL) {
return;
}
match = expand(match);
if (match != null) {
int kind = -1;
if (fme.getValue() != null) {
kind = fme.getValue().getKind();
if (fme.getValue() instanceof StringLiteral) {
kind = RutaTypeConstants.RUTA_TYPE_S;
} else if (fme.getValue() instanceof NumericLiteral) {
kind = RutaTypeConstants.RUTA_TYPE_N;
} else if (fme.getValue() instanceof RutaVariableReference) {
kind = ((RutaVariableReference) fme.getValue()).getType();
} else if (fme.getValue() instanceof RutaFunction) {
// check on function deactivates, requires correct parsing of AST with external factory
kind = -1;
}
}
boolean findFeature = findFeature(match, fref, kind);
if (findFeature || fme.getValue() instanceof NullExpression) {
} else {
pr.reportProblem(problemFactory.createUnknownFeatureProblem(fme, aref));
}
} else {
pr.reportProblem(problemFactory.createTypeProblem(fme, sourceModule));
pr.reportProblem(problemFactory.createUnknownFeatureProblem(fme, aref));
}
}
@Override
public boolean endvisit(Expression s) throws Exception {
if (s instanceof RutaRuleElement) {
matchedType = null;
}
return super.endvisit(s);
}
@Override
public boolean endvisit(Statement s) throws Exception {
if (s instanceof RutaDeclareDeclarationsStatement) {
parentTypeInDeclaration = null;
}
if (s instanceof ForEachBlock) {
knownLocalVariables.pop();
}
if (s instanceof RutaMacroDeclaration) {
knownLocalVariables.pop();
}
if (!packageChecked) {
checkPackage(null);
}
if (s instanceof RutaRule) {
rules.pop();
if (rules.isEmpty()) {
currentLabels.clear();
}
}
return super.endvisit(s);
}
@Override
public boolean endvisit(MethodDeclaration s) throws Exception {
if (s instanceof RutaBlock) {
knownLocalVariables.pop();
blocks.pop();
}
return super.endvisit(s);
}
@Override
public boolean visit(MethodDeclaration s) throws Exception {
if (s instanceof RutaBlock) {
RutaBlock b = (RutaBlock) s;
String name = b.getName();
HashMap<String, Integer> map = new HashMap<String, Integer>();
if (b instanceof ForEachBlock) {
map.put(name, RutaTypeConstants.RUTA_TYPE_UA);
}
knownLocalVariables.push(map);
blocks.push(name);
// TODO add syntax check for block extensions
}
return true;
}
private boolean findFeature(String longTypeName, String featureName, int kind) {
if (longTypeName == null) {
return false;
}
if (longTypeName.equals("Document") || longTypeName.equals("org.apache.uima.ruta.type.Document")
|| longTypeName.equals("uima.tcas.DocumentAnnotation")) {
if (featureName.equals("language") || featureName.equals("begin")
|| featureName.equals("end")) {
return true;
}
}
if (featureName.equals("begin") || featureName.equals("end")) {
return kind == -1 || kind == RutaTypeConstants.RUTA_TYPE_N;
}
if (featureName.equals("ct") || featureName.equals("coveredText")) {
return kind == -1 || kind == RutaTypeConstants.RUTA_TYPE_S;
}
Set<FeatureDescription> set = featureDescriptionMap.get(longTypeName);
if (set != null) {
for (FeatureDescription featureDescription : set) {
String fName = featureDescription.getName();
// TODO check on correct feature type, e.g., the type of the annotation
if (fName.equals(featureName)
&& (kind == -1 || checkFeatureKind(featureDescription, kind))) {
return true;
}
}
}
return false;
}
private boolean checkFeatureKind(FeatureDescription f, int kind) {
if (kind == -1) {
return true;
}
String t = f.getRangeTypeName();
if (t.equals(CAS.TYPE_NAME_BOOLEAN) && RutaTypeConstants.RUTA_TYPE_B == kind) {
return true;
} else if (t.equals(CAS.TYPE_NAME_STRING) && RutaTypeConstants.RUTA_TYPE_S == kind) {
return true;
} else if ((t.equals(CAS.TYPE_NAME_BYTE) || t.equals(CAS.TYPE_NAME_DOUBLE)
|| t.equals(CAS.TYPE_NAME_FLOAT) || t.equals(CAS.TYPE_NAME_INTEGER)
|| t.equals(CAS.TYPE_NAME_LONG) || t.equals(CAS.TYPE_NAME_SHORT))
&& RutaTypeConstants.RUTA_TYPE_N == kind) {
return true;
} else if (RutaTypeConstants.RUTA_TYPE_AT == kind) {
return true;
}
return false;
}
private void addDeclaredType(String shortName) {
String longName = getLongNameOfNewType(shortName);
importType(longName, shortName);
}
private String getLongNameOfNewType(String shortName) {
String moduleName = sourceModule.getElementName();
moduleName = moduleName.substring(0, moduleName.length() - 5);
String packagePrefix = "";
if (!packageName.isEmpty()) {
packagePrefix = packageName + ".";
}
for (String each : blocks) {
packagePrefix += each + ".";
}
String longName = packagePrefix + moduleName + "." + shortName;
return longName;
}
/**
* 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) {
if (allLongTypeNames.contains(longName)) {
// TODO: in conflict with double import
// pr.reportProblem(problemFactory.createIdenticalLongTypeNameProblem(longName,
// sourceModule));
} else {
allLongTypeNames.add(longName);
}
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<String>(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);
}
}
}
private boolean knowsVariable(String name) {
for (Map<String, Integer> each : knownLocalVariables) {
if (each.containsKey(name)) {
return true;
}
}
return false;
}
private Integer getVariableType(String name) {
for (Map<String, Integer> each : knownLocalVariables) {
Integer integer = each.get(name);
if (integer != null) {
return integer;
}
}
return null;
}
private String getFeatureName(Expression expression, String defaultValue) {
// TODO refactor AST. This is not a really straightforward!
String result = defaultValue;
List<?> childs = expression.getChilds();
if (childs != null && !childs.isEmpty()) {
Object object = childs.get(0);
if (object instanceof ASTListNode) {
List<?> childs2 = ((ASTListNode) object).getChilds();
if (childs2 != null && !childs2.isEmpty()) {
Object object2 = childs2.get(0);
if (object2 instanceof StringLiteral) {
StringLiteral sl = (StringLiteral) object2;
result = sl.getValue().replaceAll("\"", "");
}
}
}
}
return result;
}
private void initializePredefinedInformation() {
typeDescriptionMap = new HashMap<String, TypeDescription>();
featureDescriptionMap = new HashMap<String, Set<FeatureDescription>>();
try {
typeSystemDescription = getTypeSystemOfScript();
IProject project = sourceModule.getScriptProject().getProject();
List<IFolder> descriptorFolders = RutaProjectUtils.getDescriptorFolders(project);
boolean exists = false;
for (IFolder iFolder : descriptorFolders) {
IPath basicTSD = iFolder.getLocation().append("BasicTypeSystem.xml");
exists = basicTSD.toFile().exists();
if (exists) {
importCompleteTypeSystem(basicTSD, null);
break;
}
}
if (!exists) {
// not in a common ruta project
// try to find the file in the classpath
URL resource = classLoader.getResource("org/apache/uima/ruta/engine/BasicTypeSystem.xml");
importCompleteTypeSystem(null, resource);
}
} catch (Exception e) {
RutaIdeUIPlugin.error(e);
}
if (typeSystemDescription != null) {
TypeDescription[] descriptions = typeSystemDescription.getTypes();
for (TypeDescription typeDescription : descriptions) {
String typeName = typeDescription.getName();
typeDescriptionMap.put(typeName, typeDescription);
}
for (TypeDescription typeDescription : descriptions) {
Set<FeatureDescription> allFeatures = getAllDeclaredFeatures(typeDescription,
typeDescriptionMap);
featureDescriptionMap.put(typeDescription.getName(), allFeatures);
}
}
List<String> uimaPredefTypes = Arrays.asList(new String[] { "uima.cas.Boolean", "uima.cas.Byte",
"uima.cas.Short", "uima.cas.Integer", "uima.cas.Long", "uima.cas.Float", "uima.cas.Double",
"uima.cas.String", "uima.cas.BooleanArray", "uima.cas.ByteArray", "uima.cas.ShortArray",
"uima.cas.IntegerArray", "uima.cas.LongArray", "uima.cas.FloatArray",
"uima.cas.DoubleArray", "uima.cas.StringArray", "uima.cas.FSArray",
"uima.cas.AnnotationBase", "uima.tcas.Annotation", "uima.tcas.DocumentAnnotation",
"uima.cas.FloatList", "uima.cas.IntegerList", "uima.cas.StringList", "uima.cas.FSList",
"uima.cas.EmptyFloatList", "uima.cas.EmptyIntegerList", "uima.cas.EmptyStringList",
"uima.cas.EmptyFSList", "uima.cas.NonEmptyFloatList", "uima.cas.NonEmptyIntegerList",
"uima.cas.NonEmptyStringList", "uima.cas.NonEmptyFSList" });
for (String longName : uimaPredefTypes) {
String shortName = getShortName(longName);
importType(longName, shortName);
}
this.finalTypes = new HashSet<String>();
Set<String> uimaFinalTypes = new HashSet<String>();
uimaFinalTypes.addAll(Arrays.asList(new String[] { "uima.cas.Boolean", "uima.cas.Byte",
"uima.cas.Short", "uima.cas.Integer", "uima.cas.Long", "uima.cas.Float", "uima.cas.Double",
"uima.cas.BooleanArray", "uima.cas.ByteArray", "uima.cas.ShortArray",
"uima.cas.IntegerArray", "uima.cas.LongArray", "uima.cas.FloatArray",
"uima.cas.DoubleArray", "uima.cas.StringArray", "uima.cas.FSArray" }));
for (String string : uimaFinalTypes) {
int indexOf = string.lastIndexOf('.');
finalTypes.add(string);
finalTypes.add(string.substring(indexOf + 1, string.length()));
}
}
private TypeSystemDescription importCompleteTypeSystem(IPath path, URL url)
throws InvalidXMLException, MalformedURLException, IOException, CoreException {
return importTypeSystem(path, url, null, null, null);
}
private void initializeExtensionInformation() {
conditionExtensions = new HashMap<String, IIDEConditionExtension>();
actionExtensions = new HashMap<String, IIDEActionExtension>();
numberFunctionExtensions = new HashMap<String, IIDENumberFunctionExtension>();
booleanFunctionExtensions = new HashMap<String, IIDEBooleanFunctionExtension>();
stringFunctionExtensions = new HashMap<String, IIDEStringFunctionExtension>();
typeFunctionExtensions = new HashMap<String, IIDETypeFunctionExtension>();
blockExtensions = new HashMap<String, IIDEBlockExtension>();
IIDEConditionExtension[] cextensions = RutaExtensionManager.getDefault()
.getIDEConditionExtensions();
for (IIDEConditionExtension each : cextensions) {
String[] knownExtensions = each.getKnownExtensions();
for (String string : knownExtensions) {
conditionExtensions.put(string, each);
}
}
IIDEActionExtension[] aextensions = RutaExtensionManager.getDefault().getIDEActionExtensions();
for (IIDEActionExtension each : aextensions) {
String[] knownExtensions = each.getKnownExtensions();
for (String string : knownExtensions) {
actionExtensions.put(string, each);
}
}
IIDENumberFunctionExtension[] nfextensions = RutaExtensionManager.getDefault()
.getIDENumberFunctionExtensions();
for (IIDENumberFunctionExtension each : nfextensions) {
String[] knownExtensions = each.getKnownExtensions();
for (String string : knownExtensions) {
numberFunctionExtensions.put(string, each);
}
}
IIDEBooleanFunctionExtension[] bfextensions = RutaExtensionManager.getDefault()
.getIDEBooleanFunctionExtensions();
for (IIDEBooleanFunctionExtension each : bfextensions) {
String[] knownExtensions = each.getKnownExtensions();
for (String string : knownExtensions) {
booleanFunctionExtensions.put(string, each);
}
}
IIDEStringFunctionExtension[] sfextensions = RutaExtensionManager.getDefault()
.getIDEStringFunctionExtensions();
for (IIDEStringFunctionExtension each : sfextensions) {
String[] knownExtensions = each.getKnownExtensions();
for (String string : knownExtensions) {
stringFunctionExtensions.put(string, each);
}
}
IIDETypeFunctionExtension[] tfextensions = RutaExtensionManager.getDefault()
.getIDETypeFunctionExtensions();
for (IIDETypeFunctionExtension each : tfextensions) {
String[] knownExtensions = each.getKnownExtensions();
for (String string : knownExtensions) {
typeFunctionExtensions.put(string, each);
}
}
IIDEBlockExtension[] bextensions = RutaExtensionManager.getDefault().getIDEBlockExtensions();
for (IIDEBlockExtension each : bextensions) {
String[] knownExtensions = each.getKnownExtensions();
for (String string : knownExtensions) {
blockExtensions.put(string, each);
}
}
}
private Set<FeatureDescription> getAllDeclaredFeatures(TypeDescription typeDescription,
Map<String, TypeDescription> typeMap) {
Set<FeatureDescription> result = new HashSet<FeatureDescription>();
if (typeDescription == null) {
return result;
}
FeatureDescription[] features = typeDescription.getFeatures();
if (features == null) {
return result;
}
result.addAll(Arrays.asList(features));
String supertypeName = typeDescription.getSupertypeName();
if (supertypeName != null) {
TypeDescription parent = typeMap.get(supertypeName);
result.addAll(getAllDeclaredFeatures(parent, typeMap));
}
return result;
}
private String isFeatureMatch(String text) {
for (String each : namespaces.values()) {
String t = checkFeatureMatch(text, each);
if (t != null) {
return t;
}
}
for (String each : namespaces.keySet()) {
String t = checkFeatureMatch(text, each);
if (t != null) {
return t;
}
}
return null;
}
private String checkFeatureMatch(String name, String type) {
if (name.startsWith(type)) {
boolean foundAll = true;
if (name.length() > type.length()) {
String tail = name.substring(type.length() + 1);
String[] split = tail.split("[.]");
String typeToCheck = type;
for (String feat : split) {
typeToCheck = expand(typeToCheck);
typeToCheck = checkFSFeatureOfType(feat, typeToCheck);
if (StringUtils.contains(typeToCheck, CAS.TYPE_NAME_FS_ARRAY)) {
// stop here because we do not know the type
return CAS.TYPE_NAME_FS_ARRAY;
}
foundAll &= (typeToCheck != null);
if (!foundAll) {
return null;
}
}
return typeToCheck;
} else {
return type;
}
} else {
return null;
}
}
private String checkFSFeatureOfType(String featureName, String longTypeName) {
TypeDescription t = typeDescriptionMap.get(longTypeName);
if (t == null) {
return null;
}
FeatureDescription[] features = t.getFeatures();
for (FeatureDescription featureDescription : features) {
String name = featureDescription.getName();
String rangeTypeName = featureDescription.getRangeTypeName();
boolean isFS = isFeatureStructure(rangeTypeName);
if (name.equals(featureName)) {
if (isFS) {
return rangeTypeName;
} else if (StringUtils.equals(CAS.TYPE_NAME_FS_ARRAY, rangeTypeName)) {
String elementType = featureDescription.getElementType();
if (elementType == null) {
return CAS.TYPE_NAME_FS_ARRAY;
} else {
return elementType;
}
}
}
}
return null;
}
private boolean isFeatureStructure(String rangeTypeName) {
if (rangeTypeName.equals("uima.tcas.Annotation") || rangeTypeName.equals("uima.cas.TOP")) {
return true;
}
TypeDescription type = typeDescriptionMap.get(rangeTypeName);
if (type == null) {
return false;
}
String supertypeName = type.getSupertypeName();
if (supertypeName != null) {
return isFeatureStructure(supertypeName);
}
return false;
}
private boolean checkTypeOfVariable(RutaVariableReference ref) {
Integer vt = getVariableType(ref.getName());
if (vt == null) {
IProblem problem = problemFactory.createUnknownVariableProblem(ref);
pr.reportProblem(problem);
return false;
} else {
int variableType = vt.intValue();
int requiredType = ref.getType();
// reject generic types
if ((requiredType & RutaTypeConstants.RUTA_TYPE_G) != 0) {
return true;
}
if ((variableType & requiredType) == 0) {
String errMsg = "Variable \"" + ref.getName() + "\" has type "
+ RutaTypeConstants.typeStringOfInt.get(variableType) + ". But type "
+ RutaTypeConstants.typeStringOfInt.get(requiredType) + " is required.";
IProblem problem = new RutaCheckerDefaultProblem(sourceModule.getElementName(), errMsg, ref,
linetracker.getLineNumberOfOffset(ref.sourceStart()));
pr.reportProblem(problem);
return false;
}
}
return true;
}
private boolean isVariableDeclared(RutaVariableReference ref) {
if (!knowsVariable(ref.getName()) && !(ref instanceof NullExpression)) {
// declared as type?
if (namespaces.keySet().contains(ref.getName())) {
String errMsg = "\"" + ref.getName() + "\" declared as a Type. Variable of type "
+ RutaTypeConstants.typeStringOfInt.get(ref.getType()) + " required.";
IProblem problem = new RutaCheckerDefaultProblem(sourceModule.getElementName(), errMsg, ref,
linetracker.getLineNumberOfOffset(ref.sourceStart()));
pr.reportProblem(problem);
return false;
}
String errMsgHead = "Variable \"";
String errMsgTailDefault = " defined in this script or block!";
// not found
String errMsg = errMsgHead + ref.getName() + "\" not" + errMsgTailDefault;
IProblem problem = new RutaCheckerDefaultProblem(sourceModule.getElementName(), errMsg, ref,
linetracker.getLineNumberOfOffset(ref.sourceStart()));
pr.reportProblem(problem);
return false;
}
return true;
}
private String getShortName(String typeName) {
String[] nameSpace = typeName.split("[.]");
return nameSpace[nameSpace.length - 1];
}
private TypeSystemDescription getTypeSystemOfScript()
throws InvalidXMLException, IOException, CoreException {
IPath descriptorPath = RutaProjectUtils.getTypeSystemDescriptorPath(
sourceModule.getResource().getLocation(), sourceModule.getScriptProject().getProject(),
classLoader);
if (descriptorPath == null) {
return null;
}
TypeSystemDescription typeSysDescr = null;
if (descriptorPath.toFile().exists()) {
typeSysDescr = UIMAFramework.getXMLParser()
.parseTypeSystemDescription(new XMLInputSource(descriptorPath.toPortableString()));
ResourceManager resMgr = getResourceManager(classLoader);
typeSysDescr.resolveImports(resMgr);
} else {
// backup: just search for the file named correctly
String lastSegment = descriptorPath.lastSegment();
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(
classLoader);
String prefix = "classpath*:**/";
String pattern = prefix + lastSegment;
Resource[] resources = resolver.getResources(pattern);
if (resources != null && resources.length != 0) {
typeSysDescr = UIMAFramework.getXMLParser()
.parseTypeSystemDescription(new XMLInputSource(resources[0].getURL()));
ResourceManager resMgr = getResourceManager(classLoader);
typeSysDescr.resolveImports(resMgr);
}
}
return typeSysDescr;
}
private String translate(String name) {
if (name == null) {
return null;
}
if (name.equals("Annotation")) {
return "uima.tcas.Annotation";
} else if (name.equals("STRING")) {
return CAS.TYPE_NAME_STRING;
} else if (name.equals("INT")) {
return CAS.TYPE_NAME_INTEGER;
} else if (name.equals("DOUBLE")) {
return CAS.TYPE_NAME_DOUBLE;
} else if (name.equals("FLOAT")) {
return CAS.TYPE_NAME_FLOAT;
} else if (name.equals("BOOLEAN")) {
return CAS.TYPE_NAME_BOOLEAN;
} else if (name.equals("TYPE")) {
return CAS.TYPE_NAME_STRING;
}
return name;
}
private int getType(String name) {
if (name == null) {
return 0;
}
// TODO reuse field in constants
if (name.equals("STRING")) {
return RutaTypeConstants.RUTA_TYPE_S;
} else if (name.equals("STRINGLIST")) {
return RutaTypeConstants.RUTA_TYPE_SL;
} else if (name.equals("INT")) {
return RutaTypeConstants.RUTA_TYPE_I;
} else if (name.equals("INTLIST")) {
return RutaTypeConstants.RUTA_TYPE_NL;
} else if (name.equals("DOUBLE")) {
return RutaTypeConstants.RUTA_TYPE_D;
} else if (name.equals("DOUBLELIST")) {
return RutaTypeConstants.RUTA_TYPE_NL;
} else if (name.equals("FLOAT")) {
return RutaTypeConstants.RUTA_TYPE_F;
} else if (name.equals("FLOATLIST")) {
return RutaTypeConstants.RUTA_TYPE_NL;
} else if (name.equals("BOOLEAN")) {
return RutaTypeConstants.RUTA_TYPE_B;
} else if (name.equals("BOOLEANLIST")) {
return RutaTypeConstants.RUTA_TYPE_BL;
} else if (name.equals("TYPE")) {
return RutaTypeConstants.RUTA_TYPE_AT;
} else if (name.equals("TYPELIST")) {
return RutaTypeConstants.RUTA_TYPE_TL;
} else if (name.equals("ANNOTATION")) {
return RutaTypeConstants.RUTA_TYPE_UA;
} else if (name.equals("ANNOTATIONLIST")) {
return RutaTypeConstants.RUTA_TYPE_UAL;
}
return 0;
}
}