blob: 5f8f22142bbfbece1aa0802fcb56775a926ce7a5 [file] [log] [blame]
package org.eclipse.emf.henshin.sam.invcheck;
import java.util.BitSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.henshin.sam.invcheck.adapter.SamGraphInvCheckGraphAdapter;
import org.eclipse.emf.henshin.sam.invcheck.nac.GraphWithNacs;
import org.eclipse.emf.henshin.sam.invcheck.nac.NegativeApplicationCondition;
import org.eclipse.emf.henshin.sam.model.samannotation.AnnotatedElem;
import org.eclipse.emf.henshin.sam.model.samannotation.Annotation;
import org.eclipse.emf.henshin.sam.model.samgraph.Edge;
import org.eclipse.emf.henshin.sam.model.samgraph.Graph;
import org.eclipse.emf.henshin.sam.model.samgraph.Node;
import org.eclipse.emf.henshin.sam.model.samgraph.SamgraphFactory;
import org.eclipse.emf.henshin.sam.model.samrules.GraphRule;
import org.eclipse.emf.henshin.sam.model.samrules.PreservedNode;
import org.eclipse.emf.henshin.sam.model.samrules.RuleGraph;
import org.eclipse.emf.henshin.sam.model.samrules.SamrulesFactory;
import org.eclipse.emf.henshin.sam.model.samrules.SamrulesPackage;
import org.eclipse.emf.henshin.sam.model.samtrace.Match;
import org.eclipse.emf.henshin.sam.model.samtrace.SamtraceFactory;
import org.eclipse.emf.henshin.sam.model.samtypegraph.EdgeType;
import org.eclipse.emf.henshin.sam.model.samtypegraph.NodeType;
/**
* This class implements the <code>Iterator</code> interface. It is used to
* iterate over all subgraphs of a given <code>Graph</code>. Simply use it as
* a normal <code>Iterator</code>. The returned subgraphs are all Objects
* from type <code>Set</code>, containing the <code>Nodes</code> and
* <code>Edges</code> of the subgraph.
*/
public class SubgraphIterator implements Iterator<Set<AnnotatedElem>> {
private boolean cacheValid = false;
private boolean cachedHasNext = true;
/**
* this field contains the maximum for the number of bits, which currently
* could be set to <code>true</code> in the
* {@link #edgeBitSet edge bitset}.
*/
private transient int maxNumberEdges = 0;
/**
* This field stores the number of edges of the <code>Graph</code> {@link #graph}.
*/
private transient final int sizeOfEdges;
private transient final int sizeOfNodes;
/**
* This <code>Iterator</code> has no meaningful implementation for this
* method. If you invoke it, an <code>IllegalAccessError</code> will be
* thrown.
*
* @throws IllegalAccessError
* always
*/
public void remove() {
throw new IllegalAccessError(
"you may not call remove() on a SubgraphIterator.");
}
/**
* Use this method to test whether this <code>Iterator</code> has more
* elements or not.<br />
* An <code>SubgraphIterator</code> contains more elements if the
* iterator's local {@link #edgeBitSet} is <code>null</code> or if the
* number of bits, actually set in the <code>BitSet</code>, is less than
* the number of <code>Edge</code>s contained in the <code>Graph</code>
* the iterator is based on.
*
* @return <code>true</code> if there ary some more elements
* @see Iterator#hasNext()
*/
public boolean hasNext() {
if (!cacheValid) {
//if (this.nodeBitSet.cardinality() < this.graph.getNodes().size() || this.edgeBitSet == null || this.edgeBitSet.cardinality() < this.sizeOfEdges) {
if (this.nodeBitSet.cardinality() < this.sizeOfNodes || this.edgeBitSet == null || this.edgeBitSet.cardinality() < this.sizeOfEdges) {
cachedHasNext = true;
} else
cachedHasNext = false;
cacheValid = true;
}
return cachedHasNext;
}
/**
* Returns the next subgraph of the <code>Graph</code> passed to the
* constructor.
*
* @return a <code>Set</code> containing the elements of the subgraphs
* @throws NoSuchElementException
* If there isn't any remaining subgraph
* @see Iterator#next()
*/
public Set<AnnotatedElem> next() {
if (!this.hasNext()) {
throw new NoSuchElementException(
"end of iterator has been reached. no more subgraphs available");
}
this.computeNextState();/*
while (this.hasNext() && !isNecessarySubgraph()) {
//System.out.println("wasn't necessary");
this.computeNextState();
}
if (!isNecessarySubgraph()) {
return null;
}*/
Set<AnnotatedElem> tmpSet = this.buildReturnValue();
/*while (tmpSet != null && ! isValidReturnValue(tmpSet)) {
if (this.hasNext()) {
this.computeNextState();
tmpSet = this.buildReturnValue();
} else {
tmpSet = null;
}
}*/
return tmpSet;
}
private boolean isNecessarySubgraph() {
if (this.bitMask == null) {
return true;
} else {
return bitMask.intersects(nodeBitSet);
}
}
private boolean isValidReturnValue(Set<AnnotatedElem> returnValue) {
boolean result = true;
if (this.returnAllSubgraphs == false) {
result = false;
for (Iterator<AnnotatedElem> iter = returnValue.iterator(); !result && iter.hasNext(); ) {
AnnotatedElem tmpItem = iter.next();
if (tmpItem.eClass() != SamrulesPackage.eINSTANCE.getPreservedEdge() && tmpItem.eClass() != SamrulesPackage.eINSTANCE.getPreservedNode()) {
result = true;
} else if (tmpItem.eClass() == SamrulesPackage.eINSTANCE.getPreservedNode()) {
PreservedNode tmpNode = (PreservedNode) tmpItem;
//System.out.println(tmpNode);
//System.out.println(tmpNode.getRefInRule());
if (adjacentToModifiedEdges(tmpNode) || adjacentToModifiedEdges(tmpNode.getRefInRule())) {
result = true;
}
}
}
}
return result;
}
private boolean adjacentToModifiedEdges(final Node n) {
boolean result = false;
for (Iterator<Edge> edgeIter = n.getIncoming().iterator(); !result && edgeIter.hasNext(); ) {
Edge e = edgeIter.next();
if (e.eClass() != SamrulesPackage.eINSTANCE.getPreservedEdge()) {
result = true;
}
/*if (e.getRefInRule() == null) {
result = true;
}*/
}
for (Iterator<Edge> edgeIter = n.getOutgoing().iterator(); !result && edgeIter.hasNext(); ) {
Edge e = edgeIter.next();
if (e.eClass() != SamrulesPackage.eINSTANCE.getPreservedEdge()) {
result = true;
}
/*if (e.getRefInRule() == null) {
result = true;
}*/
}
return result;
}
private Set<AnnotatedElem> buildReturnValue() {
final Set<AnnotatedElem> tmpSet = new HashSet<AnnotatedElem>();
for (int i = this.nodeBitSet.nextSetBit(0); i != -1; i = this.nodeBitSet
.nextSetBit(i+1)) {
// we had to add this somehow weird condition, because it could
// happen that i gets bigger than nodeArray actually is.
if (i >= 0 && i < this.nodeArray.length && this.nodeBitSet.get(i)) {
tmpSet.add(this.nodeArray[i]);
}
}/*
for (int i = 0; i < this.nodeBitSet.size(); i++) {
if (i < this.nodeArray.length && this.nodeBitSet.get(i)) {
tmpSet.add(this.nodeArray[i]);
}
}
for (int i = 0; i < this.edgeBitSet.size(); i++) {
if (i < this.edgeArray.length && this.edgeBitSet.get(i)) {
tmpSet.add(this.edgeArray[i]);
}
}*/
if (this.edgeArray != null && this.edgeBitSet != null) {
for (int i = this.edgeBitSet.nextSetBit(0); i != -1; i = this.edgeBitSet.nextSetBit(i+1)) {
tmpSet.add(this.edgeArray[i]);
}
}
return tmpSet;
}
/**
* No comment provided by developer, please add a comment to improve
* documentation.
*/
private transient final Graph graph; // NOPMD by bbecker on 04.03.09 11:08
/**
* this array contains all <code>Nodes</code> of <code>Graph</code>
* attribute of this <code>SubgraphIterator</code>
*/
private final transient Node nodeArray[];
/**
* This array stores the edges which were inducted by the
* <code>nodeArray</code> and the <code>nodeBitSet</code>
*/
private transient Edge edgeArray[];
private transient final Edge origEdgeArray[];
/**
* This BitSet stores the <code>Nodes</code> which were contained in the
* last generated subgraph.
*/
private transient final BitSet nodeBitSet;
/**
* the <code>edgeBitSet</code> describes a subset of the
* <code>Edges</code> contained in the <code>edgeArray</code>
*/
private transient BitSet edgeBitSet;
private Set<Edge> nextStatetmpEdgeSet = null; // NOPMD by bbecker on 04.03.09 11:06
private BitSet bitMask;
public BitSet getBitMask() {
return bitMask;
}
private final boolean returnAllSubgraphs;
/**
* Constructor for class SubgraphIterator.
* Calling this constructor is equivalent to:<code>new SubgraphIterator(g,true)</code>
* @param g the <code>Graph</code> that is used as base for
* the generated subgraphs
* @see #SubgraphIterator(Graph, boolean)
*/
public SubgraphIterator(final Graph g) {
this(g, true, null);
}
public SubgraphIterator(final Graph g, final boolean all) {
this(g, all, null);
}
public SubgraphIterator(final Graph g, final Graph forbidden) {
this(g, true, forbidden);
}
/**
* Constructor for class SubgraphIterator
*
* @param g
* the <code>Graph</code> that is used as base for
* the generated subgraphs
* @param all Whether or not all subgraphs of <code>g</code> should
* be returned.<br />If set to <code>false</code> only such
* subgraphs are returned that contain at least one element
* which is modified by the rule.
* NOTE: <code>all</code> can only be used if <code>g</code>
* is a {@link RuleGraph} and if <code>g</code> is properly
* contained in a {@link GraphRule}.
*/
public SubgraphIterator(final Graph g, final boolean all, final Graph forbidden) { // NOPMD by bbecker on 04.03.09 11:05
assert g != null : "you passed null as paramter to the constructor";
this.graph = g;
//bitMask = this.calculateBitMask();
Map<NodeType, Integer> nodeTypes = null;
Map<EdgeType, Integer> edgeTypes = null;
if (forbidden != null) {
nodeTypes = InvariantCheckerUtil.calculateNodeTypeCount(forbidden);
}
if (forbidden != null) {
edgeTypes = InvariantCheckerUtil.calculateEdgeTypeCount(forbidden);
}
if (forbidden == null) {
this.sizeOfEdges = g == null ? 0 : g.getEdges().size();
this.sizeOfNodes = this.graph.getNodes().size();
this.nodeArray = new Node[this.graph.getNodes().size()];
} else {
int edgeSize = 0;
int nodeSize = 0;
for (final Iterator<Node> i = this.graph.getNodes().iterator(); i.hasNext();) {
Node n = i.next();
if (forbidden == null || nodeTypes.containsKey(n.getInstanceOf())) {
nodeSize++;
}
}
for (final Iterator<Edge> i = this.graph.getEdges().iterator(); i.hasNext();) {
Edge e = i.next();
if (forbidden == null || edgeTypes.containsKey(e.getInstanceOf())) {
edgeSize++;
}
}
//System.out.println("nodeSize: " + nodeSize);
//System.out.println("edgeSize: " + edgeSize);
this.nodeArray = new Node[nodeSize];
this.sizeOfNodes = nodeSize;
this.sizeOfEdges = edgeSize;
}
int index = 0;
for (final Iterator<Node> i = this.graph.getNodes().iterator(); i.hasNext();) {
Node n = i.next();
if (forbidden == null || nodeTypes.containsKey(n.getInstanceOf())) {
nodeArray[index] = n;
index++;
}
//nodeArray[index] = i.next();
}
this.edgeArray = new Edge[this.sizeOfEdges];
this.origEdgeArray = new Edge[this.sizeOfEdges];
index = 0;
for (final Iterator<Edge> i = this.graph.getEdges().iterator(); i.hasNext();) {
Edge e = i.next();
if (forbidden == null || edgeTypes.containsKey(e.getInstanceOf())) {
origEdgeArray[index] = e;
index++;
}
//this.origEdgeArray[index] = i.next();
}
this.edgeBitSet = new BitSet(this.sizeOfEdges);
this.nodeBitSet = new BitSet(this.nodeArray.length);
boolean tmpReturnAllSubgraphs = true;
if (all == false) {
if (g.eClass() == SamrulesPackage.eINSTANCE.getRuleGraph()) {
GraphRule graphRule = (GraphRule) g.eContainer();
if (graphRule.getLeft() != null && graphRule.getRight() != null && graphRule.getLeft() != graphRule.getRight()) {
tmpReturnAllSubgraphs = false;
}
/*if (g.eGet(SamrulesPackage.eINSTANCE.getRuleGraph_IsLeft()) != null) {
GraphRule graphRule = (GraphRule)(g.eGet(SamrulesPackage.eINSTANCE.getRuleGraph_IsLeft()) != null ? g.eGet(SamrulesPackage.eINSTANCE.getRuleGraph_IsLeft()) : g.eGet(MetamodelPackage.eINSTANCE.getRuleGraph_IsRight()));
if (graphRule.getLeft() != null && graphRule.getRight() != null && graphRule.getLeft() != graphRule.getRight()) {
tmpReturnAllSubgraphs = false;
}
} */
}
}
this.returnAllSubgraphs = tmpReturnAllSubgraphs;
}
private BitSet calculateBitMask() {
if (this.graph.eContainer() == null || this.graph.eContainer().eClass() != SamrulesPackage.eINSTANCE.getGraphRule()) {
return null;
}
RuleGraph leftSide = ((GraphRule) this.graph.eContainer()).getLeft();
BitSet result = new BitSet(this.graph.getNodes().size());
int index = 0;
for (final Iterator<Node> i = this.graph.getNodes().iterator(); i.hasNext(); index++) {
Node n = i.next();
if (n.eClass() == SamrulesPackage.eINSTANCE.getCreatedNode()) {
result.set(index);
}
}
for (Edge e : this.graph.getEdges()) {
if (e.eClass() == SamrulesPackage.eINSTANCE.getCreatedEdge()) {
result.set(this.graph.getNodes().indexOf(e.getSource()));
result.set(this.graph.getNodes().indexOf(e.getTarget()));
}
}
for (Edge e : leftSide.getEdges()) {
if (e.eClass() == SamrulesPackage.eINSTANCE.getDeletedEdge()) {
if (e.getSource().eClass() == SamrulesPackage.eINSTANCE.getPreservedNode()) {
PreservedNode presN = (PreservedNode) e.getSource();
result.set(this.graph.getNodes().indexOf(presN.getRefInRule()));
}
if (e.getTarget().eClass() == SamrulesPackage.eINSTANCE.getPreservedNode()) {
PreservedNode presN = (PreservedNode) e.getTarget();
result.set(this.graph.getNodes().indexOf(presN.getRefInRule()));
}
}
}
GraphWithNacs left = SamGraphInvCheckGraphAdapter.getInstance(leftSide);
for (NegativeApplicationCondition nac : left.getNacs()) {
for (Edge e : nac.getEdges()) {
if (e.getSource().eClass() == SamrulesPackage.eINSTANCE.getPreservedNode()) {
PreservedNode presN = (PreservedNode) e.getSource();
result.set(this.graph.getNodes().indexOf(presN.getRefInRule()));
}
if (e.getTarget().eClass() == SamrulesPackage.eINSTANCE.getPreservedNode()) {
PreservedNode presN = (PreservedNode) e.getTarget();
result.set(this.graph.getNodes().indexOf(presN.getRefInRule()));
}
}
}
//System.out.println(result);
return result;
}
public boolean isReturnAllSubgraphs() {
return this.returnAllSubgraphs;
}
/**
* No comment provided by developer, please add a comment to improve
* documentation.
*/
private void computeNextState()
{
if (this.maxNumberEdges > 0 && this.edgeBitSet.cardinality() < maxNumberEdges)
{
incrementBitSet (this.edgeBitSet);
}
else
{
incrementBitSet (this.nodeBitSet);
//this.edgeArray = null;
if (nextStatetmpEdgeSet == null) {
this.nextStatetmpEdgeSet = new HashSet<Edge>();
} else {
this.nextStatetmpEdgeSet.clear();
}
for (int i = 0; i < this.sizeOfEdges; i++)
{
final int srcIndex = indexInArray ( this.origEdgeArray[i].getSource());
if (srcIndex >=0 && this.nodeBitSet.get (srcIndex))
{
final int tgtIndex = indexInArray ( this.origEdgeArray[i].getTarget());
if (this.nodeBitSet.get (tgtIndex))
{
nextStatetmpEdgeSet.add (this.origEdgeArray[i]);
}
}
}
this.maxNumberEdges = this.nextStatetmpEdgeSet.size();
if (!this.nextStatetmpEdgeSet.isEmpty()) {
this.edgeArray = nextStatetmpEdgeSet.toArray (this.edgeArray);
}
if (this.edgeBitSet == null)
{
this.edgeBitSet = new BitSet();
}
else
{
this.edgeBitSet.clear();
}
}
}
/**
* No comment provided by developer, please add a comment to improve
* documentation.
*
* @param edge
* No description provided
* @param node
* No description provided
* @return No description provided
*/
private int indexInArray(final Node node) {
int result = -1;
for (int i = 0; result == -1 && i < this.nodeArray.length; i++) {
if (this.nodeArray[i] == node) {
result = i;
}
}
return result;
}
/**
* Increment the binary value represented by the <code>BitSet</code>
* <code>bs</code>
*
* @param bs
* the <code>BitSet</code> that gets incremented
*/
private void incrementBitSet(final BitSet bs) {
this.cacheValid = false;
final int firstClear = bs.nextClearBit(0);
bs.set(firstClear);
for (int i = firstClear - 1; i >= 0; i--) {
bs.clear(i);
}
}
/**
* Translates a given <code>Graph</code> into a subgraph containing all the graph's elements.
* @param g the <code>Graph</code> to translate.
* @return a set containing all of the graph's elements in an arbitrary order.
*/
public static Set<AnnotatedElem> graphToSubGraph(final Graph g) {
Set<AnnotatedElem> result = null;
if (g != null) {
result = new HashSet<AnnotatedElem>(g.getEdges().size() + g.getNodes().size());
result.addAll(g.getEdges());
result.addAll(g.getNodes());
//for (NegativeApplicationCondition nac : ((GraphWithNacs) Platform.getAdapterManager().getAdapter(g, GraphWithNacs.class)).getNacs()) {
for (NegativeApplicationCondition nac : SamGraphInvCheckGraphAdapter.getInstance(g).getNacs()) {
result.addAll(nac.getEdges());
result.addAll(nac.getNodes());
}
}
return result;
}
public static Set<AnnotatedElem> graphToPosSubGraph(final Graph g) {
Set<AnnotatedElem> result = null;
if (g != null) {
result = new HashSet<AnnotatedElem>(g.getEdges().size() + g.getNodes().size());
result.addAll(g.getEdges());
result.addAll(g.getNodes());
}
return result;
}
public static Match partialNacToGraph(NegativeApplicationCondition nac1, Set<EdgeType> edgeTypes, Set<NodeType> nodeTypes) {
Graph g = SamgraphFactory.eINSTANCE.createGraph();
Match matching = SamtraceFactory.eINSTANCE.createMatch();
for (Node src : nac1.getNodes()) {
if (nodeTypes.contains(src.getInstanceOf())) {
Node n = SamgraphFactory.eINSTANCE.createNode();
n = src.copy();
//n.setGraph(g);
g.getNodes().add(n);
matching.getNodeMatching().put(src, n);
}
}
for (Edge src : nac1.getEdges()) {
if (edgeTypes.contains(src.getInstanceOf())) {
Edge e = SamgraphFactory.eINSTANCE.createEdge();
e = src.copy();
//e.setGraph(g);
g.getEdges().add(e);
//if (src.partOfNacInterface()) {
if (!matching.getNodeMatching().containsKey(src.getSource())) {
Node n = SamgraphFactory.eINSTANCE.createNode();
n = src.getSource().copy();
//n.setGraph(g);
g.getNodes().add(n);
matching.getNodeMatching().put(src.getSource(), n);
}
if (!matching.getNodeMatching().containsKey(src.getTarget())) {
Node n = SamgraphFactory.eINSTANCE.createNode();
n = src.getTarget().copy();
//n.setGraph(g);
g.getNodes().add(n);
matching.getNodeMatching().put(src.getTarget(), n);
}
//}
e.setSource(matching.getNodeMatching().get(src.getSource()));
e.setTarget(matching.getNodeMatching().get(src.getTarget()));
matching.getEdgeMatching().put(src, e);
}
}
return matching;
}
public static Match nacToGraph(NegativeApplicationCondition nac1) {
Graph g = SamgraphFactory.eINSTANCE.createGraph();
Match matching = SamtraceFactory.eINSTANCE.createMatch();
for (Node src : nac1.getNodes()) {
Node n = SamgraphFactory.eINSTANCE.createNode();
n = src.copy();
//n.setGraph(g);
g.getNodes().add(n);
matching.getNodeMatching().put(src, n);
}
for (Edge src : nac1.getEdges()) {
Edge e = SamgraphFactory.eINSTANCE.createEdge();
e = src.copy();
//e.setGraph(g);
g.getEdges().add(e);
if (src.partOfNacInterface()) {
if (!nac1.getNodes().contains(src.getSource()) && !matching.getNodeMatching().containsKey(src.getSource())) {
Node n = SamgraphFactory.eINSTANCE.createNode();
n = src.getSource().copy();
//n.setGraph(g);
g.getNodes().add(n);
matching.getNodeMatching().put(src.getSource(), n);
}
if (!nac1.getNodes().contains(src.getTarget()) && !matching.getNodeMatching().containsKey(src.getTarget())) {
Node n = SamgraphFactory.eINSTANCE.createNode();
n = src.getTarget().copy();
//n.setGraph(g);
g.getNodes().add(n);
matching.getNodeMatching().put(src.getTarget(), n);
}
}
e.setSource(matching.getNodeMatching().get(src.getSource()));
e.setTarget(matching.getNodeMatching().get(src.getTarget()));
matching.getEdgeMatching().put(src, e);
}
return matching;
}
/**
* This method is used to translate a NAC to a graph while also keeping all positive elements the formal version of the NAC
* includes.
*
* The flag isPartial indicates whether the NAC is a partial negative application condition, in which case the positive parts to
* be included in the NAC are determined by checking the annotations in the NAC. (This is the special case of partial NACs
* created by merging a forbidden subgraph and a right rule side. We do not need to check left application conditions which would
* also be partially integrated into the source pattern, because in our special example, rules do not have NACs.)
*
* If it is not a partial NAC, we can simply copy all positive items from the graph.
*
* @param nac1
* @return
*/
public static Match fullNacToGraph(NegativeApplicationCondition nac1, boolean isPartial) {
boolean partial = isPartial;
if (nac1.getAnnotations().isEmpty()) {
partial = false;
} else {
partial = true;
}
Graph g = SamgraphFactory.eINSTANCE.createGraph();
Match matching = SamtraceFactory.eINSTANCE.createMatch();
for (Node src : nac1.getNodes()) {
Node n = SamgraphFactory.eINSTANCE.createNode();
n = src.copy();
//n.setGraph(g);
g.getNodes().add(n);
matching.getNodeMatching().put(src, n);
}
for (Edge src : nac1.getEdges()) {
Edge e = SamgraphFactory.eINSTANCE.createEdge();
e = src.copy();
//e.setGraph(g);
g.getEdges().add(e);
if (src.partOfNacInterface()) {
if (!nac1.getNodes().contains(src.getSource()) && !matching.getNodeMatching().containsKey(src.getSource())) {
Node n = SamgraphFactory.eINSTANCE.createNode();
n = src.getSource().copy();
//n.setGraph(g);
g.getNodes().add(n);
matching.getNodeMatching().put(src.getSource(), n);
}
if (!nac1.getNodes().contains(src.getTarget()) && !matching.getNodeMatching().containsKey(src.getTarget())) {
Node n = SamgraphFactory.eINSTANCE.createNode();
n = src.getTarget().copy();
//n.setGraph(g);
g.getNodes().add(n);
matching.getNodeMatching().put(src.getTarget(), n);
}
}
e.setSource(matching.getNodeMatching().get(src.getSource()));
e.setTarget(matching.getNodeMatching().get(src.getTarget()));
matching.getEdgeMatching().put(src, e);
}
for (Node src : nac1.getGraph().getNodes()) {
if (!isPartial) {
if (!matching.getNodeMatching().containsKey(src)) {
Node n = src.copy();
g.getNodes().add(n);
matching.getNodeMatching().put(src, n);
}
} else {
if (!matching.getNodeMatching().containsKey(src)) {
for (Annotation an : nac1.getAnnotations()) {
if (an.getSource().equals(InvariantCheckerPlugin.NAC_BOUND_ITEM) && an.getTarget() == src) {
Node n = src.copy();
g.getNodes().add(n);
matching.getNodeMatching().put(src, n);
break;
}
}
}
}
}
for (Edge src : nac1.getGraph().getEdges()) {
if (!isPartial) {
if (!matching.getEdgeMatching().containsKey(src)) {
Edge e = src.copy();
g.getEdges().add(e);
e.setSource(matching.getNodeMatching().get(src.getSource()));
e.setTarget(matching.getNodeMatching().get(src.getTarget()));
matching.getEdgeMatching().put(src, e);
}
} else {
if (!matching.getEdgeMatching().containsKey(src)) {
for (Annotation an : nac1.getAnnotations()) {
if (an.getSource().equals(InvariantCheckerPlugin.NAC_BOUND_ITEM) && an.getTarget() == src) {
Edge e = src.copy();
g.getEdges().add(e);
e.setSource(matching.getNodeMatching().get(src.getSource()));
e.setTarget(matching.getNodeMatching().get(src.getTarget()));
matching.getEdgeMatching().put(src, e);
break;
}
}
}
}
}
return matching;
}
public static Match fullNacToRuleGraph(NegativeApplicationCondition nac1, boolean isPartial) {
boolean partial = isPartial;
if (nac1.getAnnotations().isEmpty()) {
partial = false;
} else {
partial = true;
}
RuleGraph g = SamrulesFactory.eINSTANCE.createRuleGraph();
Match matching = SamtraceFactory.eINSTANCE.createMatch();
for (Node src : nac1.getNodes()) {
Node n = SamgraphFactory.eINSTANCE.createNode();
n = src.copy();
//n.setGraph(g);
g.getNodes().add(n);
matching.getNodeMatching().put(src, n);
}
for (Edge src : nac1.getEdges()) {
Edge e = SamgraphFactory.eINSTANCE.createEdge();
e = src.copy();
//e.setGraph(g);
g.getEdges().add(e);
if (src.partOfNacInterface()) {
if (!nac1.getNodes().contains(src.getSource()) && !matching.getNodeMatching().containsKey(src.getSource())) {
Node n = SamgraphFactory.eINSTANCE.createNode();
n = src.getSource().copy();
//n.setGraph(g);
g.getNodes().add(n);
matching.getNodeMatching().put(src.getSource(), n);
}
if (!nac1.getNodes().contains(src.getTarget()) && !matching.getNodeMatching().containsKey(src.getTarget())) {
Node n = SamgraphFactory.eINSTANCE.createNode();
n = src.getTarget().copy();
//n.setGraph(g);
g.getNodes().add(n);
matching.getNodeMatching().put(src.getTarget(), n);
}
}
e.setSource(matching.getNodeMatching().get(src.getSource()));
e.setTarget(matching.getNodeMatching().get(src.getTarget()));
matching.getEdgeMatching().put(src, e);
}
for (Node src : nac1.getGraph().getNodes()) {
if (!isPartial) {
if (!matching.getNodeMatching().containsKey(src)) {
Node n = src.copy();
g.getNodes().add(n);
matching.getNodeMatching().put(src, n);
}
} else {
if (!matching.getNodeMatching().containsKey(src)) {
for (Annotation an : nac1.getAnnotations()) {
if (an.getSource().equals(InvariantCheckerPlugin.NAC_BOUND_ITEM) && an.getTarget() == src) {
Node n = src.copy();
g.getNodes().add(n);
matching.getNodeMatching().put(src, n);
break;
}
}
}
}
}
for (Edge src : nac1.getGraph().getEdges()) {
if (!isPartial) {
if (!matching.getEdgeMatching().containsKey(src)) {
Edge e = src.copy();
g.getEdges().add(e);
e.setSource(matching.getNodeMatching().get(src.getSource()));
e.setTarget(matching.getNodeMatching().get(src.getTarget()));
matching.getEdgeMatching().put(src, e);
}
} else {
if (!matching.getEdgeMatching().containsKey(src)) {
for (Annotation an : nac1.getAnnotations()) {
if (an.getSource().equals(InvariantCheckerPlugin.NAC_BOUND_ITEM) && an.getTarget() == src) {
Edge e = src.copy();
g.getEdges().add(e);
e.setSource(matching.getNodeMatching().get(src.getSource()));
e.setTarget(matching.getNodeMatching().get(src.getTarget()));
matching.getEdgeMatching().put(src, e);
break;
}
}
}
}
}
return matching;
}
/**
* This method extracts a subgraph given by the parameters from a graph by copying the passed elements to a new graph and returning
* the match.
*
* @param nodes
* @param edges
* @return
*/
public static Match extractSubgraph(Set<Node> nodes, Set<Edge> edges) {
Match result = SamtraceFactory.eINSTANCE.createMatch();
Graph subgraph = SamgraphFactory.eINSTANCE.createGraph();
for (Node src : nodes) {
Node n = src.copy();
subgraph.getNodes().add(n);
result.getNodeMatching().put(src, n);
}
for (Edge src : edges) {
Edge e = src.copy();
subgraph.getEdges().add(e);
e.setSource(result.getNodeMatching().get(src.getSource()));
e.setTarget(result.getNodeMatching().get(src.getTarget()));
result.getEdgeMatching().put(src, e);
}
return result;
}
public static Match getUnmatchedPositivePart(Graph hostGraph, Match matching, NegativeApplicationCondition nac) {
Graph result = SamgraphFactory.eINSTANCE.createGraph();
Match tmp = SamtraceFactory.eINSTANCE.createMatch();
for (Node src : hostGraph.getNodes()) {
if (!matching.getNodeMatching().containsValue(src)) {
Node n = src.copy();
//n.setGraph(result);
result.getNodes().add(n);
tmp.getNodeMatching().put(src, n);
}
}
for (Edge src : nac.getEdges()) {
if (src.partOfNacInterface()) {
//if (!nac.getNodes().contains(src.getSource()) && !tmp.getNodeMatching().containsKey(src.getSource())) {
if (!InvariantCheckerUtil.isNegated(src.getSource()) && !tmp.getNodeMatching().containsKey(src.getSource())) {
Node n = src.getSource().copy();
//n.setGraph(result);
result.getNodes().add(n);
tmp.getNodeMatching().put(src.getSource(), n);
}
if (!InvariantCheckerUtil.isNegated(src.getTarget()) && !tmp.getNodeMatching().containsKey(src.getTarget())) {
Node n = src.getTarget().copy();
//n.setGraph(result);
result.getNodes().add(n);
tmp.getNodeMatching().put(src.getTarget(), n);
}
}
}
for (Edge src : hostGraph.getEdges()) {
if (!matching.getEdgeMatching().containsValue(src)) {
Edge e = src.copy();
//e.setGraph(result);
result.getEdges().add(e);
// In some cases there might be unmatched edges with matched source
// or target nodes (might for example occur when there are two edges between two nodes).
// The following conditions are included to prevent dangling edges due to this.
if (tmp.getNodeMatching().get(src.getSource()) == null) {
Node newSrc = src.getSource().copy();
//newSrc.setGraph(result);
result.getNodes().add(newSrc);
tmp.getNodeMatching().put(src.getSource(), newSrc);
}
if (tmp.getNodeMatching().get(src.getTarget()) == null) {
Node newSrc = src.getTarget().copy();
//newSrc.setGraph(result);
result.getNodes().add(newSrc);
tmp.getNodeMatching().put(src.getTarget(), newSrc);
}
e.setSource(tmp.getNodeMatching().get(src.getSource()));
e.setTarget(tmp.getNodeMatching().get(src.getTarget()));
tmp.getEdgeMatching().put(src, e);
}
}
return tmp;
}
public static Set<AnnotatedElem> removeNACsFromGraph(Graph g) {
Set<AnnotatedElem> result = null;
if (g != null) {
result = new HashSet<AnnotatedElem>(g.getEdges().size() + g.getNodes().size());
for (Iterator<Node> iter = g.getNodes().iterator(); iter.hasNext(); result.add(iter.next()));
for (Iterator<Edge> iter = g.getEdges().iterator(); iter.hasNext(); result.add(iter.next()));
for (NegativeApplicationCondition nac : ((GraphWithNacs) (Platform.getAdapterManager().getAdapter(g, GraphWithNacs.class))).getNacs()) {
for (Iterator<Node> iter = nac.getNodes().iterator(); iter.hasNext(); result.add(iter.next()));
for (Iterator<Edge> iter = nac.getEdges().iterator(); iter.hasNext(); result.add(iter.next()));
}
}
return result;
}
/**
* counts occurences of types in the given <code>Set</code>.</br>
* This method returns a <code>Map</code> with the nodes' types as keys and an <code>Integer</code>
* object storing their frequency of occurence
*
* @param subgraph a <code>Set</code> representing a valid subgraph
* @return <code>Map</code> with the frequency of occurence for each type
*/
public static Map<NodeType, Integer> computeTypesInSubgraph(Set<AnnotatedElem> subgraph) {
Map<NodeType, Integer> m = new HashMap<NodeType, Integer>();
if (subgraph != null) {
for (Iterator<AnnotatedElem> iter = subgraph.iterator(); iter.hasNext();) {
AnnotatedElem next = iter.next();
if (next instanceof Node && !(InvariantCheckerUtil.isNegated((Node) next))) {
Node node = (Node) next;
Integer i = m.get(node.getInstanceOf());
if (i != null) {
m.put(node.getInstanceOf(), new Integer(i.intValue() + 1));
} else {
m.put(node.getInstanceOf(), new Integer(1));
}
}
}
}
return m;
}
}
/*
* $Log$ Revision 1.2 2007/01/03 09:27:47 basilb removed compile errors caused
* by wrong import declarations; introduced empty plugin class to ensure correct
* loading
*
*/