// It is possible that there is already an edge between g.getSource Blue and newRed
Iterator<DirectedSparseEdge> sourceOutIt = source.getOutEdges().iterator();
Edge fromSourceToNewRed = null;
while(sourceOutIt.hasNext() && fromSourceToNewRed == null)
{
DirectedSparseEdge out = sourceOutIt.next();if (out.getDest() == newRed) fromSourceToNewRed = out;
}
if (fromSourceToNewRed == null)
{
fromSourceToNewRed = new DirectedSparseEdge(source,newRed);
fromSourceToNewRed.setUserDatum(JUConstants.LABEL, existingLabels, UserData.CLONE);// no need to clone this one since I'll delete the edge in a bit
g.addEdge(fromSourceToNewRed);
}
else
// there is already a transition from source to newRed, hence all we have to do is merge the new labels into it.
((Collection<String>)fromSourceToNewRed.getUserDatum(JUConstants.LABEL)).addAll( existingLabels );
}
// now the elements of mergedVertices are in terms of the copied graph.
for(Vertex vert:(Set<Vertex>)g.getVertices())
if (mergedVertices.containsKey(vert))
{// there are some vertices to merge with this one.
usedInputs.clear();usedInputs.addAll(s.transitionMatrix.get(vert).keySet());
for(CmpVertex toMerge:mergedVertices.get(vert))
{// for every input, I'll have a unique target state - this is a feature of PTA
// For this reason, every if multiple branches of PTA get merged, there will be no loops or parallel edges.
// As a consequence, it is safe to assume that each input/target state combination will lead to a new state.
Set<String> inputsFrom_toMerge = s.transitionMatrix.get(toMerge).keySet();
for(String input:inputsFrom_toMerge)
if (!usedInputs.contains(input))
{
Set<String> labels = new HashSet<String>();labels.add(input);
DeterministicVertex targetVert = (DeterministicVertex)s.transitionMatrix.get(toMerge).get(input);
DirectedSparseEdge newEdge = new DirectedSparseEdge(vert,targetVert);
newEdge.addUserDatum(JUConstants.LABEL, labels, UserData.CLONE);
g.removeEdges(targetVert.getInEdges());g.addEdge(newEdge);
}
usedInputs.addAll(inputsFrom_toMerge);
}
}