blob: ef5fe3e5509ec37e45299a1997ac30ef04a8dd11 [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.rule;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import org.apache.uima.cas.text.AnnotationFS;
import org.apache.uima.ruta.RutaProcessRuntimeException;
import org.apache.uima.ruta.RutaStream;
public class ComposedRuleElementMatch extends RuleElementMatch {
private Map<RuleElement, List<RuleElementMatch>> innerMatches;
private boolean textsMatchedUpdated = false;
public ComposedRuleElementMatch(ComposedRuleElement ruleElement,
ComposedRuleElementMatch containerMatch) {
super(ruleElement, containerMatch);
baseConditionMatched = false;
ComposedRuleElement cre = ruleElement;
innerMatches = new TreeMap<RuleElement, List<RuleElementMatch>>(new RuleElementComparator(cre));
List<RuleElement> ruleElements = cre.getRuleElements();
for (RuleElement eachRuleElement : ruleElements) {
innerMatches.put(eachRuleElement, null);
}
}
protected void enforceUpdate() {
textsMatchedUpdated = false;
ComposedRuleElementMatch cm = getContainerMatch();
if (cm != null) {
cm.enforceUpdate();
}
}
private void setInnerMatches(Map<RuleElement, List<RuleElementMatch>> innerMatches) {
this.innerMatches = innerMatches;
enforceUpdate();
}
public Map<RuleElement, List<RuleElementMatch>> getInnerMatches() {
return innerMatches;
}
public void addInnerMatch(RuleElement ruleElement, RuleElementMatch ruleElementMatch,
RutaStream stream) {
addInnerMatch(ruleElement, ruleElementMatch, true, stream);
}
public void addInnerMatch(RuleElement ruleElement, RuleElementMatch ruleElementMatch,
boolean included, RutaStream stream) {
List<RuleElementMatch> list = innerMatches.get(ruleElement);
if (list == null) {
list = new ArrayList<RuleElementMatch>();
innerMatches.put(ruleElement, list);
}
list.add(ruleElementMatch);
if (list.size() > stream.getMaxRuleElementMatches()) {
throw new RutaProcessRuntimeException("Rule element exceeded the allowed amount of matches ("
+ stream.getMaxRuleElementMatches() + "): " + ruleElement.toString());
}
evaluateInnerMatches(included, stream);
enforceUpdate();
}
public void evaluateInnerMatches(boolean included, RutaStream stream) {
boolean allDone = true;
boolean oneDone = false;
Set<Entry<RuleElement, List<RuleElementMatch>>> entrySet = innerMatches.entrySet();
for (Entry<RuleElement, List<RuleElementMatch>> entry : entrySet) {
RuleElement element = entry.getKey();
List<RuleElementMatch> value = entry.getValue();
MatchContext context = new MatchContext(element, null, true);
allDone &= (element.getQuantifier().isOptional(context, stream) || value != null);
if (value != null && !value.isEmpty() && included) {
for (RuleElementMatch ruleElementMatch : value) {
allDone &= ruleElementMatch.matched();
oneDone |= ruleElementMatch.matched();
}
}
}
ComposedRuleElement cre = (ComposedRuleElement) ruleElement;
if (cre.getConjunct() != null && !cre.getConjunct()) {
baseConditionMatched = oneDone;
} else {
baseConditionMatched = allDone;
}
}
@Override
public ComposedRuleElementMatch copy() {
ComposedRuleElementMatch copy = new ComposedRuleElementMatch((ComposedRuleElement) ruleElement,
containerMatch);
copy.setBaseConditionMatched(baseConditionMatched);
copy.setConditions(conditions);
copy.setConditionsMatched(conditionsMatched);
copy.setTextsMatched(textsMatched);
Map<RuleElement, List<RuleElementMatch>> newMap = new TreeMap<RuleElement, List<RuleElementMatch>>(
new RuleElementComparator((ComposedRuleElement) ruleElement));
for (Entry<RuleElement, List<RuleElementMatch>> entry : innerMatches.entrySet()) {
List<RuleElementMatch> value = entry.getValue();
if (value != null) {
List<RuleElementMatch> newValue = new ArrayList<RuleElementMatch>();
for (RuleElementMatch each : value) {
newValue.add(each.copy());
}
newMap.put(entry.getKey(), newValue);
} else {
newMap.put(entry.getKey(), null);
}
}
copy.setInnerMatches(newMap);
return copy;
}
public ComposedRuleElementMatch copy(ComposedRuleElementMatch extendedContainerMatch,
boolean after) {
ComposedRuleElementMatch copy = new ComposedRuleElementMatch((ComposedRuleElement) ruleElement,
containerMatch);
copy.setBaseConditionMatched(baseConditionMatched);
copy.setConditions(conditions);
copy.setConditionsMatched(conditionsMatched);
copy.setTextsMatched(textsMatched);
Map<RuleElement, List<RuleElementMatch>> newMap = new TreeMap<RuleElement, List<RuleElementMatch>>(
new RuleElementComparator((ComposedRuleElement) ruleElement));
for (Entry<RuleElement, List<RuleElementMatch>> entry : innerMatches.entrySet()) {
RuleElement key = entry.getKey();
List<RuleElementMatch> value = entry.getValue();
if (key.equals(extendedContainerMatch.getRuleElement())) {
// if (value.isEmpty()) {
extendedContainerMatch.setContainerMatch(copy);
if (value != null) {
List<RuleElementMatch> newValue = new ArrayList<RuleElementMatch>();
newValue.addAll(value);
newValue.set(newValue.size() - 1, extendedContainerMatch);
newMap.put(extendedContainerMatch.getRuleElement(), newValue);
}
// } else {
// List<RuleElementMatch> newValue = new ArrayList<RuleElementMatch>();
// newValue.addAll(value);
// newValue.add(extendedContainerMatch);
// newMap.put(extendedContainerMatch.getRuleElement(), newValue);
// }
} else {
if (value != null) {
List<RuleElementMatch> newValue = new ArrayList<RuleElementMatch>();
for (RuleElementMatch each : value) {
each.setContainerMatch(copy);
if (each instanceof ComposedRuleElementMatch) {
newValue.add(((ComposedRuleElementMatch) each).copy(extendedContainerMatch, after));
} else {
newValue.add(each.copy());
}
}
newMap.put(entry.getKey(), newValue);
} else {
newMap.put(entry.getKey(), null);
}
}
}
copy.setInnerMatches(newMap);
return copy;
}
public ComposedRuleElementMatch copy2(ComposedRuleElementMatch extendedContainerMatch,
boolean after) {
ComposedRuleElementMatch copy = new ComposedRuleElementMatch((ComposedRuleElement) ruleElement,
containerMatch);
copy.setBaseConditionMatched(baseConditionMatched);
copy.setConditions(conditions);
copy.setConditionsMatched(conditionsMatched);
copy.setTextsMatched(textsMatched);
Map<RuleElement, List<RuleElementMatch>> newMap = new TreeMap<RuleElement, List<RuleElementMatch>>(
new RuleElementComparator((ComposedRuleElement) ruleElement));
for (Entry<RuleElement, List<RuleElementMatch>> entry : innerMatches.entrySet()) {
RuleElement key = entry.getKey();
List<RuleElementMatch> value = entry.getValue();
if (key.equals(extendedContainerMatch.getRuleElement())) {
extendedContainerMatch.setContainerMatch(copy);
if (value != null) {
List<RuleElementMatch> newValue = new ArrayList<RuleElementMatch>();
newValue.addAll(value);
if (!newValue.isEmpty()) {
// there was no match
newValue.set(newValue.size() - 1, extendedContainerMatch);
}
newMap.put(extendedContainerMatch.getRuleElement(), newValue);
}
} else {
if (value != null && !value.isEmpty()) {
List<RuleElementMatch> newValue = new ArrayList<RuleElementMatch>();
int counter = 0;
for (RuleElementMatch each : value) {
each.setContainerMatch(copy);
// really need to copy all?
boolean isCurrentOne = false;
if (counter == value.size() - 1) {
isCurrentOne = true;
}
// should not be neccessary because empty matches are listed last
// if (after && counter == value.size() - 1) {
// isCurrentOne = true;
// }
// if (!after && counter == 0) {
// isCurrentOne = true;
// }
if (each instanceof ComposedRuleElementMatch && isCurrentOne) {
newValue.add(((ComposedRuleElementMatch) each).copy2(extendedContainerMatch, after));
} else {
newValue.add(each.copy());
}
counter++;
}
newMap.put(entry.getKey(), newValue);
} else {
newMap.put(entry.getKey(), null);
}
}
}
copy.setInnerMatches(newMap);
return copy;
}
public void update(ComposedRuleElementMatch extendedContainerMatch) {
for (Entry<RuleElement, List<RuleElementMatch>> entry : innerMatches.entrySet()) {
RuleElement key = entry.getKey();
List<RuleElementMatch> value = entry.getValue();
if (key.equals(extendedContainerMatch.getRuleElement())) {
extendedContainerMatch.setContainerMatch(this);
if (value != null) {
value.set(value.size() - 1, extendedContainerMatch);
}
} else {
if (value != null) {
for (RuleElementMatch each : value) {
if (each instanceof ComposedRuleElementMatch) {
((ComposedRuleElementMatch) each).update(extendedContainerMatch);
}
}
}
}
}
enforceUpdate();
}
@Override
public String toString() {
return "CREM" + innerMatches.toString();
}
@Override
public List<AnnotationFS> getTextsMatched() {
if (!textsMatchedUpdated || textsMatched == null) {
Collection<AnnotationFS> set = new TreeSet<AnnotationFS>(new AnnotationComparator());
Collection<List<RuleElementMatch>> values = innerMatches.values();
for (List<RuleElementMatch> list : values) {
if (list != null) {
for (RuleElementMatch ruleElementMatch : list) {
set.addAll(ruleElementMatch.getTextsMatched());
}
}
}
textsMatched = new ArrayList<AnnotationFS>(set);
textsMatchedUpdated = true;
}
return textsMatched;
}
public void setConditionInfo(List<EvaluatedCondition> evaluatedConditions) {
conditions = evaluatedConditions;
for (EvaluatedCondition each : conditions) {
conditionsMatched = conditionsMatched && each.isValue();
}
}
}