package agg.xt_basis;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import agg.attribute.AttrContext;
import agg.attribute.AttrException;
import agg.attribute.AttrInstance;
import agg.attribute.AttrManager;
import agg.attribute.AttrMapping;
import agg.attribute.handler.AttrHandlerException;
import agg.attribute.handler.HandlerExpr;
import agg.attribute.impl.AttrTupleManager;
import agg.attribute.impl.ContextView;
import agg.attribute.impl.DeclMember;
import agg.attribute.impl.ValueMember;
import agg.attribute.impl.ValueTuple;
import agg.attribute.impl.VarMember;
import agg.attribute.impl.VarTuple;
import agg.attribute.impl.CondTuple;
import agg.attribute.impl.CondMember;
import agg.util.ExtObservable;
import agg.util.XMLHelper;
import agg.util.Change;
import agg.util.Pair;
import agg.xt_basis.csp.CompletionPropertyBits;
/**
* Implementation of a graph morphism. Note: This implementation is guaranteed
* to keep morphism properties when objects are deleted/created/modified in the
* original or image graphs.
*/
// Class OrdinaryMorphism is capable of passing the following change
// informations as an argument to its observers' <code>update()</code> methods:
// Morph_Change_MappingAdded, Morph_Change_MappingRemoved.
// Additionally, the information <code>Change_ObservableGone</code>
// may be generated by its base class <code>ExtObservable</code>.
// If, however, the value of the change information is given as
// <code>null</code>, the observer is recommended to perform a full
// rescan of the morphism.
public class OrdinaryMorphism extends ExtObservable implements Morphism
// , Observer
{
protected String itsName;
protected String comment = "";
protected MorphCompletionStrategy itsCompleter;
protected boolean itsTouchedFlag = true;
protected boolean itsInteractiveFlag = true;
protected Dictionary<AttrInstance, AttrMapping> itsAttrMappings;
protected AttrContext itsAttrContext;
protected AttrManager itsAttrManager;
protected Graph itsOrig;
protected Graph itsImag;
/**
* Use this constant as a parameter in my constructors or in the
* <code>initialize()</code> method to indicate that the attribute context
* in question should not be altered.
*/
protected static final AttrContext cKeepContext = null;
final protected
Vector<GraphObject> itsDomObjects = new Vector<GraphObject>();
final protected
Vector<GraphObject> itsCodomObjects = new Vector<GraphObject>();
protected OrdinaryMorphism itsCoMorph;
protected boolean enabled = true;
boolean mappingChanged;
protected boolean changed;
protected boolean typeObjectsMapChanged;
protected boolean partialMorphCompletion;
protected boolean shifted;
protected String errorMsg;
// protected Vector<String> errors;
protected OrdinaryMorphism() {
this(new Graph(), new Graph(), cKeepContext);
}
/**
* @param ac
* my attribute context.
*/
protected OrdinaryMorphism(final AttrContext ac) {
this(new Graph(), new Graph(), ac);
}
/**
* @param orig
* my original graph.
* @param img
* my image graph.
*/
public OrdinaryMorphism(final Graph orig, final Graph img) {
this(orig, img, cKeepContext);
}
/**
* @param orig
* my original graph.
* @param img
* my image graph.
* @param ac
* my attribute context.
*/
public OrdinaryMorphism(final Graph orig, final Graph img, final AttrContext ac) {
this.itsName = "OrdinaryMorphism";
this.itsOrig = orig;
// this.itsOrig.setKind(GraphKind.SOURCE);
this.itsOrig.addUsingMorph(this);
this.itsImag = img;
// this.itsImag.setKind(GraphKind.TARGET);
this.itsImag.addUsingMorph(this);
this.itsAttrContext = ac;
this.itsAttrMappings = new Hashtable<AttrInstance, AttrMapping>(20);
this.itsAttrManager = AttrTupleManager.getDefaultManager();
setCompletionStrategy(CompletionStrategySelector.getDefault());
this.itsTouchedFlag = true;
this.itsInteractiveFlag = true;
this.errorMsg = "";
// this.errors = new Vector<String>(2, 2);
}
/**
* Remove all graph object mappings and all relations to its source and target graphs.
*/
public void dispose() {
if (this.itsCompleter != null) {
this.itsCompleter.dispose();
}
removeAllMappings();
this.itsOrig.removeUsingMorph(this);
this.itsImag.removeUsingMorph(this);
if (this.itsCoMorph != null) {
this.itsCoMorph.dispose();
this.itsCoMorph = null;
}
this.clearErrorMsg();
super.dispose();
}
/**
* Remove all graph object mappings and all relations to its source and target graphs.
* Dispose its source graph if disposableSource is TRUE,
* dispose its target graph if disposableTarget is TRUE.
*/
public void dispose(boolean disposableSource, boolean disposableTarget) {
if (this.itsCompleter != null) {
this.itsCompleter.dispose();
}
removeAllMappings();
this.itsOrig.removeUsingMorph(this);
this.itsImag.removeUsingMorph(this);
if (this.itsCoMorph != null) {
this.itsCoMorph.dispose();
this.itsCoMorph = null;
}
this.clearErrorMsg();
super.dispose();
if (disposableSource) {
this.itsOrig.dispose();
this.itsOrig = null;
}
if (disposableTarget) {
this.itsImag.dispose();
this.itsImag = null;
}
}
public boolean isInjectiveSet() {
return this.getCompletionStrategy().getProperties().get(CompletionPropertyBits.INJECTIVE);
}
public boolean isDanglingSet() {
return this.getCompletionStrategy().getProperties().get(CompletionPropertyBits.DANGLING);
}
public boolean isIdentificationSet() {
return this.getCompletionStrategy().getProperties().get(CompletionPropertyBits.IDENTIFICATION);
}
public boolean isGluingConditionSet() {
return this.getCompletionStrategy().getProperties().get(CompletionPropertyBits.DANGLING)
&& this.getCompletionStrategy().getProperties().get(CompletionPropertyBits.IDENTIFICATION);
}
public boolean isNotificationRequired() {
return (this.countObservers() > 0);
}
public void setTarget(Graph g) {
this.itsImag = g;
}
public void setSource(Graph g) {
this.itsOrig = g;
}
public boolean isTypeObjectsMapChanged() {
return this.typeObjectsMapChanged;
}
public void setTypeObjectsMapChanged(boolean b) {
this.typeObjectsMapChanged = b;
}
public boolean hasPartialMorphismCompletion() {
return this.partialMorphCompletion;
}
public void setPartialMorphismCompletion(boolean b) {
this.partialMorphCompletion = b;
}
/**
* Enable or disable this morphism to make it usable during transformation.
*/
public void setEnabled(boolean enable) {
this.enabled = enable;
}
/**
* Returns TRUE if this morphism is active otherwise
* FALSE.
*/
public boolean isEnabled() {
return this.enabled;
}
/*
* This method is used for internal computations only.
*/
public boolean isShifted() {
return this.shifted;
}
public void setErrorMsg(String msg) {
this.errorMsg = msg;
}
/**
* Return an error message if this morphism is failed, otherwise - empty
* message.
*/
public String getErrorMsg() {
return this.errorMsg;
}
/*
public void addErrorMsg(String msg) {
this.errorMsg = msg;
// this.errors.add(this.errorMsg);
}
*/
public void clearErrorMsg() {
// this.errors.clear();
this.errorMsg = "";
((agg.attribute.impl.ContextView) this.getAttrContext()).getManager()
.clearErrorMsg();
((agg.attribute.impl.ContextView) this.getAttrContext())
.clearErrorMsg();
}
/**
* Returns true, if the same source object refers the same target object,
* otherwise false.
* Precondition: this.source == m.source, this.target == m.target
*/
public final boolean isCommutative(Morphism m) {
if (this.itsOrig.getTypeSet().isArcDirected())
return isCommutative1(m);
else
return isCommutative2(m);
}
private final boolean isCommutative1(Morphism m) {
if (m == this)
return true;
if (m.getOriginal() == this.itsOrig) {
final Iterator<Node> allOrigNodes = this.itsOrig.getNodesSet().iterator();
while (allOrigNodes.hasNext()) {
GraphObject anOrig = allOrigNodes.next();
GraphObject anImage1 = this.getImage(anOrig);
GraphObject anImage2 = m.getImage(anOrig);
if (anImage1 == null) {
if (anImage2 != null)
return false;
}
else if (anImage1 != anImage2)
return false;
}
final Iterator<Arc> allOrigArcs = this.itsOrig.getArcsSet().iterator();
while (allOrigArcs.hasNext()) {
GraphObject anOrig = allOrigArcs.next();
GraphObject anImage1 = this.getImage(anOrig);
GraphObject anImage2 = m.getImage(anOrig);
if (anImage1 == null){
if (anImage2 != null)
return false;
}
else if (anImage1 != anImage2)
return false;
}
return true;
}
return false;
}
private final boolean isCommutativeORIG(Morphism m) {
if (m == this)
return true;
if (m.getOriginal() == this.itsOrig) {
final Iterator<Node> allOrigNodes = this.itsOrig.getNodesSet().iterator();
while (allOrigNodes.hasNext()) {
GraphObject anOrig = allOrigNodes.next();
GraphObject anImage1 = this.getImage(anOrig);
GraphObject anImage2 = m.getImage(anOrig);
if (anImage1 == null) {
if (anImage2 == null)
continue;
return false;
}
else if (anImage1 == anImage2)
continue;
return false;
}
final Iterator<Arc> allOrigArcs = this.itsOrig.getArcsSet().iterator();
while (allOrigArcs.hasNext()) {
GraphObject anOrig = allOrigArcs.next();
GraphObject anImage1 = this.getImage(anOrig);
GraphObject anImage2 = m.getImage(anOrig);
if (anImage1 == null){
if (anImage2 == null)
continue;
return false;
}
else if (anImage1 == anImage2)
continue;
return false;
}
return true;
}
return false;
}
private final boolean isCommutative2(Morphism m) {
if (m == this)
return true;
if (m.getOriginal() == this.itsOrig) {
final Iterator<Arc> allOrigArcs = this.itsOrig.getArcsSet().iterator();
while (allOrigArcs.hasNext()) {
Arc anOrig = allOrigArcs.next();
GraphObject anImage1 = this.getImage(anOrig);
GraphObject anImage2 = m.getImage(anOrig);
if (anImage1 == null){
if (anImage2 != null)
return false;
}
else if (anImage1 != anImage2)
return false;
}
// now check isolated nodes only
final Iterator<Node> allOrigNodes = this.itsOrig.getNodesSet().iterator();
while (allOrigNodes.hasNext()) {
GraphObject anOrig = allOrigNodes.next();
GraphObject anImage1 = this.getImage(anOrig);
GraphObject anImage2 = m.getImage(anOrig);
if (anImage1 == null) {
if (anImage2 != null)
return false;
}
else if (anImage2 == null)
return false;
else if (anImage1.getNumberOfInOutArcs() == 0
&& anImage2.getNumberOfInOutArcs() == 0) {
if (anImage1 != anImage2)
return false;
}
}
return true;
}
return false;
}
/**
* Returns true, if the same source object of m1 and (this o m2)
* refers the same target object of this:
* m2.getImage(this.getImage(obj)) == m1.getImage(obj).
* Otherwise returns false.
*
* Precondition:
* m1.source == this.source,
* m2.source == this.target,
* m1.target == m2.target
*/
public final boolean isCommutative(Morphism m1, Morphism m2) {
if (this.itsOrig.getTypeSet().isArcDirected())
return isCommutative1(m1, m2);
else
return isCommutative2(m1, m2);
}
@SuppressWarnings("unused")
private final boolean isCommutativeORIG(Morphism m1, Morphism m2) {
if (m1 == this)
return ((OrdinaryMorphism)m1).isCommutativeORIG(m2);
if (m1.getOriginal() == this.itsOrig
&& this.itsImag == m2.getOriginal()
&& m1.getImage() == m2.getImage()) {
final Iterator<Node> allOrigNodes = this.itsOrig.getNodesSet().iterator();
while (allOrigNodes.hasNext()) {
GraphObject anOrig = allOrigNodes.next();
GraphObject anImage = this.getImage(anOrig);
GraphObject anImage1 = m1.getImage(anOrig);
if (anImage == null){
if (anImage1 == null)
continue;
return false;
}
else if (m2.getImage(anImage) == anImage1)
continue;
return false;
}
final Iterator<Arc> allOrigArcs = this.itsOrig.getArcsSet().iterator();
while (allOrigArcs.hasNext()) {
GraphObject anOrig = allOrigArcs.next();
GraphObject anImage = this.getImage(anOrig);
GraphObject anImage1 = m1.getImage(anOrig);
if (anImage == null){
if (anImage1 == null)
continue;
return false;
}
else if (m2.getImage(anImage) == anImage1)
continue;
return false;
}
return true;
}
return false;
}
private boolean isCommutative1(Morphism m1, Morphism m2) {
if (m1 == this)
return ((OrdinaryMorphism)m1).isCommutative1(m2);
if (m1.getOriginal() == this.itsOrig
&& this.itsImag == m2.getOriginal()
&& m1.getImage() == m2.getImage()) {
final Iterator<Node> allOrigNodes = this.itsOrig.getNodesSet().iterator();
while (allOrigNodes.hasNext()) {
GraphObject anOrig = allOrigNodes.next();
GraphObject anImage = this.getImage(anOrig);
GraphObject anImage1 = m1.getImage(anOrig);
if (anImage == null){
if (anImage1 == null)
continue;
return false;
}
else if (m2.getImage(anImage) == anImage1)
continue;
return false;
}
final Iterator<Arc> allOrigArcs = this.itsOrig.getArcsSet().iterator();
while (allOrigArcs.hasNext()) {
GraphObject anOrig = allOrigArcs.next();
GraphObject anImage = this.getImage(anOrig);
GraphObject anImage1 = m1.getImage(anOrig);
if (anImage == null){
if (anImage1 == null)
continue;
return false;
}
else if (m2.getImage(anImage) == anImage1)
continue;
return false;
}
return true;
}
return false;
}
private boolean isCommutative2(Morphism m1, Morphism m2) {
if (m1 == this)
return ((OrdinaryMorphism)m1).isCommutative2(m2);
if (m1.getOriginal() == this.itsOrig
&& this.itsImag == m2.getOriginal()
&& m1.getImage() == m2.getImage()) {
// check arcs first
final Iterator<Arc> allOrigArcs = this.itsOrig.getArcsSet().iterator();
while (allOrigArcs.hasNext()) {
Arc anOrig = allOrigArcs.next();
GraphObject anImage = this.getImage(anOrig);
GraphObject anImage1 = m1.getImage(anOrig);
GraphObject anImage2 = m2.getImage(anImage);
if (anImage == null){
if (anImage1 != null)
return false;
}
else if (anImage2 != anImage1)
return false;
}
// now check isolated nodes only
final Iterator<Node> allOrigNodes = this.itsOrig.getNodesSet().iterator();
while (allOrigNodes.hasNext()) {
GraphObject anOrig = allOrigNodes.next();
GraphObject anImage = this.getImage(anOrig);
GraphObject anImage1 = m1.getImage(anOrig);
GraphObject anImage2 = m2.getImage(anImage);
if (anImage == null){
if (anImage1 != null)
return false;
}
else if (anImage1 == null)
return false;
else if (anImage.getNumberOfInOutArcs() == 0
&& anImage1.getNumberOfInOutArcs() == 0) {
if (anImage1 != anImage2)
return false;
}
}
return true;
}
return false;
}
/***************************************************************************
* Konstruiert aus dem Morphismus einen Match. * Der Morphismus muss
* zwischen der linken Regelseite * der mitgegebenen Regel und dem aktuellen
* Arbeitsgraphen definiert sein.*
**************************************************************************/
/**
* Construct a Match of the specified Rule from this morphism . The
* source graph is the LHS of the rule. The mapping of this morphism is used
* for the match mapping. Returns null when a BadMappingException occurred,
* otherwise true.
*/
public Match makeMatch(Rule rule) {
final Match m = (BaseFactory.theFactory()).createMatch(rule, this.itsImag);
for (Enumeration<GraphObject> elements = this.getDomain();
elements.hasMoreElements();) {
final GraphObject grob = elements.nextElement();
try {
m.addMapping(grob, this.getImage(grob));
} catch (BadMappingException e) {
this.errorMsg = e.getMessage();
// if (this.errorMsg.length()>0)
// this.errors.add(this.errorMsg);
m.dispose();
return null;
}
}
return m;
}
/**
* Make a copy of the source graph, copy of the target graph, and the
* homomorphism on both graphs. The result shall not poses far reaching
* references onto Rules, GraGras those kinds of objects.
*/
public OrdinaryMorphism morphcopy() {
synchronized (this) {
boolean failed = false;
final Hashtable<GraphObject, GraphObject> orig2copySource = new Hashtable<GraphObject, GraphObject>();
final Hashtable<GraphObject, GraphObject> orig2copyTarget = new Hashtable<GraphObject, GraphObject>();
Graph sourceCopy = this.itsOrig.copy(orig2copySource);
Graph targetCopy = this.itsImag.copy(orig2copyTarget);
if (sourceCopy == null && targetCopy == null)
return null;
else if (sourceCopy == null) {
targetCopy = null;
return null;
} else if (targetCopy == null) {
sourceCopy = null;
return null;
}
// Mapping is still empty
OrdinaryMorphism theCopy = (BaseFactory.theFactory())
.createMorphism(sourceCopy, targetCopy);
Enumeration<GraphObject> domainOrig = this.getDomain();
while (!failed && domainOrig.hasMoreElements()) {
GraphObject x = domainOrig.nextElement();
if (x.isNode()) {
Node y = (Node) this.getImage(x);
if (y != null) {
Node xCopy = (Node) orig2copySource.get(x);
Node yCopy = (Node) orig2copyTarget.get(y);
try {
theCopy.addMapping(xCopy, yCopy);
} catch (BadMappingException ex) {
}
}
}
}
domainOrig = this.getDomain();
while (!failed && domainOrig.hasMoreElements()) {
GraphObject x = domainOrig.nextElement();
if (x.isArc()) {
Node vtx1 = (Node) (((Arc) x).getSource());
Node vtx2 = (Node) (((Arc) x).getTarget());
Node vtx1Copy = (Node) orig2copySource.get(vtx1);
Node vtx2Copy = (Node) orig2copySource.get(vtx2);
Arc y = (Arc) this.getImage(x);
Node vtx3Copy = null;
Node vtx4Copy = null;
if (y != null) {
Node vtx3 = (Node) y.getSource();
Node vtx4 = (Node) y.getTarget();
vtx3Copy = (Node) orig2copyTarget.get(vtx3);
vtx4Copy = (Node) orig2copyTarget.get(vtx4);
}
Arc q = null;
if (sourceCopy != null) {
Iterator<Arc> sourceCopyArcs = sourceCopy.getArcsSet().iterator();
while (sourceCopyArcs.hasNext()) {
Arc a = sourceCopyArcs.next();
if ((((Node) a.getSource()).equals(vtx1Copy))
&& (((Node) a.getTarget()).equals(vtx2Copy))) {
q = a;
}
}
}
Arc z = null;
if (vtx3Copy != null && vtx4Copy != null && targetCopy != null) {
Iterator<Arc> targetCopyArcs = targetCopy.getArcsSet().iterator();
while (targetCopyArcs.hasNext()) {
Arc a = targetCopyArcs.next();
if ((((Node) a.getSource()).equals(vtx3Copy))
&& (((Node) a.getTarget()).equals(vtx4Copy))) {
z = a;
}
}
}
if (q != null && z != null) {
try {
if (theCopy != null)
theCopy.addMapping(q, z);
} catch (BadMappingException ex) {
}
} else {
failed = true;
if (theCopy != null)
theCopy.dispose();
theCopy = null;
if (sourceCopy != null)
sourceCopy.dispose();
sourceCopy = null;
if (targetCopy != null)
targetCopy.dispose();
targetCopy = null;
}
}
}
return (theCopy);
}
}
/**
* The current (this) morphism takes two morphisms with : <br>
* theFirst.source == theSecond.source, <br>
* this.source == theFirst.target, <br>
* this.target == theSecond.target.<br>
* Completes this morphism so that: <em>theFirst o this = theSecond</em> .
*/
//
// [Graph X]------------>[Graph Y]
// | theFirst /
// | /
// | /
// | /
// | /
// the|Second / this
// | /
// | /
// | /
// | /
// | /
// | /
// \|/ |/_
// [Graph Z]
//
// -----------------------------------------------------------
public boolean makeDiagram(final OrdinaryMorphism theFirst,
final OrdinaryMorphism theSecond) {
if (!this.itsOrig.equals(theFirst.getImage()))
return (false);
if (!this.itsImag.equals(theSecond.getImage()))
return (false);
if (!theFirst.getOriginal().equals(theSecond.getOriginal()))
return (false);
// Untersuche Anwendungsvoraussetzungen: Graphen
// (nur lesend, nicht schreibend)
// Zusicherung hier: alle drei Morphismen leben auf den gleichen
// Graphen.
// ----------------------------------------------------------------------
// Naechster Schritt: Untersuche Anwendungsvoraussetzungen.
// Gemeinsame Elemente von theFirst und theSecond,
// nur lesend, nicht schreibend
// [Im folgenden wird pessimistisch angenommen, dass
// die verwendeten Enumerationen nichtdeterministisch
// (zufaellig) gefuellt worden seien, sodass man keine
// Reihenfolgenkenntnisse effizient nutzbar machen kann.]
Enumeration<GraphObject> firstDom;
Enumeration<GraphObject> secondDom;
firstDom = theFirst.getDomain();
while (firstDom.hasMoreElements()) {
boolean result = false;
GraphObject elem1 = firstDom.nextElement();
// System.out.println("--> elem1: "+elem1);
secondDom = theSecond.getDomain();
while (secondDom.hasMoreElements()) {
GraphObject elem2 = secondDom.nextElement();
// System.out.println("--> elem2: "+elem2);
if (elem1.equals(elem2)) {
result = true;
break;
}
}
if (result == false) {
return (result);
/** EXIT * */
}
}
secondDom = theSecond.getDomain();
while (secondDom.hasMoreElements()) {
boolean result = false;
GraphObject elem1 = secondDom.nextElement();
firstDom = theFirst.getDomain();
while (firstDom.hasMoreElements()) {
GraphObject elem2 = firstDom.nextElement();
if (elem1.equals(elem2)) {
result = true;
break;
}
}
if (result == false) {
return (result);
}
}
// Zusicherung hier: theFirst und theSecond haben den
// selben Definitionsbereich.
// ----------------------------------------------------------------
// Naechster Schritt: Untersuche weitere Anwendungsvoraussetzungen.
// Kompositionseigenschaften von ``this''
// (nur lesend, nicht schreibend) **/
Enumeration<GraphObject> ownDom = this.getDomain();
while (ownDom.hasMoreElements()) {
GraphObject y = ownDom.nextElement();
GraphObject z = this.getImage(y);
Enumeration<GraphObject> manyX = theFirst.getInverseImage(y);
while (manyX.hasMoreElements()) {
GraphObject x = manyX.nextElement();
// if (theSecond.getImage(x) != z)
if (!(theSecond.getImage(x)).equals(z))
return (false);
}
}
// this.getAttrContext()).getAllowedMapping());
// Zusicherung hier: Wo this definiert ist, gilt die Gleichung
// this(theFirst(x))=theSecond(x)=z
// --------------------------------
// Letzter Schritt: Vervollstaendigung von this (schreibend!)
firstDom = theFirst.getDomain();
while (firstDom.hasMoreElements()) {
GraphObject x = firstDom.nextElement();
GraphObject y = theFirst.getImage(x);
GraphObject z = theSecond.getImage(x);
if (z != null) {
if (!z.equals(this.getImage(y))) {
try {
if (y.isNode())
this.addMapping(y, z);
else {
if (this.getImage(((Arc)y).getSource()).equals(((Arc)z).getSource())
&& this.getImage(((Arc)y).getTarget()).equals(((Arc)z).getTarget()))
this.addMapping(y, z);
}
} catch (BadMappingException ex) {
System.out.println(ex.getMessage());
}
}
}
}
return (true);
}
/**
* <b>makeWeakDiagram</b>: fuer <em>DISAGG</em><br>
* Der vorliegende Homomorphismus (this) nimmt zwei weitere (theFirst,
* theSecond) als Input und wird selbst so vervollstaendigt, dass<br>
* <em>theFirst o this <= theSecond</em>
*/
//
// [Graph X]-------------------->[Graph Y]
// \ theFirst /
// \ /
// \ /
// \ /
// \ /
// \ theSecond / this
// \ /
// \ /
// \ /
// \ /
// \ /
// \ /
// _\| |/_
// [Graph Z]
//
// -----------------------------------------------------------
public boolean makeWeakDiagram(final OrdinaryMorphism theFirst,
final OrdinaryMorphism theSecond) {
/*
* System.out.println(">>> OrdinaryMorphism.makeWeakDiagram(1, 2)");
*
* System.out.println("====="); System.out.println("FIRST : "+theFirst);
* System.out.println("SECOND: "+theSecond); System.out.println("THIS :
* "+this); if( !this.getOriginal().equals(theFirst.getImage()) )
* {return(false);} if( !this.getImage().equals(theSecond.getImage()) )
* {return(false);} if(
* !theFirst.getOriginal().equals(theSecond.getOriginal()) )
* {return(false);} // Untersuche Anwendungsvoraussetzungen: Graphen //
* (nur lesend, nicht schreibend) // Zusicherung hier: alle drei
* Morphismen leben auf den gleichen Graphen. //
* ---------------------------------------------------------------------- //
* Naechster Schritt: Untersuche Anwendungsvoraussetzungen. //
* Gemeinsame Elemente von theFirst und theSecond, // nur lesend, nicht
* schreibend // [Im folgenden wird pessimistisch angenommen, dass //
* die verwendeten Enumerationen nichtdeterministisch // (zufaellig)
* gefuellt worden seien, sodass man keine // Reihenfolgenkenntnisse
* effizient nutzbar machen kann.] /*
* if(!theFirst.getDomain().hasMoreElements()) System.out.println("-->
* firstDom is EMPTY"); if(!theSecond.getDomain().hasMoreElements())
* System.out.println("--> secondDom is EMPTY");
* if(!this.getDomain().hasMoreElements()) System.out.println("-->
* thisDom is EMPTY");
*/
if (!theFirst.getDomain().hasMoreElements()
&& !theSecond.getDomain().hasMoreElements()) {
return this.nextCompletion();
}
// Zusicherung hier: theFirst und theSecond haben den
// selben Definitionsbereich.
// ----------------------------------------------------------------
// Naechster Schritt: Untersuche weitere Anwendungsvoraussetzungen.
// Kompositionseigenschaften von ``this''
// (nur lesend, nicht schreibend) **/
Enumeration<GraphObject> ownDom = this.getDomain();
while (ownDom.hasMoreElements()) {
GraphObject y = ownDom.nextElement();
// System.out.println("--> y: "+y);
GraphObject z = this.getImage(y);
// System.out.println("--> z: "+z);
Enumeration<GraphObject> manyX = theFirst.getInverseImage(y);
while (manyX.hasMoreElements()) {
GraphObject x = manyX.nextElement();
// System.out.println("--> x: "+x);
if (!(theSecond.getImage(x)).equals(z)) {
return (false);
}
}
}
Enumeration<GraphObject> firstDom = theFirst.getDomain();
// Zusicherung hier: Wo this definiert ist, gilt die Gleichung
// this(theFirst(x))=theSecond(x)=z
// --------------------------------
// Letzter Schritt: Vervollstaendigung von this (schreibend!)
firstDom = theFirst.getDomain();
while (firstDom.hasMoreElements()) {
GraphObject x = firstDom.nextElement();
GraphObject y = theFirst.getImage(x);
GraphObject z = theSecond.getImage(x);
if (z != null) {
if (!z.equals(this.getImage(y))) {
try {
this.addMapping(y, z);
} catch (BadMappingException ex) {}
}
}
}
if (!theFirst.getDomain().hasMoreElements()
|| !theSecond.getDomain().hasMoreElements())
return this.nextCompletion();
return (true);
}
/**
* The current Homomorphismus (this) morphism takes two morphisms with : <br>
* theFirst.source == theSecond.source, <br>
* this.source == theFirst.target, <br>
* this.target == theSecond.target.<br>
* Completes this morphism so that: <em>theFirst o this = theSecond</em> .
*/
//
// [Graph X]------------------>[Graph Y]
// \ theFirst /
// \ /
// \ /
// \ /
// \ /
// \ theSecond / this
// \ /
// \ /
// \ /
// \ /
// \ /
// \ /
// _\| |/_
// [Graph Z]
//
// -----------------------------------------------------------
public boolean makeFullDiagram(final OrdinaryMorphism theFirst,
final OrdinaryMorphism theSecond) {
if (!this.itsOrig.equals(theFirst.getImage()))
return (false);
if (!this.itsImag.equals(theSecond.getImage()))
return (false);
if (!theFirst.getOriginal().equals(theSecond.getOriginal()))
return (false);
Enumeration<GraphObject> firstDom;
Enumeration<GraphObject> secondDom;
/* suche nach gemeinsammen Elementen in theFirst und theSecond */
firstDom = theFirst.getOriginal().getElements();
while (firstDom.hasMoreElements()) {
boolean result = false;
GraphObject elem1 = firstDom.nextElement();
secondDom = theSecond.getOriginal().getElements();
while (secondDom.hasMoreElements()) {
GraphObject elem2 = secondDom.nextElement();
if (elem1.equals(elem2)) {
result = true;
break;
}
}
if (!result) {
return result;
}
}
secondDom = theSecond.getOriginal().getElements();
while (secondDom.hasMoreElements()) {
boolean result = false;
GraphObject elem1 = secondDom.nextElement();
firstDom = theFirst.getOriginal().getElements();
while (firstDom.hasMoreElements()) {
GraphObject elem2 = firstDom.nextElement();
if (elem1.equals(elem2)) {
result = true;
break;
}
}
if (!result) {
return (result);
}
}
// Zusicherung hier: theFirst und theSecond haben den
// selben Definitionsbereich.
// ----------------------------------------------------------------
// Naechster Schritt: Untersuche weitere Anwendungsvoraussetzungen.
// Kompositionseigenschaften von ``this''
// (nur lesend, nicht schreibend) **/
Enumeration<GraphObject> ownDom = this.itsOrig.getElements();
while (ownDom.hasMoreElements()) {
GraphObject y = ownDom.nextElement();
GraphObject z = this.getImage(y);
if (z != null) {
Enumeration<GraphObject> manyX = theFirst.getInverseImage(y);
while (manyX.hasMoreElements()) {
GraphObject x = manyX.nextElement();
if (!theSecond.getImage(x).equals(z)) {
return false;
}
}
}
}
// Zusicherung hier: Wo this definiert ist, gilt die Gleichung
// this(theFirst(x))=theSecond(x)=z
// --------------------------------
// Letzter Schritt: Vervollstaendigung von this (schreibend!)
firstDom = theFirst.getOriginal().getElements();
while (firstDom.hasMoreElements()) {
GraphObject x = firstDom.nextElement();
GraphObject y = theFirst.getImage(x);
GraphObject z = theSecond.getImage(x);
if ((y != null) && (z != null)) {
if (!z.equals(this.getImage(y))) {
try {
this.addMapping(y, z);
} catch (BadMappingException ex) {
return false;
}
}
}
}
return true;
}
/**
* The current (this) morphism takes three morphisms, such that: this.source ==
* theFirst.target, theSecond.source == theFirst.source, theThird.source ==
* theSecond.target, this.target == theThird.target as input and this
* morphism will be completed so that the diagram comutes:
* theFirst o this == theSecond o theThird .
*/
//
// [Graph X]---------------------->[Graph Y]
// | \\ theFirst |
// | \\ |
// | \\ |
// the|Second \\ |this
// | \\ |
// | \\ |
// | \\ |
// \|/ theThird _\| \|/
// [Graph J]---------------------->[Graph H]
//
//
// -----------------------------------------------------------
public boolean makeDiagram(final OrdinaryMorphism theFirst,
final OrdinaryMorphism theSecond,
final OrdinaryMorphism theThird) {
// System.out.println(">>> OrdinaryMorphism.makeDiagram(1, 2, 3)");
OrdinaryMorphism tmpMorph = theSecond.compose(theThird);
return this.makeDiagram(theFirst, tmpMorph);
}
/**
* <b>makeWeakDiagram</b>: fuer <em>DISAGG</em><br>
* Der vorliegende Homomorphismus (this) nimmt drei weitere (theFirst,
* theSecond, theThird) als Input und wird selbst so vervollstaendigt, dass
* Diagramm schwach kommutiert.
*/
//
// [Graph X]---------------------->[Graph Y]
// | \ theFirst |
// | \ |
// | \ |
// |theSecond \ |this
// | \ |
// | \ |
// | \ |
// \|/ theThird _\| \|/
// [Graph J]---------------------->[Graph H]
//
//
// -----------------------------------------------------------
public boolean makeWeakDiagram(final OrdinaryMorphism theFirst,
final OrdinaryMorphism theSecond,
final OrdinaryMorphism theThird) {
OrdinaryMorphism tmpMorph = theSecond.compose(theThird);
if (this.makeWeakDiagram(theFirst, tmpMorph))
return true;
return false;
}
/**
* Der vorliegende Homomorphismus (this) nimmt drei weitere (theFirst,
* theSecond, theThird) als Input und wird selbst so vervollstaendigt, dass
* Diagramm kommutiert.
*/
//
// [Graph X]---------------------->[Graph Y]
// | \\ theFirst |
// | \\ |
// | \\ |
// |theSecond \\ |this
// | \\ |
// | \\ |
// | \\ |
// \|/ theThird _\\| \|/
// [Graph J]---------------------->[Graph H]
//
//
// -----------------------------------------------------------
public boolean makeFullDiagram(final OrdinaryMorphism theFirst,
final OrdinaryMorphism theSecond,
final OrdinaryMorphism theThird) {
// OrdinaryMorphism tmpMorph = theSecond.compose(theThird);
OrdinaryMorphism tmpMorph = (BaseFactory.theFactory()).createMorphism(
theSecond.getOriginal(), theThird.getImage());
final Iterator<Node> theSecondDomNodes = theSecond.getOriginal().getNodesSet().iterator();
while (theSecondDomNodes.hasNext()) {
GraphObject theSecondGo = theSecondDomNodes.next();
GraphObject theSecondGoImage = theSecond.getImage(theSecondGo);
if (theSecondGoImage != null) {
GraphObject theThirdGoImage = theThird.getImage(theSecondGoImage);
if (theThirdGoImage != null) {
try {
tmpMorph.addMapping(theSecondGo, theThirdGoImage);
} catch (BadMappingException ex) {}
}
}
}
final Iterator<Arc> theSecondDomArcs = theSecond.getOriginal().getArcsSet().iterator();
while (theSecondDomArcs.hasNext()) {
GraphObject theSecondGo = theSecondDomArcs.next();
GraphObject theSecondGoImage = theSecond.getImage(theSecondGo);
if (theSecondGoImage != null) {
GraphObject theThirdGoImage = theThird.getImage(theSecondGoImage);
if (theThirdGoImage != null) {
try {
tmpMorph.addMapping(theSecondGo, theThirdGoImage);
} catch (BadMappingException ex) {}
}
}
}
if (this.makeFullDiagram(theFirst, tmpMorph))
return true;
return false;
}
/**
* Tries to complete this morphism to be isomorphic.
*/
public boolean makeIsomorphic() {
// vergleiche Knotenanzahl
if (this.itsOrig.getNodesCount() != this.itsImag.getNodesCount()) {
return false;
}
// vergleiche Kantenanzahl
if (this.itsOrig.getArcsCount() != this.itsOrig.getArcsCount()) {
return false;
}
if (this.isTotal())
return true;
boolean result = false;
this.setCompletionStrategy(new Completion_InjCSP());
if (this.nextCompletion()) {
result = true;
// additionally, check type of source - target nodes in case of
// Typegraph with Node Type Inheritance
if (this.itsOrig.getTypeSet().getTypeGraph() != null
// && this.itsOrig.getTypeSet().getLevelOfTypeGraphCheck() >= TypeSet.ENABLED
&& this.itsOrig.getTypeSet().hasInheritance()) {
Iterator<Node> origs = this.itsOrig.itsNodes.iterator();
while (origs.hasNext() && result) {
final Node orig = origs.next();
if (!orig.getType().compareTo(this.getImage(orig).getType())) {
result = false;
}
}
}
}
return result;
}
public void setName(String n) {
this.itsName = n;
}
public String getName() {
return this.itsName;
}
/** Set textual comments for this morphism. */
public void setTextualComment(String text) {
this.comment = text;
}
/** Return textual comments of this morphism. */
public String getTextualComment() {
return this.comment;
}
/**
* This method tries to add morphism mapping between elements of my source
* graph and elements of the specified list. The elements of this list
* should be objects (nodes/edges) of my target graph. The order of the list
* has to be the order of the graph objects of my source graph. It is
* allowed to put null element into this list. A morphism mapping would be
* set for non-null elements only. As result a partial (total) graph
* morphism is done, if no errors occured.
*/
public void addMapping(final Vector<GraphObject> listOfGraphObjects)
throws BadMappingException {
// first set mapping of nodes
final Iterator<Node> origs = this.itsOrig.getNodesSet().iterator();
for (int i = 0; i < listOfGraphObjects.size() && origs.hasNext(); i++) {
final GraphObject go = listOfGraphObjects.get(i);
final GraphObject img = origs.next();
if (go instanceof Node && img instanceof Node) {
try {
addMapping(go, img);
} catch (BadMappingException ex) {
throw ex;
}
}
}
// now set mapping of edges
final Iterator<Arc> origs1 = this.itsOrig.getArcsSet().iterator();
for (int i = 0; i < listOfGraphObjects.size() && origs1.hasNext(); i++) {
final GraphObject go = listOfGraphObjects.get(i);
final GraphObject img = origs1.next();
if (go instanceof Arc && img instanceof Arc) {
try {
addMapping(go, img);
} catch (BadMappingException ex) {
throw ex;
}
}
}
}
public void addMapping(final Hashtable<GraphObject, GraphObject> obj2img)
throws BadMappingException {
// first set mapping of nodes
Enumeration<GraphObject> objs = obj2img.keys();
while (objs.hasMoreElements()) {
final GraphObject obj = objs.nextElement();
if (obj.isNode()) {
final GraphObject img = obj2img.get(obj);
try {
addMapping(obj, img);
} catch (BadMappingException ex) {
throw ex;
}
}
}
// now set mapping of edges
objs = obj2img.keys();
while (objs.hasMoreElements()) {
final GraphObject obj = objs.nextElement();
if (obj.isArc()) {
final GraphObject img = obj2img.get(obj);
try {
addMapping(obj, img);
} catch (BadMappingException ex) {
throw ex;
}
}
}
}
/**
* Returns an error if the type compatibility of the specified nodes failed,
* otherwise - null.
*/
public TypeError checkCreateMapping(final Node src, final Node tar) {
if (!checkType(src.getType(), tar.getType())) {
this.errorMsg = "Objects to map must be of the compatible type.";
return new TypeError(TypeError.NOT_COMPATIBLE_TYPE, this.errorMsg);
}
else if (this instanceof Match) {
final Enumeration<GraphObject> origEnum = getDomain();
final Match m = (Match) this;
while (origEnum.hasMoreElements()) {
final GraphObject currentObject = origEnum.nextElement();
if (currentObject instanceof Node && currentObject != src) {
final Node currentNode = (Node) currentObject;
final Node currentRuleImage = (Node) m.getRule().getImage(
currentNode);
final Node origRuleImage = (Node) m.getRule().getImage(src);
final Node currentMatchImage = (Node) m.getImage(currentNode);
if (currentRuleImage != null
&& currentRuleImage == origRuleImage) {
if (currentMatchImage != null
&& !tar.getType().compareTo(
currentMatchImage.getType())) {
this.errorMsg = "Non-injective rules must preserve types.";
return new TypeError(TypeError.NOT_COMPATIBLE_TYPE,
this.errorMsg);
}
}
}
}
}
return null;
}
/**
* Returns null if the source and target nodes of the specified edges are
* already mapped and the type compatibility of these two edges is
* satisfied, otherwise - an error.
*/
public TypeError checkCreateMapping(final Arc src, final Arc tar) {
final GraphObject aSrc = src.getSource();
final GraphObject aTar = src.getTarget();
if (!src.getType().compareTo(tar.getType())) {
this.errorMsg = "Objects to map must be of the same type.";
return new TypeError(TypeError.NOT_COMPATIBLE_TYPE, this.errorMsg);
}
if (getImage(aSrc) != null) {
if (!checkType(tar.getSource().getType(), getImage(aSrc).getType())) {
this.errorMsg = "Edge mapping must be source compatible.";
return new TypeError(TypeError.NOT_COMPATIBLE_TYPE, this.errorMsg);
}
} else {
this.errorMsg = "The sources of the edges should be already mapped.";
return new TypeError(TypeError.NOT_COMPATIBLE_TYPE, this.errorMsg);
}
if (getImage(aTar) != null) {
if (!checkType(tar.getTarget().getType(), getImage(aTar).getType())) {
this.errorMsg = "Edge mapping must be target compatible.";
return new TypeError(TypeError.NOT_COMPATIBLE_TYPE, this.errorMsg);
}
} else {
this.errorMsg = "The targets of the edges should be already mapped.";
return new TypeError(TypeError.NOT_COMPATIBLE_TYPE, this.errorMsg);
}
return null;
}
/**
* Please note: This method is only for internal use of the
* critical pair analysis for grammars with node type inheritance.
* Do not use it for any kind of implementations.
* @param o is a child node
* @param i is a parent node
* @throws BadMappingException
*/
public void addChild2ParentMapping(final GraphObject o, final GraphObject i)
throws BadMappingException {
if (this.getImage(o) != i) {
if (this.getSource().isElement(o) && this.getTarget().isElement(i)) {
try {
if (o.isNode() != i.isNode()) {
this.errorMsg = "Cannot map a node to an edge.";
// this.errors.add(this.errorMsg);
throw new BadMappingException(this.errorMsg);
}
if (!o.getType().isParentOf(i.getType())
&& !o.getType().isChildOf(i.getType())) {
this.errorMsg = "Objects to map must to have compatible types.";
// this.errors.add(this.errorMsg);
throw new BadMappingException(this.errorMsg);
}
try {
this.checkNodeTypePreserving(o, i);
} catch (BadMappingException ex) {
throw new BadMappingException(this.errorMsg);
}
try {
this.checkEdgeSourceTargetCompatibility(o, i);
} catch (BadMappingException ex) {
throw new BadMappingException(this.errorMsg);
}
final GraphObject aPreviousImage = getImage(o);
if (aPreviousImage != null)
removeMapping(o);
// try to add attribute mapping
try {
this.doAddChild2ParentAttrMapping(o, i);
// System.out.println(">>> "+o+" --> " +i);
} catch (BadMappingException exc) {
this.errorMsg = exc.getMessage();
// this.errors.add(this.errorMsg);
// restore previous mapping, if any:
if (aPreviousImage != null)
this.doAddChild2ParentAttrMapping(o, aPreviousImage);
// Beware! This does not restore the mappings which may have been
// removed IMPLICITLY above...
throw (exc);
}
} catch (BadMappingException exc) {
this.errorMsg = exc.getMessage();
// this.errors.add(this.errorMsg);
throw exc;
}
// System.out.println(">>> OrdinaryMorphism.addChild2ParentMapping OK");
}
} else {
// System.out.println("not needed to set the same graph object mapping! only add AttrMapping!");
// attr mapping has to get update
removeAttrMapping(o.getAttribute());
addAttrMapping(o.getAttribute(), i.getAttribute());
}
}
/**
* Please note: This method is only for internal use of the
* critical pair analysis for grammars with node type inheritance.
* Do not use it for any kind of implementations.
* @param orig is a child node
* @param image is a parent node
* @throws BadMappingException
*/
private void doAddChild2ParentAttrMapping(final GraphObject orig, final GraphObject image)
throws BadMappingException {
if (((ContextView) getAttrContext()).getAllowedMapping() == AttrMapping.MATCH_MAP
|| ((ContextView) getAttrContext()).getAllowedMapping() == AttrMapping.OBJECT_FLOW_MAP) {
//System.out.println("OrdinaryMorphism.doAddChild2ParentAttrMapping AttrMapping.MATCH_MAP");
if ((orig.getAttribute() == null && image.getAttribute() == null)
|| orig.getType().isChildOf(image.getType())
|| ((orig.getAttribute() != null)
&& ((ValueTuple) orig.getAttribute()).canMatchTo(
((ValueTuple) image.getAttribute()),
(ContextView) getAttrContext()))) {
boolean canMapAttr = true;
if (orig.getType().isChildOf(image.getType())
&& ((orig.getAttribute() != null)
&& !((ValueTuple) orig.getAttribute()).canMatchChild2Parent(
((ValueTuple) image.getAttribute()),
(ContextView) getAttrContext())))
canMapAttr = false;
if (canMapAttr) {
try {
addAttrMapping(orig.getAttribute(), image.getAttribute());
} catch (BadMappingException ex) {
this.errorMsg = "Attribute mapping failed!";
// this.errors.add(this.errorMsg);
throw new BadMappingException(this.errorMsg);
}
addDomainMapping(orig, image, true);
} else {
this.errorMsg = "Attribute mapping failed!";
// this.errors.add(this.errorMsg);
// System.out.println("## doAddChild2ParentAttrMapping: errorMsg: "+this.errorMsg);
throw new BadMappingException(this.errorMsg);
}
} else {
this.errorMsg = "Attribute mapping failed!";
// this.errors.add(this.errorMsg);
// System.out.println("### doAddChild2ParentAttrMapping: errorMsg: "+this.errorMsg);
throw new BadMappingException(this.errorMsg);
}
} else {
if (!orig.getType().isChildOf(image.getType())) {
addAttrMapping(orig.getAttribute(), image.getAttribute());
addDomainMapping(orig, image, true);
}
}
}
/**
* @param orig belongs to the source graph of this
* @param image belongs to the target graph of this
*/
private void addDomainMapping(final GraphObject orig, final GraphObject image, boolean notificationRequired) {
this.itsDomObjects.add(orig);
this.itsCodomObjects.add(image);
this.mappingChanged = true;
if (notificationRequired) {
if (isNotificationRequired()) {
propagateChange(new Change(Change.MAPPING_ADDED, orig, this));
propagateChange(new Change(Change.MAPPING_ADDED, image, this));
}
if (this.itsOrig.isNotificationRequired()) {
this.itsOrig.propagateChange(new Change(
Change.MAPPING_ADDED, orig, this));
}
if (this.itsImag.isNotificationRequired()){
this.itsImag.propagateChange(new Change(
Change.MAPPING_ADDED, image, this));
}
}
}
/**
* Map an object of source graph to an object of target graph.
* The original and image objects have to belong to the same morphism. *
* <p>
* <b>Pre:</b>
* <ol> *
* <li><code>o</code> is an element of <code>getOriginal()</code>. *
* <li><code>i</code> is an element of <code>getImage()</code>. *
* </ol> *
*
* @param o
* the source object of the mapping. *
* @param i
* the target object of the mapping. *
* @exception agg.xt_basis.BadMappingException
* if the given mapping violates morphism properties. *
*/
public void addMapping(final GraphObject o, final GraphObject i)
throws BadMappingException {
if (o == null || i == null) {
this.errorMsg = "Mapping failed! The source or target object is null.";
throw new BadMappingException(this.errorMsg);
}
if (this.getImage(o) != i) {
if (this.getSource().isElement(o) && this.getTarget().isElement(i)) {
try {
doAddMapping(o, i);
} catch (BadMappingException exc) {
this.errorMsg = exc.getMessage();
// this.errors.add(this.errorMsg);
throw exc;
}
} else {
this.errorMsg = "Mapping failed! Graph objects to map must belong to the same morphism.";
// this.errors.add(this.errorMsg);
throw new BadMappingException(this.errorMsg);
}
} else {
// attr mapping has to get update
removeAttrMapping(o.getAttribute());
addAttrMapping(o.getAttribute(), i.getAttribute());
}
}
/**
* The user of this method must take care about any checks for the mapping
* of the specified graph objects.
* Otherwise is null pointer exception can be thrown.
* @param o
* @param i
* @throws BadMappingException
*/
public void addMappingFast(final GraphObject o, final GraphObject i)
throws BadMappingException {
if (o == null || i == null) {
this.errorMsg = "Mapping failed! The source or target object is null.";
throw new BadMappingException(this.errorMsg);
}
if (this.getImage(o) != i) {
try {
doAddMappingFast(o, i);
} catch (BadMappingException exc) {
this.errorMsg = exc.getMessage();
// this.errors.add(this.errorMsg);
throw exc;
}
} else {
// attr mapping has to get update
removeAttrMapping(o.getAttribute());
addAttrMapping(o.getAttribute(), i.getAttribute());
}
}
/*
* The user of this method must take care about any checks.
* Otherwise null pointer exception woll be throwen.
*/
private void doAddMappingFast(final GraphObject orig, final GraphObject image)
throws BadMappingException {
// try to add attribute mapping
try {
this.doAddAttrMappingFast(orig, image);
this.addDomainMapping(orig, image, true);
this.changed = true;
} catch (BadMappingException exc) {
this.errorMsg = exc.getMessage();
// this.errors.add(this.errorMsg);
throw (exc);
}
}
/*
* The user of this method must take care about any checks.
* Otherwise null pointer exception woll be throwen.
*/
private void doAddAttrMappingFast(final GraphObject orig, final GraphObject image)
throws BadMappingException {
if (((ContextView) getAttrContext()).getAllowedMapping() == AttrMapping.MATCH_MAP) {
try {
addAttrMapping(orig.getAttribute(), image.getAttribute());
} catch (BadMappingException ex) {
this.errorMsg = "Attribute mapping failed! "+ex.getLocalizedMessage();
// this.errors.add(this.errorMsg);
throw new BadMappingException(this.errorMsg);
}
} else {
addAttrMapping(orig.getAttribute(), image.getAttribute());
}
}
/**
* Map an object of source graph to an object of target graph.
* The image object have not to belong to the same morphism,
* it will be create implicitly. *
* <p>
* <b>Pre:</b>
* <ol> *
* <li><code>o</code> is an element of <code>getOriginal()</code>. *
* <li><code>i</code> is an element of <code>getImage()</code>. *
* </ol> *
*
* @param o
* the source object of the mapping. *
* @param i
* the target object of the mapping. *
* @exception agg.xt_basis.BadMappingException
* if the given mapping violates morphism properties.
*
* @deprecated please use <code>addMapping(final GraphObject o, final GraphObject i)</code>
*/
public void addMapping(final GraphObject o, final GraphObject i,
final boolean mappingPropagation)
throws BadMappingException {
if (!mappingPropagation) {
addMapping(o, i);
return;
}
// if (!(this instanceof OrdinarySubMorphism)) {
if (this.getSource().isElement(o) && this.getTarget().isElement(i)) {
try {
doAddMapping(o, i);
} catch (BadMappingException exc) {
this.errorMsg = exc.getMessage();
// this.errors.add(this.errorMsg);
throw exc;
}
}
// } else // if(this instanceof OrdinarySubMorphism)
// ((OrdinarySubMorphism) this).getSuperMorphism().addMapping(o, i);
}
/**
* Add PLAIN morphism mapping without any checks. <br>
* Preconditions: <br>
* - to map Node to Node and Arc to Arc only,<br>
* - objects to map must be of the same type, <br>
* - source and target of an edge must be already mapped.
*
*/
protected void addPlainMapping(final GraphObject orig, final GraphObject image)
throws BadMappingException {
if (orig == null || image == null) {
this.errorMsg = "Mapping failed! The source or target object is null.";
throw new BadMappingException(this.errorMsg);
}
try {
addAttrMapping(orig.getAttribute(), image.getAttribute());
addDomainMapping(orig, image, false);
this.changed = true;
} catch (BadMappingException exc) {
this.errorMsg = exc.getMessage();
// this.errors.add(this.errorMsg);
throw exc;
}
}
/**
* Try to add a mapping of two GraphObjects without setting the attr mapping.
*
* @param orig
* @param image
* @throws BadMappingException
*/
protected void addObjectPlainMapping(final GraphObject orig, final GraphObject image)
throws BadMappingException {
if (orig == null || image == null) {
this.errorMsg = "Mapping failed! The source or target object is null.";
throw new BadMappingException(this.errorMsg);
}
try {
// addAttrMapping(orig.getAttribute(), image.getAttribute());
addDomainMapping(orig, image, false);
this.changed = true;
} catch (BadMappingException exc) {
this.errorMsg = exc.getMessage();
// this.errors.add(this.errorMsg);
throw exc;
}
}
protected boolean checkType(Type orig, Type image) {
return orig.isParentOf(image);
}
private void checkNodeTypePreserving(final GraphObject orig, final GraphObject image)
throws BadMappingException {
if (this instanceof Match && orig.isNode()) {
final Enumeration<GraphObject> origEnum = getDomain();
final Match m = (Match) this;
while (origEnum.hasMoreElements()) {
final GraphObject currentObject = origEnum.nextElement();
if (currentObject instanceof Node && currentObject != orig) {
final Node currentNode = (Node) currentObject;
final Node currentRuleImage = (Node) m.getRule().getImage(
currentNode);
final Node origRuleImage = (Node) m.getRule().getImage(orig);
final Node currentMatchImage = (Node) m.getImage(currentNode);
if (currentRuleImage != null
&& currentRuleImage == origRuleImage) {
if (currentMatchImage != null
&& !image.getType().compareTo(
currentMatchImage.getType())) {
this.errorMsg = "Non-injective rules must preserve types.";
// this.errors.add(this.errorMsg);
throw new BadMappingException(this.errorMsg);
}
}
}
}
}
}
protected void checkEdgeSourceTargetCompatibility(final GraphObject orig, final GraphObject image)
throws BadMappingException {
try {
MatchHelper.checkEdgeSourceTargetCompatibility(this, orig, image);
} catch (BadMappingException ex) {
throw ex;
}
}
private void doAddAttrMapping(final GraphObject orig, final GraphObject image)
throws BadMappingException {
if (((ContextView) getAttrContext()).getAllowedMapping() == AttrMapping.MATCH_MAP) {
if ( (orig.getAttribute() == null
|| orig.getAttribute().getNumberOfEntries() == 0)
|| ( image.getAttribute() != null
&& ((ValueTuple) orig.getAttribute())
.canMatchTo(
((ValueTuple) image.getAttribute()),
(ContextView) getAttrContext()) ) ) {
addAttrMapping(orig.getAttribute(), image.getAttribute());
} else {
this.errorMsg = "Attribute mapping failed!";
// this.errors.add(this.errorMsg);
throw new BadMappingException(this.errorMsg);
}
}
else {
addAttrMapping(orig.getAttribute(), image.getAttribute());
}
}
private void doAddMapping(final GraphObject orig, final GraphObject image)
throws BadMappingException {
if (orig.isNode() != image.isNode()) {
this.errorMsg = "Cannot map node to edge.";
// this.errors.add(this.errorMsg);
throw new BadMappingException(this.errorMsg);
}
if (!checkType(orig.getType(), image.getType())) {
this.errorMsg = "Objects to map must be of the same type.";
// this.errors.add(this.errorMsg);
throw new BadMappingException(this.errorMsg);
}
try {
this.checkNodeTypePreserving(orig, image);
} catch (BadMappingException ex) {
throw new BadMappingException(this.errorMsg);
}
try {
this.checkEdgeSourceTargetCompatibility(orig, image);
} catch (BadMappingException ex) {
this.errorMsg = ex.getLocalizedMessage();
throw new BadMappingException(this.errorMsg);
}
// store previous image of orig
final GraphObject aPreviousImage = getImage(orig);
if (aPreviousImage != null)
removeMapping(orig);
// try to add attribute mapping
try {
this.doAddAttrMapping(orig, image);
this.addDomainMapping(orig, image, true);
this.changed = true;
} catch (BadMappingException exc) {
this.errorMsg = exc.getMessage();
// this.errors.add(this.errorMsg);
// restore previous mapping, if any:
if (aPreviousImage != null)
addMappingFast(orig, aPreviousImage);
// Beware! This does not restore the mappings which may have been
// removed IMPLICITLY above...
throw (exc);
}
}
protected void addAttrMapping(final AttrInstance o, final AttrInstance i)
throws BadMappingException {
if (getAttrContext() != null) {
if (o == null && i == null) {
return;
}
else if (o != null && i != null) {
try {
this.itsAttrMappings.put(o, getAttrManager().newMapping(
getAttrContext(), o, i));
this.errorMsg = "";
// System.out.println("OrdinaryMorphism.addAttrMapping --> Mapping added");
} catch (AttrException exc) {
this.errorMsg = exc.getMessage();
// System.out.println("OrdinaryMorphism.addAttrMapping
// FAILED! \n"+this.errorMsg);
throw new BadMappingException(exc.getMessage());
}
}
else if (o != null && o.getNumberOfEntries() != 0) {
throw new BadMappingException(
"Attribute mapping failed! Attribute of source or target object is null.");
}
}
}
protected boolean removeAttrMapping = true;
protected void removeAttrMapping(final AttrInstance o) {
if (o != null) {
AttrMapping anAttrMapping = this.itsAttrMappings.get(o);
if (anAttrMapping != null && this.removeAttrMapping) {
anAttrMapping.remove();
this.itsAttrMappings.remove(o);
}
}
}
public void removeVariableValue(final AttrInstance o) {
if (o == null)
return;
final ValueTuple vt = (ValueTuple) o;
for (int i = 0; i < vt.getNumberOfEntries(); i++) {
ValueMember vm = vt.getValueMemberAt(i);
if (vm.isSet() && vm.getExpr().isVariable()) {
final VarTuple vars = (VarTuple) this.itsAttrContext.getVariables();
final VarMember var = vars.getVarMemberAt(vm.getExprAsText());
if (!var.isInputParameter()) {
var.setExpr(null);
}
}
}
}
public void updateAttrMappings() {
if (!this.itsImag.isAttributed())
return;
for (int i = 0; i < this.itsDomObjects.size(); i++) {
final GraphObject obj = this.itsDomObjects.get(i);
final GraphObject img = this.itsCodomObjects.get(i);
removeAttrMapping(obj.getAttribute());
addAttrMapping(obj.getAttribute(), img.getAttribute());
}
}
/**
* This method should be used after the method
* <code>removeMapping(GraphObject go)</code> called and befor the method
* <code>nextCompletion(Enumeration varnodes, Enumeration varedges)</code>
* performed.
*
* @param go
* is an element of my source graph
*/
public void resetCSPVariableDomainOf(GraphObject go) {
if (this.itsOrig.isElement(go))
this.itsCompleter.resetVariableDomain(go);
}
public void removeAllMappings() {
removeAttrMappings();
this.itsDomObjects.clear();
this.itsCodomObjects.clear();
this.mappingChanged = false;
}
/**
* Returns TRUE if removed, otherwise - FALSE
*/
public boolean removeMapping(final Node src, final Node tar) {
if (this.getSource().isElement(src) && this.getTarget().isElement(tar)) {
int i = this.itsDomObjects.indexOf(src);
int j = this.itsCodomObjects.indexOf(tar);
if (i >= 0 && j >= 0) {
if (i != j && this.itsDomObjects.get(j) == src)
i = j;
if (i == j) {
GraphObject aNeighbor;
Iterator<Arc> anIter = src.getIncomingArcsSet().iterator();
while (anIter.hasNext()) {
aNeighbor = anIter.next();
if (getImage(aNeighbor) != null)
removeMapping(aNeighbor);
}
anIter = src.getOutgoingArcsSet().iterator();
while (anIter.hasNext()) {
aNeighbor = anIter.next();
if (getImage(aNeighbor) != null)
removeMapping(aNeighbor);
}
// update the index of Node src
i = this.itsDomObjects.indexOf(src);
j = this.itsCodomObjects.indexOf(tar);
if (i != j && this.itsDomObjects.get(j) == src)
i = j;
if (i == j) {
removeAttrMapping(src.getAttribute());
removeDomainMapping(i, true);
return true;
}
}
}
}
return false;
}
/**
* @param i index of a graph object inside of this.itsDomObjects
*/
private void removeDomainMapping(int i, boolean notificationRequired) {
final GraphObject dom = this.itsDomObjects.get(i);
this.itsDomObjects.remove(i);
final GraphObject codom = this.itsCodomObjects.get(i);
this.itsCodomObjects.remove(i);
this.mappingChanged = true;
if (notificationRequired) {
if (isNotificationRequired()) {
propagateChange(new Change(Change.MAPPING_REMOVED, dom, this));
propagateChange(new Change(Change.MAPPING_REMOVED, codom, this));
}
if (this.itsOrig.isNotificationRequired()) {
this.itsOrig.propagateChange(new Change(Change.MAPPING_REMOVED, dom,
this));
}
if (this.itsImag.isNotificationRequired()) {
this.itsImag.propagateChange(new Change(Change.MAPPING_REMOVED,
codom, this));
}
}
}
/**
* Returns TRUE if removed, otherwise - FALSE. Note: The source and target
* nodes of the specified src and tar edges still mapped. They should be
* removed explicitly.
*/
public boolean removeMapping(final Arc src, final Arc tar) {
if (this.getSource().isElement(src) && this.getTarget().isElement(tar)) {
int i = this.itsDomObjects.indexOf(src);
int j = this.itsCodomObjects.indexOf(tar);
if (i >= 0 && j >= 0) {
if (i != j && this.itsDomObjects.get(j) == src)
i = j;
if (i == j) {
removeAttrMapping(src.getAttribute());
removeDomainMapping(i, true);
return true;
}
}
}
return false;
}
/**
* Remove the mapping of the given GraphObject.
* In case of node, any mappings of incoming / outgoing arcs will be removed as well.
*
*/
public void removeMapping(final GraphObject o) {
if (this.getSource().isElement(o)) {
doRemoveMapping(o);
} else if (this.getTarget().isElement(o)) {
final Enumeration<GraphObject> en = getInverseImage(o);
while (en.hasMoreElements()) {
doRemoveMapping(en.nextElement());
}
}
}
/**
* Remove the mapping of the given GraphObject.
* In case of node, any mappings of incoming / outgoing arcs will be removed as well.
* Precondition: <br>
* - if left is true, the obj belongs to the source graph
* - if left is false, the obj belongs to the target graph
*/
public void removeMappingFast(final GraphObject obj, boolean left) {
if (left) {
doRemoveMapping(obj);
} else {
final Enumeration<GraphObject> en = getInverseImage(obj);
while (en.hasMoreElements()) {
doRemoveMapping(en.nextElement());
}
}
}
private void doRemoveMapping(final GraphObject o) {
int i = this.itsDomObjects.indexOf(o);
if (i >= 0) {
if (o.isNode()) {
GraphObject aNeighbor;
Iterator<Arc> anIter = ((Node) o).getIncomingArcsSet().iterator();
while (anIter.hasNext()) {
aNeighbor = anIter.next();
if (getImage(aNeighbor) != null) {
doRemoveMapping(aNeighbor);
}
}
anIter = ((Node) o).getOutgoingArcsSet().iterator();
while (anIter.hasNext()) {
aNeighbor = anIter.next();
if (getImage(aNeighbor) != null) {
doRemoveMapping(aNeighbor);
}
}
// update the index of Node o
i = this.itsDomObjects.indexOf(o);
}
removeAttrMapping(o.getAttribute());
removeDomainMapping(i, true);
}
}
/**
* Remove all mappings and reset variables of its attribute context.
*/
public void clear() {
if (this.itsCoMorph != null) {
this.itsCoMorph.dispose();
}
removeAllMappings();
if (this.itsAttrContext.getVariables().getNumberOfEntries() != 0) {
((ContextView)this.itsAttrContext).resetVariableTuple();
((ContextView)this.itsAttrContext).resetConditionTuple();
// ((VarTuple) itsAttrContext.getVariables()).getContext().removeAllMappings();
// ((CondTuple) itsAttrContext.getConditions()).getContext().removeAllMappings();
// ((VarTuple) itsAttrContext.getVariables()).updateByParent();
// ((VarTuple) itsAttrContext.getVariables()).unsetNotInputVariables();
}
this.mappingChanged = false;
this.partialMorphCompletion = false;
clearErrorMsg();
}
public void removeAttrMappings() {
final Enumeration<AttrInstance> keys = this.itsAttrMappings.keys();
while (keys.hasMoreElements()) {
AttrInstance key = keys.nextElement();
key.getContext().removeAllMappings();
}
((Hashtable<AttrInstance, AttrMapping>) this.itsAttrMappings).clear();
this.itsAttrContext.removeAllMappings();
}
/**
* Return true if its morphism mapping is empty,
* otherwise - false.
*/
public boolean isEmpty() {
return this.itsDomObjects.isEmpty();
}
/** Return its source graph. */
public Graph getOriginal() {
return this.itsOrig;
}
/** Return its source graph. */
public Graph getSource() {
return this.itsOrig;
}
/** Return its target graph. */
public Graph getImage(){
return this.itsImag;
}
/** Return its target graph. */
public Graph getTarget() {
return this.itsImag;
}
public Vector<GraphObject> getDomainObjects() {
return this.itsDomObjects;
}
/**
* Return the objects of my source graph which
* are actually taking part in the current morphism mappings.
*/
public Enumeration<GraphObject> getDomain()
{
return this.itsDomObjects.elements();
}
public int getDomainSize() {
return this.itsDomObjects.size();
}
/**
* Return the objects of my target graph which
* are actually taking part in the current morphism mappings.
*/
public Enumeration<GraphObject> getCodomain() {
return this.itsCodomObjects.elements();
}
public Vector<GraphObject> getCodomainObjects() {
return this.itsCodomObjects;
}
public int getCodomainSize() {
return this.itsCodomObjects.size();
}
/***************************************************************************
* Return the image of the specified object.
*
* @return <code>null</code> if the object is not in domain.*
**************************************************************************/
public GraphObject getImage(final GraphObject o) {
int i = this.itsDomObjects.indexOf(o);
if ((i > -1) && (i < this.itsCodomObjects.size())) {
return this.itsCodomObjects.elementAt(i);
}
return null;
}
public boolean hasInverseImage(final GraphObject o) {
if (this.itsCodomObjects.indexOf(o) != -1) {
return true;
}
return false;
}
/**
* Return an Enumeration of the inverse images of the specified object. *
* Enumeration will be empty when the object is not in codomain. *
* Enumeration elements are of type <code>GraphObject</code>.
*/
public Enumeration<GraphObject> getInverseImage(final GraphObject o) {
final Vector<GraphObject> invImages = new Vector<GraphObject>();
int i = 0;
int index;
while ((i < this.itsCodomObjects.size())
&& ((index = this.itsCodomObjects.indexOf(o, i)) != -1)) {
invImages.addElement(this.itsDomObjects.elementAt(index));
i = index + 1;
}
return invImages.elements();
}
public List<GraphObject> getInverseImageList(final GraphObject o) {
final List<GraphObject> invImages = new Vector<GraphObject>();
int i = 0;
int index;
while ((i < this.itsCodomObjects.size())
&& ((index = this.itsCodomObjects.indexOf(o, i)) != -1)) {
invImages.add(this.itsDomObjects.get(index));
i = index + 1;
}
return invImages;
}
public List<GraphObject> getElementsToCreate() {
final Vector<GraphObject> created = findCreatedElements();
return created;
}
public List<GraphObject> getElementsToDelete() {
final Vector<GraphObject> deleted = findDeletedElements();
return deleted;
}
public Hashtable<GraphObject, GraphObject> morphToMap() {
final Hashtable<GraphObject, GraphObject> map = new Hashtable<GraphObject, GraphObject>();
final Enumeration<GraphObject> dom = this.getDomain();
while (dom.hasMoreElements()) {
GraphObject obj = dom.nextElement();
map.put(obj, this.getImage(obj));
}
return map;
}
/**
* Set the algorithm of morphism completion. Class
* <code>CompletionStrategySelector</code> provides a way to present and
* obtain available algorithms.
*
* @see agg.xt_basis.CompletionStrategySelector
*/
public void setCompletionStrategy(final MorphCompletionStrategy s,
boolean rewrite) {
if (rewrite) {
if (this.itsCompleter == null || this.itsCompleter != s)
this.itsCompleter = s;
} else
setCompletionStrategy(s);
}
/**
* Set the algorithm of morphism completion. Class
* <code>CompletionStrategySelector</code> provides a way to present and
* obtain available algorithms.
* The given strategy is internally cloned to prevent undesired side effects.
* @see agg.xt_basis.CompletionStrategySelector
*/
public void setCompletionStrategy(final MorphCompletionStrategy s) {
if (this.itsCompleter == null || !this.itsCompleter.equals(s)) {
this.itsCompleter = (MorphCompletionStrategy) s.clone();
}
}
public final MorphCompletionStrategy getCompletionStrategy() {
return this.itsCompleter;
}
public void unsetCompletionStrategy() {
this.itsCompleter = null;
}
/**
* Return true if my source graph can be a subgraph of the given graph g
* basically. It can only work for INJECTIVE search.
*/
public boolean canMatch(final Graph g, final MorphCompletionStrategy strategy) {
// check graph size if injective morphism
if (strategy.getProperties().get(CompletionPropertyBits.INJECTIVE)) {
if ((this.itsOrig.getNodesCount() > g.getNodesCount())
|| (this.itsOrig.getArcsCount() > g.getArcsCount()))
return false;
}
// check types: all types of the orig. graph should be in image, too
final Vector<Type> origTypes = this.itsOrig.getUsedTypes();
final Vector<Type> otherTypes = g.getUsedAndInheritedTypes();
for (int i = 0; i < origTypes.size(); i++) {
if (!otherTypes.contains(origTypes.get(i)))
return false;
}
return true;
}
/**
* Return true if this morphism can be completed basically.
*/
public boolean canComplete() {
// check graph size if injective morphism
if (this.itsCompleter.getProperties().get(CompletionPropertyBits.INJECTIVE)) {
if ((this.itsOrig.getNodesCount() > this.itsImag.getNodesCount())
|| (this.itsOrig.getArcsCount() > this.itsImag.getArcsCount()))
return false;
}
// check types: all types of the orig. graph should be in image, too
final Vector<Type> origTypes = this.itsOrig.getUsedTypes();
final Vector<Type> imagTypes = this.itsImag.getUsedAndInheritedTypes();
for (int i = 0; i < origTypes.size(); i++) {
if (!imagTypes.contains(origTypes.get(i)))
return false;
}
return true;
}
public boolean isMappingChanged() {
return this.mappingChanged;
}
/***************************************************************************
* Compute next completion: * Invoke this method successively to get all
* completions.
*
* @return <code>false</code> if there are no more completions.*
**************************************************************************/
public boolean nextCompletion() {
boolean ok = false;
this.errorMsg = "";
ok = doNextCompletion();
if (!ok) {
// get error message from attribute manager
String attrMsg = ((agg.attribute.impl.ContextView) this
.getAttrContext()).getManager().getErrorMsg();
if (attrMsg.length()>0) {
this.errorMsg = attrMsg;
// this.errors.add(this.errorMsg);
}
// else if (this.errorMsg.length()>0)
// this.errors.add(this.errorMsg);
}
return ok;
}
/***************************************************************************
* Compute next completion: * Invoke this method successively to get all
* completions for the nodes and edges specified by the Vector varnodes and
* Vector varedges, only.
*
* @return <code>false</code> if there are no more completions.*
**************************************************************************/
public boolean nextCompletion(
Collection<Node> varnodes,
Collection<Arc> varedges) {
boolean ok = false;
this.errorMsg = "";
ok = doNextCompletion(varnodes, varedges);
if (!ok) {
// get error message from attribute manager
String attrMsg = ((agg.attribute.impl.ContextView) this
.getAttrContext()).getManager().getErrorMsg();
if (attrMsg.length()>0) {
this.errorMsg = attrMsg;
// this.errors.add(this.errorMsg);
}
// else if (this.errorMsg.length()>0)
// this.errors.add(this.errorMsg);
}
return ok;
}
/**
* @deprecated replaced by <code> boolean nextCompletion(Collection<Node> varnodes,Collection<Arc> varedges)<\code>
*/
public boolean nextCompletion(
Enumeration<Node> varnodes,
Enumeration<Arc> varedges) {
return this.nextCompletion(
Collections.list(varnodes),
Collections.list(varedges));
}
/**
* Compute next completion:
* Invoke this method successively to get all completions.
*
* @return <code>false</code> if there are no more completions.
*/
public boolean nextCompletionWithConstantsChecking(
Collection<Node> varnodes,
Collection<Arc> varedges) {
// Diese Methode ist nur bei Instanzen von OrdinaryMorphism sinvoll.
// Daraus folgt: Attribute Mappingsmode ist PLAIN_MAP.
boolean found = false;
while (!found && this.nextCompletion(varnodes, varedges)) {
found = true;
if (!this.checkConstants()) {
this.errorMsg = "Mismatch of constant attribute values.";
// this.errors.add(this.errorMsg);
found = false;
}
}
return found;
}
/**
* @deprecated replaced by <code>nextCompletionWithConstantsChecking(Collection<Node> varnodes,Collection<Arc> varedges)<\code>
*/
public boolean nextCompletionWithConstantsChecking(
Enumeration<Node> varnodes,
Enumeration<Arc> varedges) {
return nextCompletionWithConstantsChecking(
Collections.list(varnodes),
Collections.list(varedges));
}
/**
* Compute next completion:
* Invoke this method successively to get all completions.
*
* @return <code>false</code> if there are no more completions.
*/
public boolean nextCompletionWithConstantsAndVariablesChecking(
Collection<Node> varnodes,
Collection<Arc> varedges) {
// Diese Methode ist nur bei Instanzen von OrdinaryMorphism sinvoll.
// Daraus folgt: Attribute Mappingsmode ist PLAIN_MAP.
boolean found = false;
while (!found && this.nextCompletion(varnodes, varedges)) {
found = true;
if (!this.checkAll()) {
this.errorMsg = "Mismatch of constant attribute values or variables.";
// this.errors.add(this.errorMsg);
found = false;
}
}
return found;
}
private boolean doNextCompletion() {
if (this.itsTouchedFlag) {
this.itsCompleter.reset();
this.itsTouchedFlag = false;
}
this.mappingChanged = false;
// temporarily turn off update processing:
this.itsInteractiveFlag = false;
boolean b = this.itsCompleter.next(this);
// this.changed = this.changed || b;
// turn update processing on again:
this.itsInteractiveFlag = true;
return b;
}
/**
* Try to get completion using only nodes and edges specified by the Vector
* varnodes and Vector varedges.
*/
private boolean doNextCompletion(
Collection<Node> varnodes,
Collection<Arc> varedges) {
if (this.itsTouchedFlag) {
this.itsCompleter.reset();
this.itsTouchedFlag = false;
}
// temporarily turn off update processing:
this.itsInteractiveFlag = false;
boolean b = this.itsCompleter.next(this, varnodes, varedges);
// this.changed = this.changed || b;
// turn update processing on again:
this.itsInteractiveFlag = true;
return b;
}
/**
* Compute next completion: * Invoke this method successively to get all
* completions. *
*
* @return <code>false</code> if there are no more completions.
*/
public boolean nextCompletionWithConstantsChecking() {
// Diese Methode ist nur bei Instanzen von OrdinaryMorphism sinvoll.
// Attribute Mappingsmode ist PLAIN_MAP.
boolean found = false;
while (!found && this.nextCompletion()) {
found = true;
if (!this.checkConstants()) {
this.errorMsg = "Mismatch of constant attribute values.";
// this.errors.add(this.errorMsg);
found = false;
}
}
return found;
}
/*
* Diese Methode ist nur bei Instanzen von OrdinaryMorphism sinvoll. *
* Daraus folgt: Attribute Mappingsmode ist PLAIN. * Bei attributierten
* Graphobjekten (original --> image) * wird die Wertbelegung durch
* Konstante auf deren Gleichheit getestet, * nur dann ist diese Methode
* erfolgreich. * So ein Test erfolgt bei der ueblichen Methode
* nextCompletion() * in PLAIN nicht.
*/
/*
private boolean single_nextCompletionWithConstantsChecking() {
// System.out.println("
// OrdinaryMorphism.nextCompletionWithConstantsChecking... ");
boolean found = false;
if (this.nextCompletion()) {
if (this.checkConstants())
found = true;
else {
this.errorMsg = "Mismatch of constant attribute values.";
// this.errors.add(this.errorMsg);
found = false;
}
}
return found;
}
*/
/**
* Compute next completion: * Invoke this method successively to get all
* completions. *
*
* @return <code>false</code> if there are no more completions.
*/
public boolean nextCompletionWithConstantsAndVariablesChecking() {
// Diese Methode ist nur bei Instanzen von OrdinaryMorphism sinvoll.
// Attribute Mappingsmode ist PLAIN_MAP.
boolean found = false;
while (!found && this.nextCompletion()) {
found = true;
if (!this.checkAll()) {
this.errorMsg = "Mismatch of constant attribute values or variables.";
// this.errors.add(this.errorMsg);
found = false;
}
}
return found;
}
/** Return <code>true</code> if this is a total morphism. */
public final boolean isTotal() {
return this.itsOrig.isEmpty()
|| (this.itsOrig.getSize() == this.itsDomObjects.size());
}
/** Return <code>true</code> if this is a right total morphism. */
public boolean isRightTotal() {
boolean res = false;
if (this.itsCodomObjects.size() == this.itsImag.getSize()
&& this.itsCodomObjects.containsAll(this.itsImag.getNodesCollection())
&& this.itsCodomObjects.containsAll(this.itsImag.getArcsCollection()))
res = true;
return res;
}
public boolean doesIgnoreAttrs() {
boolean res = true;
for (int i=0; i<this.itsDomObjects.size(); i++) {
GraphObject obj = this.itsDomObjects.get(i);
if (obj.getAttribute() == null)
continue;
GraphObject img = this.getImage(obj);
ValueTuple imgVal = (ValueTuple) img.getAttribute();
for (int j=0; j<imgVal.getNumberOfEntries(); j++) {
ValueMember vmImg = imgVal.getValueMemberAt(j);
if (vmImg.isSet() && !vmImg.isTransient()) {
ValueMember vmObj = ((ValueTuple) obj.getAttribute()).getValueMemberAt(vmImg.getName());
if (vmObj != null && vmObj.isSet()
&& vmObj.getExprAsText().equals(vmImg.getExprAsText())) {
res = false;
break;
}
}
}
}
return res;
}
/**
* Return the attribute context
* that is used for attribute matching.
*
* @see agg.attribute.AttrContext
*/
public AttrContext getAttrContext() {
return this.itsAttrContext;
}
/**
* Set the attribute context that is used for attribute matching.
*
* @see agg.attribute.AttrContext
*/
public void setAttrContext(final AttrContext ac) {
this.itsAttrContext = ac;
}
public Dictionary<AttrInstance, AttrMapping> getAttrMapping() {
// return (new Hashtable<AttrInstance, AttrMapping>())
// .putAll((Hashtable<AttrInstance, AttrMapping>)this.itsAttrMappings);
return this.itsAttrMappings;
}
public void reflectTransientOfSimilarVar(final VarTuple vars) {
final VarTuple itsVars = (VarTuple) getAttrContext().getVariables();
for (int i = 0; i < vars.getSize(); i++) {
final VarMember var = vars.getVarMemberAt(i);
final VarMember itsvar = itsVars.getVarMemberAt(var.getName());
if (itsvar != null) {
if (!itsvar.isTransient() && var.isTransient())
itsvar.setTransient(true);
}
}
}
public void adaptAttrContextValues(final AttrContext ac) {
// System.out.println("OrdinaryMorphism.adaptAttrContextValues...");
final VarTuple itsVars = (VarTuple) this.getAttrContext().getVariables();
final VarTuple vars = (VarTuple) ac.getVariables();
// vars.showVariables();
for (int i = 0; i < vars.getSize(); i++) {
final VarMember var = vars.getVarMemberAt(i);
final VarMember itsVar = itsVars.getVarMemberAt(var.getName());
if (itsVar != null) {
if (var.isSet()) {
// itsVar.setExprAsText(var.getExprAsText());
itsVar.setExpr(var.getExpr());
// check if var itself uses another variable
final VarMember tmp = vars.getVarMemberAt(var.getExprAsText());
if (tmp != null && tmp.isTransient()) {
itsVar.setTransient(true);
var.setTransient(true);
}
}
}
}
}
public void adaptAttrContextValuesFromExistingObjMapping() {
for (int i=0; i<this.itsDomObjects.size(); i++) {
GraphObject obj = this.itsDomObjects.get(i);
if (obj.getAttribute() == null)
continue;
GraphObject img = this.getImage(obj);
ValueTuple imgVal = (ValueTuple) img.getAttribute();
for (int j=0; j<imgVal.getNumberOfEntries(); j++) {
ValueMember vmImg = imgVal.getValueMemberAt(j);
if (vmImg.isSet()) {
ValueMember vmObj = ((ValueTuple) obj.getAttribute()).getValueMemberAt(vmImg.getName());
if (vmObj != null && vmObj.isSet() && vmObj.getExpr().isVariable()) {
VarMember var = ((VarTuple)this.getAttrContext().getVariables())
.getVarMemberAt(vmObj.getExprAsText());
var.setExprAsText(vmImg.getExprAsText());
}
}
}
}
}
public void addToAttrContextFromList(final List<VarMember> vars, boolean setInputParameter) {
final VarTuple itsVars = (VarTuple) getAttrContext().getVariables();
for (int i = 0; i < vars.size(); i++) {
final VarMember var = vars.get(i);
final DeclMember dm = (DeclMember) var.getDeclaration();
if (!itsVars.isDeclared(dm.getTypeName(), dm.getName())) {
itsVars.declare(dm.getHandler(),
dm.getTypeName(), dm.getName());
itsVars.getVarMemberAt(dm.getName()).setTransient(var.isTransient());
itsVars.getVarMemberAt(dm.getName()).setInputParameter(var.isInputParameter() || setInputParameter);
}
}
}
public void addToAttrContext(final VarTuple vars) {
final VarTuple itsVars = (VarTuple) getAttrContext().getVariables();
for (int i = 0; i < vars.getSize(); i++) {
final VarMember var = vars.getVarMemberAt(i);
final DeclMember dm = (DeclMember) var.getDeclaration();
if (!itsVars.isDeclared(dm.getTypeName(), dm.getName())) {
itsVars.declare(dm.getHandler(),
dm.getTypeName(), dm.getName());
itsVars.getVarMemberAt(dm.getName()).setTransient(var.isTransient());
itsVars.getVarMemberAt(dm.getName()).setInputParameter(var.isInputParameter());
}
}
}
public void addToAttrContextAccordingList(final VarTuple vars, final List<String> varNames) {
if (varNames != null && !varNames.isEmpty()) {
final VarTuple itsVars = (VarTuple) getAttrContext().getVariables();
for (int i = 0; i < vars.getSize(); i++) {
final VarMember var = vars.getVarMemberAt(i);
if (varNames.contains(var.getName())) {
final DeclMember dm = (DeclMember) var.getDeclaration();
if (!itsVars.isDeclared(dm.getTypeName(), dm.getName())) {
itsVars.declare(dm.getHandler(),
dm.getTypeName(), dm.getName());
itsVars.getVarMemberAt(dm.getName()).setTransient(var.isTransient());
itsVars.getVarMemberAt(dm.getName()).setInputParameter(var.isInputParameter());
}
}
}
}
}
public void addToAttrContext(final CondTuple conds) {
final CondTuple itsConds = (CondTuple) getAttrContext().getConditions();
for (int i = 0; i < conds.getSize(); i++) {
final CondMember cond = conds.getCondMemberAt(i);
if (!itsConds.contains(cond.getExprAsText()))
itsConds.addCondition(cond.getExprAsText());
}
}
public void addToAttrContext(final AttrContext ac) {
this.addToAttrContext((VarTuple) ac.getVariables());
this.addToAttrContext((CondTuple) ac.getConditions());
}
public final AttrManager getAttrManager() {
return this.itsAttrManager;
}
// protected synchronized void setChanged()
public synchronized void setChanged() {
if (this.itsInteractiveFlag)
this.itsTouchedFlag = true;
// force initialization of morphism completion when nextCompletion()
// is called.
super.setChanged();
}
public void writeMorphism(XMLHelper h) {
h.openSubTag("Morphism");
h.addAttr("name", this.itsName);
if (!this.comment.equals(""))
h.addAttr("comment", this.comment);
Enumeration<GraphObject> e = getDomain();
while (e.hasMoreElements()) {
GraphObject s = e.nextElement();
h.openSubTag("Mapping");
h.addObject("orig", s, false);
h.addObject("image", getImage(s), false);
h.close();
}
h.close();
}
public void readMorphism(XMLHelper h) {
if (h.readSubTag("Morphism")) {
String str = h.readAttr("name");
setName(str.replaceAll(" ", ""));
// setName(h.readAttr("name"));
str = h.readAttr("comment");
if (!str.equals(""))
this.comment = str.toString();
Hashtable<GraphObject, GraphObject> map = new Hashtable<GraphObject, GraphObject>();
while (h.readSubTag("Mapping")) {
GraphObject o = (GraphObject) h.getObject("orig", null, false);
GraphObject i = (GraphObject) h.getObject("image", null, false);
if (o != null && i != null) {
if (o instanceof Node) {
try {
addMapping(o, i);
} catch (BadMappingException ex) {}
}
else {
map.put(o, i);
}
}
h.close();
}
h.close();
Enumeration<GraphObject> en = map.keys();
while (en.hasMoreElements()) {
GraphObject o = en.nextElement();
GraphObject i = map.get(o);
GraphObject s = ((Arc) o).getSource();
GraphObject t = ((Arc) o).getTarget();
if (o instanceof UndirectedArc) {
if (((((UndirectedArc) i).getSource() == getImage(s))
&& (((UndirectedArc) i).getTarget() == getImage(t)))
|| ((((UndirectedArc) i).getTarget() == getImage(s))
&& (((UndirectedArc) i).getSource() == getImage(t)))) {
try {
addMapping(o, i);
} catch (BadMappingException ex) {}
}
}
else if ((((Arc) i).getSource() == getImage(s))
&& (((Arc) i).getTarget() == getImage(t))) {
try {
addMapping(o, i);
} catch (BadMappingException ex) {}
}
}
}
}
/*
* Create and return a new submorphism. It is automatically added to my set *
* of submorphisms. The new submorphism and its image and * original graphs
* which are newly created are initially empty. *
* <p>
* Note that the newly created image and original subgraphs are not *
* automatically removed when the submorphism itself is destroyed.
*/
// public final OrdinarySubMorphism createSubMorphism()
// {
// OrdinarySubMorphism aSubMorph = new OrdinarySubMorphism(this, this
// .getOriginal().createSubGraph(), this.getImage()
// .createSubGraph());
// itsSubMorphs.add(aSubMorph);
// return aSubMorph;
// }
/*
* Create and return a new submorphism. It is automatically added to my set *
* of submorphisms. The new submorphism's image and original graphs are set *
* to be <code>orig</code> and <code>img</code>, respectively. The
* submorphism * is filled so that it maps all the objects of
* <code>orig</code> in the same * way I do.
* <p>
* <b>Pre:</b>
* <ol> *
* <li> <code>orig</code> is subgraph of <code>this.getOriginal()</code>. *
* <li> <code>img</code> is subgraph of <code>this.getImage()</code>.
* </ol>
*/
// public final OrdinarySubMorphism createSubMorphism(SubGraph orig,
// SubGraph img)
// {
// OrdinarySubMorphism aSubMorph = new OrdinarySubMorphism(this, orig, img);
//
//// if (itsSubMorphs == null)
//// itsSubMorphs = new Vector<OrdinarySubMorphism>(5, 1);
// itsSubMorphs.add(aSubMorph);
// return aSubMorph;
// }
/*
* Remove a submorphism from my set of submorphisms. *
*
* @return <code>false</code> iff <code>sm</code> was not an element of
* my set of submorphisms.*
*/
// public final boolean destroySubMorphism(OrdinarySubMorphism sm)
// {
// if (itsSubMorphs != null && sm != null) {
// if (itsSubMorphs.removeElement(sm)) {
// sm.dispose();
// return true;
// }
// }
// return false;
// }
// private void destroySubMorphisms() {
// if (itsSubMorphs != null) {
// while (itsSubMorphs.size() > 0) {
// OrdinarySubMorphism sm = itsSubMorphs.get(0);
// itsSubMorphs.remove(sm);
// sm.dispose();
// }
// }
// }
/*
* Return an Enumeration of all of my submorphisms (not including myself).
* Enumeration elements are of type <code>OrdinarySubMorphism</code>.*
*/
// public final Enumeration<OrdinarySubMorphism> getSubMorphisms() {
// if (itsSubMorphs != null)
// return itsSubMorphs.elements();
// else
// return (new Vector<OrdinarySubMorphism>(0)).elements();
// }
// ----------- ADDITIONAL METHODS according to Gabi's new AGG design
// --------------
// -------------------- attention: yet untested! (Aug.1999)
// -----------------------
/** swop domain and range <--->, if possible */
public OrdinaryMorphism invert() {
if (!(this.isInjective())) {
this.errorMsg = "Inverting of non-injective morphism is not possible.";
return (null);
}
final OrdinaryMorphism
inv = (BaseFactory.theFactory()).createMorphism(this.itsImag, this.itsOrig);
final Enumeration<GraphObject> domain = this.itsDomObjects.elements();
while (domain.hasMoreElements()) {
final GraphObject go = domain.nextElement();
try {
inv.addMapping(this.getImage(go), go);
} catch (BadMappingException e) {
this.errorMsg = e.getMessage();
}
}
return (inv);
}
public OrdinaryMorphism simplecopy()
/***************************************************************************
* Unlike "morphcopy(.)" of above, "simplecopy()" * does only return a copy
* of itself without creating copies of its source and target graphs.*
**************************************************************************/
{
final OrdinaryMorphism output = (BaseFactory.theFactory()).createMorphism(
this.itsOrig, this.itsImag);
final Enumeration<GraphObject> mappedObjects = this.itsDomObjects.elements();
while (mappedObjects.hasMoreElements()) {
final GraphObject go = mappedObjects.nextElement();
try {
output.addMapping(go, this.getImage(go));
} catch (BadMappingException ex) {
}
}
return (output);
}
public boolean isIsomorphicTo(final OrdinaryMorphism h)
/*
* Test if morphism h is isomorphic to this morphism.
*/
{
final Enumeration<GraphObject> dom = this.getDomain();
final Vector<GraphObject> hDom = new Vector<GraphObject>();
final Enumeration<GraphObject> hd = h.getDomain();
while (hd.hasMoreElements()) {
hDom.addElement(hd.nextElement());
}
while (dom.hasMoreElements()) {
final GraphObject go = dom.nextElement();
if (hDom.contains(go)) {
if (!this.getImage(go).equals(h.getImage(go))) {
hDom.clear();
return false;
}
hDom.removeElement(go);
} else {
hDom.clear();
return false;
}
}
if (hDom.size() == 0) {
return true;
}
return false;
}
public boolean isIsomorphicTo(final OrdinaryMorphism h, final OrdinaryMorphism targetIso)
/**
* Test if the specified morphism h is isomorphic to this morphism,
* assuming that :
* - this and h are total,
* - this and h have one and the same original graph,
* - the target graph of this is the source graph of targetIso,
* - the target graph of h is the target graph of targetIso,
* - targetIso is an isomorphism.
*/
{
// System.out.println("OrdinaryMorphism.isIsomorphicTo(h, targetIso)
// ...");
if (this.getSource() != h.getSource()) {
System.out
.println("OrdinaryMorphism.isIsomorphicTo:: FAILED:: this and h have different source graphs");
// Thread.dumpStack();
return false;
} else if (h.getTarget() != targetIso.getTarget()) {
System.out
.println("OrdinaryMorphism.isIsomorphicTo:: FAILED:: targetIso and h have different target graphs");
// Thread.dumpStack();
return false;
}
final Iterator<Node> e = this.getSource().getNodesSet().iterator();
while (e.hasNext()) {
GraphObject o = e.next();
GraphObject i1 = targetIso.getImage(this.getImage(o));
GraphObject i2 = h.getImage(o);
if (i1 != i2) {
return false;
}
}
final Iterator<Arc> e1 = this.getSource().getArcsSet().iterator();
while (e1.hasNext()) {
GraphObject o = e1.next();
GraphObject i1 = targetIso.getImage(this.getImage(o));
GraphObject i2 = h.getImage(o);
if (i1 != i2) {
return false;
}
}
// System.out.println("OrdinaryMorphism.isIsomorphicTo .... TRUE ");
return true;
}
/** Return <code>true</code> if this is a partial morphism. */
public boolean isPartial() {
return !isTotal();
}
/**
* Test if this morphism is partial isomorphic to the specified morphism h,
* assuming that they have one and the same original and one and the same image graph.
*/
public boolean isPartialIsomorphicTo(final OrdinaryMorphism h) {
final Enumeration<GraphObject> dom = this.getDomain();
final Vector<GraphObject> hDomain = h.getDomainObjects();
while (dom.hasMoreElements()) {
final GraphObject go = dom.nextElement();
if (hDomain.contains(go)) {
if (!this.getImage(go).equals(h.getImage(go))) {
return (false);
}
else if (go.isArc()) {
if (!this.getImage(((Arc)go).getSource()).equals(h.getImage(((Arc)go).getSource()))
|| !this.getImage(((Arc)go).getTarget()).equals(h.getImage(((Arc)go).getTarget()))) {
return (false);
}
}
}
// else
// return (false);
}
return (true);
}
public boolean isSurjective() {
final Enumeration<GraphObject> nonMapped = nonMappedImages();
if (nonMapped.hasMoreElements())
return (false);
return (true);
}
public boolean isInjective() {
for (int i=0; i<this.itsCodomObjects.size(); i++) {
final GraphObject go = this.itsCodomObjects.get(i);
if (this.getInverseImageList(go).size() > 1)
return false;
}
return true;
}
public boolean isBijective() {
if (isInjective() && isSurjective())
return (true);
return (false);
}
public Enumeration<GraphObject> nonMappedOriginals()
/***************************************************************************
* Returns all graph objects of the original graph * that are not mapped by
* this morphism. Enumeration * elements are of type
* <code>GraphObject</code>.
*
* @see agg.xt_basis.GraphObject.*
**************************************************************************/
{
final Vector<GraphObject> nonMapped = new Vector<GraphObject>();
final Iterator<Node> nodes = this.itsOrig.getNodesSet().iterator();
while (nodes.hasNext()) {
GraphObject go = nodes.next();
if (!this.itsDomObjects.contains(go)) {
nonMapped.addElement(go);
}
}
final Iterator<Arc> arcs = this.itsOrig.getArcsSet().iterator();
while (arcs.hasNext()) {
GraphObject go = arcs.next();
if (!this.itsDomObjects.contains(go)) {
nonMapped.addElement(go);
}
}
return (nonMapped.elements());
}
public Enumeration<GraphObject> nonMappedImages()
/***************************************************************************
* Returns all graph objects of the image graph * that are not used by this
* morphism. Enumeration * elements are of type <code>GraphObject</code>.
*
* @see agg.xt_basis.GraphObject *
**************************************************************************/
{
final Vector<GraphObject> nonMapped = new Vector<GraphObject>();
final Iterator<Node> gos = this.itsImag.getNodesSet().iterator();
while (gos.hasNext()) {
GraphObject go = gos.next();
if (!this.itsCodomObjects.contains(go))
nonMapped.addElement(go);
}
final Iterator<Arc> gos1 = this.itsImag.getArcsSet().iterator();
while (gos1.hasNext()) {
GraphObject go = gos1.next();
if (!this.itsCodomObjects.contains(go))
nonMapped.addElement(go);
}
return (nonMapped.elements());
}
/**
* Constructs the composition of this morphism and the input morphism.<br>
* this.source == output.source, <br>
* this.target == input.source, <br>
* input.target == output.target.<br>
* .
*/
public OrdinaryMorphism compose(final OrdinaryMorphism input){
final OrdinaryMorphism output = (BaseFactory.theFactory()).createMorphism(
this.itsOrig, input.getImage(), true);
final Enumeration<GraphObject> thisDom = this.itsDomObjects.elements();
while (thisDom.hasMoreElements()) {
final GraphObject thisGo = thisDom.nextElement();
final GraphObject thisGoImage = this.getImage(thisGo);
final GraphObject inputGoImage = input.getImage(thisGoImage);
if (inputGoImage != null) {
try {
output.addMapping(thisGo, inputGoImage);
} catch (BadMappingException ex) {
}
}
}
return (output);
}
/**
* Constructs composition of given morphisms morph1 and morph2 morphisms, where <br>
* this.source == morph1.source <br>
* this.target == morph2.target <br>
* morph1.target == morph2.source. <br>
* Returns true, if the source-target
* condition is satisfied, otherwise - false.
*/
public boolean doCompose(final OrdinaryMorphism morph1, final OrdinaryMorphism morph2) {
if (this.itsOrig == morph1.getSource()
&& this.itsImag == morph2.getTarget()) {
final Enumeration<GraphObject> dom = morph1.getDomain();
while (dom.hasMoreElements()) {
final GraphObject obj = dom.nextElement();
final GraphObject im = morph1.getImage(obj);
final GraphObject img = morph2.getImage(im);
if (img != null) {
try {
this.addMapping(obj, img);
} catch (BadMappingException ex) {
System.out.println(ex.getClass()+" "+ex.getMessage());
return false;
}
}
}
return true;
}
return false;
}
public boolean doComposeInherit(final OrdinaryMorphism morph1, final OrdinaryMorphism morph2) {
if (this.itsOrig == morph1.getSource()
&& this.itsImag == morph2.getTarget()) {
final Enumeration<GraphObject> dom = morph1.getDomain();
while (dom.hasMoreElements()) {
final GraphObject obj = dom.nextElement();
final GraphObject img1 = morph1.getImage(obj);
final GraphObject img2 = morph2.getImage(img1);
if (img2 != null) {
try {
if (obj.getType().isParentOf(img2.getType()))
this.addMapping(obj, img2);
else if (obj.getType().isChildOf(img2.getType()))
this.addChild2ParentMapping(obj, img2);
} catch (BadMappingException ex) {
return false;
}
}
}
return true;
}
return false;
}
/**
* Given an input morphism with
* input.getSource() == this.getSource() and <br>
* input.getTarget() == output.getSource() and <br>
* this.getTarget() == output.getTarget(). <br>
* For each key try to complete
* output.addMapping(input.get(key), this.getImage(key)).<br>
* Returns true by success, otherwise true.
*/
public OrdinaryMorphism completeDiagram(final OrdinaryMorphism input) {
if (!input.isInjective()) {
this.errorMsg = "Completting with non-injective morphism is not possible";
return (null);
}
final OrdinaryMorphism compl = (BaseFactory.theFactory()).createMorphism(
input.getImage(), this.itsImag);
final Enumeration<GraphObject> inpDom = input.getDomain();
while (inpDom.hasMoreElements()) {
final GraphObject inpGo = inpDom.nextElement();
final GraphObject inpImg = input.getImage(inpGo);
final GraphObject thisImgGo = this.getImage(inpGo);
try {
compl.addMapping(inpImg, thisImgGo);
} catch (BadMappingException ex) {
(BaseFactory.theFactory()).destroyMorphism(compl);
return null;
}
}
return (compl);
}
/**
* Given d = g o f with f: A->B, g: B->C, d: A->C.
* f and d is known, g is this.
* Try to complete g.
* Returns true by success, otherwise false.
*/
public boolean completeDiagram(final Hashtable<GraphObject,GraphObject> f,
final OrdinaryMorphism d) {
if (f != null && d != null) {
Enumeration<GraphObject> dDom = d.getDomain();
while (dDom.hasMoreElements()) {
final GraphObject go3 = dDom.nextElement();
final GraphObject img3 = d.getImage(go3);
final GraphObject img1 = f.get(go3);
if (img1 != null && img3 != null) {
try {
this.addMapping(img1, img3);
} catch (BadMappingException ex) {
this.clear();
this.errorMsg = "Complete of diagram: d = g o f is not possible (object mapping failed)";
return false;
}
}
}
return true;
} else {
this.errorMsg = "Complete of diagram: d = g o f is not possible (d resp. f is null)";
return false;
}
}
/**
* We have a diagram third = first o second with first: A->B, second: B->C, third: A->C,<br>
* second and third are complete.<br>
* Try to complete first.
* Note, first morphism is this morphism.
* Returns true by success, otherwise false.
*/
public boolean completeDiagram1(
final OrdinaryMorphism second,
final OrdinaryMorphism third) {
if (second != null && third != null) {
// AttrContext context = agg.attribute.impl.AttrTupleManager
// .getDefaultManager().newContext(AttrMapping.PLAIN_MAP);
// this.setAttrContext(context);
final Enumeration<GraphObject> dom = second.getDomain();
while (dom.hasMoreElements()) {
GraphObject go2 = dom.nextElement();
GraphObject img2 = second.getImage(go2);
Enumeration<GraphObject> en = third.getInverseImage(img2);
if (en.hasMoreElements()) {
GraphObject go1 = en.nextElement();
try {
this.addMapping(go1, go2);
} catch (BadMappingException ex) {
this.clear();
this.errorMsg = "Complete of diagram1 is not possible (object mapping failed)";
return false;
}
}
}
return true;
} else {
this.errorMsg = "Complete of diagram1 is not possible (second or third is null)";
return false;
}
}
/**
* We have a diagram third = first o second with first: A->B, second: B->C, third: A->C,<br>
* first and third are complete.<br>
* Try to complete second.
* Note, second morphism is this morphism.
* Returns true by success, otherwise false.
*/
public boolean completeDiagram2(
final OrdinaryMorphism first,
final OrdinaryMorphism third) {
if (first != null && third != null) {
if (!first.isInjective()) {
this.errorMsg = "Complete of diagram2 is not possible (first is non-injective)";
return false;
}
else {
// AttrContext context = agg.attribute.impl.AttrTupleManager
// .getDefaultManager().newContext(AttrMapping.PLAIN_MAP);
// this.setAttrContext(context);
final Enumeration<GraphObject> dom = first.getDomain();
while (dom.hasMoreElements()) {
GraphObject go1 = dom.nextElement();
GraphObject img1 = first.getImage(go1);
GraphObject img3 = third.getImage(go1);
if (img3 != null) {
try {
this.addMapping(img1, img3);
} catch (BadMappingException ex) {
this.clear();
this.errorMsg = "Complete of diagram2 is not possible (object mapping failed)";
return false;
}
}
}
return true;
}
} else {
this.errorMsg = "Complete of diagram2 is not possible (first resp. third is null)";
return false;
}
}
/**
* We have a diagram third = first o second with first: A->B, second: B->C, third: A->C,<br>
* first and second are complete.<br>
* Try to complete third.
* Note, third morphism is this morphism.
* Returns true by success, otherwise false.
*/
public boolean completeDiagram3(
final OrdinaryMorphism first,
final OrdinaryMorphism second) {
if (first != null && second != null) {
if (!first.isInjective()) {
this.errorMsg = "Complete of diagram3 is not possible (first is non-injective)";
return false;
}
else {
// AttrContext context = agg.attribute.impl.AttrTupleManager
// .getDefaultManager().newContext(AttrMapping.PLAIN_MAP);
// this.setAttrContext(context);
final Enumeration<GraphObject> dom = first.getDomain();
while (dom.hasMoreElements()) {
GraphObject go1 = dom.nextElement();
GraphObject img2 = second.getImage(first.getImage(go1));
if (img2 != null) {
try {
this.addMapping(go1, img2);
} catch (BadMappingException ex) {
this.clear();
this.errorMsg = "Complete of diagram3 is not possible (object mapping failed)";
return false;
}
}
}
return true;
}
} else {
this.errorMsg = "Complete of diagram3 is not possible (first resp. second is null)";
return false;
}
}
/**
* Given this = d = g o f with f: A->B, g: B->C, d: A->C.
* d and f are complete.
* Try to complete g.
* Returns true by success, otherwise false.
*/
public boolean completeDiagram(
final OrdinaryMorphism f,
final OrdinaryMorphism g) {
if (f != null && g != null) {
if (!f.isInjective()) {
this.errorMsg = "Complete of diagram: d = g o f is not possible (f is non-injective)";
return false;
} else {
AttrContext context = agg.attribute.impl.AttrTupleManager
.getDefaultManager().newContext(AttrMapping.PLAIN_MAP);
g.setAttrContext(context);
final Enumeration<GraphObject> fDom = f.getDomain();
while (fDom.hasMoreElements()) {
final GraphObject fGO = fDom.nextElement();
final GraphObject img1 = f.getImage(fGO);
final GraphObject img2 = this.getImage(fGO);
if (img1 != null && img2 != null) {
try {
g.addMapping(img1, img2);
} catch (BadMappingException ex) {
g.clear();
this.errorMsg = "Complete of diagram: d = g o f is not possible (object mapping failed)";
return false;
}
}
}
return true;
}
} else {
this.errorMsg = "Complete of diagram: d = g o f is not possible (g resp. f is null)";
return false;
}
}
/**
* The given morphisms h1, v2, v1 are already complete.
* Try to complete this morphism : C -> D so that v2 o h1 = h2 o v1 .
*
* @param v1 : A -> C
* @param h1 : A -> B
* @param v2 : B -> D
*
* @return true if morphism this morphism : C -> D completed, otherwise false
*/
public boolean completeDiagram(final OrdinaryMorphism v1,
final OrdinaryMorphism h1,
final OrdinaryMorphism v2) {
boolean ok = true;
final Enumeration<GraphObject> dom = h1.getDomain();
while (dom.hasMoreElements() && ok) {
GraphObject obj = dom.nextElement();
GraphObject obj1 = v1.getImage(obj);
GraphObject obj2 = v2.getImage(h1.getImage(obj));
if (obj1 != null && obj2 != null) {
try {
this.addMapping(obj1, obj2);
} catch (BadMappingException ex) {
ok = false;
}
}
}
return ok;
}
public Enumeration<GraphObject> intersectCoDomains(final OrdinaryMorphism input)
/***************************************************************************
* Return all graph objects of current codomain that reside * in the
* codomain of the input morphism, too. Enumeration * elements are of type
* <code>GraphObject</code>.
*
* @see agg.xt_basis.GraphObject *
**************************************************************************/
{
final Vector<GraphObject> intersection = new Vector<GraphObject>();
final Enumeration<GraphObject> inpCodom = input.getCodomain();
while (inpCodom.hasMoreElements()) {
final GraphObject g = inpCodom.nextElement();
if (this.itsCodomObjects.contains(g)) {
intersection.addElement(g);
}
}
return (intersection.elements());
}
/**
* Check if the constant value of the same attribute member of the
* original and image graph objects are equal.
*/
public boolean checkConstants() {
if (this.itsDomObjects.isEmpty())
return true;
for (int j=0; j<this.itsDomObjects.size(); j++) {
final GraphObject orig = this.itsDomObjects.get(j);
if (orig.getAttribute() == null)
continue;
final GraphObject image = getImage(orig);
final ValueTuple valOrig = (ValueTuple) orig.getAttribute();
final ValueTuple valImage = (ValueTuple) image.getAttribute();
int n = valOrig.getNumberOfEntries();
for (int i = 0; i < n; i++) {
final String name = valOrig.getNameAsString(i);
ValueMember valMemberOrig = null;
if (valOrig.isValueSetAt(name)) {
valMemberOrig = valOrig.getValueMemberAt(name);
final HandlerExpr exprOrig = valMemberOrig.getExpr();
if ((exprOrig != null) && exprOrig.isConstant()) {
if (valImage.isValueSetAt(name)) {
final ValueMember valMemberImage = valImage
.getValueMemberAt(name);
final HandlerExpr exprImage = valMemberImage.getExpr();
if ((exprImage != null) && exprImage.isConstant()) {
if (!valMemberOrig.toString().equals(
valMemberImage.toString())) {
return false;
}
}
}
}
}
}
}
return true;
}
/**
* Check if the variable of the same attribute member of the original and
* image graph objects are equal.
*/
public boolean checkVariables() {
if (this.itsDomObjects.isEmpty())
return true;
for (int j=0; j<this.itsDomObjects.size(); j++) {
final GraphObject orig = this.itsDomObjects.get(j);
if (orig.getAttribute() == null) {
continue;
}
final GraphObject image = getImage(orig);
final ValueTuple valOrig = (ValueTuple) orig.getAttribute();
final ValueTuple valImage = (ValueTuple) image.getAttribute();
int n = valOrig.getNumberOfEntries();
for (int i = 0; i < n; i++) {
final String name = valOrig.getNameAsString(i);
ValueMember valMemberOrig = null;
if (valOrig.isValueSetAt(name)) {
valMemberOrig = valOrig.getValueMemberAt(name);
final HandlerExpr exprOrig = valMemberOrig.getExpr();
if ((exprOrig != null) && exprOrig.isVariable()) {
if (valImage.isValueSetAt(name)) {
final ValueMember valMemberImage = valImage
.getValueMemberAt(name);
final HandlerExpr exprImage = valMemberImage.getExpr();
if ((exprImage != null) && exprImage.isVariable()) {
if (!valMemberOrig.toString().equals(
valMemberImage.toString())) {
return false;
}
}
}
}
}
}
}
return true;
}
/**
* Check if the setting of the same attribute member
* of the original and image graph objects are equal.
*/
protected boolean checkAll() {
if (this.itsDomObjects.isEmpty()) {
return true;
}
for (int j=0; j<this.itsDomObjects.size(); j++) {
final GraphObject orig = this.itsDomObjects.get(j);
if (orig.getAttribute() == null)
continue;
final GraphObject image = getImage(orig);
final ValueTuple valOrig = (ValueTuple) orig.getAttribute();
final ValueTuple valImage = (ValueTuple) image.getAttribute();
int n = valOrig.getNumberOfEntries();
for (int i = 0; i < n; i++) {
final String name = valOrig.getNameAsString(i);
ValueMember valMemberOrig = null;
if (valOrig.isValueSetAt(name)) {
valMemberOrig = valOrig.getValueMemberAt(name);
if ((valMemberOrig.isSet())) {
if (valImage.isValueSetAt(name)) {
final ValueMember valMemberImage = valImage
.getValueMemberAt(name);
if (valMemberImage != null && valMemberImage.isSet()) {
if (!valMemberOrig.getExprAsText().equals(
valMemberImage.getExprAsText())) {
return false;
}
}
}
}
}
}
}
return true;
}
public void putVarToAttrContext() {
final VarTuple vars = (VarTuple) getAttrContext().getVariables();
putVarToAttrContext(this.itsOrig.getNodesSet().iterator(), vars);
putVarToAttrContext(this.itsOrig.getArcsSet().iterator(), vars);
putVarToAttrContext(this.itsImag.getNodesSet().iterator(), vars);
putVarToAttrContext(this.itsImag.getArcsSet().iterator(), vars);
}
private void putVarToAttrContext(
final Iterator<?> elems,
final VarTuple vars) {
while (elems.hasNext()) {
final GraphObject o = (GraphObject) elems.next();
if (o.getAttribute() == null)
continue;
final ValueTuple val = (ValueTuple) o.getAttribute();
int n = val.getNumberOfEntries();
for (int i = 0; i < n; i++) {
final String name = val.getNameAsString(i);
final ValueMember valMem = val.getValueMemberAt(name);
if (valMem != null && valMem.isSet()) {
if (valMem.getExpr().isVariable()) {
final String varName = valMem.getExprAsText();
if (vars.getVarMemberAt(varName) == null) {
final String varType = valMem.getDeclaration()
.getTypeName();
vars.declare(valMem.getDeclaration().getHandler(),
varType, varName);
}
}
}
}
}
}
/**
* If the value of an attribute member of the original graphobject is unset
* or is a variable, fill up such attribute value with the value (it should
* be a constant value) of the same attribute member of the image
* graphobject.
*/
public void fillUpOriginalAttrs() {
final Enumeration<GraphObject> elems = this.itsDomObjects.elements();
while (elems.hasMoreElements()) {
final GraphObject orig = elems.nextElement();
final GraphObject image = getImage(orig);
if (orig.getAttribute() != null) {
final ValueTuple valOrig = (ValueTuple) orig.getAttribute();
final ValueTuple valImage = (ValueTuple) image.getAttribute();
int n = valOrig.getNumberOfEntries();
for (int i = 0; i < n; i++) {
final String name = valOrig.getNameAsString(i);
ValueMember valMemberOrig = null;
HandlerExpr exprOrig = null;
if (valOrig.isValueSetAt(name)) {
valMemberOrig = valOrig.getValueMemberAt(name);
exprOrig = valMemberOrig.getExpr();
}
if ((exprOrig == null) || !exprOrig.isConstant()) {
if (valImage.isValueSetAt(name)) {
ValueMember valMemberImage = valImage
.getValueMemberAt(name);
HandlerExpr exprImage = valMemberImage.getExpr();
if ((exprImage != null) && exprImage.isConstant()) {
valOrig.setExprValueAt(valMemberImage
.getExprAsText(), name);
(valOrig.getValueMemberAt(name))
.setTransient(true);
valOrig.getValueMemberAt(name).checkValidity();
}
}
}
}
}
}
}
/**
* Iff the value of an attribute member of the image graphobject is unset or
* is a variable, fill up the value of such attribute member with the value
* (it should be a constant value) of the same attribute member of the
* original graphobject.
*/
public void fillUpImageAttrs() {
final Enumeration<GraphObject> elems = this.itsDomObjects.elements();
while (elems.hasMoreElements()) {
final GraphObject orig = elems.nextElement();
final GraphObject image = getImage(orig);
if (orig.getAttribute() != null) {
final ValueTuple valOrig = (ValueTuple) orig.getAttribute();
final ValueTuple valImage = (ValueTuple) image.getAttribute();
int n = valImage.getNumberOfEntries();
for (int i = 0; i < n; i++) {
final String name = valImage.getNameAsString(i);
ValueMember valMemberImage = null;
HandlerExpr exprImage = null;
if (valImage.isValueSetAt(name)) {
valMemberImage = valImage.getValueMemberAt(name);
exprImage = valMemberImage.getExpr();
}
if ((exprImage == null) || !exprImage.isConstant()) {
if (valOrig.isValueSetAt(name)) {
final ValueMember valMemberOrig = valOrig
.getValueMemberAt(name);
final HandlerExpr exprOrig = valMemberOrig.getExpr();
if ((exprOrig != null) && exprOrig.isConstant()) {
valImage.setExprValueAt(valMemberOrig
.getExprAsText(), name);
(valImage.getValueMemberAt(name))
.setTransient(true);
valImage.getValueMemberAt(name).checkValidity();
}
}
}
}
}
}
}
private Vector<GraphObject> findCreatedElements() {
final Vector<GraphObject> vec = new Vector<GraphObject>();
for (Iterator<Node> en = this.itsImag.getNodesSet().iterator(); en.hasNext();) {
final GraphObject o = en.next();
if (!getInverseImage(o).hasMoreElements())
vec.addElement(o);
}
for (Iterator<Arc> en = this.itsImag.getArcsSet().iterator(); en.hasNext();) {
final GraphObject o = en.next();
if (!getInverseImage(o).hasMoreElements())
vec.addElement(o);
}
return vec;
}
private Vector<GraphObject> findDeletedElements() {
final Vector<GraphObject> vec = new Vector<GraphObject>();
for (Iterator<Node> en = this.itsOrig.getNodesSet().iterator(); en.hasNext();) {
final GraphObject o = en.next();
if (getImage(o) == null)
vec.addElement(o);
}
for (Iterator<Arc> en = this.itsOrig.getArcsSet().iterator(); en.hasNext();) {
final GraphObject o = en.next();
if (getImage(o) == null)
vec.addElement(o);
}
return vec;
}
/**
* Iff the value of an attribute member of the original graphobject is an
* expression, unset it.
*/
public void unsetOriginalAttrsIfExpression() {
final Iterator<Node> elems = this.itsOrig.getNodesSet().iterator();
while (elems.hasNext()) {
GraphObject orig = elems.next();
if (orig.getAttribute() == null)
continue;
ValueTuple valOrig = (ValueTuple) orig.getAttribute();
int n = valOrig.getNumberOfEntries();
for (int i = 0; i < n; i++) {
String name = valOrig.getNameAsString(i);
ValueMember valMemberOrig = null;
HandlerExpr exprOrig = null;
if (valOrig.isValueSetAt(name)) {
valMemberOrig = valOrig.getValueMemberAt(name);
if(valMemberOrig != null) {
exprOrig = valMemberOrig.getExpr();
if ((exprOrig != null) && exprOrig.isComplex())
valMemberOrig.setExpr(null);
}
}
}
}
final Iterator<Arc> elems1 = this.itsOrig.getArcsSet().iterator();
while (elems1.hasNext()) {
GraphObject orig = elems1.next();
if (orig.getAttribute() == null)
continue;
ValueTuple valOrig = (ValueTuple) orig.getAttribute();
int n = valOrig.getNumberOfEntries();
for (int i = 0; i < n; i++) {
String name = valOrig.getNameAsString(i);
ValueMember valMemberOrig = null;
HandlerExpr exprOrig = null;
if (valOrig.isValueSetAt(name)) {
valMemberOrig = valOrig.getValueMemberAt(name);
if(valMemberOrig != null) {
exprOrig = valMemberOrig.getExpr();
if ((exprOrig != null) && exprOrig.isComplex())
valMemberOrig.setExpr(null);
}
}
}
}
}
public void fillUpAttrContext(final AttrContext other) {
if ((other == null) || (this.getAttrContext() == null))
return;
// System.out.println(">>>
// OrdinaryMorphism.fillUpAttrContext(AttrContext other) ");
final VarTuple avt = (VarTuple) this.getAttrContext().getVariables();
final VarTuple avtOther = (VarTuple) other.getVariables();
// System.out.println("--> "+avt+" "+avtOther);
// gehe <other> Attrcontext durch und stelle fest
// ob er schon in <this> attrcontext vorhandene Variablen
// mit einem Wert als Konstante hat oder
// eine neue Variable mit einem konstanten Wert,
// und ersetze oder hinzufuege diese Variable.
int nn = avtOther.getNumberOfEntries();
for (int i = 0; i < nn; i++) {
final VarMember avmOther = avtOther.getVarMemberAt(i);
final String name = avtOther.getNameAsString(i);
final VarMember avm = avt.getVarMemberAt(name);
// System.out.println(name+" "+avm+" "+avmOther);
if (avm != null) {
// if(avmOther.isInputParameter())
{
// setze den Wert
if (avmOther.isSet() && avmOther.getExpr().isConstant()) {
avm.setExprAsText(avmOther.getExprAsText());
// System.out.println(name+" "+avm+"\nas copy of:
// "+avmOther);
}
}
}
}
}
public void copyAttrContext(final AttrContext other) {
if ((other == null) || (this.getAttrContext() == null))
return;
final VarTuple avt = (VarTuple) this.itsAttrContext.getVariables();
final VarTuple avtOther = (VarTuple) other.getVariables();
int nn = avtOther.getNumberOfEntries();
for (int i = 0; i < nn; i++) {
final VarMember avmOther = avtOther.getVarMemberAt(i);
final String name = avtOther.getNameAsString(i);
final VarMember avm = avt.getVarMemberAt(name);
// System.out.println(name+" "+avm+" "+avmOther);
if (avm != null) {
// ersetze den Wert von der Variablen
if (avmOther.isSet() && avmOther.getExpr().isConstant()) {
avm.setExprAsText(avmOther.getExprAsText());
// System.out.println(name+" "+avm+"\nas copy of:
// "+avmOther);
}
if (avmOther.isInputParameter())
avm.setInputParameter(true);
}
// fuege eine neue Variable mit/ohne einem Wert hinzu
else {
// System.out.println("add new member");
final DeclMember dm = (DeclMember) avmOther.getDeclaration();
avt.declare(dm.getHandler(), dm.getTypeName(), dm.getName());
final ValueMember newMember = avt.getVarMemberAt(dm.getName());
if ((newMember != null) && (avmOther.getExpr() != null)
&& avmOther.getExpr().isConstant()) {
newMember.setExprAsText(avmOther.getExprAsText());
// System.out.println(name+" "+avm+"\nas copy of:
// "+avmOther);
}
(avt.getVarMemberAt(dm.getName())).setInputParameter(avmOther
.isInputParameter());
(avt.getVarMemberAt(dm.getName())).setTransient(avmOther
.isTransient());
// System.out.println(name+" "+newMember+"\nas copy of:
// "+avmOther);
}
}
}
/*
* Returns a hashtable where the key is an input parameter and the object is
* a vector of pairs. The first pair element is an attribute member and the
* second pair element is appropriate graphobject type.
*/
public Hashtable<VarMember, Vector<Pair<ValueMember, Type>>> getUsageOfInputParameters(
final AttrContext attrContext) {
// AttrContext attrContext = getAttrContext();
final Hashtable<VarMember, Vector<Pair<ValueMember, Type>>>
ht = new Hashtable<VarMember, Vector<Pair<ValueMember, Type>>>();
// if (this instanceof SubRule) {
// System.out.println("OrdinaryMorphism.getUsageOfInputParameters :
// this instance of SubRule");
// attrContext = ((SubRule) this).getSuperRule().getAttrContext();
// }
if (attrContext == null || attrContext.getVariables() == null)
return ht;
final Vector<Type> tmp = new Vector<Type>();
final VarTuple avt = (VarTuple) attrContext.getVariables();
for (int i = 0; i < avt.getSize(); i++) {
final VarMember avm = avt.getVarMemberAt(i);
if (avm.getExpr() == null)
return ht;
// System.out.println(avm+" "+avm.getExpr());
// System.out.println(avm.getDeclaration().getName());
final Vector<Pair<ValueMember, Type>> v = new Vector<Pair<ValueMember, Type>>();
if (avm.isInputParameter()) {
// System.out.println("search source graph");
final Iterator<Node> en = getSource().getNodesSet().iterator();
while (en.hasNext()) {
GraphObject go = en.next();
if (go.getAttribute() == null)
continue;
final ValueTuple vt = (ValueTuple) go.getAttribute();
for (int j = 0; j < vt.getSize(); j++) {
final ValueMember vm = vt.getValueMemberAt(j);
if ((vm.getExpr() != null) && vm.getExpr().isVariable()) {
// System.out.println("value member:
// "+vm.getExprAsText());
// System.out.println("input param :
// "+avm.getDeclaration().getName());
if (vm.getExprAsText().equals(
avm.getDeclaration().getName())) {
v.addElement(new Pair<ValueMember, Type>(vm, go
.getType()));
tmp.addElement(go.getType());
}
}
}
}
final Iterator<Arc> en1 = getSource().getArcsSet().iterator();
while (en1.hasNext()) {
final GraphObject go = en1.next();
if (go.getAttribute() == null)
continue;
final ValueTuple vt = (ValueTuple) go.getAttribute();
for (int j = 0; j < vt.getSize(); j++) {
final ValueMember vm = vt.getValueMemberAt(j);
if ((vm.getExpr() != null) && vm.getExpr().isVariable()) {
// System.out.println("value member:
// "+vm.getExprAsText());
// System.out.println("input param :
// "+avm.getDeclaration().getName());
if (vm.getExprAsText().equals(
avm.getDeclaration().getName())) {
v.addElement(new Pair<ValueMember, Type>(vm, go
.getType()));
tmp.addElement(go.getType());
}
}
}
}
// System.out.println("search target graph");
final Iterator<Node> en2 = getTarget().getNodesSet().iterator();
while (en2.hasNext()) {
final GraphObject go = en2.next();
if (go.getAttribute() == null)
continue;
final ValueTuple vt = (ValueTuple) go.getAttribute();
for (int j = 0; j < vt.getSize(); j++) {
final ValueMember vm = vt.getValueMemberAt(j);
if ((vm.getExpr() != null) && vm.getExpr().isVariable()) {
// System.out.println("value member:
// "+vm.getExprAsText());
// System.out.println("input param :
// "+avm.getDeclaration().getName());
if (vm.getExprAsText().equals(
avm.getDeclaration().getName())) {
// System.out.println(" will be used!");
if (tmp.isEmpty()
|| !tmp.contains(go.getType())) {
v.addElement(new Pair<ValueMember, Type>(
vm, go.getType()));
tmp.addElement(go.getType());
}
}
}
}
}
final Iterator<Arc> en3 = getTarget().getArcsSet().iterator();
while (en3.hasNext()) {
final GraphObject go = en3.next();
if (go.getAttribute() == null)
continue;
final ValueTuple vt = (ValueTuple) go.getAttribute();
for (int j = 0; j < vt.getSize(); j++) {
final ValueMember vm = vt.getValueMemberAt(j);
if ((vm.getExpr() != null) && vm.getExpr().isVariable()) {
// System.out.println("value member:
// "+vm.getExprAsText());
// System.out.println("input param :
// "+avm.getDeclaration().getName());
if (vm.getExprAsText().equals(
avm.getDeclaration().getName())) {
// System.out.println(" will be used!");
if (tmp.isEmpty()
|| !tmp.contains(go.getType())) {
v.addElement(new Pair<ValueMember, Type>(
vm, go.getType()));
tmp.addElement(go.getType());
}
}
}
}
}
if (v.size() != 0)
ht.put(avm, v);
}
}
// System.out.println("Count of input parameters: "+ht.size());
return ht;
}
/**
* Computes an overlapping set of the graphs: - this.source with
* other.source if other instance of OrdinaryMorphism and left is true, or -
* this.target with other.target if other instance of OrdinaryMorphism and
* left is false, or - this.sorce with other if other instance of Graph and
* left is true, or - this.target with other if other instance of Graph and
* left is false, or with respect of the rules if this and other are
* instances of Rule.
*
* @param union
* If true - the overlappings contain disjunion, too. Enumeration
* elements are of type <code>Pair</code>.
* @return A set of overlappings.
*/
public Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings(
final Object other, boolean left, boolean union) {
return MatchHelper.getOverlappingsVector(this, other, left, union).elements();
}
public Vector<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappingsVector(
final Object other,
boolean left,
boolean union) {
return MatchHelper.getOverlappingsVector(this, other, left, union);
}
/**
* Computes an overlapping set of the graphs: - this.source with
* other.source if other instance of OrdinaryMorphism and left is true, or -
* this.target with other.target if other instance of OrdinaryMorphism and
* left is false, or - this.sorce with other if other instance of Graph and
* left is true, or - this.target with other if other instance of Graph and
* left is false, or with respect of the rules if this and other are
* instances of Rule.
*
* @param sizeOfInclusions
* The size of graph object inclusions.
* @param union
* If true - the overlappings contain disjunion, too. Enumeration
* elements are of type <code>Pair</code>.
* @return A set of overlappings.
*/
public Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings(
final Object other, boolean left,
int sizeOfInclusions, boolean union) {
return MatchHelper.getOverlappingsVector(this, other, left, sizeOfInclusions, union).elements();
}
public Vector<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappingsVector(
final Object otherObj,
boolean left,
int sizeOfInclusions,
boolean union) {
return MatchHelper.getOverlappingsVector(this, otherObj, left, sizeOfInclusions, union);
}
public void setCoMorphism(final OrdinaryMorphism aCoMorph) {
this.itsCoMorph = aCoMorph;
}
public OrdinaryMorphism getCoMorphism() {
return this.itsCoMorph;
}
protected void deleteTransientContextVariables(Graph g) {
// System.out.println("OrdinaryMorphism.deleteTransientContextVariables()");
final VarTuple vars = (VarTuple) getAttrContext().getVariables();
delTransientContextVar(g.getNodesSet().iterator(), vars);
delTransientContextVar(g.getArcsSet().iterator(), vars);
}
private void delTransientContextVar(
final Iterator<?> elems,
final VarTuple vars) {
while (elems.hasNext()) {
GraphObject obj = (GraphObject) elems.next();
if (obj.getAttribute() == null)
continue;
ValueTuple value = (ValueTuple) obj.getAttribute();
for (int i = 0; i < value.getNumberOfEntries(); i++) {
ValueMember valuem = value.getValueMemberAt(i);
if (valuem.isTransient()) {
// System.out.println(valuem+" "+valuem.getExprAsText());
if (!vars.isEmpty())
vars.getTupleType().deleteMemberAt(valuem.getExprAsText());
valuem.setExpr(null);
}
}
}
}
public int getSize() {
return this.itsDomObjects.size();
}
public boolean compareTo(OrdinaryMorphism morph) {
String errMsgHolder = null;
if (!getSource().compareTo(morph.getSource())) {
errMsgHolder = errMsgHolder + "LHS is different";
return false;
}
if (!getTarget().compareTo(morph.getTarget())) {
errMsgHolder = errMsgHolder + "RHS is different";
return false;
}
// compare mapping
Enumeration<GraphObject> e = morph.getDomain();
Vector<GraphObject> another = new Vector<GraphObject>();
while (e.hasMoreElements()) {
another.add(e.nextElement());
}
if (this.itsDomObjects.size() != another.size()) {
return false;
}
for (int i = 0; i < this.itsDomObjects.size(); i++) {
GraphObject obj = this.itsDomObjects.elementAt(i);
GraphObject img = this.getImage(obj);
for (int j = another.size() - 1; j >= 0; j--) {
GraphObject obj1 = another.elementAt(j);
if (obj.compareTo(obj1)) {
GraphObject img1 = morph.getImage(obj1);
if (img == null && img1 == null) {
another.remove(obj1);
break;
} else if (img != null && img1 == null) {
} else if (img == null && img1 != null) {
} else if (img != null && img.compareTo(img1)) {
another.remove(obj1);
break;
}
}
}
}
if (another.size() != 0) {
errMsgHolder = errMsgHolder + "Morphism mapping is different";
return false;
}
return true;
}
/**
* Returns a vector with variable declarations used in LHS and RHS of this
* graph morphism. An Element of the vector is a Pair.
*
* @see agg.util.Pair
* The first element is a type, the second
* element is a name of a variable declaration, both elements are of
* the type String.
*/
public Vector<Pair<String, String>> getVariableDeclarations() {
final Vector<Pair<String, String>>
varDecls = new Vector<Pair<String, String>>(2);
// search left graph
putVarDecl(this.itsOrig.getNodesSet().iterator(), varDecls);
putVarDecl(this.itsOrig.getArcsSet().iterator(), varDecls);
// search right graph
// first search values as a variable
putVarDecl(this.itsImag.getNodesSet().iterator(), varDecls);
putVarDecl(this.itsImag.getArcsSet().iterator(), varDecls);
// now search values as a complex expression
putVarOfExpr(this.itsImag.getNodesSet().iterator(), varDecls);
putVarOfExpr(this.itsImag.getArcsSet().iterator(), varDecls);
return varDecls;
}
private void putVarDecl(
final Iterator<?> elems,
final Vector<Pair<String, String>> varDecls) {
while (elems.hasNext()) {
GraphObject o = (GraphObject) elems.next();
if (o.getAttribute() == null)
continue;
AttrInstance attr = o.getAttribute();
ValueTuple vt = (ValueTuple) attr;
for (int k = 0; k < vt.getSize(); k++) {
ValueMember vm = vt.getValueMemberAt(k);
if (vm.isSet() && vm.getExpr().isVariable()) {
String n = vm.getExprAsText();
String t = vm.getDeclaration().getTypeName();
// System.out.println(o.getContext().getName()+" "+n+" "+t);
Pair<String, String> p = new Pair<String, String>(t, n);
boolean found = false;
for (int j = 0; j < varDecls.size(); j++) {
Pair<String, String> pj = varDecls.elementAt(j);
if (t.equals(pj.first) && n.equals(pj.second)) {
found = true;
break;
}
}
if (!found)
varDecls.addElement(p);
}
// else if (vm.isSet() && !vm.getExpr().isVariable()) {
// String n = vm.getExprAsText();
// String t = vm.getDeclaration().getTypeName();
//
// System.out.println(o.getContext().getName()+" "+n+" ### "+t);
// }
}
}
}
private void putVarOfExpr(
final Iterator<?> elems,
final Vector<Pair<String, String>> varDecls) {
while (elems.hasNext()) {
GraphObject o = (GraphObject) elems.next();
if (o.getAttribute() == null)
continue;
AttrInstance attr = o.getAttribute();
ValueTuple vt = (ValueTuple) attr;
for (int k = 0; k < vt.getSize(); k++) {
ValueMember vm = vt.getValueMemberAt(k);
if (vm.isSet() && vm.getExpr().isComplex()) {
Vector<String> vec = vm.getAllVariableNamesOfExpression();
// System.out.println("vec: "+vec);
if (vec.size() != 0) {
for (int l = 0; l < vec.size(); l++) {
Pair<String, String> p = null;
String n = vec.elementAt(l);
String t = "";
VarMember var = getAttrContext().getVariables()
.getVarMemberAt(n);
if ((var != null) && (var.getDeclaration() != null)) {
t = var.getDeclaration().getTypeName();
p = new Pair<String, String>(t, n);
// System.out.println("decl pair: "+p);
} else {
String className = isClassName(n);
if (className != null) {
t = className;
p = new Pair<String, String>(t, n);
// System.out.println("class pair: "+p);
} else {
p = new Pair<String, String>(t, n);
}
}
boolean found = false;
for (int j = 0; j < varDecls.size(); j++) {
Pair<String, String> pj = varDecls
.elementAt(j);
if (t.equals(pj.first)
&& n.equals(pj.second))
found = true;
}
if (!found)
varDecls.addElement(p);
}
}
}
}
}
}
public String isClassName(String name) {
return AttrTupleManager.getDefaultManager().isClassName(name);
}
public Vector<Type> getUsedTypes() {
final Vector<Type> vec = new Vector<Type>();
addUsedType(this.itsOrig.getNodesSet().iterator(), vec);
addUsedType(this.itsOrig.getArcsSet().iterator(), vec);
addUsedType(this.itsImag.getNodesSet().iterator(), vec);
addUsedType(this.itsImag.getArcsSet().iterator(), vec);
return vec;
}
private void addUsedType(final Iterator<?> elems, final Vector<Type> vec) {
while (elems.hasNext()) {
GraphObject o = (GraphObject) elems.next();
if (!vec.contains(o.getType()))
vec.add(o.getType());
}
}
protected final void propagateChange(agg.util.Change ch) {
setChanged();
notifyObservers(ch);
}
/**
* Disables attribute conditions in which a variable inside is not declared.
*/
public void disableUnusedAttrCondition() {
final VarTuple avt = (VarTuple) this.getAttrContext().getVariables();
final CondTuple act = (CondTuple) this.getAttrContext().getConditions();
for (int k = 0; k < act.getSize(); k++) {
final CondMember cm = act.getCondMemberAt(k);
final Vector<String> vars = cm.getAllVariables();
if (!vars.isEmpty()) {
for (int i=0; i<vars.size(); i++) {
final VarMember var = avt.getVarMemberAt(vars.get(i));
if (var == null) {
cm.setEnabled(false);
break;
}
}
}
}
}
public void enableUnusedAttrCondition() {
final VarTuple avt = (VarTuple) this.getAttrContext().getVariables();
final CondTuple act = (CondTuple) this.getAttrContext().getConditions();
for (int k = 0; k < act.getSize(); k++) {
final CondMember cm = act.getCondMemberAt(k);
final Vector<String> vars = cm.getAllVariables();
if (!vars.isEmpty()) {
for (int i=0; i<vars.size(); i++) {
final VarMember var = avt.getVarMemberAt(vars.get(i));
if (var == null) {
cm.setEnabled(true);
break;
}
}
}
}
}
public void removeUnusedVariableOfAttrContext() {
VarTuple vars = (VarTuple) this.getAttrContext().getVariables();
for (int i=0; i<vars.getNumberOfEntries(); i++) {
VarMember vm = vars.getVarMemberAt(i);
String var = vm.getName();
if (!this.getSource().getVariableNamesOfAttributes().contains(var)) {
if (!this.getTarget().getVariableNamesOfAttributes().contains(var)) {
vars.getTupleType().deleteMemberAt(var);
// System.out.println("Rule.removeVariableOfAttrContext:: removed: "+var);
}
}
}
}
protected boolean tryToApplyAttrExpr(final Hashtable<String, String> valMembeHashcode2Expr) {
return tryComputeAttrExpr(this.getSource().getNodesSet().iterator(),
valMembeHashcode2Expr)
&&
tryComputeAttrExpr(this.getSource().getArcsSet().iterator(),
valMembeHashcode2Expr);
}
private boolean tryComputeAttrExpr(
final Iterator<?> elems,
final Hashtable<String, String> valMemberHashcode2Expr) {
// ((VarTuple)ac.getVariables()).showVariables();
// final VarTuple vars = ((VarTuple)this.getAttrContext().getVariables());
// final CondTuple conds = (CondTuple)this.getAttrContext().getConditions();
while (elems.hasNext()) {
final GraphObject go = (GraphObject) elems.next();
if (go.getAttribute() != null) {
final ValueTuple val = (ValueTuple) go.getAttribute();
for (int i=0; i<val.getNumberOfEntries(); i++) {
ValueMember mem = val.getValueMemberAt(i);
if (mem.isSet() && mem.getExpr().isComplex()) {
boolean applied = false;
String expr = mem.getExprAsText();
valMemberHashcode2Expr.put(String.valueOf(mem.hashCode()), expr);
try {
// System.out.println("tryComputeAttrExprOfNode::: "+expr);
mem.getExpr().evaluate(this.getAttrContext());
applied = true;
} catch (AttrHandlerException ex) {}
if (!applied) {
return false;
}
}
}
}
}
return true;
}
protected void resetAttrValueAsExpr(final Hashtable<String, String> valMembeHashcoder2Expr) {
resetAttrValueAsExpr(this.getSource().getNodesSet().iterator(), valMembeHashcoder2Expr);
resetAttrValueAsExpr(this.getSource().getArcsSet().iterator(), valMembeHashcoder2Expr);
}
private void resetAttrValueAsExpr(final Iterator<?> elems,
final Hashtable<String, String> valMembeHashcoder2Expr) {
final VarTuple vars = ((VarTuple)this.getAttrContext().getVariables());
final CondTuple conds = (CondTuple)this.getAttrContext().getConditions();
while (elems.hasNext()) {
final GraphObject go = (GraphObject) elems.next();
if (go.getAttribute() != null) {
final ValueTuple val = (ValueTuple) go.getAttribute();
for (int i=0; i<val.getNumberOfEntries(); i++) {
ValueMember mem = val.getValueMemberAt(i);
String expr = valMembeHashcoder2Expr.get(String.valueOf(mem.hashCode()));
if (expr != null) {
// System.out.println(mem.getExprAsText());
mem.setExprAsText(expr);
// System.out.println(mem.getExprAsText());
for (int j=0; j<conds.getSize(); j++) {
CondMember cond = (CondMember) conds.getMemberAt(j);
if (cond.getExprAsText().endsWith("=".concat(expr))
&& cond.isTransient()
&& (cond.getMark() == CondMember.NAC || cond.getMark() == CondMember.PAC)) {
String nameStr = cond.getName();
conds.getTupleType().deleteMemberAt(j);
vars.getTupleType().deleteMemberAt(nameStr);
}
}
}
}
}
}
// vars.showVariables();
// conds.showConditions();
}
/**
* Trims the capacity of used vectors to be the vector's current
* size.
*/
public void trimToSize() {
this.itsOrig.trimToSize();
this.itsImag.trimToSize();
this.itsDomObjects.trimToSize();
this.itsDomObjects.trimToSize();
}
}