package agg.xt_basis;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;
import java.util.Hashtable;
import java.util.List;
import agg.attribute.AttrContext;
import agg.attribute.AttrInstance;
import agg.attribute.AttrManager;
import agg.attribute.AttrMapping;
import agg.attribute.impl.AttrTupleManager;
import agg.attribute.impl.ValueTuple;
import agg.attribute.impl.ValueMember;
import agg.attribute.impl.VarTuple;
import agg.attribute.impl.VarMember;
import agg.attribute.impl.ContextView;
import agg.util.Change;
import agg.util.CopyMemory;
import agg.util.ExtObservable;
import agg.util.LinkedGOHashSet;
import agg.util.Pair;
import agg.util.XMLHelper;
import agg.util.XMLObject;
import agg.xt_basis.csp.CompletionPropertyBits;
/**
* This class extends simple graphs with the possibility
* to have arcs between nodes.
*
* @version $Id: Graph.java,v 1.145 2010/11/16 23:34:19 olga Exp $
* @author $Author: olga $
*/
// * Class Graph is capable of passing the following change informations
// * as an argument to its observers' <code>update()</code> methods:
// * Graph_Change_ObjectCreated, Graph_Change_ObjectDestroyed,
// * Graph_Change_ObjectModified.
// * Additionally, <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 graph.
// * @see agg.xt_basis.Graph_Change_ObjectCreated
// * @see agg.xt_basis.Graph_Change_ObjectDestroyed
// * @see agg.xt_basis.Graph_Change_ObjectModified
// * @see agg.util.Change_ObservableGone
public class Graph extends ExtObservable
implements Observer, XMLObject
{
// test: node XY-position as attribute
public boolean xyAttr = false;
protected Vector<Observer> observer;
protected LinkedGOHashSet<Node> itsNodes;
protected LinkedGOHashSet<Arc> itsArcs;
protected Hashtable<String, HashSet<GraphObject>> itsTypeObjectsMap;
protected Vector<OrdinaryMorphism> itsUsingMorphs;
protected String kind;
protected String itsName;
protected String comment;
protected String info;
protected AttrContext itsAttrContext;
boolean notificationRequired;
protected boolean attributed;
protected boolean changed;
/* object for creating and checking types and holding the type graph */
protected TypeSet itsTypes;
/* true for a host graph, false - otherwise */
protected boolean completeGraph;
/**
* Creates an empty graph with an empty TypeSet.
*
* Use {@link #Graph(boolean)}, to create a complete graph
* (a host graph).
*/
public Graph() {
this.itsTypes = new TypeSet();
init();
}
/**
* Creates an empty graph with the specified TypeSet.
*
* Use {@link #Graph(TypeSet,boolean)}, to create a complete
* graph (a host graph).
*/
public Graph(TypeSet aTypeSet) {
this.itsTypes = aTypeSet;
init();
}
/**
* Creates an empty graph with an empty TypeSet.
*
* @param completeGraph
* true, to create a host graph
*/
public Graph(boolean completeGraph) {
this.itsTypes = new TypeSet();
this.completeGraph = completeGraph;
init();
}
/**
* Creates an empty graph with the specified TypeSet.
*
* @param aTypeSet
* the TypeSet to use
* @param completeGraph
* true, to create a host graph
*/
public Graph(TypeSet aTypeSet, boolean completeGraph) {
this.itsTypes = aTypeSet;
this.completeGraph = completeGraph;
init();
}
private void init() {
observer = new Vector<Observer>();
itsNodes = new LinkedGOHashSet<Node>();
itsArcs = new LinkedGOHashSet<Arc>();
itsTypeObjectsMap = new Hashtable<String, HashSet<GraphObject>>();
itsUsingMorphs = new Vector<OrdinaryMorphism>();
kind = GraphKind.GRAPH;
comment = "";
itsName = "Graph";
info = "";
}
/**
* @see java.util.Observable#addObserver(java.util.Observer)
*/
public synchronized void addObserver(Observer o) {
if (!this.observer.contains(o)) {
this.observer.add(o);
this.notificationRequired = true;
super.addObserver(o);
}
}
/**
* @see java.util.Observable#deleteObserver(java.util.Observer)
*/
public synchronized void deleteObserver(Observer o) {
if (this.observer.contains(o)) {
this.observer.remove(o);
super.deleteObserver(o);
if(this.observer.isEmpty())
this.notificationRequired = false;
}
}
public List<Observer> getObservers() {
return this.observer;
}
public void setObservers(List<?> o) {
if (o == null)
return;
for (int i = 0; i < o.size(); i++) {
this.addObserver((Observer) o.get(i));
}
}
/**
* A kind is a role of a graph in a grammar,
* for exmpl.: a type graph - TG, a host graph - HOST,
* the left graph of a rule - LHS, the right graph of a rule - RHS,
* a NAC graph - NAC, a PAC graph - PAC and so on.
*
* @see agg.xt_basis.GraphKind
*
* @return the kind of this graph
*/
public String getKind() {
return this.kind;
}
/**
* A kind is a role of a graph in a grammar,
* for exmpl.: a type graph - TG, a host graph - HOST,
* the left graph of a rule - LHS, the right graph of a rule - RHS,
* a NAC graph - NAC, a PAC graph - PAC and so on.
*
* @see agg.xt_basis.GraphKind
*/
public void setKind(final String aKind) {
this.kind = aKind;
}
public void setNotificationRequired(boolean b) {
this.notificationRequired = b;
}
public boolean isNotificationRequired() {
return this.notificationRequired;
}
public boolean hasChanged() {
return this.changed;
}
/**
* Set the given type set to its type set.
* @param types
* a type set which contains all types already used in this
* graph. This won't be checked.
*/
public void setTypeSet(TypeSet types) {
this.itsTypes = types;
}
/**
* Returns its type set.
*/
public TypeSet getTypeSet() {
return this.itsTypes;
}
/**
* Tries to add a copy of the specified graph to my elements.
* The existing type graph should be disabled.
*
* @param g
* @return true if a copy was added, otherwise - false.
*/
public boolean addCopyOfGraph(Graph g, boolean disabledTypeGraph) {
synchronized (this) {
if (!disabledTypeGraph
|| this.itsTypes.getLevelOfTypeGraphCheck() == TypeSet.DISABLED) {
boolean failed = false;
final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(g
.getSize());
Iterator<Node> vtxList = g.getNodesSet().iterator();
while (vtxList.hasNext()) {
Node vtxOrig = vtxList.next();
Node vtxCopy = null;
Type type = this.itsTypes.getSimilarType(vtxOrig.getType());
if (type == null) {
type = this.itsTypes.getTypeByName(vtxOrig.getType()
.getName());
if (type != null && !type.isNodeType())
type = null;
}
try {
if (type != null) {
vtxCopy = this.createNode(type);
vtxCopy.setObjectName(vtxOrig.getObjectName());
vtxCopy.copyAttributes(vtxOrig);
vtxCopy.setContextUsage(vtxOrig
.getContextUsage());
memo1.put(vtxOrig, vtxCopy);
propagateChange(new Change(
Change.OBJECT_CREATED, vtxCopy));
}
} catch (TypeException e) {
}
}
Iterator<Arc> arcList = g.getArcsSet().iterator();
while (arcList.hasNext()) {
Arc arcOrig = arcList.next();
Arc arcCopy = null;
Type type = this.itsTypes.getSimilarType(arcOrig.getType());
if (type == null) {
type = this.itsTypes.getTypeByName(arcOrig.getType()
.getName());
if (type != null && !type.isArcType())
type = null;
}
try {
if (type != null) {
Node source = (Node) arcOrig.getSource();
Node target = (Node) arcOrig.getTarget();
Node srcImg = memo1.get(source);
Node tgtImg = memo1.get(target);
arcCopy = this.createArc(type, srcImg, tgtImg);
arcCopy.setObjectName(arcOrig.getObjectName());
arcCopy.copyAttributes(arcOrig);
arcCopy.setContextUsage(arcOrig
.getContextUsage());
propagateChange(new Change(
Change.OBJECT_CREATED, arcCopy));
}
} catch (TypeException e) {}
}
memo1.clear();
if (!failed)
return true;
}
}
return false;
}
@SuppressWarnings("unused")
private boolean integrateCopyOfGraph(Graph g) {
synchronized (this) {
if (this.itsTypes.getLevelOfTypeGraphCheck() == TypeSet.DISABLED) {
boolean failed = false;
final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(g
.getSize());
Iterator<Node> vtxList = g.getNodesSet().iterator();
while (vtxList.hasNext()) {
Node vtxOrig = vtxList.next();
Node vtxCopy = null;
Type type = this.itsTypes.getSimilarType(vtxOrig.getType());
if (type == null) {
type = this.itsTypes.getTypeByName(vtxOrig.getType()
.getName());
if (type != null && !type.isNodeType())
type = null;
}
try {
if (type != null) {
boolean found = false;
String keystr = type.convertToKey();
HashSet<GraphObject> objSet = this.itsTypeObjectsMap.get(keystr);
if (objSet != null) {
Iterator<GraphObject> iter = objSet.iterator();
while (iter.hasNext()) {
GraphObject o = iter.next();
if (vtxOrig.compareTo(o)) {
found = true;
memo1.put(vtxOrig, (Node)o);
}
}
}
if (!found) {
vtxCopy = this.createNode(type);
vtxCopy.setObjectName(vtxOrig.getObjectName());
vtxCopy.copyAttributes(vtxOrig);
vtxCopy.setContextUsage(vtxOrig
.getContextUsage());
memo1.put(vtxOrig, vtxCopy);
propagateChange(new Change(
Change.OBJECT_CREATED, vtxCopy));
}
}
} catch (TypeException e) {
}
}
Iterator<Arc> arcList = g.getArcsSet().iterator();
while (arcList.hasNext()) {
Arc arcOrig = arcList.next();
Type type = this.itsTypes.getSimilarType(arcOrig.getType());
if (type == null) {
type = this.itsTypes.getTypeByName(arcOrig.getType()
.getName());
if (type != null && !type.isArcType())
type = null;
}
try {
if (type != null) {
Node source = (Node) arcOrig.getSource();
Node target = (Node) arcOrig.getTarget();
Node src = memo1.get(source);
Node tar = memo1.get(target);
boolean found = false;
String keystr = src.convertToKey()
+ arcOrig.getType().convertToKey()
+ tar.convertToKey();
HashSet<GraphObject> objSet = this.itsTypeObjectsMap.get(keystr);
if (objSet != null) {
Iterator<GraphObject> iter = objSet.iterator();
while (iter.hasNext()) {
GraphObject o = iter.next();
if (arcOrig.compareTo(o)) {
found = true;
}
}
}
if (!found) {
Arc arcCopy = this.createArc(type, src, tar);
arcCopy.setObjectName(arcOrig.getObjectName());
arcCopy.copyAttributes(arcOrig);
arcCopy.setContextUsage(arcOrig
.getContextUsage());
propagateChange(new Change(
Change.OBJECT_CREATED, arcCopy));
}
}
} catch (TypeException e) {}
}
memo1.clear();
if (!failed)
return true;
}
}
return false;
}
public Graph copyLight(TypeSet typeSet) {
synchronized (this) {
TypeError typeError = null;
int tglevel = typeSet.getLevelOfTypeGraphCheck();
if (tglevel == TypeSet.ENABLED_MAX_MIN)
typeSet.setLevelOfTypeGraphCheck(TypeSet.ENABLED_MAX);
boolean failed = false;
final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(this
.getSize());
Graph theCopy = BaseFactory.theFactory().createGraph(typeSet);
theCopy.setCompleteGraph(this.isCompleteGraph());
if ((this.getAttrContext() != null)
&& ((ContextView) this.getAttrContext())
.getAllowedMapping() == AttrMapping.GRAPH_MAP) {
agg.attribute.AttrContext aGraphContext = agg.attribute.impl.AttrTupleManager
.getDefaultManager().newContext(
agg.attribute.AttrMapping.GRAPH_MAP);
theCopy.setAttrContext(agg.attribute.impl.AttrTupleManager
.getDefaultManager().newRightContext(aGraphContext));
}
Iterator<?> iter = this.itsNodes.iterator();
while (iter.hasNext()) {
Node vtxOrig = (Node)iter.next();
Node vtxCopy = null;
Type type = typeSet.getSimilarType(vtxOrig.getType());
if (type == null) {
type = typeSet.getTypeByName(vtxOrig.getType().getName());
if (type != null && !type.isNodeType())
type = null;
}
if (type != null) {
try {
vtxCopy = theCopy.createNode(type);
/** side effect! */
if (vtxCopy != null) {
// check this graph against the type graph
typeError = typeSet.checkType(vtxCopy, this
.isCompleteGraph());
if (typeError != null) {
theCopy.dispose();
throw new TypeException(typeError);
}
vtxCopy.setObjectName(vtxOrig.getObjectName());
if (vtxOrig.getAttribute() != null) {
if (vtxCopy.getAttribute() == null) {
vtxCopy.createAttributeInstance();
}
((ValueTuple) vtxCopy.getAttribute())
.copyEntriesToSimilarMembers(vtxOrig
.getAttribute());
}
vtxCopy.setContextUsage(vtxOrig
.getContextUsage());
memo1.put(vtxOrig, vtxCopy);
}
} catch (TypeException e) {
// e.printStackTrace();
failed = true;
theCopy.dispose();
}
}
}
iter = this.itsArcs.iterator();
while (!failed && iter.hasNext()){
Arc arcOrig = (Arc)iter.next();
Arc arcCopy = null;
Type type = typeSet.getSimilarType(arcOrig.getType());
if (type == null) {
type = typeSet.getTypeByName(arcOrig.getType()
.getName());
if (type != null && !type.isArcType())
type = null;
}
if (type != null) {
try {
Node source = (Node) arcOrig.getSource();
Node target = (Node) arcOrig.getTarget();
Node srcImg = memo1.get(source);
Node tgtImg = memo1.get(target);
arcCopy = theCopy.createArc(type, srcImg, tgtImg);
if (arcCopy != null) {
arcCopy.setObjectName(arcOrig.getObjectName());
if (arcOrig.getAttribute() != null) {
if (arcCopy.getAttribute() == null) {
arcCopy.createAttributeInstance();
}
((ValueTuple) arcCopy.getAttribute())
.copyEntriesToSimilarMembers(arcOrig
.getAttribute());
}
arcCopy.setContextUsage(arcOrig
.getContextUsage());
}
} catch (TypeException e) {
// e.printStackTrace();
failed = true;
theCopy.dispose();
}
}
}
if (!failed) {
if (tglevel == TypeSet.ENABLED_MAX_MIN)
typeSet.setLevelOfTypeGraphCheck(TypeSet.ENABLED_MAX_MIN);
}
memo1.clear();
if (failed)
return null;
return (theCopy);
}
}
/**
* Returns a copy of this graph using specified type set.
* The specified type set should be compatible to its type set.
*/
public Graph copy(TypeSet types) {
return graphcopy(types);
}
private Graph graphcopy(final TypeSet typeSet) {
synchronized (this) {
TypeError typeError = null;
int tglevel = typeSet.getLevelOfTypeGraphCheck();
if (tglevel == TypeSet.ENABLED_MAX_MIN)
typeSet.setLevelOfTypeGraphCheck(TypeSet.ENABLED_MAX);
boolean failed = false;
final Hashtable<Node, Node>
memo1 = new Hashtable<Node, Node>(this.getSize());
Graph theCopy = BaseFactory.theFactory().createGraph(typeSet);
theCopy.setCompleteGraph(this.isCompleteGraph());
if ((this.getAttrContext() != null)
&& ((ContextView) this.getAttrContext())
.getAllowedMapping() == AttrMapping.GRAPH_MAP) {
agg.attribute.AttrContext aGraphContext = agg.attribute.impl.AttrTupleManager
.getDefaultManager().newContext(
agg.attribute.AttrMapping.GRAPH_MAP);
theCopy.setAttrContext(agg.attribute.impl.AttrTupleManager
.getDefaultManager().newRightContext(aGraphContext));
}
Iterator<?> iter = this.itsNodes.iterator();
while (!failed && iter.hasNext()) {
Node vtxOrig = (Node)iter.next();
Node vtxCopy = null;
try {
Type type = typeSet.getSimilarType(vtxOrig.getType());
if (type != null) {
vtxCopy = theCopy.createNode(type);
/** side effect! */
if (vtxCopy != null) {
// not a type graph, so check this graph
// against the type graph
typeError = typeSet.checkType(vtxCopy, this
.isCompleteGraph());
if (typeError != null) {
theCopy.dispose();
throw new TypeException(typeError);
}
vtxCopy.setObjectName(vtxOrig.getObjectName());
vtxCopy.copyAttributes(vtxOrig);
vtxCopy.setContextUsage(vtxOrig.getContextUsage());
memo1.put(vtxOrig, vtxCopy);
propagateChange(new Change(Change.OBJECT_CREATED,
vtxCopy));
}
}
} catch (TypeException e) {
// If this graph is checked, the copy should also be ok
// so no Exception should happen.
// e.printStackTrace();
failed = true;
theCopy.dispose();
}
/***************************************************************
* At loop termination, the memory hashtable contains *
* information about the node twins that are induced * by the
* copyprocess. At this point, the copied graph contains its
* nodes but yet no arcs.*
**************************************************************/
}
iter = this.itsArcs.iterator();
while (!failed && iter.hasNext()) {
Arc arcOrig = (Arc)iter.next();
Arc arcCopy = null;
try {
Type type = typeSet.getSimilarType(arcOrig.getType());
if (type != null) {
Node source = (Node) arcOrig.getSource();
Node target = (Node) arcOrig.getTarget();
Node srcImg = memo1.get(source);
Node tgtImg = memo1.get(target);
arcCopy = theCopy.createArc(type, srcImg, tgtImg);
if (arcCopy != null) {
// not a type graph, so check this graph
// against the type graph
// typeError = typeSet.checkType(arcCopy, this
// .isCompleteGraph());
// if (typeError != null) {
// theCopy.dispose();
// throw new TypeException(typeError);
// }
arcCopy.setObjectName(arcOrig.getObjectName());
arcCopy.copyAttributes(arcOrig);
arcCopy.setContextUsage(arcOrig.getContextUsage());
// propagateChange(new
// Change(Change.OBJECT_CREATED,arcCopy));
}
}
} catch (TypeException e) {
// If the given graph is well typed,
// the resulting graph should be also well typed
// e.printStackTrace();
failed = true;
theCopy.dispose();
}
}
if (!failed) {
if (tglevel == TypeSet.ENABLED_MAX_MIN)
typeSet.setLevelOfTypeGraphCheck(TypeSet.ENABLED_MAX_MIN);
// set Observers ???
// for(Iterator it = getObservers().iterator();
// it.hasNext();)
// theCopy.addObserver((Observer)it.next());
}
memo1.clear();
if (failed)
return null;
return (theCopy);
}
}
/**
* Returns a copy of this graph
*
* @param orig2copy
* the specified table is used to store pairs (original, copy),
* where an original is a node/edge of this graph and a copy
* is the appropriate node/edge of the graph copy.
* @return a copy of this graph or null if an error occurred
*/
public Graph copy(final Hashtable<GraphObject, GraphObject> orig2copy) {
return graphcopy(orig2copy);
}
/**
* Makes a copy of this graph and stores elements into the specified Hashtable.
*
* @param orig2copy
* the table is used to store the relation of this graph to the copy.
* Keys are nodes resp. edges of this graph and values are the corresponding
* nodes resp. edges of the copy.
* @return a copy of this graph or null if an error occurred
*/
private Graph graphcopy(final Hashtable<GraphObject, GraphObject> orig2copy) {
synchronized (this) {
int currentLevelOfTGcheck = this.getTypeSet().getLevelOfTypeGraphCheck();
if (currentLevelOfTGcheck == TypeSet.ENABLED_MAX_MIN)
this.getTypeSet().setLevelOfTypeGraph(TypeSet.ENABLED_MAX);
boolean failed = false;
Graph theCopy = BaseFactory.theFactory().createGraph(getTypeSet());
if ((this.getAttrContext() != null)
&& ((ContextView) this.getAttrContext())
.getAllowedMapping() == AttrMapping.GRAPH_MAP) {
agg.attribute.AttrContext aGraphContext = agg.attribute.impl.AttrTupleManager
.getDefaultManager().newContext(
agg.attribute.AttrMapping.GRAPH_MAP);
theCopy.setAttrContext(agg.attribute.impl.AttrTupleManager
.getDefaultManager().newRightContext(aGraphContext));
}
Iterator<?> iter = this.itsNodes.iterator();
while (!failed && iter.hasNext()) {
Node vtxOrig = (Node)iter.next();
Node vtxCopy = null;
try {
vtxCopy = theCopy.copyNode(vtxOrig);
/** side effect! */
vtxCopy.setContextUsage(vtxOrig.getContextUsage());
orig2copy.put(vtxOrig, vtxCopy);
} catch (TypeException e) {
// e.printStackTrace();
failed = true;
theCopy.dispose();
}
}
iter = this.itsArcs.iterator();
while (!failed && iter.hasNext()) {
Arc arcOrig = (Arc)iter.next();
Node source = (Node) arcOrig.getSource();
Node target = (Node) arcOrig.getTarget();
Node srcImg = (Node) orig2copy.get(source);
Node tgtImg = (Node) orig2copy.get(target);
try {
Arc arcCopy = theCopy.copyArc(arcOrig, srcImg, tgtImg);
arcCopy.setContextUsage(arcOrig.getContextUsage());
orig2copy.put(arcOrig, arcCopy);
} catch (TypeException e) {
// e.printStackTrace();
failed = true;
theCopy.dispose();
}
}
if (currentLevelOfTGcheck == TypeSet.ENABLED_MAX_MIN)
this.getTypeSet().setLevelOfTypeGraph(currentLevelOfTGcheck);
if (!failed) {
// set Observers ???
// for(Iterator it = getObservers().iterator();
// it.hasNext();)
// theCopy.addObserver((Observer)it.next());
return theCopy;
}
return null;
}
}
/**
* Returns a copy of the graph itself. The mappings of
* original nodes / arcs and copied nodes / arcs are stored in a Hashtable
* of the class <code>CopyMemory</code>. The method
* <code>CopyMemory.REQUEST(n)</code> returns an appropriate Hashtable.
*
* @param n
* can be 1 or 2.
*/
public Graph graphcopy(int n) {
synchronized (this) {
int currentLevelOfTGcheck = this.getTypeSet().getLevelOfTypeGraphCheck();
if (currentLevelOfTGcheck == TypeSet.ENABLED_MAX_MIN)
this.getTypeSet().setLevelOfTypeGraph(TypeSet.ENABLED_MAX);
boolean failed = false;
CopyMemory.INSTALL(n);
Graph theCopy = BaseFactory.theFactory().createGraph(getTypeSet());
if ((this.getAttrContext() != null)
&& ((ContextView) this.getAttrContext())
.getAllowedMapping() == AttrMapping.GRAPH_MAP) {
agg.attribute.AttrContext aGraphContext = agg.attribute.impl.AttrTupleManager
.getDefaultManager().newContext(
agg.attribute.AttrMapping.GRAPH_MAP);
theCopy.setAttrContext(agg.attribute.impl.AttrTupleManager
.getDefaultManager().newRightContext(aGraphContext));
}
theCopy.setCompleteGraph(this.isCompleteGraph());
theCopy.setName(this.getName() + "_copy");
Iterator<?> iter = this.itsNodes.iterator();
while (!failed && iter.hasNext()) {
Node vtxOrig = (Node)iter.next();
Node vtxCopy = null;
try {
vtxCopy = theCopy.newNode(vtxOrig.getType());
vtxCopy.setObjectName(vtxOrig.getObjectName());
vtxCopy.copyAttributes(vtxOrig);
vtxCopy.setContextUsage(vtxOrig.getContextUsage());
CopyMemory.STORE(vtxOrig, vtxCopy, n);
} catch (TypeException e) {
failed = true;
theCopy.dispose();
}
}
iter = this.itsArcs.iterator();
while (!failed && iter.hasNext()) {
Arc arcOrig = (Arc)iter.next();
try {
Node source = (Node) arcOrig.getSource();
Node target = (Node) arcOrig.getTarget();
Node srcImg = (Node) CopyMemory.SELECT(source, n);
Node tgtImg = (Node) CopyMemory.SELECT(target, n);
Arc arcCopy = theCopy.newArc(arcOrig.getType(), srcImg,
tgtImg);
if (arcCopy != null) {
arcCopy.setObjectName(arcOrig.getObjectName());
arcCopy.copyAttributes(arcOrig);
arcCopy.setContextUsage(arcOrig.getContextUsage());
CopyMemory.STORE(arcOrig, arcCopy, n);
}
} catch (TypeException e) {
failed = true;
theCopy.dispose();
}
}
if (currentLevelOfTGcheck == TypeSet.ENABLED_MAX_MIN)
this.getTypeSet().setLevelOfTypeGraph(currentLevelOfTGcheck);
if (failed)
return null;
return theCopy;
}
}
/**
* The method returns a copy of the graph itself.
*/
public Graph graphcopy() {
synchronized (this) {
int currentLevelOfTGcheck = this.getTypeSet().getLevelOfTypeGraphCheck();
if (currentLevelOfTGcheck == TypeSet.ENABLED_MAX_MIN)
this.getTypeSet().setLevelOfTypeGraph(TypeSet.ENABLED_MAX);
boolean failed = false;
Graph theCopy = BaseFactory.theFactory().createGraph(this.itsTypes);
if ((this.getAttrContext() != null)
&& ((ContextView) this.getAttrContext())
.getAllowedMapping() == AttrMapping.GRAPH_MAP) {
agg.attribute.AttrContext aGraphContext = agg.attribute.impl.AttrTupleManager
.getDefaultManager().newContext(
agg.attribute.AttrMapping.GRAPH_MAP);
theCopy.setAttrContext(agg.attribute.impl.AttrTupleManager
.getDefaultManager().newRightContext(aGraphContext));
}
theCopy.setCompleteGraph(this.isCompleteGraph());
theCopy.setName(this.getName() + "_copy");
final Hashtable<Node, Node>
memo1 = new Hashtable<Node, Node>(this.getSize());
Iterator<?> iter = this.itsNodes.iterator();
while (!failed && iter.hasNext()) {
Node vtxOrig = (Node)iter.next();
Node vtxCopy = null;
try {
vtxCopy = theCopy.newNode(vtxOrig.getType());
vtxCopy.setObjectName(vtxOrig.getObjectName());
vtxCopy.copyAttributes(vtxOrig);
vtxCopy.setContextUsage(vtxOrig.getContextUsage());
memo1.put(vtxOrig, vtxCopy);
} catch (TypeException e) {
failed = true;
theCopy.dispose();
}
}
iter = this.itsArcs.iterator();
while (!failed && iter.hasNext()) {
Arc arcOrig = (Arc)iter.next();
try {
Node source = (Node) arcOrig.getSource();
Node target = (Node) arcOrig.getTarget();
Node srcImg = memo1.get(source);
Node tgtImg = memo1.get(target);
Arc arcCopy = theCopy.newArc(arcOrig.getType(), srcImg,
tgtImg);
if (arcCopy != null) {
arcCopy.setObjectName(arcOrig.getObjectName());
arcCopy.copyAttributes(arcOrig);
arcCopy.setContextUsage(arcOrig.getContextUsage());
}
} catch (TypeException e) {
failed = true;
theCopy.dispose();
}
}
memo1.clear();
if (currentLevelOfTGcheck == TypeSet.ENABLED_MAX_MIN)
this.getTypeSet().setLevelOfTypeGraph(currentLevelOfTGcheck);
return failed ? null : theCopy;
}
}
/**
* Returns a flat copy (without references) of this graph.
*/
public Graph copy() {
return graphcopy();
}
/**
* Copy the specified Graph g into this graph.<br>
* Pre-condition: this graph has to be empty and has to use the same type
* set as the Graph g .
*/
public Graph graphcopy(Graph g) {
synchronized (g) {
int currentLevelOfTGcheck = this.getTypeSet().getLevelOfTypeGraphCheck();
if (currentLevelOfTGcheck == TypeSet.ENABLED_MAX_MIN)
this.getTypeSet().setLevelOfTypeGraph(TypeSet.ENABLED_MAX);
boolean failed = false;
final Hashtable<Node, Node>
memo1 = new Hashtable<Node, Node>(g.getSize());
Graph theCopy = this;
if ((g.getAttrContext() != null)
&& ((ContextView) g.getAttrContext()).getAllowedMapping() == AttrMapping.GRAPH_MAP) {
agg.attribute.AttrContext aGraphContext = agg.attribute.impl.AttrTupleManager
.getDefaultManager().newContext(
agg.attribute.AttrMapping.GRAPH_MAP);
theCopy.setAttrContext(agg.attribute.impl.AttrTupleManager
.getDefaultManager().newRightContext(aGraphContext));
}
Iterator<Node> vtxList = g.getNodesSet().iterator();
while (!failed && vtxList.hasNext()) {
Node vtxOrig = vtxList.next();
Node vtxCopy = null;
try {
vtxCopy = theCopy.copyNode(vtxOrig);
vtxCopy.setContextUsage(vtxOrig.getContextUsage());
memo1.put(vtxOrig, vtxCopy);
} catch (TypeException e) {
failed = true;
}
}
Iterator<Arc> arcList = g.getArcsSet().iterator();
while (!failed && arcList.hasNext()) {
try {
Arc arcOrig = arcList.next();
Node source = (Node) arcOrig.getSource();
Node target = (Node) arcOrig.getTarget();
Node srcImg = memo1.get(source);
Node tgtImg = memo1.get(target);
Arc arcCopy = theCopy.copyArc(arcOrig, srcImg, tgtImg);
if (arcCopy != null)
arcCopy.setContextUsage(arcOrig.getContextUsage());
} catch (TypeException e) {
failed = true;
}
}
memo1.clear();
if (currentLevelOfTGcheck == TypeSet.ENABLED_MAX_MIN)
this.getTypeSet().setLevelOfTypeGraph(currentLevelOfTGcheck);
if (failed)
theCopy.clear();
return theCopy;
}
}
// public OrdinaryMorphism extendByGraph(final Graph g) {
// final OrdinaryMorphism map = BaseFactory.theFactory().createMorphism(g, this);
// Enumeration<Node> nodes = g.getNodes();
// while (nodes.hasMoreElements()) {
// Node elem= nodes.nextElement();
// try {
// Node copy = this.copyNode(elem);
//// System.out.println("Graph.extendByGraph:: Node copy: "+copy+" orig: "+elem);
//// if (copy != null) {
// map.addMapping(elem, copy);
//// }
//// else {
//// System.out.println("Graph.extendByGraph:: Node copy: "+copy+" orig: "+elem);
//// }
// }
// catch (TypeException ex) {}
// catch (BadMappingException e) {}
// }
// Enumeration<Arc> arcs = g.getArcs();
// while (arcs.hasMoreElements()) {
// Arc elem = arcs.nextElement();
// try {
// Node s = (Node) map.getImage(elem.getSource());
// Node t = (Node) map.getImage(elem.getTarget());
// Arc copy = this.copyArc(elem, s, t);
//// if (copy != null) {
// map.addMapping(elem, copy);
//// }
//// else {
//// System.out.println("Graph.extendByGraph:: Arc copy : "+copy+" src: "+s+" tar: "+t);
//// System.out.println("Graph.extendByGraph:: Arc original: "+elem+" src: "+elem.getSource()+" tar: "+elem.getTarget());
//// }
// }
// catch (TypeException ex) {}
// catch (BadMappingException e) {}
// }
// return map;
// }
/**
* Prepares this graph for garbage collection, so cut all connections to
* other objects and dispose all graph object contained.
* @throws ClassNotFoundException
*/
public void dispose() {
if (this.observer != null) {
this.observer.clear();
this.observer.trimToSize();
super.dispose(); // dispose observer
}
this.itsName = "Graph";
if (this.itsUsingMorphs != null) {
this.itsUsingMorphs.clear();
this.itsUsingMorphs.trimToSize();
}
destroyArcs();
destroyNodes();
this.itsNodes = null;
this.itsArcs = null;
this.itsAttrContext = null;
this.itsTypes = null;
this.changed = false;
// System.out.println("Graph.dispose() DONE "+this.hashCode());
}
public void finalize() {
}
private void destroyNodes() {
if (this.itsNodes != null) {
Iterator<Node> iter = this.itsNodes.iterator();
while (iter.hasNext()) {
this.destroyNodeFast(iter.next());
iter = this.itsNodes.iterator();
}
}
}
private void destroyArcs() {
if (this.itsArcs != null) {
Iterator<Arc> iter = this.itsArcs.iterator();
while (iter.hasNext()) {
this.destroyArcFast(iter.next());
iter = this.itsArcs.iterator();
}
}
}
public final void update(Observable obs, Object change) {
}
public final void setName(String n) {
this.itsName = n;
}
public final String getName() {
return this.itsName;
}
/**
* The user of AGG APIs can set help info for his own purposes.
* He takes care of usage and unset this help info, too.
*
* @param str help info
*/
public void setHelpInfo(String str) {
this.info = str;
}
public String getHelpInfo() {
return this.info;
}
public String getHelpInfoAboutVariableEquality() {
if (this.info.indexOf(":VariableEquality:") != -1) {
final String[] array = this.info.split(":VariableEquality:");
if (array.length == 1)
return array[0];
else if (array.length == 2)
return array[1];
}
return "";
}
public String getHelpInfoAboutPAC() {
if (this.info.indexOf(":VariableEquality:") != -1) {
final String[] array = this.info.split(":VariableEquality:");
if (array.length == 2) {
if (array[0].indexOf("PAC") != -1)
return array[0].replaceFirst("PAC:", "");
}
} else if (this.info.indexOf("PAC") != -1) {
return this.info.replaceFirst("PAC:", "");
}
return "";
}
public String getHelpInfoAboutNAC() {
if (this.info.indexOf(":VariableEquality:") != -1) {
final String[] array = this.info.split(":VariableEquality:");
if (array.length == 2) {
if (array[0].indexOf("NAC:") != -1)
return array[0].replaceFirst("NAC:", "");
}
} else if (this.info.indexOf("NAC:") != -1) {
return this.info.replaceFirst("NAC:", "");
}
return "";
}
/** Set textual comments (description) of this graph.
* This description can be used in AGG GUI.
*/
public void setTextualComment(String text) {
this.comment = text;
}
/** Return textual comments of this graph. */
public String getTextualComment() {
return this.comment;
}
/**
* @deprecated moved to {@link TypeSet}
* @see agg.xt_basis.Type
*/
public final Enumeration<Type> getTypes() {
return this.itsTypes.getTypes();
}
public Vector<Type> getUsedTypes() {
final Vector<Type> vec = new Vector<Type>();
getTypesOfGOs(this.itsNodes.iterator(), vec);
getTypesOfGOs(this.itsArcs.iterator(), vec);
vec.trimToSize();
return vec;
}
private void getTypesOfGOs(final Iterator<?> iter, final Vector<Type> result) {
while (iter.hasNext()) {
GraphObject o = (GraphObject)iter.next();
if (!result.contains(o.getType()))
result.add(o.getType());
}
}
public Vector<Type> getUsedAndInheritedTypes() {
final Vector<Type> vec = new Vector<Type>();
Iterator<?> iter = this.itsNodes.iterator();
while (iter.hasNext()) {
GraphObject o = (GraphObject)iter.next();
Type t = o.getType();
if (!vec.contains(t))
vec.add(t);
Vector<Type> pars = t.getAllParents();
for (int i = 0; i < pars.size(); i++) {
Type pt = pars.get(i);
if (!vec.contains(pt))
vec.add(pt);
}
}
iter = this.itsArcs.iterator();
while (iter.hasNext()) {
GraphObject o = (GraphObject)iter.next();
Type t = o.getType();
if (!vec.contains(t))
vec.add(t);
}
vec.trimToSize();
return vec;
}
/**
* Adds the specified node to my nodes. The type of the specified node has
* to be in my type set.
*/
public void addNode(Node n) {
if (!this.itsNodes.contains(n))
{
this.itsNodes.add(n);
addToTypeObjectsMap(n);
// if (n.getAttribute() != null) {
// ((ValueTuple) n.getAttribute()).addObserver(n);
// }
this.attributed = this.attributed || n.getAttribute() != null;
this.changed = true;
}
}
protected void removeNode(final Node n) {
if (n.getContext() == this) {
for (int i = 0; i < this.itsUsingMorphs.size(); i++) {
this.itsUsingMorphs.get(i).removeMapping(n);
}
Iterator<Arc> anIter = n.getIncomingArcsSet().iterator();
while (anIter.hasNext()) {
Arc aNeighbor = anIter.next();
removeArc(aNeighbor);
anIter = n.getIncomingArcsSet().iterator();
}
anIter = n.getOutgoingArcsSet().iterator();
while (anIter.hasNext()) {
Arc aNeighbor = anIter.next();
removeArc(aNeighbor);
anIter = n.getOutgoingArcsSet().iterator();
}
this.itsNodes.remove(n);
removeNodeFromTypeObjectsMap(n);
this.changed = true;
}
}
/**
* Adds the specified edge to my edges. The type of the specified edge has
* to be in my type set.
*/
public void addArc(Arc anArc) {
if (!this.itsArcs.contains(anArc)) {
this.itsArcs.add(anArc);
addToTypeObjectsMap(anArc);
this.attributed = this.attributed || anArc.getAttribute() != null;
this.changed = true;
}
}
protected void removeArc(final Arc a) {
if (a.getContext() == this) {
// remove arc from its source / target
((Node)a.getSource()).removeOut(a);
((Node)a.getTarget()).removeIn(a);
for (int i = 0; i < this.itsUsingMorphs.size(); i++) {
this.itsUsingMorphs.get(i).removeMapping(a);
}
this.itsArcs.remove(a);
removeArcFromTypeObjectsMap(a);
this.changed = true;
}
}
/**
* Creates and adds a new node.
*/
protected Node newNode(Type t) throws TypeException {
Node aNode = new Node(t, this);
// check for type mismatches, also multiplicity max
TypeError typeError = this.itsTypes.checkType(aNode, this.isCompleteGraph());
if (typeError != null) {
throw new TypeException(typeError);
}
this.attributed = this.attributed || aNode.getAttribute() != null;
this.itsNodes.add(aNode);
addToTypeObjectsMap(aNode);
this.changed = true;
propagateChange(new Change(Change.OBJECT_CREATED, aNode));
return aNode;
}
protected Node newNodeFast(Type t) {
Node aNode = new Node(t, this);
this.attributed = this.attributed || aNode.getAttribute() != null;
this.itsNodes.add(aNode);
addToTypeObjectsMap(aNode);
this.changed = true;
propagateChange(new Change(Change.OBJECT_CREATED, aNode));
return aNode;
}
/** Creates and adds a new Node of the specified type.
* */
public Node createNode(Type type) throws TypeException {
Type t = this.itsTypes.adoptClan(type);
Node aNode = new Node(t, this);
// check for type mismatches
TypeError typeError = this.itsTypes.checkType(aNode, this.isCompleteGraph());
if (typeError != null) {
throw new TypeException(typeError);
}
this.attributed = this.attributed || aNode.getAttribute() != null;
this.itsNodes.add(aNode);
addToTypeObjectsMap(aNode);
this.changed = true;
propagateChange(new Change(Change.OBJECT_CREATED, aNode));
return aNode;
}
/**
* @deprecated use the method <code>copyNode(Node orig)</code>
*/
public Node createNode(Node orig) throws TypeException {
Node aNode = createNode(orig.getType());
if (aNode != null) {
if (orig.getAttribute() != null) {
((ValueTuple) aNode.getAttribute()).copyEntries(orig
.getAttribute());
}
}
return aNode;
}
/**
* Creates a new node as a copy of the specified <code>orig</code>.
* Only type and attributes are copied,
* the structural context (incoming/outgoing arcs) - is not.
*/
public Node copyNode(Node orig) throws TypeException {
try {
Node node = createNode(orig.getType());
if (node != null) {
node.setObjectName(orig.getObjectName());
if (orig.getAttribute() != null) {
node.createAttributeInstance();
((ValueTuple) node.getAttribute()).
copyEntries(orig.getAttribute());
}
} else {
throw new TypeException("Graph.copyNode:: Cannot create a Node of type : "
+orig.getType().getStringRepr());
}
return node;
} catch (TypeException ex) {
throw new TypeException("Graph.copyNode:: "+ex.getLocalizedMessage());
}
}
/**
* Deletes a Node. Dangling arcs are deleted implicitly. The node is
* removed from this graph and from all morphism mappings using this
* node.
*
* @throws TypeException
* If this graph is a type graph, and there are nodes of this
* type node in one of other graphs, an exception is thrown.
*/
public void destroyNode(Node node) throws TypeException {
destroyNode(node, true);
}
/**
* Deletes a Node. Dangling arcs are deleted implicitly. The node is
* removed from this graph and from all morphism mappings using this
* node.
*
* If the specified parameter checkFirst is false,
* the arc is destroyed without any checks.
*
* @throws TypeException
* If this graph is a type graph, and there are nodes of this
* type node in one of other graphs, an exception is thrown.
*/
public synchronized void destroyNode(Node node, boolean checkFirst)
throws TypeException {
destroyNode(node, checkFirst, false);
}
/**
* Deletes a Node. Dangling arcs are deleted implicitly. The node is
* removed from this graph and from all morphism mappings using this
* node.
*
* If the specified parameter checkFirst is false,
* the arc is destroyed without any checks.
*
* @throws TypeException
* If this graph is a type graph, and there are nodes of this
* type node in one of other graphs, an exception is thrown when
* forceDestroy is false, otherwise - does thrown any exception.
*/
public synchronized void destroyNode(final Node node, boolean checkFirst,
boolean forceDestroy) throws TypeException {
// can we remove this node?
// check for multiplicity
if (checkFirst && this.isCompleteGraph()
&& !forceDestroy) {
TypeError typeError = this.itsTypes.checkIfRemovable(node);
if (typeError != null) {
typeError.setContainingGraph(this);
throw new TypeException(typeError);
}
}
// remove mapping of node
for (int i = 0; i < this.itsUsingMorphs.size(); i++) {
OrdinaryMorphism morph = this.itsUsingMorphs.get(i);
morph.removeMapping(node);
}
// destroy incoming/outgoing arcs
Arc a;
Iterator<Arc> iter = node.getIncomingArcsSet().iterator();
while (iter.hasNext()) {
a = iter.next();
destroyArc(a, false, false);
iter = node.getIncomingArcsSet().iterator();
}
iter = node.getOutgoingArcsSet().iterator();
while (iter.hasNext()) {
a = iter.next();
destroyArc(a, false, false);
iter = node.getOutgoingArcsSet().iterator();
}
propagateChange(new Change(Change.WANT_DESTROY_OBJECT, node));
removeNodeFromTypeObjectsMap(node);
this.itsNodes.remove(node);
node.dispose();
this.changed = true;
propagateChange(new Change(Change.OBJECT_DESTROYED, node));
}
public synchronized void destroyNodeFast(final Node node) {
// remove mapping of node
for (int i = 0; i < this.itsUsingMorphs.size(); i++) {
this.itsUsingMorphs.get(i).removeMapping(node);
}
// destroy incoming arcs
while (node.getIncomingArcsSet().iterator().hasNext()) {
destroyArcFast(node.getIncomingArcsSet().iterator().next());
}
// destroy outgoing arcs
while (node.getOutgoingArcsSet().iterator().hasNext()) {
destroyArcFast(node.getOutgoingArcsSet().iterator().next());
}
propagateChange(new Change(Change.WANT_DESTROY_OBJECT, node));
removeNodeFromTypeObjectsMap(node);
this.itsNodes.remove(node);
node.dispose();
this.changed = true;
propagateChange(new Change(Change.OBJECT_DESTROYED, node));
}
/**
* Creates and adds a new arc.
*/
protected Arc newArc(Type t, Node src, Node tar) throws TypeException {
TypeError typeError = this.checkConnectValid(t, src, tar);
if (typeError != null) {
throw new TypeException(typeError);
}
Arc anArc = new Arc(t, src, tar, this);
anArc.setDirected(!(this instanceof UndirectedGraph));
// check for type mismatches, also multiplicity max of source and target
typeError = this.itsTypes.checkType(anArc, this.isCompleteGraph());
if (typeError != null) {
((Node)anArc.getSource()).removeOut(anArc);
((Node)anArc.getTarget()).removeIn(anArc);
throw new TypeException(typeError);
}
this.attributed = this.attributed || anArc.getAttribute() != null;
this.itsArcs.add(anArc);
addToTypeObjectsMap(anArc);
this.changed = true;
propagateChange(new Change(Change.OBJECT_CREATED, anArc));
return anArc;
}
protected Arc newArcFast(Type t, Node src, Node tar) {
// long time = System.nanoTime();
Arc anArc = new Arc(t, src, tar, this);
anArc.setDirected(!(this instanceof UndirectedGraph));
this.attributed = this.attributed || anArc.getAttribute() != null;
this.itsArcs.add(anArc);
addToTypeObjectsMap(anArc);
this.changed = true;
propagateChange(new Change(Change.OBJECT_CREATED, anArc));
// System.out.println("Arc created in: "+(System.nanoTime()-time)+"nano");
return anArc;
}
/**
* Creates and add a new Arc of the specified type, source and target nodes,
* which must be part of this graph.
*/
public Arc createArc(Type type, Node src, Node tar) throws TypeException {
if (src == null || tar == null) {
throw new TypeException("Graph.createArc:: Cannot create an Arc of type : "+type.getStringRepr()+" Source or target node is null!");
} else if (!this.isNode(src) || !this.isNode(tar)) {
throw new TypeException("Graph.createArc:: Cannot create an Arc of type : "+type.getStringRepr()+" Source or target is not a Node!");
}
Type t = null;
if (this.itsTypes.containsType(type))
t = type;
if (t == null) {
t = this.itsTypes.getSimilarType(type);
if (t == null)
t = this.itsTypes.addType(type);
if (t.getAdditionalRepr().indexOf("[EDGE]") == -1)
t.setAdditionalRepr("[EDGE]");
}
TypeError typeError = this.checkConnectValid(t, src, tar);
if (typeError != null) {
throw new TypeException(typeError);
}
Arc anArc = new Arc(t, src, tar, this);
anArc.setDirected(!(this instanceof UndirectedGraph));
// if this is not a type graph, so check this graph
// against its type graph
typeError = this.itsTypes.checkType(anArc, this.isCompleteGraph());
if (typeError != null) {
((Node)anArc.getSource()).removeOut(anArc);
((Node)anArc.getTarget()).removeIn(anArc);
throw new TypeException(typeError);
}
this.attributed = this.attributed || anArc.getAttribute() != null;
this.itsArcs.add(anArc);
addToTypeObjectsMap(anArc);
this.changed = true;
propagateChange(new Change(Change.OBJECT_CREATED, anArc));
return anArc;
}
/**
* Creates a new Arc as a copy of the <code>orig</code>.
* Only its type and attributes are copied,
* the structural context (source, target) - is not.
* The specified source <code>src</code> and target <code>tar</code> objects
* must be a part of this graph, but this is not checked here.
*/
public Arc copyArc(final Arc orig, final Node src, final Node tar) throws TypeException {
Arc arc = null;
try {
arc = createArc(orig.getType(), src, tar);
if (arc != null) {
arc.setDirected(!(this instanceof UndirectedGraph));
arc.setObjectName(orig.getObjectName());
if (orig.getAttribute() != null) {
arc.createAttributeInstance();
((ValueTuple) arc.getAttribute()).copyEntries(orig
.getAttribute());
}
} else {
throw new TypeException("Graph.copyArc:: Cannot create an Arc of type : "
+orig.getType().getName());
}
} catch (TypeException ex) {
if (src != null && tar != null) {
throw new TypeException(" "
+orig.getType().getName()
+" from "+src.getType().getName()
+" to "+tar.getType().getName()
+" "+ex.getLocalizedMessage());
}
throw new TypeException(ex.getLocalizedMessage());
}
return arc;
}
/**
* Deletes the specified arc. The arc will be removed from this graph and
* from all morphism mappings with this arc.
*
* @throws TypeException
* If this graph is a type graph, and there are arcs of this
* type arc in one of other graphs, an exception is thrown.
*/
public void destroyArc(Arc arc) throws TypeException {
destroyArc(arc, true, false);
}
/**
* Deletes the specified arc. The arc will be removed from this graph and
* from all morphism mappings with this arc.
*
* If the specified parameter checkFirst is false,
* the arc is destroyed without any checks.
*
* @throws TypeException
* If this graph is a type graph, and there are arcs of this
* type arc in one of other graphs, an exception is thrown.
*/
public synchronized void destroyArc(Arc arc, boolean checkFirst)
throws TypeException {
destroyArc(arc, checkFirst, false);
}
/**
* Deletes the specified arc. The arc will be removed from this graph and
* from all morphism mappings with this arc.
*
* If the specified parameter checkFirst is false,
* the arc is destroyed without any checks.
*
* @throws TypeException
* If this graph is a type graph, and there are arcs of this
* type arc in one of other graphs, an exception is thrown when
* forceDestroy is false, otherwise - does thrown any exception.
*/
public synchronized void destroyArc(
final Arc arc,
final boolean checkFirst,
final boolean forceDestroy) throws TypeException {
if (arc != null) {
// can we remove this arc?
// check for multiplicity
if (checkFirst
&& this.isCompleteGraph()
&& !forceDestroy) {
TypeError typeError = this.itsTypes.checkIfRemovable(arc);
if (typeError != null) {
typeError.setContainingGraph(this);
throw new TypeException(typeError);
}
}
propagateChange(new Change(Change.WANT_DESTROY_OBJECT, arc));
// remove mapping of arc
for (int i = 0; i < this.itsUsingMorphs.size(); i++) {
OrdinaryMorphism morph = this.itsUsingMorphs.get(i);
morph.removeMapping(arc);
}
removeArcFromTypeObjectsMap(arc);
this.itsArcs.remove(arc);
arc.dispose();
this.changed = true;
propagateChange(new Change(Change.OBJECT_DESTROYED, arc));
}
}
public synchronized void destroyArcFast(final Arc arc) {
propagateChange(new Change(Change.WANT_DESTROY_OBJECT, arc));
// remove mapping of arc
for (int i = 0; i < this.itsUsingMorphs.size(); i++) {
this.itsUsingMorphs.get(i).removeMapping(arc);
}
removeArcFromTypeObjectsMap(arc);
// long t0 = System.nanoTime();
this.itsArcs.remove(arc);
// System.out.println(this.itsArcs.size()+") "+(System.nanoTime()-t0)+" nano");
arc.dispose();
this.changed = true;
propagateChange(new Change(Change.OBJECT_DESTROYED, arc));
}
public void destroyObject(GraphObject obj) throws TypeException {
if (obj.isNode()) {
destroyNode((Node) obj, true, false);
} else if (obj.isArc()) {
destroyArc((Arc) obj, true, false);
}
}
public void forceDestroyObject(GraphObject obj) throws TypeException {
if (obj.isNode()) {
destroyNode((Node) obj, true, true);
} else if (obj.isArc()) {
destroyArc((Arc) obj, true, true);
}
}
public boolean destroyObjectsOfType(Type t) {
boolean done = false;
Iterator<?> iter = this.itsArcs.iterator();
while (iter.hasNext()) {
Arc o = (Arc)iter.next();
if (o.getType().compareTo(t)) {
try {
destroyArc(o, false, true);
done = true;
} catch (TypeException e) {
System.out.println("Graph.destroyObjectsOfType FAILED! "
+ e.getMessage());
}
}
}
if (done)
return true;
iter = this.itsNodes.iterator();
while (iter.hasNext()) {
Node o = (Node)iter.next();
if (t.isParentOf(o.getType())) {
try {
destroyNode(o, false, true);
done = true;
} catch (TypeException e) {
System.out.println("Graph.destroyObjectsOfType FAILED! "
+ e.getMessage());
}
}
}
return done;
}
/**
*
* @param types
* @return null if destroy was successful, otherwise a list with failed types
*/
public Vector<String> destroyObjectsOfTypes(Vector<Type> types) {
Vector<String> failed = null;
for (int i = 0; i < types.size(); i++) {
Type t = types.get(i);
if (!destroyObjectsOfType(t)) {
if (failed == null)
failed = new Vector<String>(5);
failed.add("Graph: ".concat(this.itsName).concat(" Type: ").concat(t.getName()));
}
}
return failed;
}
public HashSet<Node> getNodesSet() {
return this.itsNodes;
}
public Collection<Node> getNodesCollection() {
return this.itsNodes;
}
/**
* @deprecated replaced by <code>HashSet<Node> getNodesSet()</code>
*/
public Enumeration<Node> getNodes() {
return this.itsNodes.elements();
}
/**
* @deprecated replaced by <code>HashSet<Node> getNodesSet()</code>
*/
public List<Node> getNodesList() {
return this.itsNodes.list();
}
public int getNodesCount() {
return this.itsNodes.size();
}
public HashSet<Arc> getArcsSet() {
return this.itsArcs;
}
public Collection<Arc> getArcsCollection() {
return this.itsArcs;
}
/**
* @deprecated replaced by <code>HashSet<Arc> getArcsSet()</code>
*/
public Enumeration<Arc> getArcs() {
return this.itsArcs.elements();
}
/**
* @deprecated replaced by <code>HashSet<Arc> getArcsSet()</code>
*/
public List<Arc> getArcsList() {
return this.itsArcs.list();
}
public int getArcsCount() {
return this.itsArcs.size();
}
/**
* Returns edges between specified source and target objects, otherwise null.
*/
public Vector<Arc> getArcs(final GraphObject src, final GraphObject tar) {
Vector<Arc> res = null;
Iterator<Arc> outs = ((Node)src).getOutgoingArcsSet().iterator();
while (outs.hasNext()) {
Arc go = outs.next();
if (go.getTarget() == tar) {
if (res == null)
res = new Vector<Arc>();
res.add(go);
}
}
return res;
}
/**
* Returns nodes of the specified type, otherwise null.
*/
public List<Node> getNodes(final Type t) {
Vector<Node> res = null;
Iterator<Node> iter = this.itsNodes.iterator();
while (iter.hasNext()) {
Node go = iter.next();
if (t.isParentOf(go.getType())) {
if (res == null)
res = new Vector<Node>();
res.add(go);
}
}
return res;
}
/**
* Iterate through my nodes to find related nodes of the specified type.
*/
public Vector<Node> getNodesByParentType(final Type t) {
Vector<Node> res = null;
Iterator<Node> iter = this.itsNodes.iterator();
while (iter.hasNext()) {
Node go = iter.next();
if (t.isParentOf(go.getType())) {
if (res == null)
res = new Vector<Node>();
res.add(go);
}
}
return res;
}
/**
* Iterate through my nodes to find nodes with type equal to the specified type.
* Otherwise returns null.
*/
public Vector<Node> getNodesByCompareType(final Type t) {
Vector<Node> res = null;
Iterator<Node> iter = this.itsNodes.iterator();
while (iter.hasNext()) {
Node go = iter.next();
if (go.getType().compareTo(t)) {
if (res == null)
res = new Vector<Node>();
res.add(go);
}
}
return res;
}
/**
* Iterate through my edges to find edges of the specified type between the
* specified source and target. Otherwise returns null.
*/
public Vector<Arc> getArcs(final Type t, final GraphObject src, final GraphObject tar) {
Vector<Arc> res = null;
Iterator<Arc> outs = ((Node)src).getOutgoingArcsSet().iterator();
while (outs.hasNext()) {
Arc go = outs.next();
if ( (go.getTarget() == tar)
&& go.getType().compareTo(t)
//&& go.getType().isRelatedTo(t)
) {
if (res == null)
res = new Vector<Arc>();
res.add(go);
}
}
return res;
}
/**
* Iterate through my edges to find edges of the specified type.
* Otherwise returns null.
*/
public Vector<Arc> getArcs(final Type type) {
Vector<Arc> res = null;
Iterator<Arc> iter = this.itsArcs.iterator();
while (iter.hasNext()){
Arc obj = iter.next();
if(obj.getType().compareTo(type)) {
if (res == null)
res = new Vector<Arc>();
res.add(obj);
}
}
return res;
}
/**
* Returns type names of nodes and edges of this graph.
* If a type is unnamed, returns "[UNNAMED_NODE]" or "[UNNAMED_EDGE]".
* The order of the type names is the order of the node
* and edges of this graph.
*/
public Vector<String> getTypeNamesOfGraphObjects() {
final Vector<String> v = new Vector<String>(getSize());
getTypeNamesOfGOs(this.itsNodes.iterator(), v);
getTypeNamesOfGOs(this.itsArcs.iterator(), v);
return v;
}
private void getTypeNamesOfGOs(final Iterator<?> iter, final Vector<String> result) {
while (iter.hasNext()) {
GraphObject o = (GraphObject)iter.next();
String goname = o.getType().getName();
if (goname.equals(""))
goname = "[UNNAMED_NODE]";
result.add(goname);
}
}
/**
* Iterate through my nodes and arcs.
*
* @see agg.xt_basis.GraphObject
*/
public Enumeration<GraphObject> getElements() {
Vector<GraphObject> elems = new Vector<GraphObject>(this.itsNodes);
elems.addAll(this.itsArcs);
return elems.elements();
}
/**
* Iterate through my nodes and arcs to find all elements of type with
* specified typeName.
*
* @see agg.xt_basis.GraphObject
*/
public Enumeration<GraphObject> getElementsOfType(final String typeName) {
return getElementsOfTypeAsVector(typeName).elements();
}
/**
* Iterate through my Nodes and Arcs to find all elements of type with
* specified typeName.
*
* @see agg.xt_basis.GraphObject
*/
public Vector<GraphObject> getElementsOfTypeAsVector(final String typeName) {
final Vector<GraphObject> elems = new Vector<GraphObject>();
if (!this.getElemsOfTypeName(typeName, this.itsNodes.iterator(), elems))
this.getElemsOfTypeName(typeName, this.itsArcs.iterator(), elems);
return elems;
}
private boolean getElemsOfTypeName(
final String typeName,
final Iterator<?> iter,
final Vector<GraphObject> result) {
while (iter.hasNext()){
GraphObject obj = (GraphObject)iter.next();
if(obj.getType().getName().equals(typeName))
result.addElement(obj);
}
return !result.isEmpty();
}
/**
* Iterate through my nodes and arcs to find all elements of type with
* specified type.
*
* @see agg.xt_basis.GraphObject
*/
public Enumeration<GraphObject> getElementsOfType(final Type type) {
return getElementsOfTypeAsVector(type).elements();
}
/**
* Iterate through my Nodes and Arcs to find all elements of type with
* specified type.
* @see agg.xt_basis.GraphObject
*/
public Vector<GraphObject> getElementsOfTypeAsVector(final Type type) {
final Vector<GraphObject> elems = new Vector<GraphObject>();
if (!this.getElemsOfType(type, this.itsNodes.iterator(), elems))
this.getElemsOfType(type, this.itsArcs.iterator(), elems);
return elems;
}
private boolean getElemsOfType(
final Type type,
final Iterator<?> iter,
final Vector<GraphObject> result) {
while (iter.hasNext()){
GraphObject obj = (GraphObject)iter.next();
if(obj.getType().compareTo(type))
result.addElement(obj);
}
return !result.isEmpty();
}
public Vector<GraphObject> getElementsOfTypeAsVector(final Type type,
final boolean withChildren) {
final Vector<GraphObject> elems = new Vector<GraphObject>();
Iterator<?> iter = this.itsNodes.iterator();
while (iter.hasNext()) {
Node obj = (Node)iter.next();
if (obj.getType().compareTo(type)
|| (withChildren
&& obj.getType().isChildOf(type))) {
elems.addElement(obj);
}
}
if(!elems.isEmpty()) {
return elems;
}
iter = this.itsArcs.iterator();
while (iter.hasNext()) {
Arc obj = (Arc)iter.next();
if(obj.getType().compareTo(type)) {
elems.addElement(obj);
}
}
return elems;
}
/**
* Iterate through my arcs to find all elements of type with specified
* type, source and target.
*
* @see agg.xt_basis.GraphObject
*/
public Enumeration<GraphObject> getElementsOfType(Type type, Type src, Type tar) {
return getElementsOfTypeAsVector(type, src, tar).elements();
}
/**
* Iterate through my edges to find all edges of the specified type. For
* all these edges holds: the source is of the specified src type and the
* target is of the specified tar type.
*
* @see agg.xt_basis.GraphObject
*/
public Vector<GraphObject> getElementsOfTypeAsVector(final Type type, final Type src,
final Type tar) {
final Vector<GraphObject> elems = new Vector<GraphObject>();
Iterator<Arc> iter = this.itsArcs.iterator();
while (iter.hasNext()) {
Arc obj = iter.next();
if (obj.getType().compareTo(type)
&& (obj.getSource().getType().compareTo(src)
|| obj.getSource().getType().isChildOf(src))
&& (obj.getTarget().getType().compareTo(tar)
|| obj.getTarget().getType().isChildOf(tar))) {
elems.addElement(obj);
}
}
return elems;
}
/**
* Iterate through my Nodes and Arcs * to find all elements of type with
* specified type.
*
* @see agg.xt_basis.GraphObject
*/
public Enumeration<GraphObject> getElementsOfType(final GraphObject type) {
return getElementsOfTypeAsVector(type).elements();
}
/**
* Iterate through my Nodes and Arcs to find all elements of type with
* specified type.
*
* @see agg.xt_basis.GraphObject
*/
public Vector<GraphObject> getElementsOfTypeAsVector(final GraphObject type) {
Vector<GraphObject> elems = new Vector<GraphObject>();
if (type.isNode()) {
elems = getElementsOfTypeAsVector(type.getType());
if (!elems.isEmpty())
return elems;
} else {
elems = getElementsOfTypeAsVector(type.getType(), ((Arc) type)
.getSource().getType(), ((Arc) type).getTarget().getType());
if (!elems.isEmpty())
return elems;
}
return elems;
}
public void setAttrContext(AttrContext context) {
this.itsAttrContext = context;
}
public AttrContext getAttrContext() {
return this.itsAttrContext;
}
public AttrManager getAttrManager() {
return AttrTupleManager.getDefaultManager();
}
public void createAttrInstanceWhereNeeded() {
Iterator<Node> iterNodes = this.itsNodes.iterator();
while (iterNodes.hasNext()) {
Node go = iterNodes.next();
if ((!go.getType().isAttrTypeEmpty() || !go.getType().isParentAttrTypeEmpty())
&& go.getAttribute() == null) {
go.createAttributeInstance();
}
}
Iterator<Arc> iterArcs = this.itsArcs.iterator();
while (iterArcs.hasNext()) {
Arc go = iterArcs.next();
if (!go.getType().isAttrTypeEmpty()
&& go.getAttribute() == null) {
go.createAttributeInstance();
}
}
}
public void createAttrInstanceOfTypeWhereNeeded(final Type t) {
Iterator<Node> iterNodes = this.itsNodes.iterator();
while (iterNodes.hasNext()) {
Node go = iterNodes.next();
if ((go.getType() == t || t.isParentOf(go.getType()))
&& (!t.isAttrTypeEmpty()
|| !t.isParentAttrTypeEmpty())
&& go.getAttribute() == null) {
go.createAttributeInstance();
}
}
Iterator<Arc> iterArcs = this.itsArcs.iterator();
while (iterArcs.hasNext()) {
Arc go = iterArcs.next();
if (go.getType() == t
&& !t.isAttrTypeEmpty()
&& go.getAttribute() == null) {
go.createAttributeInstance();
}
}
}
protected void propagateChange(agg.util.Change ch) {
if (this.notificationRequired) {
setChanged();
notifyObservers(ch);
}
}
/**
* Stores the specified morphism if it is its source or target graph.
* @param m
*/
public void addUsingMorph(OrdinaryMorphism m) {
this.itsUsingMorphs.add(m);
}
/**
* Removes the specified morphism from stored morphisms.
*/
public boolean removeUsingMorph(final OrdinaryMorphism m) {
return this.itsUsingMorphs.remove(m);
}
public boolean isEmpty() {
return this.itsNodes.isEmpty();
}
/** Returns <code>true</code> if it contains the specified graph object. */
public boolean isElement(GraphObject obj) {
if (this.itsNodes == null) {
System.out.println(this.itsName);
}
if (obj.getContext() == this)
return true;
else
return false;
}
/** Returns <code>true</code> if its nodes contain the specified node. */
public boolean isNode(Node obj) {
return this.itsNodes.contains(obj);
}
/** Returns <code>true</code> if its arcs contain the specified arc. */
public boolean isArc(Arc obj) {
return this.itsArcs.contains(obj);
}
/** Returns <code>true</code> if this graph uses the specified type. */
public boolean isUsingType(GraphObject t) {
if (t.isArc()) {
boolean hasTypeGraphArc = this.getTypeSet().getTypeGraphArc(
t.getType(), ((Arc) t).getSource().getType(),
((Arc) t).getTarget().getType()) != null ? true : false;
Iterator<Arc> iter = this.itsArcs.iterator();
while (iter.hasNext()) {
Arc o = iter.next();
if (hasTypeGraphArc) {
if (o.getType().compareTo(t.getType())
&& ((o.getSource().getType().compareTo(((Arc) t)
.getSource().getType())) || (o.getSource()
.getType().isChildOf(((Arc) t).getSource()
.getType())))
&& ((o.getTarget().getType().compareTo(((Arc) t)
.getTarget().getType())) || (o.getTarget()
.getType().isChildOf(((Arc) t).getTarget()
.getType())))) {
return true;
}
}
else if (o.getType().compareTo(t.getType())) {
return true;
}
}
} else {
while (this.itsNodes.iterator().hasNext()) {
Node o = this.itsNodes.iterator().next();
if (o.getType().compareTo(t.getType()))
return true;
else if (o.getType().isChildOf(t.getType()))
return true;
}
}
return false;
}
public boolean isUsingType(Type t) {
return doesUseType(t, this.itsNodes.iterator())
|| doesUseType(t, this.itsArcs.iterator());
}
private boolean doesUseType(final Type t, final Iterator<?> iter) {
while (iter.hasNext()) {
GraphObject go = (GraphObject)iter.next();
if (go.getType().compareTo(t))
return true;
else if (go.getType().isChildOf(t))
return true;
}
return false;
}
public boolean isUsingVariable(VarMember v) {
return this.doUseVar(v, this.itsNodes.iterator())
|| this.doUseVar(v, this.itsArcs.iterator());
}
private boolean doUseVar(final VarMember v, final Iterator<?> iter) {
while (iter.hasNext()){
GraphObject go = (GraphObject)iter.next();
if (go.getAttribute() == null)
continue;
ValueTuple val = (ValueTuple) go.getAttribute();
for (int j = 0; j < val.getSize(); j++) {
ValueMember mem = val.getValueMemberAt(j);
if (mem.getExpr() != null) {
if (mem.getExpr().isVariable()) {
if (mem.getDeclaration().getTypeName().equals(
v.getDeclaration().getTypeName())
&& mem.getExprAsText().equals(v.getName()))
return true;
} else if (mem.getExpr().isComplex()) {
if (mem.getAllVariableNamesOfExpression().contains(
v.getName()))
return true;
}
}
}
}
return false;
}
/**
* Delete all of my graph objects.
* <p>
* <b>Post:</b> <code>isEmpty()</code>*
*/
public void clear() {
this.changed = false;
this.itsUsingMorphs.clear();
this.destroyArcs();
this.destroyNodes();
propagateChange(new Change(Change.OBJECT_DESTROYED, null));
}
/**
* Tries to glue two graph objects.
* The context of the graph object to keep will be extended
* by out- and in-edges of the glue object.
* The unset attributes of the keep object will get the attribute value
* of the glue object if it is a constant.
* At the end the glue object will be destroyed.
*/
public synchronized boolean glue(
final GraphObject keep,
final GraphObject glue) throws TypeException {
return glue(keep, glue, null);
}
public synchronized boolean glue(
final GraphObject keep,
final GraphObject glue,
final GraphObject targetObj) throws TypeException {
if (keep.equals(glue)) {
return true;
}
if ((glue == null)
|| !glue.getType().isParentOf(keep.getType())) {
// if (!keep.getType().compareTo(glue.getType())) {
return false;
}
// System.out.println("Graph.glue: keep: "+keep.getType().getName()+" glue: "+glue.getType().getName());
if (keep.isArc()
&& (!glue(((Arc) keep).getSource(), ((Arc) glue).getSource())
|| !glue(((Arc) keep).getTarget(), ((Arc) glue).getTarget()))) {
return false;
}
// check attr. value
if (keep.getAttribute() != null && glue.getAttribute() != null) {
for (int i = 0; i < ((ValueTuple) keep.getAttribute())
.getNumberOfEntries(); i++) {
ValueMember amKeep = ((ValueTuple) keep.getAttribute())
.getValueMemberAt(i);
ValueMember amGlue = ((ValueTuple) glue.getAttribute())
.getValueMemberAt(amKeep.getName());
if (amKeep.isSet() && amGlue != null && amGlue.isSet()) {
if (amKeep.getExpr().isConstant()) {
if (amGlue.getExpr().isConstant()) {
if (targetObj != null) {
ValueMember tarVal = ((ValueTuple) targetObj.getAttribute())
.getValueMemberAt(amKeep.getName());
if (tarVal != null && !tarVal.isSet()
&& !amKeep.getExprAsText().equals(amGlue.getExprAsText())) {
throw new TypeException("Graph.glue: Checking attribute constant values of objects to glue failed!");
// return false;
}
}
else if (!amKeep.getExprAsText().equals(amGlue.getExprAsText())) {
throw new TypeException("Graph.glue: Checking attribute constant values of objects to glue failed!");
// return false;
}
}
} else if (amKeep.getExpr().isVariable()) {
// if ((amGlue.getExpr().isConstant()
// || amGlue.getExpr().isVariable()))
// ;
} else {
throw new TypeException("Graph.glue: Checking attribute (expresion) values of objects to glue failed!");
// return false;
}
}
}
}
if (glue.isNode()) {
// Move Incoming Arcs context from "glue" to "keep"
// Inverse relations are implicitly updated
final List<Arc> incoms = new Vector<Arc> (((Node)glue).getIncomingArcsSet());
for (int i=0; i<incoms.size(); i++) {
Arc arc = incoms.get(i);
if ((this.itsTypes.checkIfRemovableFromTarget(arc) == null)
&& (this.itsTypes.checkIfEdgeCreatable(arc.getType(), (Node) arc
.getSource(), (Node) keep) == null)) {
propagateChange(new Change(Change.TARGET_UNSET, arc));
arc.setTarget((Node) keep);
propagateChange(new Change(Change.TARGET_SET, arc));
}
else {
throw new TypeException("Graph.glue: Checking arcs (type multiplicity) to glue failed!");
// return false;
}
}
incoms.clear();
// Move Outgoing Arcs context from "glue" to "keep"
final List<Arc> outcoms = new Vector<Arc> (((Node)glue).getOutgoingArcsSet());
for (int i=0; i<outcoms.size(); i++) {
Arc arc = outcoms.get(i);
if ((this.itsTypes.checkIfRemovableFromSource(arc) == null)
&& (this.itsTypes.checkIfEdgeCreatable(arc.getType(),
(Node) keep, (Node) arc.getTarget()) == null)) {
propagateChange(new Change(Change.SOURCE_UNSET, arc));
arc.setSource((Node) keep);
propagateChange(new Change(Change.SOURCE_SET, arc));
}
else {
throw new TypeException("Graph.glue: Checking arcs (type multiplicity) to glue failed!");
// return false;
}
}
outcoms.clear();
}
// set attr. value
if (keep.getAttribute() != null && glue.getAttribute() != null) {
for (int i = 0; i < ((ValueTuple) keep.getAttribute())
.getNumberOfEntries(); i++) {
ValueMember amKeep = ((ValueTuple) keep.getAttribute())
.getValueMemberAt(i);
ValueMember amGlue = ((ValueTuple) glue.getAttribute())
.getValueMemberAt(i);
if ((!amKeep.isSet() || amKeep.getExpr().isVariable())
&& (amGlue != null && amGlue.isSet() && amGlue.getExpr().isConstant())) {
amKeep.setExprAsText(amGlue.getExprAsText());
}
}
}
// propagateChange(new Change(Change.OBJECT_GLUED,
// new Pair<GraphObject, GraphObject>(keep, glue)));
try {
if (glue.isNode())
this.destroyNode((Node) glue, true, false);
else
this.destroyArc((Arc) glue, true, false);
propagateChange(new Change(Change.OBJECT_DESTROYED, glue));
} catch (TypeException e) {
// must not happened, because we removed all relations,
// so the glue object should be removable
throw e; //return false;
}
return true;
}
/**
* Returns false if not all attributes of its graph objects are set,
* otherwise - true.
*/
public boolean isReadyForTransform() {
return (isAttributeSet(this.itsNodes.iterator(), null)
&& isAttributeSet(this.itsArcs.iterator(), null));
}
protected boolean isAttributeSet(
final Iterator<?> iter,
final Vector<GraphObject> storeOfFailedObjs) {
boolean failed = false;
while (iter.hasNext() && !failed) {
GraphObject o = (GraphObject)iter.next();
if (o.getAttribute() == null) {
if ((o.getType().getAttrType() != null)
&& (o.getType().getAttrType().getNumberOfEntries() != 0)) {
o.createAttributeInstance();
this.attributed = true;
} else
continue;
}
if (o.isNode())
failed = !applyDefaultAttrValuesOfTypeGraph((Node)o, storeOfFailedObjs);
else
failed = !applyDefaultAttrValuesOfTypeGraph((Arc)o, storeOfFailedObjs);
}
return !failed;
}
public GraphObject getObjectWithVariableOfAttrs(VarMember v) {
Iterator<Node> niter = this.itsNodes.iterator();
while (niter.hasNext()) {
Node n = niter.next();
if (n.getAttribute() != null) {
AttrInstance attrs = n.getAttribute();
for (int i=0; i<attrs.getNumberOfEntries(); i++) {
ValueMember val = (ValueMember)attrs.getMemberAt(i);
if (val.getExpr() != null
&& val.getExprAsText().equals(v.getName())) {
return n;
}
}
}
}
Iterator<Arc> aiter = this.itsArcs.iterator();
while (aiter.hasNext()) {
Arc a = aiter.next();
if (a.getAttribute() != null) {
AttrInstance attrs = a.getAttribute();
for (int i=0; i<attrs.getNumberOfEntries(); i++) {
ValueMember val = (ValueMember)attrs.getMemberAt(i);
if (val.getExpr() != null
&& val.getExprAsText().equals(v.getName())) {
return a;
}
}
}
}
return null;
}
protected boolean applyDefaultAttrValuesOfTypeGraph(final Node go, final Vector<GraphObject> storeOfFailedObjs) {
final Node typeNode = go.getType().getTypeGraphNodeObject();
if (typeNode != null
&& typeNode.getAttribute() != null) {
final ValueTuple value = (ValueTuple) go.getAttribute();
// search all parents for default attribute value
final Vector<Type> itsParents = go.getType().getAllParents();
for (int p=0; p<itsParents.size(); p++) {
final Node pNode = itsParents.get(p).getTypeGraphNodeObject();
if (pNode != null) {
final ValueTuple pNodeAttr = (ValueTuple) pNode.getAttribute();
if (pNodeAttr == null) {
continue;
}
for (int i = 0; i < value.getSize(); i++) {
ValueMember vm = value.getValueMemberAt(i);
if (!vm.isSet()) {
ValueMember pnvm = pNodeAttr.getValueMemberAt(vm.getName());
if (pnvm != null && pnvm.isSet()) {
vm.setExpr(pnvm.getExpr());
}
}
}
}
}
if (!this.getTypeSet().isEmptyAttrAllowed()) {
// check for not set attribute
for (int i = 0; i < value.getSize(); i++) {
ValueMember vm = value.getValueMemberAt(i);
if (!vm.isSet()) {
if (storeOfFailedObjs != null)
storeOfFailedObjs.add(go);
else
return false;
}
}
}
}
return true;
}
protected boolean applyDefaultAttrValuesOfTypeGraph(final Arc go, final Vector<GraphObject> storeOfFailedObjs) {
final Arc typeArc = go.getType().getTypeGraphArcObject(go.getSourceType(), go.getTargetType());
if (typeArc != null
&& typeArc.getAttribute() != null) {
final ValueTuple typeValue = (ValueTuple) typeArc.getAttribute();
final ValueTuple value = (ValueTuple) go.getAttribute();
for (int i = 0; i < value.getSize(); i++) {
ValueMember vm = value.getValueMemberAt(i);
if (!vm.isSet()) {
ValueMember typevm = typeValue.getValueMemberAt(vm.getName());
if (typevm != null && typevm.isSet()) {
vm.setExprAsText(typevm.getExprAsText());
}
}
}
// search for not set attribute value and return false if found
for (int i = 0; i < value.getSize(); i++) {
ValueMember vm = value.getValueMemberAt(i);
if (!vm.isSet()) {
if (storeOfFailedObjs != null)
storeOfFailedObjs.add(go);
else
return false;
}
}
}
return true;
}
/**
* Returns false if not all attributes of its graph objects are set,
* otherwise - true. The specified Vector
* <code>storeOfFailedObjs</code> will contain nodes and edges which are
* not initialized completely.
*/
public boolean isReadyForTransform(final Vector<GraphObject> storeOfFailedObjs) {
return isAttributeSet(this.itsNodes.iterator(), storeOfFailedObjs)
&& isAttributeSet(this.itsArcs.iterator(), storeOfFailedObjs);
}
public boolean isIsomorphicTo(Graph g) {
final OrdinaryMorphism h = this.getIsomorphicWith(g);
if (h == null)
return false;
return true;
}
/**
* Tries to compute an isomorphic morphism
* of this graph into the specified graph g.
*
* @param g
* is target graph of the result morphism
* @return an isomorphic morphism or null.
*/
public OrdinaryMorphism getIsomorphicWith(final Graph g) {
if (this.getNodesCount() != g.getNodesCount()
|| this.getArcsCount() != g.getArcsCount()) {
return null;
}
boolean result = false;
OrdinaryMorphism h = BaseFactory.theFactory().createMorphism(this, g);
h.setCompletionStrategy(new Completion_InjCSP());
if (h.nextCompletion()) {
result = true;
// additionally, check type of source - target nodes in case of
// Typegraph with Node Type Inheritance
if (this.getTypeSet().getTypeGraph() != null
// && this.getTypeSet().getLevelOfTypeGraphCheck() >= TypeSet.ENABLED
&& this.getTypeSet().hasInheritance()) {
Iterator<Node> origs = this.itsNodes.iterator();
while (origs.hasNext() && result) {
final Node orig = origs.next();
if (!orig.getType().compareTo(h.getImage(orig).getType())) {
result = false;
}
}
}
}
if (!result) {
h.dispose();
h = null;
}
return h;
}
/**
* Tries to compute isomorphic morphisms of this graph into the
* specified graph.
*
* @param g
* the target graph of a morphism
* @param map
* contains morphism mappings : keys are elements of
* this graph, values are elements of the graph g.
*
* @return computed isomorphic morphisms or null
*/
public Vector<OrdinaryMorphism> getIsomorphicWith(final Graph g,
final Hashtable<GraphObject, GraphObject> map) {
// fast test
if (this.getNodesCount() != g.getNodesCount()
|| this.getArcsCount() != g.getArcsCount()) {
return null;
}
final Vector<OrdinaryMorphism> isos = new Vector<OrdinaryMorphism>(5);
// try to get an isomorphism
OrdinaryMorphism h = BaseFactory.theFactory().createMorphism(this, g);
h.setCompletionStrategy(new Completion_InjCSP());
// set mappings
Enumeration<GraphObject> keys = map.keys();
while (keys.hasMoreElements()) {
GraphObject o = keys.nextElement();
GraphObject i = map.get(o);
if (o != null && i != null) {
try {
h.addMapping(o, i);
} catch (BadMappingException exc) {}
}
}
// make possible completions
while (h.nextCompletion()) {
boolean result = true;
// additionally, check type of source - target nodes in case of
// Typegraph with Node Type Inheritance
if (this.getTypeSet().getTypeGraph() != null
&& this.getTypeSet().getLevelOfTypeGraphCheck() >= TypeSet.ENABLED
&& this.getTypeSet().hasInheritance()) {
Iterator<Node> origs = this.itsNodes.iterator();
while (origs.hasNext() && result) {
final Node orig = origs.next();
if (!orig.getType().compareTo(h.getImage(orig).getType())) {
result = false;
}
}
}
if (result) {
// store this completion
OrdinaryMorphism
m = BaseFactory.theFactory().createMorphism(this, g);
Enumeration<GraphObject> e = h.getDomain();
while (e.hasMoreElements()) {
GraphObject o = e.nextElement();
m.addMapping(o, h.getImage(o));
}
isos.add(m);
}
}
return isos.isEmpty() ? null : isos;
}
/**
* Tries to compute all isomorphic morphisms
* of this graph into the specified graph g.
*
* @param g
* is target graph of morphisms
* @param all
* is true - compute all possible isomorphic morphisms,
* otherwise - only first one.
* @return computed isomorphic morphisms or null
*/
public Vector<OrdinaryMorphism> getIsomorphicWith(final Graph g, final boolean all) {
Vector<OrdinaryMorphism> allIsos = new Vector<OrdinaryMorphism>(5);
if (!all) {
OrdinaryMorphism h = getIsomorphicWith(g);
if (h != null) {
allIsos.add(h);
}
return allIsos;
}
if ((this.getNodesCount() != g.getNodesCount())
|| (this.getArcsCount() != g.getArcsCount())) {
return null;
}
OrdinaryMorphism h = BaseFactory.theFactory().createMorphism(this, g);
h.setCompletionStrategy(new Completion_InjCSP());
// make possible completions
while (h.nextCompletion()) {
boolean result = true;
// additionally, check type of source - target nodes in case of
// Typegraph with Node Type Inheritance
if (this.getTypeSet().getTypeGraph() != null
&& this.getTypeSet().getLevelOfTypeGraphCheck() >= TypeSet.ENABLED
&& this.getTypeSet().hasInheritance()) {
Iterator<Node> origs = this.itsNodes.iterator();
while (origs.hasNext() && result) {
final Node orig = origs.next();
if (!orig.getType().compareTo(h.getImage(orig).getType())) {
result = false;
}
}
}
if (result) {
// store this completion
OrdinaryMorphism
m = BaseFactory.theFactory().createMorphism(this, g);
Enumeration<GraphObject> e = h.getDomain();
while (e.hasMoreElements()) {
GraphObject o = e.nextElement();
try {
m.addMapping(o, h.getImage(o));
} catch (Exception ex) {}
}
allIsos.add(m);
}
}
return allIsos;
}
/**
* Returns an isomorphism between this graph and its ad-hoc-created copy.
*
* @deprecated replaced by <code>isomorphicCopy()</code>
*/
public OrdinaryMorphism isoToCopy(int n) {
return isomorphicCopy();
}
/**
* Returns an isomorphism between this graph and its ad-hoc-created copy.
* The attributes values are copied, too.
*
* @return morphism this --> copy
*/
public OrdinaryMorphism isomorphicCopy() {
return this.isomorphicCopy(false);
}
/**
* @see OrdinaryMorphism isomorphicCopy()
* @return morphism this --> copy
*/
public OrdinaryMorphism isoCopy() {
return this.isomorphicCopy(false);
}
/**
* Returns an isomorphism between this graph and its ad-hoc-created copy.
* The attributes values are copied, too.
*
* @return morphism copy --> this
*/
public OrdinaryMorphism inverseIsoCopy() {
return this.isomorphicCopy(true);
}
public OrdinaryMorphism plainCopy() {
synchronized (this) {
Graph copy = BaseFactory.theFactory().createGraph(getTypeSet(), this.isCompleteGraph());
OrdinaryMorphism iso = new OrdinaryMorphism(this, copy,
agg.attribute.impl.AttrTupleManager
.getDefaultManager().newContext(AttrMapping.PLAIN_MAP));
copy.setName(this.getName().concat("_copy"));
iso.setName("IsoMorph");
if (makeIsocopy(false, iso, copy))
return iso;
else {
iso.dispose();
copy.dispose();
copy = null;
iso = null;
return null;
}
}
}
/**
* Returns an isomorphism between this graph and its ad-hoc-created copy.
* The attributes values are copied, too.
*
* @return morphism this --> copy if inverse is FALSE, otherwise copy --> this
*/
private OrdinaryMorphism isomorphicCopy(boolean inverse) {
synchronized (this) {
Graph copy = BaseFactory.theFactory().createGraph(getTypeSet(), this.isCompleteGraph());
OrdinaryMorphism iso = null;
if (inverse)
iso = BaseFactory.theFactory().createMorphism(copy, this);
else
iso = BaseFactory.theFactory().createMorphism(this, copy);
copy.setName(this.getName().concat("_copy"));
iso.setName("IsoMorph");
if (makeIsocopy(inverse, iso, copy))
return iso;
else {
iso.dispose();
copy.dispose();
copy = null;
iso = null;
return null;
}
}
}
/**
* Makes the given empty graph <code>theCopy</code> to a copy of myself.
* The attributes values are copied, too.
* If inverse is TRUE, the <code>iso</code> morphism is given by <code>theCopy -> this</code>,
* otherwise by <code>this -> theCopy</code>
*/
public boolean makeIsocopy(boolean inverse, OrdinaryMorphism iso, Graph theCopy) {
boolean failed = false;
final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(this
.getSize());
Iterator<?> iter = this.itsNodes.iterator();
while (!failed && iter.hasNext()) {
Node vtxOrig = (Node)iter.next();
try {
Node vtxCopy = theCopy.copyNode(vtxOrig);
vtxCopy.setContextUsage(vtxOrig.getContextUsage());
memo1.put(vtxOrig, vtxCopy);
try {
if (inverse)
iso.addPlainMapping(vtxCopy, vtxOrig);
else
iso.addPlainMapping(vtxOrig, vtxCopy);
} catch (BadMappingException bme) {
failed = true;
}
} catch (TypeException ex) {
failed = true;
}
}
iter = this.itsArcs.iterator();
while (!failed && iter.hasNext()) {
Arc arcOrig = (Arc)iter.next();
Node source = (Node) arcOrig.getSource();
Node target = (Node) arcOrig.getTarget();
Node srcImg = memo1.get(source);
Node tgtImg = memo1.get(target);
if ((srcImg != null) && (tgtImg != null)) {
try {
Arc arcCopy = theCopy.copyArc(arcOrig, srcImg, tgtImg);
arcCopy.setContextUsage(arcOrig.getContextUsage());
try {
if (inverse)
iso.addPlainMapping(arcCopy, arcOrig);
else
iso.addPlainMapping(arcOrig, arcCopy);
} catch (BadMappingException bme) {
failed = true;
}
} catch (TypeException ex) {
failed = true;
}
}
}
memo1.clear();
return !failed;
}
/**
* Returns an isomorphism between this graph and its graph-structure copy.
* The attributes values are not copied.
*
* @return morphism this --> copy
*/
public OrdinaryMorphism isoGraph() {
return isomorphicGraph(false);
}
/**
* Returns an isomorphism between a graph-structure copy and this graph.
* The attributes values are not copied.
*
* @return morphism copy --> this
*/
public OrdinaryMorphism inverseIsoGraph() {
return isomorphicGraph(true);
}
/**
* Returns an isomorphism between this graph and its graph-structure copy.
* The attributes values are not copied.
*/
public OrdinaryMorphism isomorphicGraph(boolean inverse) {
synchronized (this) {
boolean failed = false;
Graph theCopy = BaseFactory.theFactory().createGraph(getTypeSet(), this.isCompleteGraph());
OrdinaryMorphism iso = null;
if (inverse)
iso = BaseFactory.theFactory().createMorphism(theCopy, this);
else
iso = BaseFactory.theFactory().createMorphism(this, theCopy);
theCopy.setName(this.getName().concat("_copy"));
iso.setName("IsoMorph");
final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(this
.getSize());
Iterator<?> iter = this.itsNodes.iterator();
while (!failed && iter.hasNext()) {
Node vtxOrig = (Node)iter.next();
try {
Node vtxCopy = theCopy.createNode(vtxOrig.getType());
vtxCopy.setObjectName(vtxOrig.getObjectName());
vtxCopy.setContextUsage(vtxOrig.getContextUsage());
memo1.put(vtxOrig, vtxCopy);
try {
if (inverse)
iso.addPlainMapping(vtxCopy, vtxOrig);
else
iso.addPlainMapping(vtxOrig, vtxCopy);
} catch (BadMappingException bme) {
failed = true;
iso.dispose();
theCopy.dispose();
}
} catch (TypeException ex) {}
}
iter = this.itsArcs.iterator();
while (!failed && iter.hasNext()) {
Arc arcOrig = (Arc)iter.next();
Node srcImg = memo1.get(arcOrig.getSource());
Node tgtImg = memo1.get(arcOrig.getTarget());
if ((srcImg != null) && (tgtImg != null)) {
try {
Arc arcCopy = theCopy.createArc(arcOrig.getType(), srcImg, tgtImg);
arcCopy.setObjectName(arcOrig.getObjectName());
arcCopy.setContextUsage(arcOrig.getContextUsage());
try {
if (inverse)
iso.addPlainMapping(arcCopy, arcOrig);
else
iso.addPlainMapping(arcOrig, arcCopy);
} catch (BadMappingException bme) {
failed = true;
iso.dispose();
theCopy.dispose();
}
} catch (TypeException ex) {}
}
}
memo1.clear();
return (iso);
}
}
/**
* Returns an isomorphism between ad-hoc-created copy and this graph.
*/
public OrdinaryMorphism reverseIsomorphicCopy() {
synchronized (this) {
boolean failed = false;
Iterator<Arc> arcList = this.itsArcs.iterator();
Iterator<Node> vtxList = this.itsNodes.iterator();
Graph theCopy = BaseFactory.theFactory().createGraph(getTypeSet());
theCopy.setName(this.getName().concat("_copy"));
OrdinaryMorphism iso = BaseFactory.theFactory().createMorphism(
theCopy, this);
iso.setName("IsoMorph");
final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(this
.getSize());
while (vtxList.hasNext()) {
Node vtxOrig = vtxList.next();
Node vtxCopy = null;
try {
vtxCopy = theCopy.copyNode(vtxOrig);
/** side effect! */
vtxCopy.setContextUsage(vtxOrig.getContextUsage());
iso.addMapping(vtxCopy, vtxOrig);
/** output construction */
memo1.put(vtxOrig, vtxCopy);
} catch (TypeException e) {
// e.printStackTrace();
failed = true;
}
}
while (!failed && arcList.hasNext()) {
Arc arcOrig = arcList.next();
Node source = (Node) arcOrig.getSource();
Node target = (Node) arcOrig.getTarget();
Node srcImg = memo1.get(source);
Node tgtImg = memo1.get(target);
Arc arcCopy = null;
if ((srcImg != null) && (tgtImg != null)) {
try {
arcCopy = theCopy.copyArc(arcOrig, srcImg, tgtImg);
arcCopy.setContextUsage(arcOrig.getContextUsage());
iso.addMapping(arcCopy, arcOrig);
} catch (TypeException e) {
// e.printStackTrace();
failed = true;
}
}
}
memo1.clear();
return (iso);
}
}
/**
* see appropriate method <code>BaseFactory.getOverlappings</code>
*/
public Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings(Graph g, boolean withIsomorphic) {
return BaseFactory.theBaseFactory.getOverlappings(this, g, withIsomorphic);
}
/**
* see appropriate method <code>BaseFactory.getOverlappings</code>
*/
public Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings(Graph g, boolean disjunion,
boolean withIsomorphic) {
return BaseFactory.theBaseFactory.getOverlappings(this, g, disjunion, withIsomorphic);
}
/**
* see appropriate method <code>BaseFactory.getOverlappings</code>
*/
public Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings(Graph g, int sizeOfInclusions,
boolean withIsomorphic) {
return BaseFactory.theBaseFactory.getOverlappings(this, g, sizeOfInclusions, withIsomorphic);
}
/**
* see appropriate method <code>BaseFactory.getOverlappings</code>
*/
public Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings(Graph g, int sizeOfInclusions,
boolean disjunion, boolean withIsomorphic) {
return BaseFactory.theBaseFactory.getOverlappings(this, g, sizeOfInclusions, disjunion, withIsomorphic);
}
/**
* Implements the interface of XMLObject
*/
public void XwriteObject(XMLHelper h) {
this.refreshAttributed();
this.changed = false;
h.openNewElem("Graph", this);
if (!this.kind.equals(""))
h.addAttr("kind", this.kind);
h.addAttr("name", getName());
if (!this.comment.equals(""))
h.addAttr("comment", this.comment);
if (!this.info.equals(""))
h.addAttr("info", this.info);
h.addIteration("", this.itsNodes.iterator(), true);
h.addIteration("", this.itsArcs.iterator(), true);
h.close();
// updateTypeObjectsMap();
}
/**
* Implements the interface of XMLObject
*/
public void XreadObject(XMLHelper h) {
if (h.isTag("Graph", this)) {
String str = h.readAttr("name");
setName(str.replaceAll(" ", ""));
str = h.readAttr("comment");
if (!str.equals(""))
this.comment = str.toString();
str = h.readAttr("info");
if (!str.equals(""))
this.info = str.toString();
Enumeration<?> en = h.getEnumeration("", null, true, "Node");
while (en.hasMoreElements()) {
h.peekElement(en.nextElement());
Type t = (Type) h.getObject("type", null, false);
if (t != null) {
Node n = null;
try {
n = newNode(t);
n = (Node) h.loadObject(n);
} catch (TypeException e) {
// while loading the type check should be disabled,
// so this Exception should never be thrown
System.out.println("Graph.XreadObject: cannot load a Node : <"
+t.getName()+"> into graph <"+this.getName()+"> "
+e.getMessage());
}
}
h.close();
}
en = h.getEnumeration("", null, true, "Edge");
while (en.hasMoreElements()) {
h.peekElement(en.nextElement());
Type t = (Type) h.getObject("type", null, false);
Node n1 = (Node) h.getObject("source", null, false);
Node n2 = (Node) h.getObject("target", null, false);
if (t != null && n1 != null && n2 != null) {
try {
Arc a = newArc(t, n1, n2);
a = (Arc) h.loadObject(a);
} catch (TypeException e) {
// while loading the type check should be disabled,
// so this Exception should never be thrown
System.out.println("Graph.XreadObject: cannot load an Arc : <"
+t.getName()+"> into graph <"+this.getName()+"> "
+e.getMessage());
}
}
h.close();
}
h.close();
}
// this.showTypeMap(this.getTypeObjectsMap());
}
public String toString() {
return showGraph();
}
public String showGraph() {
String result = this.getName();
result = "\nGraph: " + this.getName() + " {\n";
Iterator<Arc> e = this.itsArcs.iterator();
while (e.hasNext()) {
Arc arc = e.next();
result += ((Node) arc.getSource()).toString() + arc.toString()
+ ((Node) arc.getTarget()).toString();
}
if (this.isTypeGraph()) {
Vector<Arc> inheritArcs = this.getTypeSet().getInheritanceArcs();
e = inheritArcs.iterator();
while (e.hasNext()) {
Arc arc = e.next();
result += ((Node) arc.getSource()).toString() + "--inherits-->"
+ ((Node) arc.getTarget()).toString();
}
}
Iterator<Node> e1 = this.itsNodes.iterator();
while (e1.hasNext()) {
Node node = e1.next();
if (!node.getIncomingArcsSet().iterator().hasNext()
&& !node.getOutgoingArcsSet().iterator().hasNext())
result += node.toString();
}
result += " }\n";
return result;
}
/*
protected String showNodes() {
String result = this.getName();
result = "\nGraph: " + this.getName() + " Nodes:: "
+ getNodesCount() + "{\n";
Iterator<Node> e = this.itsNodes.iterator();
while (e.hasNext()) {
Node node = e.next();
result += node.toString();
}
result += " }\n";
return result;
}
protected String showArcs() {
String result = this.getName();
result = "\nGraph: " + this.getName() + " Edges:: " + getArcsCount()
+ "{\n";
Iterator<Arc> e = this.itsArcs.iterator();
while (e.hasNext()) {
Arc arc = e.next();
result += ((Node) arc.getSource()).toString() + arc.toString()
+ ((Node) arc.getTarget()).toString();
}
if (this.isTypeGraph()) {
Vector<Arc> inheritArcs = this.getTypeSet().getInheritanceArcs();
e = inheritArcs.iterator();
while (e.hasNext()) {
Arc arc = e.next();
result += ((Node) arc.getSource()).toString()
// +arc.toString()
+ "--inherits-->" + ((Node) arc.getTarget()).toString();
}
}
result += " }\n";
return result;
}
private String attributesToString() {
String result = "\nGraph: " + this.getName() + " {\n";
Iterator<Node> e = this.itsNodes.iterator();
while (e.hasNext()) {
Node node = e.next();
// if(!node.getIncomingArcs().hasMoreElements()
// && !node.getOutgoingArcs().hasMoreElements())
{
result += node.toString();
result += attributeToString(node);
}
}
//
// e = getArcs(); while(e.hasMoreElements()) { Arc arc = (Arc)
// e.nextElement(); result += arc.toString(); result +=
// attributeToString(arc); }
//
result += "\n}";
return result;
}
*/
// private String attributeToString(GraphObject o) {
// return o.attributeToString();
// }
/**
* Returns true if the given set of graph objects represents a valid graph.
*
* @param goSet
* a Vector of GraphObjects
*
* @see GraphObject
* @see TypeSet#checkType(Graph)
*/
public boolean isGraph(final List<GraphObject> goSet) {
for (int i=0; i<goSet.size(); i++) {
GraphObject go = goSet.get(i);
if (go.isArc()) {
if (!goSet.contains(((Arc)go).getSource())
|| !goSet.contains(((Arc)go).getTarget()))
return false;
}
}
return true;
}
/**
* Returns true if this graph is used as a type graph. This works only if
* this graph is registered as type graph in its own {@link TypeSet}.
*/
public boolean isTypeGraph() {
if (this.itsTypes == null) {
return false;
}
return this == this.itsTypes.getTypeGraph();
}
public boolean isAttributed() {
return this.attributed;
}
public boolean areAnyAttributesSet(final Iterator<?> iter) {
boolean anyAttrsSet = false;
while (iter.hasNext()) {
GraphObject a = (GraphObject) iter.next();
if (a.getAttribute() == null)
continue;
ValueTuple value = (ValueTuple) a.getAttribute();
for (int j = 0; j < value.getSize(); j++) {
if (value.getValueMemberAt(j).isSet()) {
anyAttrsSet = true;
break;
}
}
}
return anyAttrsSet;
}
public boolean areAnyAttributesOfNodesSet() {
return this.areAnyAttributesSet(this.itsNodes.iterator());
}
public boolean areAnyAttributesOfArcsSet() {
return this.areAnyAttributesSet(this.itsArcs.iterator());
}
/**
* Returns true, if this graph is a complete graph.
* A complete graph is not allowed to use variables in attributes
* of its node and edges.
* The host graph of a gragra is always a complete graph.
*
*/
public boolean isCompleteGraph() {
return this.completeGraph;
}
/**
* A complete graph is not allowed to use variables in attributes
* of its node and edges.
*/
public void setCompleteGraph(boolean complete) {
this.completeGraph = complete;
}
public boolean isDirected() {
return this.getTypeSet().isArcDirected();
}
/**
* return TRUE if this graph is a NAC graph
*/
public boolean isNacGraph() {
return (this.kind == GraphKind.NAC) ? true : false;
}
/**
* return TRUE if this graph is a PAC graph
*/
public boolean isPacGraph() {
return (this.kind == GraphKind.PAC) ? true : false;
}
/**
* return TRUE if this graph is a nested Appl Cond graph
*/
public boolean isApplCondGraph() {
return (this.kind == GraphKind.AC) ? true : false;
}
public boolean compareTo(Graph g) {
if (this.getNodesCount() != g.getNodesCount()) {
return (false);
}
if (this.getArcsCount() != g.getArcsCount()) {
return (false);
}
boolean result = false;
OrdinaryMorphism m = (BaseFactory.theFactory()).createMorphism(this, g);
m.setCompletionStrategy(new Completion_InjCSP(), true);
// m.getCompletionStrategy().showProperties();
while (!result && m.nextCompletionWithConstantsChecking()) {
result = true;
// 1. check free objects in g
Iterator<?> e = g.getNodesSet().iterator();
while (result && e.hasNext()) {
GraphObject o = (GraphObject) e.next();
if (!m.getInverseImage(o).hasMoreElements()) {
result = false;
}
}
e = g.getArcsSet().iterator();
while (result && e.hasNext()) {
GraphObject o = (GraphObject) e.next();
if (!m.getInverseImage(o).hasMoreElements()) {
result = false;
}
}
// 2. check objects using compareTo
e = this.getNodesSet().iterator();
while (result && e.hasNext()) {
GraphObject o = (GraphObject) e.next();
GraphObject i = m.getImage(o);
if (!o.compareTo(i)) {
result = false;
}
}
e = this.getArcsSet().iterator();
while (result && e.hasNext()) {
GraphObject o = (GraphObject) e.next();
GraphObject i = m.getImage(o);
if (!o.compareTo(i)) {
result = false;
}
}
}
m.dispose();
m = null;
return result;
}
public boolean contains(Graph g) {
return contains(g, null);
}
public boolean contains(Graph g, MorphCompletionStrategy mcs) {
boolean result = false;
if (g.isEmpty()) {
result = true;
} else if (this.getSize() >= g.getSize()) {
if (!this.isEmpty() && mcs != null) {
if (mcs.getProperties().get(CompletionPropertyBits.INJECTIVE)
&& this.getSize() < g.getSize()) {
return false;
}
OrdinaryMorphism m = (BaseFactory.theFactory()).createMorphism(g, this);
m.setCompletionStrategy(mcs, true);
while (!result && m.nextCompletionWithConstantsChecking()) {
result = true;
// check objects using compareTo
Iterator<?> e = g.getNodesSet().iterator();
while (result && e.hasNext()) {
GraphObject o = (GraphObject) e.next();
GraphObject i = m.getImage(o);
if (!o.compareTo(i)) {
result = false;
}
}
e = g.getArcsSet().iterator();
while (result && e.hasNext()) {
GraphObject o = (GraphObject) e.next();
GraphObject i = m.getImage(o);
if (!o.compareTo(i)) {
result = false;
}
}
}
m.dispose();
m = null;
}
} else {
result = true;
}
return result;
}
public int getSize() {
return this.itsNodes.size() +this.itsArcs.size();
}
public int getSizeOfNodes() {
return this.itsNodes.size();
}
public int getSizeOfArcs() {
return this.itsArcs.size();
}
/**
* Checks if the specified edge to create is allowed.
*/
public TypeError checkConnectValid(Type edgeType, Node src, Node tar) {
if (this.itsTypes.getTypeGraph() == null
|| this.itsTypes.getLevelOfTypeGraphCheck() == TypeSet.DISABLED
|| this.itsTypes.getLevelOfTypeGraphCheck() == TypeSet.ENABLED_INHERITANCE) {
if (isParallelArcAllowed(edgeType, src, tar)) {
return null;
}
return new TypeError(TypeError.NO_PARALLEL_ARC,
"No parallel edges allowed");
}
Arc typearc = this.itsTypes.getTypeGraphArc(
edgeType, src.getType(), tar.getType());
if (typearc != null) {
if (isParallelArcAllowed(edgeType, src, tar)) {
return null;
}
return new TypeError(TypeError.NO_PARALLEL_ARC,
"No parallel edges allowed");
}
return new TypeError(TypeError.NO_SUCH_TYPE,
"The edge of the type \"" + edgeType.getName()
+ "\" is not allowed between node types \""
+ src.getType().getName() + "\" and \""
+ tar.getType().getName() + "\".");
}
public boolean isParallelArcAllowed(Type edgeType, Node src, Node tar) {
if (this.itsTypes.isArcParallel()
|| (src.getOutgoingArc(edgeType, tar) == null))
return true;
else
return false;
}
public TypeError checkNodeRequiresArc(final int actTypeGraphLevel) {
if (this.itsTypes.getTypeGraph() == null
|| actTypeGraphLevel != TypeSet.ENABLED_MAX_MIN)
return null;
Iterator<Node> iter = this.itsNodes.iterator();
while (iter.hasNext()) {
Node n = iter.next();
List<String> list = this.itsTypes.nodeRequiresArc(n);
if (list != null && !list.isEmpty()) {
return new TypeError(TypeError.TO_LESS_ARCS,
"Node type "
+ "\""+n.getType().getName()+ "\" \n"
+ "requires edge(s) of type: \n"
+ list.toString(), n.getType());
}
}
return null;
}
/**
* Returns en error if the type multiplicity check failed after a node of
* the specified type would be created, otherwise - null.
*/
public TypeError canCreateNode(
final Type nodeType,
int currentTypeGraphLevel) {
return this.itsTypes.canCreateNode(this, nodeType,
currentTypeGraphLevel);
}
/**
* Returns an error if the type multiplicity check failed after an edge of
* the specified type would be created, otherwise - null.
*/
public TypeError canCreateArc(
final Type edgeType,
final Node source,
final Node target,
int currentTypeGraphLevel) {
return this.itsTypes.canCreateArc(this, edgeType, source, target,
currentTypeGraphLevel);
}
public Vector<String> getVariableNamesOfAttributes() {
final Vector<String> result = new Vector<String>();
getVarNamesOfAttrs(this.itsNodes.iterator(), result);
getVarNamesOfAttrs(this.itsArcs.iterator(), result);
return result;
}
private void getVarNamesOfAttrs(final Iterator<?> iter, final Vector<String> result) {
while (iter.hasNext()) {
GraphObject o = (GraphObject)iter.next();
if (o.getAttribute() == null) {
continue;
}
Vector<String> vars = o.getVariableNamesOfAttribute();
for (int i = 0; i < vars.size(); i++) {
String name = vars.elementAt(i);
if (!result.contains(name))
result.addElement(name);
}
}
}
public Vector<VarMember> getSameVariablesOfAttributes() {
final Vector<VarMember> result = new Vector<VarMember>();
final AttrContext ac = getAttrContext();
final VarTuple avt = (VarTuple) ac.getVariables();
final Hashtable<VarMember, Boolean> used = new Hashtable<VarMember, Boolean>(
avt.getSize());
for (int i = 0; i < avt.getSize(); i++) {
VarMember var = avt.getVarMemberAt(i);
used.put(var, Boolean.valueOf(false));
}
if (used.isEmpty())
return result;
this.getSameVarsOfAttrs(avt, this.itsNodes.iterator(), used, result);
this.getSameVarsOfAttrs(avt, this.itsArcs.iterator(), used, result);
return result;
}
public void getSameVarsOfAttrs(
final VarTuple avt,
final Iterator<?> iter,
final Hashtable<VarMember, Boolean> used,
final Vector<VarMember> result) {
while (iter.hasNext()) {
GraphObject o = (GraphObject)iter.next();
if (o.getAttribute() == null)
continue;
ValueTuple vt = (ValueTuple) o.getAttribute();
for (int k = 0; k < vt.getSize(); k++) {
ValueMember vm = vt.getValueMemberAt(k);
if (vm.isSet()) {
if (vm.getExpr().isVariable()) {
VarMember var = avt.getVarMemberAt(vm.getExprAsText());
if (!var.isInputParameter()) {
if (used.get(var).booleanValue() == false)
used.put(var, Boolean.valueOf(true));
else {
if (!result.contains(var))
result.add(var);
}
}
}
}
}
}
}
/*
*
* @deprecated use {@link #copyNode} or {@link #copyArc}, this method
* cannot work properly in case a type graph is defined and in
* use.
*
public final Object execute(Object obj) {
try {
if (((GraphObject) obj).isNode()) {
return copyNode((Node) obj);
} else {
return copyArc((Arc) obj, (Node) ((Arc) obj).getSource(),
(Node) ((Arc) obj).getTarget());
}
} catch (TypeException e) {
// Whoever use this function, could not
// recieve the Exception in case of type mismatch.
// so this method is deprecated.
System.out.println(e);
e.printStackTrace();
return null;
}
}
*/
public void graphDidChange() {
propagateChange(new Change(Change.MODIFIED));
}
public void unsetCriticalObjects() {
Iterator<?> e = this.itsArcs.iterator();
while (e.hasNext()) {
GraphObject o = (GraphObject) e.next();
o.setCritical(false);
}
e = this.itsNodes.iterator();
while (e.hasNext()) {
GraphObject o = (GraphObject) e.next();
o.setCritical(false);
}
}
public void unsetTransientAttrValues() {
this.unsetTransAttrValues(this.itsNodes.iterator());
this.unsetTransAttrValues(this.itsArcs.iterator());
}
private void unsetTransAttrValues(final Iterator<?> iter) {
while (iter.hasNext()) {
GraphObject go = (GraphObject)iter.next();
if (go.getAttribute() == null)
continue;
ValueTuple val = (ValueTuple) go.getAttribute();
for (int i = 0; i < val.getNumberOfEntries(); i++) {
ValueMember vm = val.getValueMemberAt(i);
if (vm.isTransient()) {
vm.setExpr(null);
}
}
}
}
public void unsetAttributeValueWhereVariable() {
this.unsetAttrValueWhichIsVar(this.itsNodes.iterator());
this.unsetAttrValueWhichIsVar(this.itsArcs.iterator());
}
private void unsetAttrValueWhichIsVar(final Iterator<?> iter) {
while (iter.hasNext()) {
GraphObject go = (GraphObject)iter.next();
if (go.getAttribute() == null)
continue;
ValueTuple vt = (ValueTuple) go.getAttribute();
for (int j = 0; j < vt.getNumberOfEntries(); j++) {
ValueMember vm = vt.getValueMemberAt(j);
if (vm.isSet() && vm.getExpr().isVariable())
vm.setExpr(null);
}
}
}
/**
* Tries to compute partial morphisms of this graph
* into the specified set of graph objects.
*
* @param set is target of morphisms
*
* @return set of computed partial morphisms,
* where keys are objects of this graph,
* values - objects of the specified target set
*/
public Vector<Hashtable<GraphObject, GraphObject>> getPartialMorphismIntoSet(
final Vector<GraphObject> set) {
if (set.isEmpty() || set.size() > this.getSize()) {
return null;
}
final Vector<Hashtable<GraphObject, GraphObject>>
result = new Vector<Hashtable<GraphObject, GraphObject>>();
final Hashtable<GraphObject, GraphObject>
store = new Hashtable<GraphObject, GraphObject>();
// create graph g from set and store new/original objects
Graph g = BaseFactory.theFactory().createGraph(this.getTypeSet());
for (int i = 0; i < set.size(); i++) {
GraphObject go = set.get(i);
if (go.isNode()) {
try {
Node n = g.copyNode((Node) go);
store.put(n, go);
} catch (TypeException e) {
}
} else {
try {
Arc a = g.copyArc((Arc) go, (Node) ((Arc) go).getSource(),
(Node) ((Arc) go).getTarget());
store.put(a, go);
} catch (TypeException e) {
}
}
}
// create morphism m: g -> this
OrdinaryMorphism m = BaseFactory.theFactory().createMorphism(g, this);
// because this can be LHS of a rule set variable attr context
((AttrTupleManager) m.getAttrManager()).setVariableContext(true);
while (m.nextCompletion()) {
final Hashtable<GraphObject, GraphObject>
table = new Hashtable<GraphObject, GraphObject>();
Enumeration<GraphObject> en = m.getDomain();
while (en.hasMoreElements()) {
GraphObject obj = en.nextElement();
GraphObject img = m.getImage(obj);
table.put(img, store.get(obj));
}
result.add(table);
}
return result;
}
/**
* Returns object domains for used types.
* The key of a node type is built by <code>type.convertToKey()</code>,
* the key of an arc type by
* <code>srcNodeType.convertToKey()+type.convertToKey()+tarNodeType.convertToKey()</code>.
*/
public Hashtable<String, HashSet<GraphObject>> getTypeObjectsMap() {
if (this.itsTypeObjectsMap.isEmpty()) {
fillTypeObjectsMap();
}
return this.itsTypeObjectsMap;
}
/**
* Refreshs object domains for used types.
*/
public void updateTypeObjectsMap() {
this.itsTypeObjectsMap.clear();
// fill domain vector of each type with new objects
fillTypeObjectsMap();
}
protected void addToTypeObjectsMap(GraphObject anObj) {
if (anObj.isNode()) {
extendTypeObjectsMapByNode((Node)anObj);
} else {
extendTypeObjectsMapByArc((Arc)anObj);
}
}
protected void removeNodeFromTypeObjectsMap(final Node anObj) {
if (anObj.getType().hasParent()) {
Vector<Type> myParents = anObj.getType().getAllParents();
for (int i = 0; i < myParents.size(); ++i) {
final String keystr = myParents.get(i).convertToKey();
final HashSet<GraphObject> anObjVec = this.itsTypeObjectsMap.get(keystr);
if (anObjVec != null) {
anObjVec.remove(anObj);
}
}
} else {
final String keystr = anObj.getType().convertToKey();
final HashSet<GraphObject> anObjVec = this.itsTypeObjectsMap.get(keystr);
if (anObjVec != null) {
anObjVec.remove(anObj);
}
}
}
protected void removeArcFromTypeObjectsMap(final Arc anObj) {
if (anObj.getSource() != null
&& anObj.getTarget() != null) {
if (anObj.getSource().getType().hasParent()
|| anObj.getTarget().getType().hasParent()) {
Vector<Type> mySrcParents = anObj.getSource().getType().getAllParents();
Vector<Type> myTarParents = anObj.getTarget().getType().getAllParents();
for (int i = 0; i < mySrcParents.size(); ++i) {
for (int j = 0; j < myTarParents.size(); ++j) {
String keystr = mySrcParents.get(i).convertToKey()
+ anObj.getType().convertToKey()
+ myTarParents.get(j).convertToKey();
final HashSet<GraphObject> anObjVec = this.itsTypeObjectsMap.get(keystr);
if (anObjVec != null) {
anObjVec.remove(anObj);
}
}
}
} else {
String keystr = anObj.convertToKey();
final HashSet<GraphObject> anObjVec = this.itsTypeObjectsMap.get(keystr);
if (anObjVec != null) {
anObjVec.remove(anObj);
}
}
}
}
protected void removeFromTypeObjectsMap(final GraphObject anObj) {
if (anObj instanceof Node)
removeNodeFromTypeObjectsMap((Node) anObj);
else
removeArcFromTypeObjectsMap((Arc) anObj);
}
public void fillTypeObjectsMap() {
Iterator<?> iter = this.itsNodes.iterator();
while (iter.hasNext()) {
final Node obj = (Node)iter.next();
extendTypeObjectsMapByNode(obj);
}
iter = this.itsArcs.iterator();
while (iter.hasNext()) {
extendTypeObjectsMapByArc((Arc)iter.next());
}
}
protected void extendTypeObjectsMap(final Type childType, final Type parentType) {
final Iterator<Node> iter = this.itsNodes.iterator();
while (iter.hasNext()) {
Node obj = iter.next();
if (childType.isParentOf(obj.getType())) {
extendTypeObjectsMapByNode(obj, parentType);
Iterator<Arc> iter2 = obj.getOutgoingArcsSet().iterator();
while (iter2.hasNext()) {
extendTypeObjectsMapByArc(iter2.next());
}
iter2 = obj.getIncomingArcsSet().iterator();
while (iter2.hasNext()) {
extendTypeObjectsMapByArc(iter2.next());
}
}
}
}
private void extendTypeObjectsMapByNode(final Node node, final Type parent) {
Vector<Type> newParents = parent.getAllParents();
for (int i = 0; i < newParents.size(); ++i) {
String keystr = newParents.get(i).convertToKey();
HashSet<GraphObject> anObjVec = this.itsTypeObjectsMap.get(keystr);
if (anObjVec == null) {
anObjVec = new LinkedHashSet<GraphObject>();
this.itsTypeObjectsMap.put(keystr, anObjVec);
}
anObjVec.add(node);
}
}
protected void extendTypeObjectsMapByNode(final Node node) {
if (node.getType().hasParent()) {
Vector<Type> myParents = node.getType().getAllParents();
for (int i = 0; i < myParents.size(); ++i) {
String keystr = myParents.get(i).convertToKey();
HashSet<GraphObject> objSet = this.itsTypeObjectsMap.get(keystr);
if (objSet == null) {
objSet = new LinkedHashSet<GraphObject>();
this.itsTypeObjectsMap.put(keystr, objSet);
}
objSet.add(node);
}
} else {
String keystr = node.convertToKey();
HashSet<GraphObject> objSet = this.itsTypeObjectsMap.get(keystr);
if (objSet == null) {
objSet = new LinkedHashSet<GraphObject>();
this.itsTypeObjectsMap.put(keystr, objSet);
}
objSet.add(node);
}
}
protected void extendTypeObjectsMapByArc(final Arc arc) {
if (this.itsTypes.hasInheritance()
&& arc.getSource().getType().hasParent()
|| arc.getTarget().getType().hasParent()) {
Vector<Type> srcParents = arc.getSource().getType().getAllParents();
Vector<Type> tarParents = arc.getTarget().getType().getAllParents();
for (int i = 0; i < srcParents.size(); ++i) {
for (int j = 0; j < tarParents.size(); ++j) {
String keystr = srcParents.get(i).convertToKey()
+ arc.getType().convertToKey()
+ tarParents.get(j).convertToKey();
HashSet<GraphObject> objSet = this.itsTypeObjectsMap.get(keystr);
if (objSet == null) {
objSet = new LinkedHashSet<GraphObject>();
this.itsTypeObjectsMap.put(keystr, objSet);
}
objSet.add(arc);
}
}
} else {
String keystr = arc.convertToKey();
HashSet<GraphObject> objSet = this.itsTypeObjectsMap.get(keystr);
if (objSet == null) {
objSet = new LinkedHashSet<GraphObject>();
this.itsTypeObjectsMap.put(keystr, objSet);
}
objSet.add(arc);
}
}
public void refreshAttributed() {
this.attributed = false;
Iterator<?> iter = this.itsNodes.iterator();
while (iter.hasNext()) {
GraphObject o = (GraphObject)iter.next();
if ((o.getType().getAttrType() != null)
&& (o.getType().getAttrType().getNumberOfEntries() != 0)) {
this.attributed = true;
}
}
iter = this.itsArcs.iterator();
while (iter.hasNext()) {
GraphObject o = (GraphObject)iter.next();
if ((o.getType().getAttrType() != null)
&& (o.getType().getAttrType().getNumberOfEntries() != 0)) {
this.attributed = true;
}
}
}
/**
* Trims the capacity of used vectors to be the vector's current
* size.
*/
public void trimToSize() {
this.observer.trimToSize();
this.itsUsingMorphs.trimToSize();
}
/*
private void showTypeMap(Hashtable<String, List<GraphObject>> d) {
System.out.println("****** TYPE DOMAINS ******");
Enumeration<String> keys = d.keys();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
System.out.println(key);
List<GraphObject> v = d.get(key);
for (int i = 0; i < v.size(); i++) {
GraphObject go = v.get(i);
System.out.print(go + " ");
}
System.out.println();
}
System.out.println("***********");
}
*/
java.lang.String s;
}