/* | |
* 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.visitor; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Map.Entry; | |
import java.util.Set; | |
import org.apache.uima.cas.text.AnnotationFS; | |
import org.apache.uima.fit.util.FSCollectionFactory; | |
import org.apache.uima.jcas.JCas; | |
import org.apache.uima.jcas.cas.FSArray; | |
import org.apache.uima.ruta.RutaElement; | |
import org.apache.uima.ruta.RutaStatement; | |
import org.apache.uima.ruta.RutaStream; | |
import org.apache.uima.ruta.ScriptApply; | |
import org.apache.uima.ruta.block.BlockApply; | |
import org.apache.uima.ruta.rule.AbstractRule; | |
import org.apache.uima.ruta.rule.AbstractRuleMatch; | |
import org.apache.uima.ruta.rule.ComposedRuleElement; | |
import org.apache.uima.ruta.rule.ComposedRuleElementMatch; | |
import org.apache.uima.ruta.rule.EvaluatedCondition; | |
import org.apache.uima.ruta.rule.RegExpRule; | |
import org.apache.uima.ruta.rule.RegExpRuleMatch; | |
import org.apache.uima.ruta.rule.RuleApply; | |
import org.apache.uima.ruta.rule.RuleElement; | |
import org.apache.uima.ruta.rule.RuleElementMatch; | |
import org.apache.uima.ruta.rule.RuleMatch; | |
import org.apache.uima.ruta.rule.RutaRuleElement; | |
import org.apache.uima.ruta.type.DebugBlockApply; | |
import org.apache.uima.ruta.type.DebugEvaluatedCondition; | |
import org.apache.uima.ruta.type.DebugFailedRuleMatch; | |
import org.apache.uima.ruta.type.DebugInlinedBlock; | |
import org.apache.uima.ruta.type.DebugMatchedRuleMatch; | |
import org.apache.uima.ruta.type.DebugRuleApply; | |
import org.apache.uima.ruta.type.DebugRuleElementMatch; | |
import org.apache.uima.ruta.type.DebugRuleElementMatches; | |
import org.apache.uima.ruta.type.DebugRuleMatch; | |
import org.apache.uima.ruta.type.DebugScriptApply; | |
import org.apache.uima.ruta.verbalize.RutaVerbalizer; | |
public class DebugInfoFactory { | |
private RutaVerbalizer verbalizer; | |
public DebugInfoFactory(RutaVerbalizer verbalizer) { | |
super(); | |
this.verbalizer = verbalizer; | |
} | |
public DebugBlockApply createDummyBlockApply(RuleMatch ruleMatch, RutaStream stream, | |
boolean addToIndex, boolean withMatches, Map<RutaElement, Long> timeInfo) { | |
JCas cas = stream.getJCas(); | |
DebugBlockApply dba = new DebugBlockApply(cas); | |
AnnotationFS matchedAnnotation = ruleMatch | |
.getMatchedAnnotationsOfElement(ruleMatch.getRule().getRoot()).get(0); | |
dba.setElement(matchedAnnotation.getCoveredText()); | |
dba.setBegin(matchedAnnotation.getBegin()); | |
dba.setEnd(matchedAnnotation.getEnd()); | |
return dba; | |
} | |
public DebugBlockApply createDebugBlockApply(BlockApply blockApply, RutaStream stream, | |
boolean addToIndex, boolean withMatches, Map<RutaElement, Long> timeInfo) { | |
JCas cas = stream.getJCas(); | |
DebugBlockApply dba = new DebugBlockApply(cas); | |
List<DebugScriptApply> innerApply = new ArrayList<DebugScriptApply>(); | |
// TODO refactor and remove counting hotfix | |
int applied = blockApply.getRuleApply().getApplied(); | |
RutaElement element = blockApply.getElement(); | |
String verbalize = ""; | |
verbalize = verbalizer.verbalize(element); | |
if (applied > 1) { | |
List<ScriptApply> innerApplies = blockApply.getInnerApplies(); | |
List<List<ScriptApply>> loops = new ArrayList<List<ScriptApply>>(); | |
for (int i = 0; i < applied; i++) { | |
loops.add(new ArrayList<ScriptApply>()); | |
} | |
int counter = 0; | |
int size = innerApplies.size(); | |
int parts = size / applied; | |
for (ScriptApply each : innerApplies) { | |
int listIndex = Math.max(0, counter / parts); | |
List<ScriptApply> list = loops.get(listIndex); | |
list.add(each); | |
counter++; | |
} | |
counter = 0; | |
for (List<ScriptApply> list : loops) { | |
AbstractRuleMatch<? extends AbstractRule> ruleMatch = blockApply.getRuleApply().getList() | |
.get(counter); | |
DebugBlockApply dummyBlockApply = createDummyBlockApply((RuleMatch) ruleMatch, stream, | |
addToIndex, withMatches, timeInfo); | |
List<DebugRuleMatch> ruleMatches = new ArrayList<DebugRuleMatch>(); | |
ruleMatches.add(createDebugRuleMatch(ruleMatch, stream, addToIndex, withMatches, timeInfo)); | |
dummyBlockApply.setApplied(1); | |
dummyBlockApply.setTried(1); | |
dummyBlockApply.setRules(FSCollectionFactory.createFSArray(cas, ruleMatches)); | |
List<DebugScriptApply> innerInnerApply = new ArrayList<DebugScriptApply>(); | |
for (ScriptApply each : list) { | |
DebugScriptApply eachInnerInner = createDebugScriptApply(each, stream, addToIndex, | |
withMatches, timeInfo); | |
innerInnerApply.add(eachInnerInner); | |
} | |
dummyBlockApply.setInnerApply(FSCollectionFactory.createFSArray(cas, innerInnerApply)); | |
innerApply.add(dummyBlockApply); | |
counter++; | |
} | |
dba.setInnerApply(FSCollectionFactory.createFSArray(cas, innerApply)); | |
dba.setElement(verbalize); | |
DebugRuleApply ruleApply = createDebugRuleApply(blockApply.getRuleApply(), stream, addToIndex, | |
withMatches, timeInfo); | |
dba.setApplied(ruleApply.getApplied()); | |
dba.setTried(ruleApply.getTried()); | |
dba.setRules(ruleApply.getRules()); | |
dba.setBegin(ruleApply.getBegin()); | |
dba.setEnd(ruleApply.getEnd()); | |
if (timeInfo != null) { | |
long time = timeInfo.get(element); | |
dba.setTime(time); | |
} | |
if (addToIndex) | |
dba.addToIndexes(); | |
return dba; | |
} else { | |
for (ScriptApply each : blockApply.getInnerApplies()) { | |
innerApply.add(createDebugScriptApply(each, stream, addToIndex, withMatches, timeInfo)); | |
} | |
dba.setInnerApply(FSCollectionFactory.createFSArray(cas, innerApply)); | |
dba.setElement(verbalize); | |
DebugRuleApply ruleApply = createDebugRuleApply(blockApply.getRuleApply(), stream, addToIndex, | |
withMatches, timeInfo); | |
dba.setApplied(ruleApply.getApplied()); | |
dba.setTried(ruleApply.getTried()); | |
dba.setRules(ruleApply.getRules()); | |
dba.setBegin(ruleApply.getBegin()); | |
dba.setEnd(ruleApply.getEnd()); | |
if (timeInfo != null) { | |
Long time = timeInfo.get(element); | |
if (time != null) { | |
dba.setTime(time); | |
} | |
} | |
if (addToIndex) | |
dba.addToIndexes(); | |
return dba; | |
} | |
} | |
public DebugRuleApply createDebugRuleApply(RuleApply ruleApply, RutaStream stream, | |
boolean addToIndex, boolean withMatches, Map<RutaElement, Long> timeInfo) { | |
JCas cas = stream.getJCas(); | |
DebugRuleApply dra = new DebugRuleApply(cas); | |
List<DebugRuleMatch> ruleMatches = new ArrayList<DebugRuleMatch>(); | |
int begin = Integer.MAX_VALUE; | |
int end = 0; | |
if (withMatches) { | |
for (AbstractRuleMatch<? extends AbstractRule> match : ruleApply.getList()) { | |
DebugRuleMatch debugRuleMatch = createDebugRuleMatch(match, stream, addToIndex, withMatches, | |
timeInfo); | |
begin = Math.min(begin, debugRuleMatch.getBegin()); | |
end = Math.max(end, debugRuleMatch.getEnd()); | |
ruleMatches.add(debugRuleMatch); | |
} | |
} | |
if (begin >= end) { | |
begin = end; | |
} | |
dra.setRules(FSCollectionFactory.createFSArray(cas, ruleMatches)); | |
RutaElement element = ruleApply.getElement(); | |
String namespace = ""; | |
if (element instanceof RutaStatement) { | |
RutaStatement rs = (RutaStatement) element; | |
namespace = rs.getParent().getScript().getRootBlock().getNamespace(); | |
} | |
dra.setElement(verbalizer.verbalize(element)); | |
dra.setApplied(ruleApply.getApplied()); | |
dra.setTried(ruleApply.getTried()); | |
dra.setId(((AbstractRule) element).getId()); | |
dra.setScript(namespace); | |
dra.setBegin(begin); | |
dra.setEnd(end); | |
if (timeInfo != null) { | |
Long time = timeInfo.get(element); | |
if (time != null) { | |
dra.setTime(time); | |
} | |
} | |
if (addToIndex) | |
dra.addToIndexes(); | |
return dra; | |
} | |
public DebugRuleMatch createDebugRuleMatch(AbstractRuleMatch<? extends AbstractRule> match, | |
RutaStream stream, boolean addToIndex, boolean withMatches, | |
Map<RutaElement, Long> timeInfo) { | |
JCas cas = stream.getJCas(); | |
DebugRuleMatch drm = null; | |
if (match.matchedCompletely()) { | |
drm = new DebugMatchedRuleMatch(cas); | |
} else { | |
drm = new DebugFailedRuleMatch(cas); | |
} | |
drm.setMatched(match.matchedCompletely()); | |
if (match instanceof RuleMatch) { | |
ComposedRuleElementMatch rootMatch = ((RuleMatch) match).getRootMatch(); | |
setInnerMatches(stream, addToIndex, withMatches, timeInfo, drm, rootMatch); | |
// if (match.matched()) { | |
List<DebugScriptApply> delegates = new ArrayList<DebugScriptApply>(); | |
for (ScriptApply rem : ((RuleMatch) match).getDelegateApply().values()) { | |
delegates.add(createDebugScriptApply(rem, stream, addToIndex, withMatches, timeInfo)); | |
} | |
drm.setDelegates(FSCollectionFactory.createFSArray(cas, delegates)); | |
// } | |
} else if (match instanceof RegExpRuleMatch) { | |
RegExpRuleMatch rerm = (RegExpRuleMatch) match; | |
Map<Integer, List<AnnotationFS>> map = rerm.getMap(); | |
Set<Entry<Integer, List<AnnotationFS>>> entrySet = map.entrySet(); | |
List<DebugRuleElementMatches> ruleElementMatches = new ArrayList<DebugRuleElementMatches>(); | |
for (Entry<Integer, List<AnnotationFS>> entry : entrySet) { | |
DebugRuleElementMatches drems = new DebugRuleElementMatches(cas); | |
RegExpRule rule = rerm.getRule(); | |
Integer key = entry.getKey(); | |
List<AnnotationFS> value = entry.getValue(); | |
drems.setElement(verbalizer.verbalize(rule)); | |
List<DebugRuleElementMatch> remList = new ArrayList<DebugRuleElementMatch>(); | |
if (value != null) { | |
for (AnnotationFS each : value) { | |
DebugRuleElementMatch drem = new DebugRuleElementMatch(cas); | |
DebugEvaluatedCondition base = new DebugEvaluatedCondition(cas); | |
base.setValue(true); | |
String baseString = "Group " + key; | |
base.setElement(baseString); | |
drem.setBaseCondition(base); | |
if (each.getBegin() <= each.getEnd()) { | |
drem.setBegin(each.getBegin()); | |
drem.setEnd(each.getEnd()); | |
} | |
if (addToIndex) { | |
drem.addToIndexes(); | |
} | |
remList.add(drem); | |
} | |
} | |
drems.setMatches(FSCollectionFactory.createFSArray(cas, remList)); | |
if (addToIndex) { | |
drems.addToIndexes(); | |
} | |
ruleElementMatches.add(drems); | |
} | |
drm.setElements(FSCollectionFactory.createFSArray(cas, ruleElementMatches)); | |
} | |
if (timeInfo != null) { | |
long time = timeInfo.get(match.getRule()); | |
drm.setTime(time); | |
} | |
List<AnnotationFS> matchedAnnotationsOfRoot = match.getMatchedAnnotationsOfRoot(); | |
if (!matchedAnnotationsOfRoot.isEmpty()) { | |
AnnotationFS matchedAnnotation = matchedAnnotationsOfRoot.get(0); | |
if (matchedAnnotation != null) { | |
drm.setBegin(matchedAnnotation.getBegin()); | |
drm.setEnd(matchedAnnotation.getEnd()); | |
if (addToIndex || withMatches) | |
drm.addToIndexes(); | |
} | |
} | |
return drm; | |
} | |
private void setInnerMatches(RutaStream stream, boolean addToIndex, boolean withMatches, | |
Map<RutaElement, Long> timeInfo, DebugRuleMatch drm, ComposedRuleElementMatch rootMatch) { | |
Set<Entry<RuleElement, List<RuleElementMatch>>> entrySet = rootMatch.getInnerMatches() | |
.entrySet(); | |
List<DebugRuleElementMatches> ruleElementMatches = new ArrayList<DebugRuleElementMatches>(); | |
for (Entry<RuleElement, List<RuleElementMatch>> entry : entrySet) { | |
RuleElement re = entry.getKey(); | |
List<RuleElementMatch> rems = entry.getValue(); | |
ruleElementMatches.add( | |
createDebugRuleElementMatches(re, rems, stream, addToIndex, withMatches, timeInfo)); | |
} | |
drm.setElements(FSCollectionFactory.createFSArray(stream.getJCas(), ruleElementMatches)); | |
} | |
private void setInnerMatches(RutaStream stream, boolean addToIndex, boolean withMatches, | |
Map<RutaElement, Long> timeInfo, DebugRuleElementMatch drm, | |
ComposedRuleElementMatch rootMatch) { | |
Set<Entry<RuleElement, List<RuleElementMatch>>> entrySet = rootMatch.getInnerMatches() | |
.entrySet(); | |
List<DebugRuleElementMatches> ruleElementMatches = new ArrayList<DebugRuleElementMatches>(); | |
for (Entry<RuleElement, List<RuleElementMatch>> entry : entrySet) { | |
RuleElement re = entry.getKey(); | |
List<RuleElementMatch> rems = entry.getValue(); | |
ruleElementMatches.add( | |
createDebugRuleElementMatches(re, rems, stream, addToIndex, withMatches, timeInfo)); | |
} | |
drm.setElements(FSCollectionFactory.createFSArray(stream.getJCas(), ruleElementMatches)); | |
} | |
public DebugRuleElementMatches createDebugRuleElementMatches(RuleElement re, | |
List<RuleElementMatch> rems, RutaStream stream, boolean addToIndex, boolean withMatches, | |
Map<RutaElement, Long> timeInfo) { | |
JCas cas = stream.getJCas(); | |
DebugRuleElementMatches drems = new DebugRuleElementMatches(cas); | |
drems.setElement(verbalizer.verbalize(re)); | |
List<DebugRuleElementMatch> remList = new ArrayList<DebugRuleElementMatch>(); | |
if (rems != null) { | |
for (RuleElementMatch each : rems) { | |
DebugRuleElementMatch rem = null; | |
if (each instanceof ComposedRuleElementMatch) { | |
rem = createDebugComposedRuleElementMatch((ComposedRuleElementMatch) each, stream, | |
addToIndex, withMatches, timeInfo); | |
} else { | |
rem = createDebugRuleElementMatch(each, stream, addToIndex); | |
} | |
FSArray<DebugInlinedBlock> inlinedConditionBlocks = createInlinedBlocks( | |
each.getInlinedConditionRules(), stream, true, addToIndex, withMatches, timeInfo); | |
rem.setInlinedConditionBlocks(inlinedConditionBlocks); | |
if (rem != null) { | |
remList.add(rem); | |
} | |
} | |
} | |
if (rems != null && !rems.isEmpty()) { | |
drems.setRuleAnchor(rems.get(0).isRuleAnchor()); | |
} | |
drems.setMatches(FSCollectionFactory.createFSArray(cas, remList)); | |
FSArray<DebugInlinedBlock> inlinedActionBlocks = createInlinedActionBlocks(rems, stream, | |
addToIndex, withMatches, timeInfo); | |
drems.setInlinedActionBlocks(inlinedActionBlocks); | |
if (addToIndex) | |
drems.addToIndexes(); | |
return drems; | |
} | |
private FSArray<DebugInlinedBlock> createInlinedBlocks(List<List<ScriptApply>> blocks, | |
RutaStream stream, boolean asCondition, boolean addToIndex, boolean withMatches, | |
Map<RutaElement, Long> timeInfo) { | |
JCas jcas = stream.getJCas(); | |
if (blocks == null || blocks.isEmpty()) { | |
return null; | |
} | |
List<DebugInlinedBlock> blockList = new ArrayList<>(); | |
for (List<ScriptApply> block : blocks) { | |
List<DebugScriptApply> list = new ArrayList<>(); | |
boolean oneRuleApplied = false; | |
for (ScriptApply ruleApply : block) { | |
if (ruleApply instanceof RuleApply) { | |
if (((RuleApply) ruleApply).getApplied() > 0) { | |
oneRuleApplied = true; | |
} | |
} | |
DebugScriptApply debugScriptApply = createDebugScriptApply(ruleApply, stream, addToIndex, | |
withMatches, timeInfo); | |
list.add(debugScriptApply); | |
} | |
DebugInlinedBlock debugInlinedBlock = new DebugInlinedBlock(jcas); | |
debugInlinedBlock.setInlinedRules(FSCollectionFactory.createFSArray(jcas, list)); | |
debugInlinedBlock.setAsCondition(asCondition); | |
if (asCondition) { | |
debugInlinedBlock.setElement(verbalizer.verbalizeInlinedConditionRuleBlock(block)); | |
debugInlinedBlock.setMatched(oneRuleApplied); | |
} else { | |
debugInlinedBlock.setElement(verbalizer.verbalizeInlinedActionRuleBlock(block)); | |
} | |
blockList.add(debugInlinedBlock); | |
} | |
return FSCollectionFactory.createFSArray(jcas, blockList); | |
} | |
private FSArray<DebugInlinedBlock> createInlinedActionBlocks(List<RuleElementMatch> rems, | |
RutaStream stream, boolean addToIndex, boolean withMatches, | |
Map<RutaElement, Long> timeInfo) { | |
if (rems == null || rems.isEmpty()) { | |
return null; | |
} | |
return createInlinedBlocks(rems.get(0).getInlinedActionRules(), stream, false, addToIndex, | |
withMatches, timeInfo); | |
} | |
public DebugRuleElementMatch createDebugComposedRuleElementMatch(ComposedRuleElementMatch rem, | |
RutaStream stream, boolean addToIndex, boolean withMatches, | |
Map<RutaElement, Long> timeInfo) { | |
JCas cas = stream.getJCas(); | |
DebugRuleElementMatch drem = new DebugRuleElementMatch(cas); | |
DebugEvaluatedCondition base = new DebugEvaluatedCondition(cas); | |
base.setValue(rem.isBaseConditionMatched()); | |
setInnerMatches(stream, addToIndex, withMatches, timeInfo, drem, rem); | |
String baseString = verbalizer.verbalize(rem.getRuleElement()); | |
base.setElement(baseString); | |
drem.setBaseCondition(base); | |
drem.setConditions(createEvaluatedConditions(rem, stream, addToIndex)); | |
List<AnnotationFS> annotations = rem.getTextsMatched(); | |
if (!annotations.isEmpty()) { | |
int begin = annotations.get(0).getBegin(); | |
int end = annotations.get(annotations.size() - 1).getEnd(); | |
if (begin <= end) { | |
drem.setBegin(begin); | |
drem.setEnd(end); | |
} | |
} | |
if (addToIndex) | |
drem.addToIndexes(); | |
return drem; | |
} | |
public DebugRuleElementMatch createDebugRuleElementMatch(RuleElementMatch rem, RutaStream stream, | |
boolean addToIndex) { | |
JCas cas = stream.getJCas(); | |
DebugRuleElementMatch drem = new DebugRuleElementMatch(cas); | |
DebugEvaluatedCondition base = new DebugEvaluatedCondition(cas); | |
base.setValue(rem.isBaseConditionMatched()); | |
RuleElement ruleElement = rem.getRuleElement(); | |
String baseString = ""; | |
if (ruleElement instanceof RutaRuleElement) { | |
baseString = verbalizer.verbalizeMatcher((RutaRuleElement) ruleElement); | |
} else if (ruleElement instanceof ComposedRuleElement) { | |
baseString = verbalizer.verbalizeComposed((ComposedRuleElement) ruleElement); | |
} | |
base.setElement(baseString); | |
drem.setBaseCondition(base); | |
drem.setConditions(createEvaluatedConditions(rem, stream, addToIndex)); | |
List<AnnotationFS> annotations = rem.getTextsMatched(); | |
if (!annotations.isEmpty()) { | |
int begin = annotations.get(0).getBegin(); | |
int end = annotations.get(annotations.size() - 1).getEnd(); | |
if (begin <= end) { | |
drem.setBegin(begin); | |
drem.setEnd(end); | |
} | |
} | |
if (addToIndex) { | |
drem.addToIndexes(); | |
} | |
return drem; | |
} | |
private FSArray<DebugEvaluatedCondition> createEvaluatedConditions(RuleElementMatch rem, | |
RutaStream stream, boolean addToIndex) { | |
JCas cas = stream.getJCas(); | |
List<DebugEvaluatedCondition> ecs = new ArrayList<DebugEvaluatedCondition>(); | |
if (rem.getConditions() != null) { | |
for (EvaluatedCondition each : rem.getConditions()) { | |
DebugEvaluatedCondition ec = new DebugEvaluatedCondition(cas); | |
ec.setValue(each.isValue()); | |
ec.setElement(verbalizer.verbalize(each.getCondition())); | |
ec.setConditions(createEvaluatedConditions(each, stream, addToIndex)); | |
ecs.add(ec); | |
} | |
} | |
FSArray<DebugEvaluatedCondition> result = FSCollectionFactory.createFSArray(cas, ecs); | |
return result; | |
} | |
private FSArray<DebugEvaluatedCondition> createEvaluatedConditions(EvaluatedCondition eval, | |
RutaStream stream, boolean addToIndex) { | |
JCas cas = stream.getJCas(); | |
List<DebugEvaluatedCondition> ecs = new ArrayList<DebugEvaluatedCondition>(); | |
for (EvaluatedCondition each : eval.getConditions()) { | |
DebugEvaluatedCondition ec = new DebugEvaluatedCondition(cas); | |
ec.setValue(each.isValue()); | |
ec.setElement(verbalizer.verbalize(each.getCondition())); | |
ec.setConditions(createEvaluatedConditions(each, stream, addToIndex)); | |
ecs.add(ec); | |
} | |
FSArray<DebugEvaluatedCondition> result = FSCollectionFactory.createFSArray(cas, ecs); | |
return result; | |
} | |
public DebugScriptApply createDebugScriptApply(ScriptApply apply, RutaStream stream, | |
boolean addToIndex, boolean withMatches, Map<RutaElement, Long> timeInfo) { | |
DebugScriptApply debug = null; | |
if (apply instanceof BlockApply) { | |
debug = createDebugBlockApply((BlockApply) apply, stream, addToIndex, withMatches, timeInfo); | |
} else if (apply instanceof RuleApply) { | |
debug = createDebugRuleApply((RuleApply) apply, stream, addToIndex, withMatches, timeInfo); | |
} | |
if (addToIndex) | |
debug.addToIndexes(); | |
return debug; | |
} | |
} |