/* | |
* 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.verbalize; | |
import java.util.Iterator; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Map.Entry; | |
import java.util.stream.Collectors; | |
import org.apache.commons.lang3.StringUtils; | |
import org.apache.uima.ruta.RutaElement; | |
import org.apache.uima.ruta.RutaStatement; | |
import org.apache.uima.ruta.ScriptApply; | |
import org.apache.uima.ruta.action.AbstractRutaAction; | |
import org.apache.uima.ruta.block.ForEachBlock; | |
import org.apache.uima.ruta.block.RutaBlock; | |
import org.apache.uima.ruta.condition.AbstractRutaCondition; | |
import org.apache.uima.ruta.expression.IRutaExpression; | |
import org.apache.uima.ruta.expression.bool.IBooleanExpression; | |
import org.apache.uima.ruta.expression.number.INumberExpression; | |
import org.apache.uima.ruta.expression.string.IStringExpression; | |
import org.apache.uima.ruta.expression.type.ITypeExpression; | |
import org.apache.uima.ruta.rule.AbstractRuleElement; | |
import org.apache.uima.ruta.rule.ComposedRuleElement; | |
import org.apache.uima.ruta.rule.ConjunctRulesRuleElement; | |
import org.apache.uima.ruta.rule.RegExpRule; | |
import org.apache.uima.ruta.rule.RuleElement; | |
import org.apache.uima.ruta.rule.RutaMatcher; | |
import org.apache.uima.ruta.rule.RutaOptionalRuleElement; | |
import org.apache.uima.ruta.rule.RutaRule; | |
import org.apache.uima.ruta.rule.RutaRuleElement; | |
import org.apache.uima.ruta.rule.WildCardRuleElement; | |
import org.apache.uima.ruta.rule.quantifier.MinMaxGreedy; | |
import org.apache.uima.ruta.rule.quantifier.MinMaxReluctant; | |
import org.apache.uima.ruta.rule.quantifier.NormalQuantifier; | |
import org.apache.uima.ruta.rule.quantifier.PlusGreedy; | |
import org.apache.uima.ruta.rule.quantifier.PlusReluctant; | |
import org.apache.uima.ruta.rule.quantifier.QuestionGreedy; | |
import org.apache.uima.ruta.rule.quantifier.QuestionReluctant; | |
import org.apache.uima.ruta.rule.quantifier.RuleElementQuantifier; | |
import org.apache.uima.ruta.rule.quantifier.StarGreedy; | |
import org.apache.uima.ruta.rule.quantifier.StarReluctant; | |
public class ScriptVerbalizer { | |
private static final String COLON = ":"; | |
private static final String CBCLOSE = "}"; | |
private static final String CBOPEN = "{"; | |
private static final String THEN = "->"; | |
private static final String THEN2 = "<-"; | |
private RutaVerbalizer verbalizer; | |
public ScriptVerbalizer(RutaVerbalizer verbalizer) { | |
super(); | |
this.verbalizer = verbalizer; | |
} | |
public String verbalizeBlock(RutaBlock block, boolean withElements) { | |
StringBuilder result = new StringBuilder(); | |
RutaRule rule = block.getRule(); | |
List<RutaStatement> elements = block.getElements(); | |
String name = block.getName(); | |
if (block instanceof ForEachBlock) { | |
result.append("FOREACH"); | |
} else { | |
result.append("BLOCK"); | |
} | |
if (name != null) { | |
result.append("("); | |
result.append(name); | |
if (block instanceof ForEachBlock) { | |
IBooleanExpression direction = ((ForEachBlock) block).getDirection(); | |
if (direction != null) { | |
result.append(", "); | |
result.append(verbalizer.verbalize(direction)); | |
} | |
} | |
result.append(")"); | |
} | |
result.append(" "); | |
if (rule != null) { | |
result.append(verbalizeRule(rule)); | |
} | |
if (withElements) { | |
result.append(" {\n"); | |
for (RutaStatement each : elements) { | |
if (each instanceof RutaBlock) { | |
result.append(verbalizeBlock((RutaBlock) each, withElements)); | |
} else if (each instanceof RutaRule) { | |
result.append(verbalizeRule((RutaRule) each)); | |
} | |
result.append(";"); | |
result.append("\n"); | |
} | |
result.append(" }\n"); | |
} | |
return result.toString(); | |
} | |
public String verbalizeRule(RutaRule rule) { | |
List<RuleElement> elements = rule.getRuleElements(); | |
StringBuilder result = new StringBuilder(); | |
Iterator<RuleElement> iterator = elements.iterator(); | |
while (iterator.hasNext()) { | |
RuleElement each = iterator.next(); | |
result.append(verbalizeRuleElement(each)); | |
if (iterator.hasNext()) { | |
result.append(" "); | |
} | |
} | |
result.append(";"); | |
return result.toString(); | |
} | |
public String verbalizeRuleElement(RuleElement re) { | |
List<AbstractRutaCondition> conditions = re.getConditions(); | |
List<AbstractRutaAction> actions = re.getActions(); | |
RuleElementQuantifier quantifier = re.getQuantifier(); | |
StringBuilder result = new StringBuilder(); | |
if (!StringUtils.isBlank(re.getLabel())) { | |
result.append(re.getLabel()); | |
result.append(COLON); | |
} | |
if (re.isStartAnchor()) { | |
result.append("@"); | |
} | |
if (re instanceof ConjunctRulesRuleElement) { | |
result.append(verbalizeConjunct((ConjunctRulesRuleElement) re)); | |
} else if (re instanceof ComposedRuleElement) { | |
result.append(verbalizeComposed((ComposedRuleElement) re)); | |
} else if (re instanceof RutaOptionalRuleElement) { | |
result.append("_"); | |
} else if (re instanceof RutaRuleElement) { | |
RutaRuleElement tmre = (RutaRuleElement) re; | |
RutaMatcher matcher = tmre.getMatcher(); | |
// action-only rule | |
boolean actionOnlyRule = false; | |
if (matcher == null) { | |
result.append("_"); | |
} else { | |
IRutaExpression expression = matcher.getExpression(); | |
actionOnlyRule = expression == null; | |
if (expression != null) { | |
String verbalize = verbalizer.verbalize(expression); | |
if (StringUtils.isBlank(verbalize)) { | |
actionOnlyRule = true; | |
} else { | |
result.append(verbalize); | |
} | |
} | |
} | |
if (actionOnlyRule) { | |
Iterator<AbstractRutaAction> ait = actions.iterator(); | |
while (ait.hasNext()) { | |
AbstractRutaAction each = ait.next(); | |
result.append(verbalizer.verbalize(each)); | |
if (ait.hasNext()) { | |
result.append(","); | |
} | |
} | |
return result.toString(); | |
} | |
} else if (re instanceof WildCardRuleElement) { | |
result.append("#"); | |
} | |
result.append(verbalizeQuantifier(quantifier)); | |
if (!conditions.isEmpty() || !actions.isEmpty()) { | |
result.append(CBOPEN); | |
Iterator<AbstractRutaCondition> cit = conditions.iterator(); | |
while (cit.hasNext()) { | |
AbstractRutaCondition each = cit.next(); | |
result.append(verbalizer.verbalize(each)); | |
if (cit.hasNext()) { | |
result.append(","); | |
} | |
} | |
if (!actions.isEmpty()) { | |
result.append(THEN); | |
Iterator<AbstractRutaAction> ait = actions.iterator(); | |
while (ait.hasNext()) { | |
AbstractRutaAction each = ait.next(); | |
result.append(verbalizer.verbalize(each)); | |
if (ait.hasNext()) { | |
result.append(","); | |
} | |
} | |
} | |
result.append(CBCLOSE); | |
} | |
if (re instanceof AbstractRuleElement) { | |
AbstractRuleElement are = (AbstractRuleElement) re; | |
List<List<RutaStatement>> inlinedConditionRuleBlocks = are.getInlinedConditionRuleBlocks(); | |
for (List<RutaStatement> inlinedConditionRules : inlinedConditionRuleBlocks) { | |
result.append(verbalizeInlinedConditionRuleBlock(inlinedConditionRules)); | |
} | |
List<List<RutaStatement>> inlinedActionRuleBlocks = are.getInlinedActionRuleBlocks(); | |
for (List<RutaStatement> inlinedActionRules : inlinedActionRuleBlocks) { | |
result.append(verbalizeInlinedActionRuleBlock(inlinedActionRules)); | |
} | |
} | |
return result.toString(); | |
} | |
public String verbalizeInlinedActionRuleBlock(List<RutaStatement> inlinedActionRules) { | |
StringBuilder result = new StringBuilder(); | |
if (inlinedActionRules != null && !inlinedActionRules.isEmpty()) { | |
result.append(THEN); | |
result.append(CBOPEN); | |
for (RutaStatement rutaStatement : inlinedActionRules) { | |
result.append(verbalize(rutaStatement)); | |
} | |
result.append(CBCLOSE); | |
} | |
return result.toString(); | |
} | |
public String verbalizeInlinedConditionRuleBlock(List<RutaStatement> inlinedConditionRules) { | |
StringBuilder result = new StringBuilder(); | |
if (inlinedConditionRules != null && !inlinedConditionRules.isEmpty()) { | |
result.append(THEN2); | |
result.append(CBOPEN); | |
for (RutaStatement rutaStatement : inlinedConditionRules) { | |
result.append(verbalize(rutaStatement)); | |
} | |
result.append(CBCLOSE); | |
} | |
return result.toString(); | |
} | |
public String verbalizeInlinedConditionRuleApplyBlock(List<ScriptApply> block) { | |
List<RutaStatement> list = block.stream().map(a -> a.getElement()) | |
.filter(RutaStatement.class::isInstance).map(s -> (RutaStatement) s) | |
.collect(Collectors.toList()); | |
return verbalizeInlinedConditionRuleBlock(list); | |
} | |
public String verbalizeInlinedActionRuleApplyBlock(List<ScriptApply> block) { | |
List<RutaStatement> list = block.stream().map(a -> a.getElement()) | |
.filter(RutaStatement.class::isInstance).map(s -> (RutaStatement) s) | |
.collect(Collectors.toList()); | |
return verbalizeInlinedActionRuleBlock(list); | |
} | |
private String verbalizeConjunct(ConjunctRulesRuleElement re) { | |
StringBuilder result = new StringBuilder(); | |
String sep = " % "; | |
List<RuleElement> ruleElements = re.getRuleElements(); | |
for (RuleElement each : ruleElements) { | |
if (re.getRuleElements().indexOf(each) != 0) { | |
result.append(sep); | |
} | |
result.append(verbalizeRuleElement(each)); | |
} | |
return result.toString(); | |
} | |
public String verbalizeComposed(ComposedRuleElement cre) { | |
StringBuilder result = new StringBuilder(); | |
List<RuleElement> ruleElements = cre.getRuleElements(); | |
result.append("("); | |
String sep = " "; | |
Boolean conjunct = cre.getConjunct(); | |
if (conjunct != null) { | |
if (conjunct) { | |
sep = " & "; | |
} else { | |
sep = " | "; | |
} | |
} | |
for (RuleElement each : ruleElements) { | |
if (cre.getRuleElements().indexOf(each) != 0) { | |
result.append(sep); | |
} | |
result.append(verbalizeRuleElement(each)); | |
} | |
result.append(")"); | |
return result.toString(); | |
} | |
public String verbalizeMatcher(RutaRuleElement re) { | |
StringBuilder result = new StringBuilder(); | |
RutaMatcher matcher = re.getMatcher(); | |
if (matcher != null) { | |
result.append(verbalizer.verbalize(matcher.getExpression())); | |
} | |
return result.toString(); | |
} | |
public String verbalizeQuantifier(RuleElementQuantifier quantifier) { | |
if (quantifier instanceof NormalQuantifier) { | |
return ""; | |
} else if (quantifier instanceof MinMaxGreedy) { | |
MinMaxGreedy mmg = (MinMaxGreedy) quantifier; | |
return "[" + verbalizer.verbalize(mmg.getMin()) + "," + verbalizer.verbalize(mmg.getMax()) | |
+ "]"; | |
} else if (quantifier instanceof MinMaxReluctant) { | |
MinMaxReluctant mmr = (MinMaxReluctant) quantifier; | |
return "[" + verbalizer.verbalize(mmr.getMin()) + "," + verbalizer.verbalize(mmr.getMax()) | |
+ "]?"; | |
} else if (quantifier instanceof PlusGreedy) { | |
return "+"; | |
} else if (quantifier instanceof PlusReluctant) { | |
return "+?"; | |
} else if (quantifier instanceof QuestionGreedy) { | |
return "?"; | |
} else if (quantifier instanceof QuestionReluctant) { | |
return "??"; | |
} else if (quantifier instanceof StarGreedy) { | |
return "*"; | |
} else if (quantifier instanceof StarReluctant) { | |
return "*?"; | |
} | |
return null; | |
} | |
public String verbalize(RutaElement element) { | |
if (element instanceof RutaBlock) { | |
return verbalizeBlock((RutaBlock) element, false); | |
} else if (element instanceof RuleElementQuantifier) { | |
return verbalizeQuantifier((RuleElementQuantifier) element); | |
} else if (element instanceof RutaRule) { | |
return verbalizeRule((RutaRule) element); | |
} else if (element instanceof RegExpRule) { | |
return verbalizeRegExpRule((RegExpRule) element); | |
} else if (element instanceof RutaRuleElement) { | |
return verbalizeRuleElement((RutaRuleElement) element); | |
} | |
return null; | |
} | |
private String verbalizeRegExpRule(RegExpRule rule) { | |
StringBuilder sb = new StringBuilder(); | |
String regexp = verbalizer.verbalize(rule.getRegExp()); | |
sb.append(regexp); | |
sb.append(THEN); | |
Iterator<Entry<ITypeExpression, INumberExpression>> iterator = rule.getTypeMap().entrySet() | |
.iterator(); | |
while (iterator.hasNext()) { | |
Entry<ITypeExpression, INumberExpression> next = iterator.next(); | |
String type = verbalizer.verbalize(next.getKey()); | |
INumberExpression value = next.getValue(); | |
if (value != null) { | |
String group = verbalizer.verbalize(value); | |
sb.append(group + " = " + type); | |
} else { | |
sb.append(type); | |
} | |
Map<ITypeExpression, Map<IStringExpression, IRutaExpression>> featureAssignments = rule | |
.getFeatureAssignments(); | |
if (featureAssignments != null) { | |
Map<IStringExpression, IRutaExpression> map = featureAssignments.get(next.getKey()); | |
if (map != null) { | |
sb.append("("); | |
Iterator<Entry<IStringExpression, IRutaExpression>> fit = map.entrySet().iterator(); | |
while (fit.hasNext()) { | |
Map.Entry<IStringExpression, IRutaExpression> entry = fit.next(); | |
sb.append(verbalizer.verbalize(entry.getKey())); | |
sb.append(" = "); | |
sb.append(verbalizer.verbalize(entry.getValue())); | |
if (fit.hasNext()) { | |
sb.append(", "); | |
} | |
} | |
sb.append(")"); | |
} | |
} | |
if (iterator.hasNext()) { | |
sb.append(", "); | |
} | |
} | |
sb.append(";"); | |
return sb.toString(); | |
} | |
} |