
org.ow2.bonita.deployment.IterationDetectionNoException Maven / Gradle / Ivy
The newest version!
/**
* Copyright (C) 2011-2012 BonitaSoft S.A.
* BonitaSoft, 31 rue Gustave Eiffel - 38000 Grenoble
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation
* version 2.1 of the License.
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301, USA.
**/
package org.ow2.bonita.deployment;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.ow2.bonita.facade.def.element.impl.IterationDescriptor;
import org.ow2.bonita.iteration.IterationNode;
import org.ow2.bonita.iteration.IterationNode.SplitType;
import org.ow2.bonita.iteration.IterationProcess;
import org.ow2.bonita.iteration.IterationTransition;
/**
* @author Nicolas Chabanoles
* @author Matthieu Chaffotte
*
*/
public class IterationDetectionNoException {
private static final Logger LOG = Logger.getLogger(IterationDetection.class.getName());
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
protected IterationDetectionNoException() {
super();
}
/*
* Implements a deep first search to list all the paths in the process.
* DFS (graph G, node s) { Mark(s); For each node n : Neighbour(s) do if
* !marked(n) then DFS(G,n); End-if end }
*/
public static SortedSet findIterations(final IterationProcess inProcess) {
final SortedMap allProcessNodes = inProcess.getNodes();
final SortedSet allPorcessNodesSorted = new TreeSet(allProcessNodes.values());
// store path during recursive search
final List path = new ArrayList(allProcessNodes.size());
// store visited nodes
final SortedSet visitedNodes = new TreeSet();
final SortedSet iterationDescriptors = new TreeSet();
for (final IterationNode sourceNode : allPorcessNodesSorted) {
final SortedSet incomingTransitions = new TreeSet(
sourceNode.getIncomingTransitions());
final SortedSet temporaryIterationDescriptors = new TreeSet();
for (final IterationTransition transition : incomingTransitions) {
// List all paths form sourceNode to sourceNode, i.e. find all cycles.
// We need to take care not to looping forever, that is why we need to
// remember already visited nodes.
listCycles(inProcess, sourceNode, transition.getSource(), path, visitedNodes, temporaryIterationDescriptors);
iterationDescriptors.addAll(temporaryIterationDescriptors);
}
}
return iterationDescriptors;
}
private static void listCycles(final IterationProcess inProcess, final IterationNode sourceNode,
final IterationNode targetNode, final List path, final SortedSet visitedNodes,
final SortedSet iterationDescriptors) {
// Add node into the path.
path.add(sourceNode);
// SourceNode == targetNode --> stop recursive search
if (sourceNode.getName().equals(targetNode.getName())) {
final IterationDescriptor descriptor = buildIterationDescriptor(path);
iterationDescriptors.add(descriptor);
path.remove(sourceNode);
return;
}
visitedNodes.add(sourceNode); // mark node
// search recursively...
final SortedSet outgoingTransitions = new TreeSet(
sourceNode.getOutgoingTransitions());
for (final IterationTransition transition : outgoingTransitions) {
if (!visitedNodes.contains(transition.getDestination())) {
// do not follow transitions that points to a visited node to avoid
// looping infinitely.
listCycles(inProcess, transition.getDestination(), targetNode, path, visitedNodes, iterationDescriptors);
}
}
visitedNodes.remove(sourceNode); // un-mark node
path.remove(sourceNode);
}
/*
* Build an iteration descriptor based on nodes in path. Entry nodes: nodes
* that have an incoming transition from a node that do not belong to the
* cycle. Exit nodes: nodes that have an outgoing transition to a node that do
* not belong to the cycle. Other nodes: nodes that have an incoming
* transition from a node that do not belong to the cycle.
*/
private static IterationDescriptor buildIterationDescriptor(final List path) {
final List nodesInPath = getNodeNames(path);
final SortedSet entryNodes = new TreeSet();
final SortedSet exitNodes = new TreeSet();
final SortedSet otherNodes = new TreeSet();
for (final IterationNode node : path) {
final Set incomingTransitions = node.getIncomingTransitions();
final Set outgoingTransitions = node.getOutgoingTransitions();
final String nodeName = node.getName();
for (final IterationTransition transition : incomingTransitions) {
if (!path.contains(transition.getSource())) {
entryNodes.add(nodeName);
}
}
for (final IterationTransition transition : outgoingTransitions) {
if (!path.contains(transition.getDestination())) {
exitNodes.add(nodeName);
final SplitType splitType = node.getSplitType();
// Only allow XOR split for exit nodes
if (!SplitType.XOR.equals(splitType) && LOG.isLoggable(Level.WARNING)) {
final StringBuilder builder = new StringBuilder("Potential issue in iteration : ");
builder.append(nodeName).append(" is an exit node for cycle ").append(nodesInPath).append('.')
.append(LINE_SEPARATOR);
builder.append("Split type of this node is ").append(splitType).append(" but only XOR is supported.")
.append(LINE_SEPARATOR);
builder
.append("An exception will be thrown at runtime if more than one transition is enabled at the same time.");
LOG.warning(builder.toString());
}
}
}
if (!entryNodes.contains(nodeName) && !exitNodes.contains(nodeName)) {
otherNodes.add(nodeName);
}
}
return new IterationDescriptor(otherNodes, entryNodes, exitNodes);
}
private static List getNodeNames(final List path) {
final List nodeNames = new ArrayList();
for (final IterationNode iterationNode : path) {
nodeNames.add(iterationNode.getName());
}
return nodeNames;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy