307 lines
11 KiB
Java
307 lines
11 KiB
Java
package eu.dnetlib.data.collective.transformation.rulelanguage.visitor;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.LinkedHashSet;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.Argument;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.Condition;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.IRule;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.Rules;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.RulesSet;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.Argument.Type;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.parser.ASTMyAssign;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.parser.ASTMyAttribute;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.parser.ASTMyCondition;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.parser.ASTMyCopy;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.parser.ASTMyEmpty;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.parser.ASTMyImport;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.parser.ASTMyNs;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.parser.ASTMyOp;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.parser.ASTMyPreprocess;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.parser.ASTMyScript;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.parser.ASTMyScript.SCRIPTTYPE;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.parser.ASTMySet;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.parser.ASTMySkip;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.util.Converter;
|
|
import eu.dnetlib.data.collective.transformation.rulelanguage.util.FunctionCall;
|
|
|
|
/**
|
|
* Implementation of the visitor pattern; maps production rules into Java data structures
|
|
* @author jochen
|
|
*
|
|
*/
|
|
public class RuleLanguageVisitor extends AbstractVisitor{
|
|
|
|
private static final Log log = LogFactory.getLog(RuleLanguageVisitor.class);
|
|
|
|
private String scriptName = "";
|
|
private ASTMyScript.SCRIPTTYPE scriptType;
|
|
private Map<String, Set<IRule>> elementMappingRules = new LinkedHashMap<String, Set<IRule>>();
|
|
private Map<String, IRule> variableMappingRules = new LinkedHashMap<String, IRule>();
|
|
private Map<String, IRule> templateMappingRules = new LinkedHashMap<String, IRule>();
|
|
private List<String> importedScriptList = new LinkedList<String>();
|
|
private List<FunctionCall> functionCallList = new LinkedList<FunctionCall>();
|
|
private Map<String, String> namespaceDeclMap = new HashMap<String, String>();
|
|
private List<Map<String, String>> preprocessingMap = new LinkedList<Map<String,String>>();
|
|
|
|
|
|
/**
|
|
* @return the name of the rule script
|
|
*/
|
|
public String getScriptName(){
|
|
return this.scriptName;
|
|
}
|
|
|
|
/**
|
|
* @return the type of the script
|
|
*/
|
|
public SCRIPTTYPE getScriptType(){
|
|
return this.scriptType;
|
|
}
|
|
|
|
/**
|
|
* @return the mapping of all rules
|
|
*/
|
|
public Map<String, Set<IRule>> getElementMappingRules(){
|
|
return this.elementMappingRules;
|
|
}
|
|
|
|
public Map<String, IRule> getVariableMappingRules(){
|
|
return this.variableMappingRules;
|
|
}
|
|
|
|
public Map<String, IRule> getTemplateMappingRules(){
|
|
return this.templateMappingRules;
|
|
}
|
|
|
|
/**
|
|
* @return the list of function calls - this is a subset of the rule mapping
|
|
*/
|
|
public List<FunctionCall> getFunctionCalls(){
|
|
return this.functionCallList;
|
|
}
|
|
|
|
/**
|
|
* @return the list of scripts that are declared as import
|
|
*/
|
|
public List<String> getImportedScripts(){
|
|
return this.importedScriptList;
|
|
}
|
|
|
|
/**
|
|
* @return the map of name-space declarations made in the script
|
|
*/
|
|
public Map<String, String> getNamespaceDeclarations(){
|
|
return this.namespaceDeclMap;
|
|
}
|
|
|
|
/**
|
|
* @return the map of preprocessings (functions, parameters)
|
|
*/
|
|
public List<Map<String, String>> getPreprocessings(){
|
|
return this.preprocessingMap;
|
|
}
|
|
|
|
public Object visit(ASTMyAssign node, Object data) {
|
|
String attrValue = "";
|
|
String fieldExprValue = "";
|
|
Rules r = node.getRule();
|
|
|
|
if (node.isFieldExpression()){
|
|
// todo e.g. convert field-expression into a xpath-expression
|
|
fieldExprValue = node.getFieldExpression();
|
|
if (fieldExprValue.startsWith("xpath:")){
|
|
fieldExprValue = Converter.getXpathFromXpathExpr(fieldExprValue);
|
|
r.setXpath(fieldExprValue);
|
|
}else if (fieldExprValue.startsWith("$") && !fieldExprValue.startsWith("$job.")){
|
|
// variable
|
|
log.debug("ruleLangVisitor: assign variable:" + fieldExprValue);
|
|
r.setAssignmentVariable(fieldExprValue);
|
|
}
|
|
}else if (node.isAttribute()){
|
|
attrValue = node.getValue();
|
|
}else {
|
|
// shouldn't happen
|
|
attrValue = "value not defined: " + node.getValue();
|
|
}
|
|
r.setConstant(attrValue);
|
|
if (r.getUniqueName().trim().length() > 0){
|
|
addRule(r, r.getUniqueName());
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Object visit(ASTMyCopy node, Object data) {
|
|
Rules r = node.getRule();
|
|
r.setTemplateMatch(node.getTemplateMatchName());
|
|
r.getProperties().setProperty("applyTemplateSelectExpression", node.getApplyTemplateSelectExpression());
|
|
r.getProperties().setProperty("copySelectExpression", node.getCopySelectExpression());
|
|
addRule(r, r.getUniqueName());
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Object visit(ASTMySet aNode, Object aData) {
|
|
log.debug("called method: RuleLanguageVisitor.visit(ASTMySet)");
|
|
// check if the outputfield is the same in rules of this production
|
|
Rules myRule = aNode.getRule();
|
|
|
|
if (aNode.isValueExpression()){
|
|
// todo e.g. convert field-expression into a xpath-expression
|
|
String exprValue = aNode.getValueExpression();
|
|
if (exprValue.startsWith("xpath:")){
|
|
exprValue = Converter.getXpathFromXpathExpr(exprValue);
|
|
myRule.setXpath(exprValue);
|
|
}else if (exprValue.startsWith("$") && !exprValue.startsWith("$job.")){
|
|
// variable
|
|
log.debug("ruleLangVisitor: assign variable:" + exprValue);
|
|
myRule.setAssignmentVariable(exprValue);
|
|
}
|
|
}
|
|
|
|
List<Rules> rules = aNode.getRules();
|
|
RulesSet set = new RulesSet();
|
|
//set.setPrimaryRule(rules.get(0));
|
|
myRule.setRulesSet(set);
|
|
log.debug("rulelangvisitor rule name: " + myRule.getUniqueName() + " , hasSet : " + myRule.hasSet());
|
|
set.getPendingRules().addAll(rules);
|
|
addRule(myRule, myRule.getUniqueName());
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Object visit(ASTMyEmpty node, Object data) {
|
|
Rules r = node.getRule();
|
|
r.setEmpty(node.isEmpty());
|
|
addRule(r, r.getUniqueName());
|
|
return null;
|
|
}
|
|
|
|
|
|
/**
|
|
* vist a production rule that is defined as an operation or external function call
|
|
* @see eu.dnetlib.data.collective.transformation.rulelanguage.visitor.AbstractVisitor#visit(eu.dnetlib.data.collective.transformation.rulelanguage.parser.ASTMyOp, java.lang.Object)
|
|
*/
|
|
public Object visit(ASTMyOp node, Object data) {
|
|
Rules r = node.getRule();
|
|
r.setFunctionCall(node.createFunctionCall(r.isStatic()));
|
|
functionCallList.add(r.getFunctionCall());
|
|
log.debug("fc name: " + r.getFunctionCall().getExternalFunctionName());
|
|
for(int i =0; i < node.jjtGetNumChildren(); i++) {
|
|
ASTMyAttribute sn = (ASTMyAttribute)node.jjtGetChild(i);
|
|
Argument arg = null;
|
|
if (sn.getAttributeValue() != null){
|
|
arg = new Argument(Type.VALUE, sn.getAttributeValue());
|
|
}else if (sn.getAttributeInputField() != null){
|
|
if (sn.getAttributeInputField().startsWith("xpath:")){
|
|
arg = new Argument(Type.INPUTFIELD, Converter.getXpathFromXpathExpr(sn.getAttributeInputField()));
|
|
}else if (sn.getAttributeInputField().startsWith("$job.")){
|
|
// job constant
|
|
arg = new Argument(Type.JOBCONST, sn.getAttributeInputField());
|
|
}else{
|
|
// variable
|
|
arg = new Argument(Type.VAR, sn.getAttributeInputField());
|
|
}
|
|
}else{
|
|
throw new IllegalStateException("Argument with neither value nor inputfield is not allowed.");
|
|
}
|
|
log.debug("argument: " + arg.getArgument());
|
|
r.getFunctionCall().addArgument(arg);
|
|
}
|
|
if (r.getFunctionCall().getParameters() != null){
|
|
Set<String> keys = r.getFunctionCall().getParameters().keySet();
|
|
for (String key: keys){
|
|
log.debug("key: " + key + " , value: " + r.getFunctionCall().getParameters().get(key));
|
|
}
|
|
}
|
|
log.debug("add rule with declaration: " + r.getRuleDeclaration());
|
|
addRule(r, r.getUniqueName());
|
|
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Object visit(ASTMyImport node, Object data) {
|
|
importedScriptList.add(node.getScriptName());
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Object visit(ASTMyNs node, Object data) {
|
|
namespaceDeclMap.put(node.getNsPrefix(), node.getNsUri());
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Object visit(ASTMyScript node, Object data) {
|
|
this.scriptName = node.getScript();
|
|
this.scriptType = node.getScriptType();
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Object visit(ASTMyCondition node, Object data) {
|
|
Condition condition = new Condition();
|
|
if (node.getApplyExpression().length() > 0){
|
|
String applyExpr = Converter.getXpathFromXpathExpr(node.getApplyExpression());
|
|
condition.setApplyExpression(applyExpr);
|
|
}
|
|
|
|
String conditionalExpr = Converter.getXpathFromXpathExpr(node.getConditionalExpression());
|
|
condition.setConditionExpression(conditionalExpr);
|
|
condition.setPrimaryRule(node.getPrimaryRule());
|
|
node.getPrimaryRule().setCondition(condition);
|
|
condition.setSecondaryRule(node.getSecondaryRule());
|
|
node.getSecondaryRule().setCondition(condition);
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Object visit(ASTMyPreprocess node, Object data) {
|
|
Map<String, String> functionMap = new HashMap<String, String>();
|
|
functionMap.put(node.getFunctionName(), node.getParameter());
|
|
preprocessingMap.add(functionMap);
|
|
return null;
|
|
}
|
|
|
|
|
|
|
|
|
|
private void addRule(IRule rule, String key){
|
|
log.debug("add rule with key: " + key);
|
|
Set<IRule> ruleSet = null;
|
|
if (rule.definesVariable()){
|
|
variableMappingRules.put(key, rule);
|
|
}else if (rule.definesTemplate()){
|
|
templateMappingRules.put(key, rule);
|
|
}else{
|
|
if (elementMappingRules.containsKey(key)){
|
|
ruleSet = elementMappingRules.get(key);
|
|
}else{
|
|
ruleSet = new LinkedHashSet<IRule>();
|
|
elementMappingRules.put(key, ruleSet);
|
|
}
|
|
ruleSet.add(rule);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Object visit(ASTMySkip node, Object data) {
|
|
Rules r = node.getRule();
|
|
r.setSkip(true);
|
|
addRule(r, r.getUniqueName()); // ??? actually no targetField defined
|
|
return null;
|
|
}
|
|
|
|
|
|
}
|