// Copyright 2012 Georg-August-Universität Göttingen, Germany // // Licensed 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 de.ugoe.cs.autoquest.tasktrees.temporalrelation; import java.util.LinkedList; import java.util.List; import de.ugoe.cs.autoquest.tasktrees.nodeequality.NodeEquality; import de.ugoe.cs.autoquest.tasktrees.nodeequality.NodeEqualityRuleManager; import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration; import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection; import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence; import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeBuilder; import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNode; import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNodeFactory; /** *

* TODO comment *

* * @author Patrick Harms */ class SimpleIterationDetectionRule implements TemporalRelationshipRule { /** *

* the task tree node factory to be used for creating substructures for the temporal * relationships identified during rule *

*/ private ITaskTreeNodeFactory taskTreeNodeFactory; /** *

* the task tree builder to be used for creating substructures for the temporal relationships * identified during rule application *

*/ private ITaskTreeBuilder taskTreeBuilder; /** *

* the node comparator used for comparing task tree nodes with each other *

*/ private TaskTreeNodeComparator nodeComparator; /** *

* instantiates the rule and initializes it with a node equality rule manager and the minimal * node equality identified sublist must have to consider them as iterated. *

*/ SimpleIterationDetectionRule(NodeEqualityRuleManager nodeEqualityRuleManager, NodeEquality minimalNodeEquality, ITaskTreeNodeFactory taskTreeNodeFactory, ITaskTreeBuilder taskTreeBuilder) { this.taskTreeNodeFactory = taskTreeNodeFactory; this.taskTreeBuilder = taskTreeBuilder; this.nodeComparator = new TaskTreeNodeComparator(nodeEqualityRuleManager, minimalNodeEquality); } /** *

* instantiates the rule and initializes it with a node equality rule manager and the minimal * node equality identified sublist must have to consider them as iterated. *

*/ SimpleIterationDetectionRule(TaskTreeNodeComparator nodeComparator, ITaskTreeNodeFactory taskTreeNodeFactory, ITaskTreeBuilder taskTreeBuilder) { this.nodeComparator = nodeComparator; this.taskTreeNodeFactory = taskTreeNodeFactory; this.taskTreeBuilder = taskTreeBuilder; } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "SimpleIterationDetectionRule"; } /* * (non-Javadoc) * * @see de.ugoe.cs.tasktree.temporalrelation.TemporalRelationshipRule#apply(TaskTreeNode, * boolean) */ @Override public RuleApplicationResult apply(ITaskTreeNode parent, boolean finalize) { if (!(parent instanceof ISequence)) { return null; } if (!finalize) { // this rule can only finalize whole trees return null; } RuleApplicationResult result = new RuleApplicationResult(); applyOn(parent, result); if (result.getNewlyCreatedParentNodes().size() > 0) { result.setRuleApplicationStatus(RuleApplicationStatus.FINISHED); } return result; } /** * */ private void applyOn(ITaskTreeNode node, RuleApplicationResult result) { int iterationStartIndex = -1; ITaskTreeNode iteratedChild = null; int index = 0; List children = node.getChildren(); while (index < children.size()) { ITaskTreeNode child = children.get(index); if (iteratedChild == null) { // new iteration may start iterationStartIndex = index; iteratedChild = child; } else { if (!nodeComparator.equals(iteratedChild, child)) { // iteration finished handleIteration(node, iterationStartIndex, index - 1, result); // children may have changed children = node.getChildren(); // new iteration may start index = iterationStartIndex + 1; iterationStartIndex = index; iteratedChild = child; } } index++; } if (iterationStartIndex > -1) { handleIteration(node, iterationStartIndex, children.size() - 1, result); } } /** * */ private void handleIteration(ITaskTreeNode parent, int startIndex, int endIndex, RuleApplicationResult result) { if (startIndex == endIndex) { // only one child return; } IIteration iteration = taskTreeNodeFactory.createNewIteration(); result.addNewlyCreatedParentNode(iteration); List children = parent.getChildren(); List equalChildren = new LinkedList(); for (int i = endIndex - startIndex; i >= 0; i--) { equalChildren.add(children.get(startIndex)); taskTreeBuilder.removeChild((ISequence) parent, startIndex); } // merge the identified variants, but preserve the differences in form of selections // by using lexical equality for merge comparisons TaskTreeNodeMerger merger = new TaskTreeNodeMerger (taskTreeNodeFactory, taskTreeBuilder, nodeComparator); merger.mergeTaskNodes(equalChildren); if (equalChildren.size() == 1) { taskTreeBuilder.setChild(iteration, equalChildren.get(0)); taskTreeBuilder.setDescription(iteration, "several " + equalChildren.get(0)); } else { taskTreeBuilder.setDescription(iteration, "several " + equalChildren.get(0)); // create a selection of all variants ISelection selection = taskTreeNodeFactory.createNewSelection(); result.addNewlyCreatedParentNode(selection); taskTreeBuilder.setChild(iteration, selection); taskTreeBuilder.setDescription(selection, "variants"); for (ITaskTreeNode variant : equalChildren) { taskTreeBuilder.addChild(selection, variant); } } taskTreeBuilder.addChild((ISequence) parent, startIndex, iteration); } }