package agg.xt_basis;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.Hashtable;
import agg.util.Change;
import agg.util.Link;
import agg.attribute.AttrContext;
import agg.attribute.AttrMapping;
import agg.attribute.impl.ValueTuple;
import agg.attribute.impl.AttrImplException;
import agg.attribute.impl.VarTuple;
/**
* This class implements a direct graph transformation step in the single
* pushout (SPO) approach to algebraic graph transformation. The transformation
* is performed <i>in place</i>, i.e. the host graph is modified according to
* the rule's instructions.
*/
public class Step {
private boolean computeColimitBasedPushout = false;
public Step() {}
public final Morphism executeColimBased(final Match match) throws TypeException {
this.computeColimitBasedPushout = true;
return execute(match, false, false);
}
public final Morphism executeColimBased(
final Match match,
boolean allowAttrVarsInGraph) throws TypeException {
this.computeColimitBasedPushout = true;
return execute(match, allowAttrVarsInGraph, false);
}
public final Morphism executeColimBased(
final Match match,
boolean allowAttrVarsInGraph,
boolean wrtEqualAttrVarName) throws TypeException {
this.computeColimitBasedPushout = true;
return execute(match, allowAttrVarsInGraph, wrtEqualAttrVarName);
}
/**
* Perform an in-place graph transformation step: apply the rule given by
* <code>match.getRule()</code> via <code>match</code> on the host graph
* given by <code>match.getImage()</code>. The host graph is modified to
* represent the result of the rule application.
*
* @return the co-match morphism from the right side of the rule into the
* result graph.
* @see agg.xt_basis.Morphism#getImage() Return NULL if execute of the step
* is failed.
*/
public final Morphism execute(final Match match) throws TypeException {
return execute(match, false, false);
}
/**
* Perform an in-place graph transformation step
* with respecting of
* allowing usage of variables for values of
* attributes of graph objects in a graph to be transformed.
*/
public final Morphism execute(
final Match match,
boolean allowAttrVarsInGraph) throws TypeException {
return execute(match, allowAttrVarsInGraph, false);
}
/**
* Perform an in-place graph transformation step <br>
* with respecting of allowing usage variables for values of
* attributes of objects inside of a graph, <br>
* and when usage of variables is allowed <br>
* then do it respecting equal names of variables
* inside of graph and the right hand side if of the rule of the given match.
*/
public final Morphism execute(
final Match match,
boolean allowAttrVarsInGraph,
boolean wrtEqualAttrVarName) throws TypeException {
// int typeLevel = match.getImage().getTypeSet().getLevelOfTypeGraphCheck();
final Rule rule = match.getRule();
final Graph aHostGraph = match.getImage();
OrdinaryMorphism
aMatchStar = new OrdinaryMorphism(
rule.getImage(),
aHostGraph,
match.getAttrManager().newContext(
AttrMapping.PLAIN_MAP));
try {
match.getAttrContext().freeze();
// use colimits to get pushout
if (this.computeColimitBasedPushout) {
// System.out.println("Step: Colimit Based Pushout ... ");
final ColimDiagram aPushoutDiagram = new ColimDiagram(aHostGraph);
aPushoutDiagram.addNode(aHostGraph);
aPushoutDiagram.addNode(rule.getOriginal());
aPushoutDiagram.addNode(rule.getImage());
aPushoutDiagram.addEdge(rule);
aPushoutDiagram.addEdge(match);
aPushoutDiagram.requestEdge(aMatchStar);
aPushoutDiagram.computeColimit();
}
// use simplified pushout
else if (!match.isInjective() && !match.isGluingConditionSet()) {
aMatchStar = pushoutOfNonInjectiveMatch(rule, match, aMatchStar);
} else {
aMatchStar = pushout(rule, match, aMatchStar);
}
if (aMatchStar == null) {
throw new TypeException("Step failed!");
}
aMatchStar.setName("CoMorphOf_"+match.getName());
try {
computeAttributes(match, aMatchStar, match.getAttrContext(),
allowAttrVarsInGraph, wrtEqualAttrVarName);
} catch (AttrImplException ex1) {
aMatchStar = null;
match.getAttrContext().defreeze();
if (match.getTarget().isAttributed()) {
match.getRule().restoreVariableDeclaration();
((VarTuple) match.getAttrContext().getVariables())
.unsetInputParameters();
}
throw new TypeException(ex1.getMessage());
}
match.getAttrContext().defreeze();
match.setCoMorphism(aMatchStar);
} catch (TypeException ex) {
aMatchStar = null;
match.getAttrContext().defreeze();
if (match.getTarget().isAttributed()) {
match.getRule().restoreVariableDeclaration();
((VarTuple) match.getAttrContext().getVariables())
.unsetInputParameters();
}
throw (ex);
}
try {
match.updateAttrMappings();
} catch (BadMappingException exc) {
}
// the variables used in NACs can lose their declaration,
// if step was successful, so restore the declaration.
if (match.getTarget().isAttributed()) {
match.getRule().restoreVariableDeclaration();
((VarTuple) match.getAttrContext().getVariables())
.unsetInputParameters();
}
return aMatchStar;
}
/*
* Here <br>
* Rule r = match.getRule() <br>
* match: rule.LHS -> G <br>
* comatch: rule.RHS -> G <br>
* G is changed after in-place trafo step
*/
private final void computeAttributes(
final Match match,
final OrdinaryMorphism comatch,
final AttrContext context,
boolean allowVariables,
boolean wrtEqualAttrVarName) throws AttrImplException {
if (!comatch.getTarget().isAttributed())
return;
final List<GraphObject> done = new Vector<GraphObject>(match.getSource().getSize());
final Rule r = match.getRule();
GraphObject lhsObj, rhsObj, gObj;
// compute attributes of preserved objects
final Enumeration<GraphObject> dom = match.getDomain();
while (dom.hasMoreElements()) {
lhsObj = dom.nextElement();
gObj = match.getImage(lhsObj);
if (!gObj.attrExists() //gObj.getAttribute() == null
|| done.contains(gObj)) {
continue;
}
done.add(gObj);
rhsObj = r.getImage(lhsObj);
if (rhsObj != null && rhsObj.getAttribute() != null) {
// if (rhsObj.getAttribute() == null) {
// throw new AttrImplException("Rule: "+r.getName()+": Attribute of RHS preserved object failed (null).");
// }
final ValueTuple rai = (ValueTuple) rhsObj.getAttribute();
final ValueTuple ai = (ValueTuple) gObj.getAttribute();
if (!allowVariables) {
match.getTarget().propagateChange(
new Change(Change.WANT_MODIFY_OBJECT, gObj));
ai.apply(rai, context);
} else {
ai.apply(rai, context, allowVariables, wrtEqualAttrVarName);
}
}
}
// now compute attributes of new objects only
// Enumeration<GraphObject> anInvImage;
final Enumeration<GraphObject> anObjIter = comatch.getCodomain();
while (anObjIter.hasMoreElements()) {
rhsObj = anObjIter.nextElement();
if (r.getInverseImage(rhsObj).hasMoreElements())
continue;
gObj = comatch.getImage(rhsObj);
if (!gObj.attrExists()) //gObj.getAttribute() == null)
continue;
if (rhsObj.getAttribute() == null) {
throw new AttrImplException("Rule: "+r.getName()+": Attribute of RHS new object failed (null).");
}
final ValueTuple rai = (ValueTuple) rhsObj.getAttribute();
final ValueTuple ai = (ValueTuple) gObj.getAttribute();
if (!allowVariables) {
comatch.getTarget().propagateChange(
new Change(Change.WANT_MODIFY_OBJECT, gObj));
try {
ai.apply(rai, context);
} catch (AttrImplException ex) {
System.out.println("TestStep.computeAttributes: Rule: "+r.getName()+" : "+ex.getMessage());
// throw new AttrImplException("Rule: "+r.getName()+" : "+ex.getMessage());
}
} else {
ai.apply(rai, context, allowVariables);
}
}
}
/*
* Calculates the pushout of two morphisms. L----r--->R and L----m--->G to
* get the co-morphism p R----p--->G It returns the resulting co-morphism p.
*/
private synchronized OrdinaryMorphism pushout(
final OrdinaryMorphism r,
final OrdinaryMorphism m,
final OrdinaryMorphism p) throws TypeException {
// p is co-match of m
if (!m.isTotal()) {
return null;
}
final Hashtable<GraphObject, Link> hashMap = new Hashtable<GraphObject, Link>();
final Graph L = r.getOriginal();
final Graph G = m.getTarget();
boolean sameType = (G.getTypeSet() == r.getTarget().getTypeSet());
fillHashMap(hashMap, r, m, L);
/*
* Now we link together all graphobjects which somehow are mapped to
* each other. This UNION/FIND structure enables us to find quickly
* nodes which must be identified.
*/
// first link nodes
Iterator<Node> nodes = L.getNodesSet().iterator();
while (nodes.hasNext()) {
GraphObject lgo = nodes.next();
GraphObject img1 = r.getImage(lgo);
GraphObject img2 = m.getImage(lgo);
Link l = hashMap.get(lgo);
if (img1 != null && img2 != null) {
l.link(hashMap.get(img1)).link(hashMap.get(img2));
try {
(hashMap.get(img1)).set(img2);
} catch (BadMappingException ex1) {
throw new TypeException(ex1.getLocalizedMessage());
}
}
}
// now link edges
Iterator<Arc> arcs = L.getArcsSet().iterator();
while (arcs.hasNext()) {
GraphObject lgo = arcs.next();
GraphObject img1 = r.getImage(lgo);
GraphObject img2 = m.getImage(lgo);
Link l = hashMap.get(lgo);
if (img1 != null && img2 != null) {
l.link(hashMap.get(img1)).link(hashMap.get(img2));
try {
(hashMap.get(img1)).set(img2);
} catch (BadMappingException ex1) {
if (r.getInverseImageList(img1).size() > 1) {
// do ignore it because of glue edges
} else {
throw new TypeException(ex1.getLocalizedMessage());
}
}
}
}
// first destroy arcs
arcs = L.getArcsSet().iterator();
while (arcs.hasNext()) {
GraphObject lgo = arcs.next();
GraphObject img2 = m.getImage(lgo);
if (r.getImage(lgo) == null && img2 != null) {
destroyArc((Arc)img2, G);
}
}
// destroy nodes
nodes = L.getNodesSet().iterator();
while (nodes.hasNext()) {
GraphObject lgo = nodes.next();
GraphObject img2 = m.getImage(lgo);
if (r.getImage(lgo) == null && img2 != null) {
destroyNode((Node)img2, G);
}
}
/* Now we can create new objects in G. We first create nodes. */
final Iterator<Node> nodesP = p.getOriginal().getNodesSet().iterator(); // RHS nodes
while (nodesP.hasNext()) {
Node n = nodesP.next(); // RHS node
Link l = (hashMap.get(n)).find();
Node n2 = (Node) l.get();
if (n2 == null) {
try {
createNode(n, G, p, sameType);
} catch (TypeException ex) {
throw new TypeException(ex.getLocalizedMessage());
}
} else {
// non-injective rule? try to glue nodes of the host graph
try {
glueNodesOfSameImageNode(n, r, m, p, G);
} catch (TypeException ex) {
throw new TypeException(ex.getLocalizedMessage());
}
}
}
/* now create new edges in G */
final Iterator<Arc> arcsP = p.getOriginal().getArcsSet().iterator(); // RHS edges
while (arcsP.hasNext()) {
Arc a = arcsP.next();
Link l = hashMap.get(a).find();
Arc a2 = (Arc) l.get();
if (a2 == null) {
try {
createArc(a, G, p, sameType);
} catch (TypeException ex) {
throw new TypeException(ex.getLocalizedMessage());
}
} else {
// non-injective rule? try to glue arcs of the host graph
try {
glueArcsOfSameImageArc(a, r, m, p, G);
} catch (TypeException ex) {
throw new TypeException(ex.getLocalizedMessage());
}
}
}
return p;
}
/*
* Calculates the pushout of two morphisms. L----r--->R and L----m--->G to
* get the co-morphism p R----p--->G It returns the resulting co-morphism p.
* The morphism m is NON-INJECTIVE and gluing condition must not be applied.
*/
private synchronized OrdinaryMorphism pushoutOfNonInjectiveMatch(
final OrdinaryMorphism r,
final OrdinaryMorphism m,
final OrdinaryMorphism p) throws TypeException {
// p is co-match of m
if (!m.isTotal()) {
return null;
}
final Hashtable<GraphObject, Link> hashMap = new Hashtable<GraphObject, Link>();
final Graph L = r.getOriginal();
final Graph G = m.getTarget();
boolean sameType = (G.getTypeSet() == r.getTarget().getTypeSet());
fillHashMap(hashMap, r, m, L);
/*
* Now we link together all graph objects which somehow are mapped to
* each other. This UNION/FIND structure enables us to find quickly
* nodes which must be identified.
*/
// first link nodes
Iterator<Node> nodes = L.getNodesSet().iterator();
while (nodes.hasNext()) {
GraphObject lgo = nodes.next();
GraphObject img1 = r.getImage(lgo);
GraphObject img2 = m.getImage(lgo);
Link l = hashMap.get(lgo);
if (img1 != null && img2 != null) {
l.link(hashMap.get(img1)).link(hashMap.get(img2));
try {
(hashMap.get(img1)).set(img2);
} catch (BadMappingException ex1) {
throw new TypeException(ex1.getLocalizedMessage());
}
}
}
// now link edges
Iterator<Arc> arcs = L.getArcsSet().iterator();
while (arcs.hasNext()) {
GraphObject lgo = arcs.next();
GraphObject img1 = r.getImage(lgo);
GraphObject img2 = m.getImage(lgo);
Link l = hashMap.get(lgo);
if (img1 != null && img2 != null) {
l.link(hashMap.get(img1)).link(hashMap.get(img2));
try {
(hashMap.get(img1)).set(img2);
} catch (BadMappingException ex1) {
if (r.getInverseImageList(img1).size() > 1) {
// do ignore it because of glue edges
} else {
throw new TypeException(ex1.getLocalizedMessage());
}
}
}
}
// first destroy arcs
arcs = L.getArcsSet().iterator();
while (arcs.hasNext()) {
GraphObject lgo = arcs.next();
GraphObject img2 = m.getImage(lgo);
if (r.getImage(lgo) == null && img2 != null) {
if (!m.isIdentificationSet()) {
if (r instanceof ParallelRule
&& m instanceof Match) {
if (!canDeleteWhenParallelRule(G, r, m, img2))
throw new TypeException(
"Step pushout: Cannot finish transformation step. Delete edge of parallel rule failed!");
}
else {
// destroyArc((Arc)img2, G);
G.destroyArcFast((Arc)img2);
}
} else {
boolean canDelete = true;
final List<GraphObject> lgos = m.getInverseImageList(img2);
if (lgos.size() > 1) {
for (int i=0; i<lgos.size(); i++) {
if (r.getImage(lgos.get(i)) != null) {
canDelete = false;
break;
}
}
}
if (canDelete)
destroyArc((Arc)img2, G);
}
}
}
// destroy nodes
nodes = L.getNodesSet().iterator();
while (nodes.hasNext()) {
GraphObject lgo = nodes.next();
GraphObject img2 = m.getImage(lgo);
if (r.getImage(lgo) == null && img2 != null) {
if (!m.isIdentificationSet()) {
if (r instanceof ParallelRule
&& m instanceof Match) {
if (!canDeleteWhenParallelRule(G, r, m, img2))
throw new TypeException(
"Step pushout: Cannot finish transformation step. Delete node of parallel rule failed!");
}
else {
destroyNode((Node)img2, G);
}
} else {
boolean canDelete = true;
final List<GraphObject> lgos = m.getInverseImageList(img2);
if (lgos.size() > 1) {
for (int i=0; i<lgos.size(); i++) {
if (r.getImage(lgos.get(i)) != null) {
canDelete = false;
break;
}
}
}
if (canDelete)
destroyNode((Node)img2, G);
}
}
}
/* Now we can create new objects in G. We first create nodes. */
final Iterator<Node> nodesP = p.getOriginal().getNodesSet().iterator(); // RHS nodes
while (nodesP.hasNext()) {
Node n = nodesP.next(); // RHS node
Link l = (hashMap.get(n)).find();
Node n2 = (Node) l.get();
if (n2 == null) {
try {
createNodeOfNonInjectiveMatch(hashMap, n, G, r, m, p, sameType);
} catch (TypeException ex) {
throw new TypeException(ex.getLocalizedMessage());
}
} else {
// non-injective rule? try to glue nodes of the host graph
try {
glueNodesOfSameImageNode(n, r, m, p, G);
} catch (TypeException ex) {
throw new TypeException(ex.getLocalizedMessage());
}
}
}
/* now create new edges in G */
final Iterator<Arc> arcsP = p.getOriginal().getArcsSet().iterator(); // RHS edges
while (arcsP.hasNext()) {
Arc a = arcsP.next();
Link l = hashMap.get(a).find();
Arc a2 = (Arc) l.get();
if (a2 == null) {
try {
createArcOfNonInjectiveMatch(hashMap, a, G, r, m, p, sameType);
} catch (TypeException ex) {
throw new TypeException(ex.getLocalizedMessage());
}
} else {
// non-injective rule? try to glue arcs of the host graph
try {
glueArcsOfSameImageArc(a, r, m, p, G);
} catch (TypeException ex) {
throw new TypeException(ex.getLocalizedMessage());
}
}
}
return p;
}
private boolean canDeleteWhenParallelRule(
final Graph g,
final OrdinaryMorphism r,
final OrdinaryMorphism m,
final GraphObject go) {
boolean canDelete = true;
if (m instanceof Match
&& r instanceof ParallelRule) {
final List<GraphObject> lgos = m.getInverseImageList(go);
if (lgos.size() > 1) {
GraphObject go1 = lgos.get(0);
GraphObject img_go1 = r.getImage(go1);
final OrdinaryMorphism embedding = ((ParallelRule)r).getLeftEmbeddingOfObject(go1);
for (int i=0; i<lgos.size(); i++) {
GraphObject go2 = lgos.get(i);
if ((img_go1 != null || r.getImage(go2) != null)
&& (((ParallelRule)r).getLeftEmbeddingOfObject(go2)
!= embedding)) {
canDelete = false;
break;
}
}
}
}
return canDelete;
}
private void fillHashMap(
final Hashtable<GraphObject, Link> hashMap,
final OrdinaryMorphism r,
final OrdinaryMorphism m,
final Graph left) {
Iterator<?> iter = left.getNodesSet().iterator();
while (iter.hasNext()) {
GraphObject go = (GraphObject)iter.next();
hashMap.put(go, new Link());
hashMap.put(m.getImage(go), new Link());
}
iter = left.getArcsSet().iterator();
while (iter.hasNext()) {
GraphObject go = (GraphObject) iter.next();
hashMap.put(go, new Link());
hashMap.put(m.getImage(go), new Link());
}
iter = r.getImage().getNodesSet().iterator();
while (iter.hasNext()) {
hashMap.put((GraphObject)iter.next(), new Link());
}
iter = r.getImage().getArcsSet().iterator();
while (iter.hasNext()) {
hashMap.put((GraphObject)iter.next(), new Link());
}
}
private void createNode(
final Node n,
final Graph g,
final OrdinaryMorphism p,
boolean sameType)
throws TypeException {
try {
if (sameType) {
// long t = System.nanoTime();
createNodeOfSameType(n, g, p);
// System.out.println("node created in time: "+(System.nanoTime()-t)+"nano");
}
else {
createNodeOfSimilarType(n, g, p);
}
} catch (TypeException ex) {
// System.out.println(n.getType().getName()+" FAILED!");
throw new TypeException(ex.getLocalizedMessage());
}
}
private void createNodeOfNonInjectiveMatch(
final Hashtable<GraphObject, Link> hashMap,
final Node n,
final Graph g,
final OrdinaryMorphism r,
final OrdinaryMorphism m,
final OrdinaryMorphism p,
boolean sameType)
throws TypeException {
if (!m.isIdentificationSet()) {
final Node go = (Node)hashMap.get(n).get();
if (go != null) {
final List<GraphObject> lgos = m.getInverseImageList(go);
if (lgos.size() > 1) {
for (int i=0; i<lgos.size(); i++) {
if (r.getImage(lgos.get(i)) == null) {
return;
}
}
}
} else if (r.getInverseImage(n).hasMoreElements()) {
return;
}
}
createNode(n, g, p, sameType);
}
private void destroyNode(final Node n, final Graph g) {
// this.todelete.add(n);
// destroy node without img1
// first destroy all outgoing edges
Iterator<?> iter = n.getOutgoingArcsSet().iterator();
while (iter.hasNext()) {
GraphObject a = (GraphObject)iter.next();
g.destroyArcFast((Arc) a);
iter = n.getOutgoingArcsSet().iterator();
}
// then destroy all incoming edges
iter = n.getIncomingArcsSet().iterator();
while (iter.hasNext()) {
GraphObject a = (GraphObject)iter.next();
g.destroyArcFast((Arc) a);
iter = n.getIncomingArcsSet().iterator();
}
// and now destroy the node
g.destroyNodeFast(n);
}
private void createArc(
final Arc a,
final Graph g,
final OrdinaryMorphism p,
boolean sameType)
throws TypeException {
GraphObject src = p.getImage(a.getSource());
GraphObject tgt = p.getImage(a.getTarget());
if (src != null && tgt != null) {
try {
if (sameType) {
// long t = System.nanoTime();
createArcOfSameType(a, src, tgt, g, p);
}
else {
createArcOfSimilarType(a, src, tgt, g, p);
}
} catch (TypeException ex) {
throw new TypeException(ex.getLocalizedMessage());
}
}
}
private void createArcOfNonInjectiveMatch(
final Hashtable<GraphObject, Link> hashMap,
final Arc a,
final Graph g,
final OrdinaryMorphism r,
final OrdinaryMorphism m,
final OrdinaryMorphism p,
boolean sameType)
throws TypeException {
if (!m.isIdentificationSet()) {
final Arc go = (Arc)hashMap.get(a).get();
if (go != null) {
final List<GraphObject> lgos = m.getInverseImageList(go);
if (lgos.size() > 1) {
for (int i=0; i<lgos.size(); i++) {
if (r.getImage(lgos.get(i)) == null) {
return;
}
}
}
} else if (r.getInverseImage(a).hasMoreElements()) {
return;
}
}
createArc(a, g, p, sameType);
}
private void destroyArc(final Arc a, final Graph g) {
g.destroyArcFast(a);
}
private void glueNodesOfSameImageNode(
final Node n,
final OrdinaryMorphism r,
final OrdinaryMorphism m,
final OrdinaryMorphism p,
final Graph g) throws TypeException {
// non-injective rule? try to glue nodes of the host graph
boolean glued = false;
final List<GraphObject> origs = r.getInverseImageList(n);
if (!origs.isEmpty()) {
final Hashtable<Arc, Arc> arc2arcimg = new Hashtable<Arc, Arc>();
final GraphObject ol1 = origs.get(0);
final GraphObject og1 = m.getImage(ol1);
if (og1 != null ) {
for (int j=1; j<origs.size(); j++) {
final Node ol2 = (Node) origs.get(j);
final Node og2 = (Node) m.getImage(ol2);
if (og2 != null ) {
Iterator<?> iter = ol2.getIncomingArcsSet().iterator();
while (iter.hasNext()) {
final Arc arc = (Arc)iter.next();
if (m.getImage(arc) != null)
arc2arcimg.put(arc, (Arc) m.getImage(arc));
}
iter = ol2.getOutgoingArcsSet().iterator();
while (iter.hasNext()) {
final Arc arc = (Arc)iter.next();
if (m.getImage(arc) != null)
arc2arcimg.put(arc, (Arc) m.getImage(arc));
}
// if (p.getImage(n) == og2)
// p.removeMapping(n, og2);
if (g.glue(og1, og2)) {
glued = true;
} else {
throw new TypeException(
"Step.pushout: Cannot glue nodes of type "+og1.getType().getName()+" !");
}
} else if (m.isIdentificationSet()){
throw new TypeException(
"Step.pushout: Cannot finish transformation step. Identification condition failed!");
}
}
try {
if (p.getImage(n) == null || p.getImage(n) != og1)
p.addPlainMapping(n, og1);
} catch (BadMappingException ex1) {
throw new TypeException(ex1.getLocalizedMessage());
}
if (glued) {
// reset mappings of LHS glued nodes
for (int j=1; j<origs.size(); j++) {
final GraphObject ol2 = origs.get(j);
try {
m.addObjectPlainMapping(ol2, og1);
} catch (BadMappingException ex1) {
throw new TypeException(ex1.getLocalizedMessage());
}
}
// reset mappings of new Source/Target of Edges
final Enumeration<Arc> inoutarcs = arc2arcimg.keys();
while (inoutarcs.hasMoreElements()) {
final Arc arc = inoutarcs.nextElement();
try {
m.addObjectPlainMapping(arc, arc2arcimg.get(arc));
} catch (BadMappingException ex1) {
throw new TypeException(ex1.getLocalizedMessage());
}
}
}
} else if (m.isIdentificationSet()){
throw new TypeException(
"Step.pushout: Cannot finish transformation step. Identification condition failed!");
}
}
}
private void glueArcsOfSameImageArc(
final Arc a,
final OrdinaryMorphism r,
final OrdinaryMorphism m,
final OrdinaryMorphism p,
final Graph g) throws TypeException {
// non-injective rule? try to glue arcs of the host graph
boolean glued = false;
final List<GraphObject> origs = r.getInverseImageList(a);
if (!origs.isEmpty()) {
GraphObject ol1 = origs.get(0);
GraphObject og1 = m.getImage(ol1);
if (og1 != null) {
for (int j=1; j<origs.size(); j++) {
Arc ol2 = (Arc) origs.get(j);
Arc og2 = (Arc) m.getImage(ol2);
if (og2 != null) {
// if (p.getImage(a) == og2)
// p.removeMapping(a, og2);
if (g.glue(og1, og2)) {
glued = true;
}
else {
throw new TypeException(
"Step.pushout: Cannot glue edges of type "+og1.getType().getName()+" !");
}
} else if (m.isIdentificationSet()){
throw new TypeException(
"Step.pushout: Cannot finish transformation step. Identification condition failed!");
}
}
try {
if (p.getImage(a) == null)
p.addPlainMapping(a, og1);
} catch (BadMappingException ex1) {
throw new TypeException(ex1.getLocalizedMessage());
}
try {
if (p.getImage(a) == null || p.getImage(a) != og1)
p.addPlainMapping(a, og1);
} catch (BadMappingException ex1) {
throw new TypeException(ex1.getLocalizedMessage());
}
if (glued) {
// reset mappings of LHS glued edges
for (int j=1; j<origs.size(); j++) {
final GraphObject ol2 = origs.get(j);
try {
m.addObjectPlainMapping(ol2, og1);
} catch (BadMappingException ex1) {
throw new TypeException(ex1.getLocalizedMessage());
}
}
}
} else if (m.isIdentificationSet()){
throw new TypeException(
"Step.pushout: Cannot finish transformation step. Identification condition failed!");
}
}
}
private void createNodeOfSameType(
final Node n,
final Graph G,
final OrdinaryMorphism p) throws TypeException {
try {
final Type nodetype = n.getType();
if (nodetype != null) {
try {
final Node n2 = G.newNodeFast(nodetype);
n2.setContextUsage(n.getContextUsage());
try {
p.addMappingFast(n, n2);
} catch (BadMappingException ex1) {
throw new TypeException(ex1.getLocalizedMessage());
}
} catch (TypeException ex2) {
throw new TypeException(ex2.getLocalizedMessage());
}
} else
throw new TypeException("Step.pushout: Cannot create node! "
+ "Node type not found!");
} catch (TypeException ex) {
throw new TypeException(ex.getLocalizedMessage());
}
}
private void createNodeOfSimilarType(
final Node n,
final Graph G,
final OrdinaryMorphism p) throws TypeException {
try {
final Type nodetype = G.getTypeSet().getSimilarType(n.getType());
if (nodetype != null) {
try {
final Node n2 = G.createNode(nodetype);
n2.setContextUsage(n.getContextUsage());
try {
p.addMapping(n, n2);
} catch (BadMappingException ex1) {
throw new TypeException(ex1.getLocalizedMessage());
}
}catch (TypeException ex2) {
throw new TypeException(ex2.getLocalizedMessage());
}
} else
throw new TypeException("Step.pushout: Cannot create node! "
+ "Node type not found!");
} catch (TypeException ex) {
throw new TypeException(ex.getLocalizedMessage());
}
}
private void createArcOfSameType(
final Arc a,
final GraphObject src,
final GraphObject tar,
final Graph G,
final OrdinaryMorphism p) throws TypeException {
try {
final Type arctype = a.getType();
if (arctype != null) {
// if (G.isParallelArcAllowed(arctype, (Node)src, (Node)tar)) {
final Arc a2 = G.newArcFast(arctype, (Node)src, (Node)tar);
a2.setContextUsage(a.getContextUsage());
try {
p.addMappingFast(a, a2);
} catch (BadMappingException ex1) {
throw new BadMappingException(ex1.getLocalizedMessage());
}
// } else {
// throw new TypeException("Step pushout: Cannot create edge! "
// + "No parallel edges allowed.");
// }
} else {
throw new TypeException("Step.pushout: Cannot create edge! "
+ "Edge type not found.");
}
} catch (TypeException ex) {
throw new TypeException(ex.getLocalizedMessage());
}
}
private void createArcOfSimilarType(
final Arc a,
final GraphObject src,
final GraphObject tgt,
final Graph G,
final OrdinaryMorphism p) throws TypeException {
try {
final Type arctype = G.getTypeSet().getSimilarType(a.getType());
if (arctype != null) {
try {
final Arc a2 = G.createArc(arctype, (Node) src, (Node) tgt);
a2.setContextUsage(a.getContextUsage());
try {
p.addMapping(a, a2);
} catch (BadMappingException ex1) {
throw new BadMappingException(ex1.getLocalizedMessage());
}
} catch (TypeException ex2) {
throw new TypeException(ex2.getLocalizedMessage());
}
} else
throw new TypeException("Step.pushout: Cannot create edge! "
+ "Edge type not found.");
} catch (TypeException ex) {
throw new TypeException(ex.getLocalizedMessage());
}
}
public List<GraphObject> getCreatedNodes(
final Rule r,
final Morphism comatch) {
final List<GraphObject> list = new Vector<GraphObject>();
if (r.getRight() == ((OrdinaryMorphism)comatch).getSource()) {
Enumeration<GraphObject> dom = comatch.getDomain();
while (dom.hasMoreElements()) {
GraphObject go = dom.nextElement();
if (go.isNode() && !r.getInverseImage(go).hasMoreElements()) {
list.add(go);
}
}
}
return list;
}
public List<GraphObject> getCreatedObjects(
final Rule r,
final Morphism comatch) {
final List<GraphObject> list = new Vector<GraphObject>();
if (r.getRight() == ((OrdinaryMorphism)comatch).getSource()) {
Enumeration<GraphObject> dom = comatch.getDomain();
while (dom.hasMoreElements()) {
GraphObject go = dom.nextElement();
if (!r.getInverseImage(go).hasMoreElements()) {
list.add(go);
}
}
}
return list;
}
}