// Module : $RCSfile: DefaultSequenceDetectionRule.java,v $ // Version : $Revision: 0.0 $ $Author: patrick $ $Date: 18.03.2012 $ // Project : TaskTreeCreator // Creation : 2012 by patrick // Copyright : Patrick Harms, 2012 package de.ugoe.cs.quest.tasktrees.temporalrelation; import de.ugoe.cs.quest.eventcore.gui.IInteraction; import de.ugoe.cs.quest.tasktrees.treeifc.IEventTask; import de.ugoe.cs.quest.tasktrees.treeifc.ISequence; import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeBuilder; import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode; import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNodeFactory; /** * TODO comment * * @version $Revision: $ $Date: 18.03.2012$ * @author 2012, last modified by $Author: patrick$ */ public class DefaultGuiEventSequenceDetectionRule implements TemporalRelationshipRule { /* * (non-Javadoc) * * @see de.ugoe.cs.tasktree.temporalrelation.TemporalRelationshipRule#apply(TaskTreeNode, * TaskTreeBuilder, TaskTreeNodeFactory) */ @Override public RuleApplicationResult apply(ITaskTreeNode parent, ITaskTreeBuilder builder, ITaskTreeNodeFactory nodeFactory, boolean finalize) { if (!(parent instanceof ISequence)) { return null; } RuleApplicationResult result = new RuleApplicationResult(); int sequenceStartingIndex = -1; int index = 0; while (index < parent.getChildren().size()) { ITaskTreeNode child = parent.getChildren().get(index); if ((child instanceof IEventTask) && (((IEventTask) child).getEventType() instanceof IInteraction)) { IInteraction eventType = (IInteraction) ((IEventTask) child).getEventType(); if (eventType.finishesLogicalSequence() && (sequenceStartingIndex > -1)) { // There are several situations in which this implementation may cause infinite // loops. This is because the rule manager will reapply rules until // no rule is applied anymore. A sequence identified in a first iteration will // be identified as a sequence also in a second iteration. As an example // many sequences start with an interaction starting that sequence and end // with an interaction ending that sequence. This will be reidentified as // further subsequence. It must therefore be assured, that a sequence, that // was once identified is not reidentified in a further application of the rule. // For this, the implementation performs a kind of dry run. It creates a list of // children that would belong to an identified sequence. Only if this list is // not a reidentification then a new sequence is created and added to the // parent. If it is a reidentification can be identified, if the list of // children will contain all children of the parent, or if the list of children // only consists of one sequence. Further, an identified sequence must at least // have one child. if (((sequenceStartingIndex != 0) || (index != (parent.getChildren().size() - 1))) && (((index - sequenceStartingIndex) > 0) || (((index - sequenceStartingIndex) == 0) && (!eventType.startsLogicalSequence())))) { boolean allNewChildrenAreSequences = true; for (int j = sequenceStartingIndex; ((allNewChildrenAreSequences) && (j < index)); j++) { allNewChildrenAreSequences &= (parent.getChildren().get(j) instanceof ISequence); } if (!allNewChildrenAreSequences) { ISequence sequence = nodeFactory.createNewSequence(); for (int j = sequenceStartingIndex; j < index; j++) { builder.addChild (sequence, parent.getChildren().get(sequenceStartingIndex)); builder.removeChild((ISequence) parent, sequenceStartingIndex); } if (!eventType.startsLogicalSequence()) { builder.addChild (sequence, parent.getChildren().get(sequenceStartingIndex)); builder.removeChild((ISequence) parent, sequenceStartingIndex); } builder.addChild((ISequence) parent, sequenceStartingIndex, sequence); result.addNewlyCreatedParentNode(sequence); result.setRuleApplicationStatus (RuleApplicationStatus.RULE_APPLICATION_FINISHED); return result; } } } if (eventType.startsLogicalSequence()) { sequenceStartingIndex = index; } } index++; } if (sequenceStartingIndex >= 0) { result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FEASIBLE); } return result; } }