package agg.xt_basis;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Vector;
import java.util.Hashtable;
import agg.attribute.AttrInstance;
import agg.attribute.impl.ValueTuple;
import agg.attribute.impl.VarMember;
import agg.util.Change;
import agg.util.Pair;
import agg.util.XMLHelper;
public class TypeGraph extends Graph {
/**
* Creates an empty type graph for the specified type set.
*/
public TypeGraph(TypeSet aTypeSet) {
super(aTypeSet);
this.completeGraph = false;
this.kind = GraphKind.TG;
}
/**
* prepare this graph for garbage collection. so cut all connections to
* other objects and dispose all graph object contained.
*/
public void dispose() {
this.observer.removeAllElements();
this.itsTypes.setLevelOfTypeGraph(TypeSet.DISABLED);
Iterator<?> iter = this.itsArcs.iterator();
while (iter.hasNext()) {
try {
this.destroyArc((Arc)iter.next(), false, false);
iter = this.itsArcs.iterator();
} catch (TypeException e) {
System.out.println("TypeGraph.dispose:: destroyArc FAILED!: "+e.getMessage());
}
}
iter = this.itsNodes.iterator();
while (iter.hasNext()) {
try {
Node n = (Node)iter.next();
if (!n.getType().hasChild()) {
this.destroyNode(n, false, false);
iter = this.itsNodes.iterator();
}
} catch (TypeException e) {
System.out.println("TypeGraph.dispose:: destroyNode FAILED!: "+e.getMessage());
}
}
super.dispose();
}
public void finalize() {
}
/**
* Only new type nodes are created for the node types inside of the
* specified types. The types should be a subset of the type set of this
* type graph.
*
* @param types
* is a subset of my type set.
*/
public void tryToExtendByTypeNodes(final Vector<Type> types) {
for (int i = 0; i < types.size(); i++) {
Type t = types.get(i);
if (!this.itsTypes.containsType(t))
continue;
if (!this.getElementsOfType(t).hasMoreElements()) {
if (t.isNodeType()) {
try {
createNode(t);
} catch (TypeException ex) {
}
} else if (t.isArcType()) {
}
}
}
}
private void refreshGraph() {
Iterator<?> iter = this.itsArcs.iterator();
while (iter.hasNext()) {
Arc o = (Arc) iter.next();
if (o.getType() == null
|| o.getSource() == null
|| o.getTarget() == null) {
this.removeArc(o);
iter = this.itsArcs.iterator();
}
}
iter = this.itsNodes.iterator();
while (iter.hasNext()) {
Node o = (Node)iter.next();
if (o.getType() == null) {
this.removeNode(o);
iter = this.itsNodes.iterator();
}
}
}
/**
* Adds a copy of the specified Graph g. The Graph g should be an instance
* of TypeGraph. The type graph check of this type graph should be disabled.
*
* @param g
* another TypeGraph instance
* @return true if a copy of the type graph g was added, otherwise false.
*/
public boolean addCopyOfGraph(final Graph g) {
synchronized (this) {
if (g instanceof TypeGraph) {
boolean failed = false;
if (this.itsTypes.getLevelOfTypeGraphCheck() == TypeSet.DISABLED) {
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;
}
if (type != null) {
if (type.getTypeGraphNodeObject() == null) {
try {
vtxCopy = this.newNode(type);
if (vtxCopy != null) {
// add inheritance edge
for (int i = 0; i < vtxOrig.getType()
.getParents().size(); i++) {
Type parentOrig = vtxOrig.getType()
.getParents().get(i);
Type parent = this.itsTypes
.getSimilarType(parentOrig);
if (parent == null) {
parent = this.itsTypes
.getTypeByName(parentOrig
.getName());
if (parent != null
&& !parent.isNodeType())
parent = null;
}
if (parent != null)
this.itsTypes.addInheritanceRelation(type,
parent);
}
vtxCopy.copyAttributes(vtxOrig);
vtxCopy.setContextUsage(vtxOrig
.getContextUsage());
memo1.put(vtxOrig, vtxCopy);
if(this.notificationRequired)
propagateChange(new Change(
Change.OBJECT_CREATED, vtxCopy));
}
} catch (TypeException e) {
// type node already exists
Node node = this.itsTypes.getTypeGraphNode(type);
memo1.put(vtxOrig, node);
}
}
else {
memo1.put(vtxOrig, type.getTypeGraphNodeObject());
}
}
}// while
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;
}
if (type != null) {
Node source = (Node) arcOrig.getSource();
Node target = (Node) arcOrig.getTarget();
Node srcImg = memo1.get(source);
Node tgtImg = memo1.get(target);
if (type.getTypeGraphArcObject(srcImg.getType(), tgtImg.getType()) == null) {
if (type.getName().equals("next")) {
if (srcImg.getType().getName().equals("Activity")
&& tgtImg.getType().getName().equals("Activity")) {
System.out.println("Activity - next - Activity");
}
else if (srcImg.getType().getName().equals("BusinessActivity")
&& tgtImg.getType().getName().equals("BusinessActivity")) {
System.out.println("BusinessActivity - next - BusinessActivity");
}
}
try {
arcCopy = this.newArc(type, srcImg, tgtImg);
if (arcCopy != null) {
arcCopy.copyAttributes(arcOrig);
arcCopy.setContextUsage(arcOrig
.getContextUsage());
Type srctype = arcCopy.getSource().getType();
Type tartype = arcCopy.getTarget().getType();
// check source multiplicity
int m1 = arcOrig.getType().getSourceMin(
arcOrig.getSource().getType(),
arcOrig.getTarget().getType());
type.setSourceMin(srctype, tartype, m1);
m1 = arcOrig.getType().getSourceMax(
arcOrig.getSource().getType(),
arcOrig.getTarget().getType());
type.setSourceMax(srctype, tartype, m1);
m1 = arcOrig.getType().getTargetMin(
arcOrig.getSource().getType(),
arcOrig.getTarget().getType());
type.setTargetMin(srctype, tartype, m1);
m1 = arcOrig.getType().getTargetMax(
arcOrig.getSource().getType(),
arcOrig.getTarget().getType());
type.setTargetMax(srctype, tartype, m1);
if(this.notificationRequired)
propagateChange(new Change(
Change.OBJECT_CREATED, arcCopy));
}
} catch (TypeException e) {}
}
}
}// while
memo1.clear();
refreshGraph();
} else {
failed = true;
}
return !failed;
}
return false;
}
}
public boolean makeFromPlainGraph(final Graph g) {
boolean failed = false;
if (this.itsTypes.getLevelOfTypeGraphCheck() == TypeSet.DISABLED) {
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;
}
if (type != null) {
if (type.getTypeGraphNodeObject() == null) {
try {
vtxCopy = this.newNode(type);
if (vtxCopy != null) {
// add inheritance edge
for (int i = 0; i < vtxOrig.getType()
.getParents().size(); i++) {
Type parentOrig = vtxOrig.getType()
.getParents().get(i);
Type parent = this.itsTypes
.getSimilarType(parentOrig);
if (parent == null) {
parent = this.itsTypes
.getTypeByName(parentOrig
.getName());
if (parent != null
&& !parent.isNodeType())
parent = null;
}
if (parent != null)
this.itsTypes.addInheritanceRelation(type,
parent);
}
vtxCopy.copyAttributes(vtxOrig);
vtxCopy.setContextUsage(vtxOrig
.getContextUsage());
memo1.put(vtxOrig, vtxCopy);
if(this.notificationRequired)
propagateChange(new Change(
Change.OBJECT_CREATED, vtxCopy));
}
} catch (TypeException e) {
// type node already exists
Node node = this.itsTypes.getTypeGraphNode(type);
memo1.put(vtxOrig, node);
}
}
else {
memo1.put(vtxOrig, type.getTypeGraphNodeObject());
}
}
}// while
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;
}
if (type != null) {
Node source = (Node) arcOrig.getSource();
Node target = (Node) arcOrig.getTarget();
Node srcImg = memo1.get(source);
Node tgtImg = memo1.get(target);
if (type.getTypeGraphArcObject(srcImg.getType(), tgtImg.getType()) == null) {
try {
arcCopy = this.newArc(type, srcImg, tgtImg);
if (arcCopy != null) {
arcCopy.copyAttributes(arcOrig);
arcCopy.setContextUsage(arcOrig
.getContextUsage());
Type srctype = arcCopy.getSource().getType();
Type tartype = arcCopy.getTarget().getType();
// check source multiplicity
int m1 = arcOrig.getType().getSourceMin(
arcOrig.getSource().getType(),
arcOrig.getTarget().getType());
type.setSourceMin(srctype, tartype, m1);
m1 = arcOrig.getType().getSourceMax(
arcOrig.getSource().getType(),
arcOrig.getTarget().getType());
type.setSourceMax(srctype, tartype, m1);
m1 = arcOrig.getType().getTargetMin(
arcOrig.getSource().getType(),
arcOrig.getTarget().getType());
type.setTargetMin(srctype, tartype, m1);
m1 = arcOrig.getType().getTargetMax(
arcOrig.getSource().getType(),
arcOrig.getTarget().getType());
type.setTargetMax(srctype, tartype, m1);
if(this.notificationRequired)
propagateChange(new Change(
Change.OBJECT_CREATED, arcCopy));
}
} catch (TypeException e) {}
}
}
}// while
memo1.clear();
refreshGraph();
} else {
failed = true;
}
return !failed;
}
/**
* Adds a copy of the specified Graph g. The Graph g should be an instance
* of TypeGraph. The type graph check of this type graph should be disabled.
*
* @param g
* another TypeGraph instance
* @param disabledTypeGraph
* has always to be true
* @return true if a copy of the type graph was added, otherwise false.
*/
public boolean addCopyOfGraph(final Graph g, final boolean disabledTypeGraph) {
return this.addCopyOfGraph(g);
}
public Graph copyLight(final TypeSet typeSet) {
synchronized (this) {
// int tglevel =
typeSet.getLevelOfTypeGraphCheck();
boolean failed = false;
final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(this
.getSize());
TypeGraph theCopy = typeSet.isArcDirected()? new TypeGraph(typeSet): new UndirectedTypeGraph(typeSet);
Iterator<?> iter = this.itsNodes.iterator();
while (!failed && 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.newNode(type);
/** side effect! */
if (vtxCopy != null) {
if (vtxCopy.getAttribute() != null
&& vtxOrig.getAttribute() != null)
((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) {
if (arcCopy.getAttribute() != null
&& arcOrig.getAttribute() != null)
((ValueTuple) arcCopy.getAttribute())
.copyEntriesToSimilarMembers(arcOrig
.getAttribute());
arcCopy.setContextUsage(arcOrig
.getContextUsage());
}
} catch (TypeException e) {
// e.printStackTrace();
failed = true;
theCopy.dispose();
}
}
}
memo1.clear();
if (failed)
return null;
return (theCopy);
}
}
/**
* Returns a copy of this type graph typed above the specified typeset. The
* specified typeset should be compatible to its typeset.
*/
public Graph copy(final TypeSet types) {
return graphcopy(types);
}
private Graph graphcopy(final TypeSet typeSet) {
synchronized (this) {
typeSet.getLevelOfTypeGraphCheck();
boolean failed = false;
Iterator<Arc> arcList = this.getArcsSet().iterator();
Iterator<Node> vtxList = this.getNodesSet().iterator();
TypeGraph theCopy = typeSet.isArcDirected()? new TypeGraph(typeSet): new UndirectedTypeGraph(typeSet);
final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(this
.getSize());
while (vtxList.hasNext() && !failed) {
Node vtxOrig = vtxList.next();
Node vtxCopy = null;
try {
Type type = typeSet.getSimilarType(vtxOrig.getType());
if (type != null) {
vtxCopy = theCopy.newNode(type);
/** side effect! */
if (vtxCopy != null) {
vtxCopy.copyAttributes(vtxOrig);
vtxCopy.setContextUsage(vtxOrig.getContextUsage());
memo1.put(vtxOrig, 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();
}
}// while
while (arcList.hasNext() && !failed) {
Arc arcOrig = arcList.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) {
arcCopy.copyAttributes(arcOrig);
arcCopy.setContextUsage(arcOrig.getContextUsage());
}
}
} catch (TypeException e) {
// If the given graph is well typed,
// the resulting graph should be also well typed
// e.printStackTrace();
failed = true;
theCopy.dispose();
}
}// while
memo1.clear();
if (failed)
return null;
return (theCopy);
}
}
/**
* Makes a copy of this graph
*
* @param orig2copy
* this hashtable is used to store the pairs (original, copy),
* where an original is a node or edge of this graph and a copy
* is a copied node or edge of the graph copy.
* @return a copy of this graph or null if an error occured
*/
public Graph copy(final Hashtable<GraphObject, GraphObject> orig2copy) {
return graphcopy(orig2copy);
}
/**
* Makes a copy of this graph
*
* @param orig2copy
* this hashtable is used to store the pairs (original, copy),
* where an original is a node or edge of this graph and a copy
* is a copied node or edge of the graph copy.
* @return a copy of this graph or null if an error occured
*/
protected Graph graphcopy(
final Hashtable<GraphObject, GraphObject> orig2copy) {
synchronized (this) {
boolean failed = false;
TypeGraph theCopy = new TypeGraph(getTypeSet());
Iterator<?> iter = this.itsNodes.iterator();
while (!failed && iter.hasNext()) {
Node vtxOrig = (Node)iter.next();
Node vtxCopy = null;
Type type = this.itsTypes.getSimilarType(vtxOrig.getType());
if (type != null) {
try {
vtxCopy = theCopy.newNode(type);
/** side effect! */
if (vtxCopy != null) {
vtxCopy.copyAttributes(vtxOrig);
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();
Type type = this.itsTypes.getSimilarType(arcOrig.getType());
if (type != null) {
try {
Node source = (Node) arcOrig.getSource();
Node target = (Node) arcOrig.getTarget();
Node srcImg = (Node) orig2copy.get(source);
Node tgtImg = (Node) orig2copy.get(target);
Arc arcCopy = theCopy.createArc(type, srcImg,
tgtImg);
if (arcCopy != null) {
arcCopy.copyAttributes(arcOrig);
arcCopy.setContextUsage(arcOrig
.getContextUsage());
orig2copy.put(arcOrig, arcCopy);
}
} catch (TypeException e) {
// e.printStackTrace();
failed = true;
theCopy.dispose();
}
}
}
if (failed)
return null;
return (theCopy);
}
}
/**
* The method returns a flat copy of the graph itself.
*/
public Graph graphcopy() {
synchronized (this) {
boolean failed = false;
final Hashtable<Node, Node> memo1 = new Hashtable<Node, Node>(this
.getSize());
TypeGraph theCopy = new TypeGraph(getTypeSet());
Iterator<?> iter = this.itsNodes.iterator();
while (!failed && iter.hasNext()) {
Node vtxOrig = (Node)iter.next();
Node vtxCopy = null;
try {
vtxCopy = theCopy.createNode(vtxOrig);
/** side effect! */
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();
try {
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) {
// e.printStackTrace();
failed = true;
theCopy.dispose();
}
}
memo1.clear();
if (failed)
return null;
return (theCopy);
}
}
/**
* Copy a graph The method returns a flat copy (without references) of the
* graph.
*/
public Graph copy() {
return this.graphcopy();
}
/**
* THIS METHOD IS NOT IMPLEMENTED FOR THIS CLASS.
*
* @return null
*/
public Graph graphcopy(TypeGraph g) {
return null;
}
/**
* Adds the specified node to my nodes. The type of the specified node has
* to be in my type set.
*/
public void addNode(final Node n) {
if (!this.itsNodes.contains(n)) {
TypeError typeError = this.itsTypes.addTypeGraphObject(n);
if (typeError != null) {
n.dispose();
} else {
this.itsNodes.add(n);
addNodeToTypeObjectsMap(n);
if (n.getAttribute() != null) {
((ValueTuple) n.getAttribute()).addObserver(n);
this.attributed = true;
}
this.changed = true;
}
}
}
/***************************************************************************
* Create a new Node as a copy of <code>orig</code>. Only the type and
* the * attributes are copied, the structural context (incoming/outgoing
* arcs) is not. *
**************************************************************************/
public Node copyNode(final Node orig) throws TypeException {
Node aNode = createNode(orig.getType());
if (aNode != null) {
if (orig.getAttribute() != null && aNode.getAttribute() == null) {
aNode.createAttributeInstance();
}
}
return aNode;
}
protected void removeNode(final Node n) {
if (this.itsNodes.contains(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);
// n.getType().removeTypeUser(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(final Arc a) {
if (!this.itsArcs.contains(a)) {
TypeError typeError = this.itsTypes.addTypeGraphObject(a);
if (typeError != null) {
a.dispose();
} else {
this.itsArcs.add(a);
addArcToTypeObjectsMap(a);
if (a.getAttribute() != null)
((ValueTuple) a.getAttribute()).addObserver(a);
this.changed = true;
}
}
}
protected void removeArc(final Arc a) {
if (this.itsArcs.contains(a)) {
((Node)a.getSource()).removeOut(a);
((Node)a.getTarget()).removeIn(a);
this.itsArcs.remove(a);
// a.getType().removeTypeUser(a);
removeArcFromTypeObjectsMap(a);
this.changed = true;
}
}
protected Node newNode(final Type t) throws TypeException {
final Node aNode = new Node(t, this);
TypeError typeError = this.itsTypes.addTypeGraphObject(aNode);
if (typeError != null) {
aNode.dispose();
throw new TypeException(typeError);
}
this.attributed = aNode.getAttribute() != null;
this.itsNodes.add(aNode);
addNodeToTypeObjectsMap(aNode);
this.changed = true;
if(this.notificationRequired)
propagateChange(new Change(Change.OBJECT_CREATED, aNode));
return aNode;
}
/** Create a new Node of the specified Type. */
public Node createNode(final Type type) throws TypeException {
Type t = this.itsTypes.adoptClan(type);
Node aNode = newNode(t);
return aNode;
}
/**
* Creates a new Node of the specified Type.
*/
public Node createTypeNode(final Type type) throws TypeException {
return createNode(type);
}
/**
* Returns the type graph node of the specified type or <code>null</code>.
*/
public Node getTypeNode(final Type type) {
return this.itsTypes.getTypeGraphNode(type);
}
/**
* Returns the attribute tuple of the type node of the specified type.
* Otherwise, if the node is not attributed - returns <code>null</code>.
*/
public AttrInstance getAttrValueOfTypeNode(final Type type) {
Node n = this.itsTypes.getTypeGraphNode(type);
if (n != null && !type.isAttrTypeEmpty()) {
return n.getAttribute();
}
return null;
}
/**
* @deprecated use the method <code>copyNode(Node orig)</code>
*/
public Node createNode(final Node orig) throws TypeException {
Node aNode = createNode(orig.getType());
if (aNode != null) {
if (orig.getAttribute() != null && aNode.getAttribute() == null)
aNode.createAttributeInstance();
}
return aNode;
}
/**
* Delete a Node. Dangling Arcs are deleted implicitly.
*
* @throws TypeException
* If the parameter forceDestroy is false and there are objects
* of this node, the type exception will be thrown, otherwise
* not.
*/
public synchronized void destroyNode(
final Node node,
final boolean checkFirst,
final boolean forceDestroy) throws TypeException {
TypeError typeError = null;
if (forceDestroy
|| this.itsTypes.getLevelOfTypeGraphCheck() <= TypeSet.DISABLED) {
this.itsTypes.forceRemoveTypeGraphObject(node);
} else {
typeError = this.itsTypes.removeTypeGraphObject(node);
if (!forceDestroy && (typeError != null)) {
throw new TypeException(typeError);
}
}
//TODO: move to the GUI Type Graph
boolean clanUsed = false; //this.itsTypes.isClanUsed(node.getType());
if (clanUsed
&& (this.itsTypes.getLevelOfTypeGraphCheck() != TypeSet.DISABLED)
&& (this.itsTypes.getLevelOfTypeGraphCheck() != TypeSet.ENABLED_INHERITANCE)) {
typeError = new TypeError(TypeError.TYPE_IS_IN_USE, "\nThe type \""
+ node.getType().getName()
+ "\" cannot be deleted from the type graph,"
+ "\nbecause at least one graph object uses it."
+ "\nPlease disable the type graph before delete a type.",
node, node.getType());
typeError.setContainingGraph(this);
}
if (!forceDestroy && (typeError != null))
throw new TypeException(typeError);
Type myType = node.getType();
this.itsTypes.removeAllInheritanceRelations(myType);
Iterator<Node> en = getNodesSet().iterator();
while (en.hasNext()) {
Node currentNode = en.next();
Type currentType = currentNode.getType();
for (int i = 0; i < currentType.getParents().size(); i++) {
Type p = currentType.getParents().get(i);
if (p == myType) {
this.itsTypes.removeInheritanceRelation(currentType, p);
if (currentNode.getAttribute() != null)
((ValueTuple) currentNode.getAttribute())
.refreshParents();
break;
}
}
}
this.itsTypes.refreshInheritanceArcs();
// 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();
}
if(this.notificationRequired)
propagateChange(new Change(Change.WANT_DESTROY_OBJECT, node));
this.itsNodes.remove(node);
this.changed = true;
if(this.notificationRequired)
propagateChange(new Change(Change.OBJECT_DESTROYED, node));
node.dispose();
}
/**
* Create a new Arc with given Type, source and target objects. Source and
* target object must be part of this graph.
*/
protected Arc newArc(final Type t, final Node src, final Node tar) throws TypeException {
final Arc anArc = new Arc(t, src, tar, this);
if (t.getAttrType() != null
&& t.getAttrType().getNumberOfEntries() != 0)
anArc.createAttributeInstance();
TypeError typeError = this.itsTypes.addTypeGraphObject(anArc);
if (typeError != null) {
anArc.dispose();
throw new TypeException(typeError);
}
if (anArc.getAttribute() != null)
this.attributed = true;
this.itsArcs.add(anArc);
addArcToTypeObjectsMap(anArc);
this.changed = true;
if(this.notificationRequired)
propagateChange(new Change(Change.OBJECT_CREATED, anArc));
return anArc;
}
protected Arc newArcFast(Type t, Node src, Node tar) {
try {
return this.newArc(t, src, tar);
} catch (TypeException ex) {
return null;}
}
/**
* Create a new Arc with given Type, source and target objects. Source and
* target object must be part of this graph.
*/
public Arc createArc(final Type type, final Node src, final Node tar) throws TypeException {
if (src == null || tar == null)
return null;
if (!this.isElement(src) || !this.isElement(tar))
return null;
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);
}
Arc anArc = newArc(t, src, tar);
return anArc;
}
/**
* Create a new Arc of the specified Type, source and target objects.
* Source and target object must be part of <code>this</code> graph.
*/
public Arc createTypeArc(final Type type, final Node src, final Node tar) throws TypeException {
return this.createArc(type, src, tar);
}
/**
* Returns the type graph edge of the specified type <code>t</code>, with
* a source node of the specified type <code>source</code> and a target
* node of the specified type <code>target</code>, otherwise returns
* <code>null</code>.
*/
public Arc getTypeGraphArc(final Type t, final Type source, final Type target) {
Iterator<Arc> arcs = this.itsArcs.iterator();
while (arcs.hasNext()) {
Arc a = arcs.next();
if (a.getType().compareTo(t)
&& a.getSource().getType().isParentOf(source)
&& a.getTarget().getType().isParentOf(target)) {
return a;
}
}
return null;
}
/* The TypeGraph already contains a similar edge
* with the source node is a parent of the specified source
* and the target node is a parent of the specified target node type.
* Returns this edge, otherwise - null.
*/
public Arc getTypeGraphParentArc(final Type t, final Type source, final Type target) {
Iterator<Arc> arcs = this.itsArcs.iterator();
while (arcs.hasNext()) {
Arc a = arcs.next();
if (a.getType().compareTo(t)
&& a.getSource().getType().isParentOf(source)
&& a.getTarget().getType().isParentOf(target)) {
return a;
}
}
return null;
}
/* The TypeGraph already contains a similar edge
* with the source node is a child of the specified source
* and the target node is a child of the specified target node type.
* Returns this edge, otherwise - null.
*/
public Arc getTypeGraphChildArc(final Type t, final Type source, final Type target) {
Iterator<Arc> arcs = this.itsArcs.iterator();
while (arcs.hasNext()) {
Arc a = arcs.next();
if (a.getType().compareTo(t)
&& a.getSource().getType().isChildOf(source)
&& a.getTarget().getType().isChildOf(target)) {
return a;
}
}
return null;
}
/**
* Create a new Arc as a copy of <code>orig</code>. Only the type and the
* attributes are copied, the structural context (source, target) is not.
* Source and target object must be part of this graph.
*/
public Arc copyArc(final Arc orig, final Node src, final Node tar) throws TypeException {
try {
Arc anArc = createArc(orig.getType(), src, tar);
if (anArc != null) {
if (orig.getAttribute() != null && anArc.getAttribute() == null) {
anArc.createAttributeInstance();
this.attributed = true;
}
}
return anArc;
} catch (TypeException ex) {
throw new TypeException("TypeGraph.copyArc:: Cannot create an Arc of type : "
+orig.getType().getName()
+" from "+src.getType().getName()
+" to "+tar.getType().getName()
+" "+ex.getLocalizedMessage());
}
}
/**
* The specified arc will be removed from this type graph.
*
* @throws TypeException
* If the parameter forceDestroy is false and there are objects
* of this node, the type exception will be thrown, otherwise
* not.
*/
public synchronized void destroyArc(final Arc arc, final boolean checkFirst,
final boolean forceDestroy) throws TypeException {
if (arc == null)
return;
TypeError typeError = null;
if (forceDestroy
|| this.itsTypes.getLevelOfTypeGraphCheck() <= TypeSet.DISABLED) {
this.itsTypes.forceRemoveTypeGraphObject(arc);
} else {
typeError = this.itsTypes.removeTypeGraphObject(arc);
if (!forceDestroy && (typeError != null)) {
throw new TypeException(typeError);
}
}
if(this.notificationRequired)
propagateChange(new Change(Change.WANT_DESTROY_OBJECT, arc));
this.itsArcs.remove(arc);
arc.dispose();
this.changed = true;
propagateChange(new Change(Change.OBJECT_DESTROYED, arc));
}
public boolean contains(final Graph g) {
boolean result = false;
if (g.isEmpty()) {
result = true;
} else {
if (this.getSize() >= g.getSize()) {
final Hashtable<GraphObject, GraphObject> table = new Hashtable<GraphObject, GraphObject>();
boolean found = true;
Iterator<?> iterG = g.getArcsSet().iterator();
while (found && iterG.hasNext()) {
Arc elemi = (Arc)iterG.next();
found = false;
Iterator<Arc> iter = this.itsArcs.iterator();
while (iter.hasNext()) {
Arc elemj = iter.next();
if (elemi.getType().compareTo(elemj.getType())) {
if (elemi.getSource() == elemi.getTarget()
&& elemj.getSource() == elemj.getTarget()) {
if (elemi.getSource().compareTo(elemj.getSource())) {
found = true;
table.put(elemi, elemj);
table.put(elemi.getSource(), elemj.getSource());
break;
}
} else if (elemi.getSource() != elemi.getTarget()
&& elemj.getSource() != elemj.getTarget()) {
if (elemi.getSource().compareTo(elemj.getSource())
&& elemi.getTarget().compareTo(elemj.getTarget())) {
found = true;
table.put(elemi, elemj);
table.put(elemi.getSource(), elemj.getSource());
table.put(elemi.getTarget(), elemj.getTarget());
break;
}
}
}
}
}
iterG = g.getNodesSet().iterator();
while (found && iterG.hasNext()) {
Node elemi = (Node)iterG.next();
found = false;
Iterator<Node> iter = this.itsNodes.iterator();
while (iter.hasNext()) {
Node elemj = iter.next();
if (table.get(elemi) == null) {
if (elemi.compareTo(elemj)) {
found = true;
table.put(elemi, elemj);
break;
}
}
}
}
if (table.size() == g.getSize()) {
result = true;
}
} else {
result = false;
}
}
return result;
}
/**
* Adds the given Node to the list for type key = anObj.getType().convertToKey().
*
*/
protected void addNodeToTypeObjectsMap(Node n) {
String keystr = n.getType().convertToKey();
HashSet<GraphObject> anObjVec = new LinkedHashSet<GraphObject>(1);
anObjVec.add(n);
this.itsTypeObjectsMap.put(keystr, anObjVec);
}
/**
* Adds the given Arc to the list of type key.
* key = ((Arc) anObj).getSource().getType().convertToKey()
* + anObj.getType().convertToKey() + ((Arc) anObj).getTarget().getType().convertToKey().
* Additionally, this Arc object is added to the keys of all children of its source
* resp. target Node because of the inherited edge relation.
*
*/
protected void addArcToTypeObjectsMap(Arc arc) {
Vector<Type> mySrcChildren = arc.getSource().getType().getAllChildren();
Vector<Type> myTarChildren = arc.getTarget().getType().getAllChildren();
for (int i = 0; i < mySrcChildren.size(); ++i) {
for (int j = 0; j < myTarChildren.size(); ++j) {
String keystr = mySrcChildren.get(i).convertToKey()
+ arc.getType().convertToKey()
+ myTarChildren.get(j).convertToKey();
HashSet<GraphObject> anObjVec = new LinkedHashSet<GraphObject>(1);
anObjVec.add(arc);
this.itsTypeObjectsMap.put(keystr, anObjVec);
}
}
}
/**
* Adds the given GraphObject to the list for type key.
* For a Node object then key = anObj.getType().convertToKey(),
* for an Arc object then key = ((Arc) anObj).getSource().getType().convertToKey()
* + anObj.getType().convertToKey() + ((Arc) anObj).getTarget().getType().convertToKey().
* Additionally, this Arc object is added to the keys for all children of its source
* resp. target Node because of the inherited edge relation.
*
*/
protected void addToTypeObjectsMap(GraphObject anObj) {
if (anObj.isNode()) {
this.addNodeToTypeObjectsMap((Node) anObj);
} else {
this.addArcToTypeObjectsMap((Arc) anObj);
}
}
protected void removeNodeFromTypeObjectsMap(final Node anObj) {
final String keystr = anObj.getType().convertToKey();
this.itsTypeObjectsMap.remove(keystr);
}
protected void removeArcFromTypeObjectsMap(final Arc anObj) {
if (anObj.getSource() != null
&& anObj.getTarget() != null) {
Vector<Type> mySrcChildren = anObj.getSource().getType().getAllChildren();
Vector<Type> myTarChildren = anObj.getTarget().getType().getAllChildren();
for (int i = 0; i < mySrcChildren.size(); ++i) {
for (int j = 0; j < myTarChildren.size(); ++j) {
String keystr = mySrcChildren.get(i).convertToKey()
+ anObj.getType().convertToKey()
+ myTarChildren.get(j).convertToKey();
this.itsTypeObjectsMap.remove(keystr);
}
}
}
}
/**
* Extends the type-objects map by adding all inherited edges of the given node type
* as child type.
*
*/
protected void extendTypeObjectsMap(final Type nodeType) {
// System.out.println("TypeGraph.extendTypeObjectsMap: ");
Node parNode = null;
List<Type> parents = nodeType.getAllParents();
for (int i=0; i<parents.size(); i++) {
final Type parType = parents.get(i);
String typeKey = parType.convertToKey();
if (this.itsTypeObjectsMap.get(typeKey) != null
&& !this.itsTypeObjectsMap.get(typeKey).isEmpty())
parNode = (Node)this.itsTypeObjectsMap.get(typeKey).iterator().next();
if (parNode != null) {
Iterator<Arc> parArcs = parNode.getOutgoingArcsSet().iterator();
while (parArcs.hasNext()) {
Arc a = parArcs.next();
if (a.isInheritance())
continue;
String keystr = nodeType.convertToKey()
.concat(a.getType().convertToKey())
.concat(a.getTargetType().convertToKey());
HashSet<GraphObject> anObjVec = new LinkedHashSet<GraphObject>(1);
anObjVec.add(a);
this.itsTypeObjectsMap.put(keystr, anObjVec);
// System.out.println("TypeGraph.extendTypeObjectsMap: "
// +nodeType.getName()+" - "
// +a.getType().getName()+" -> "
// +a.getTargetType().getName());
}
parArcs = parNode.getIncomingArcsSet().iterator();
while (parArcs.hasNext()) {
Arc a = parArcs.next();
if (a.isInheritance())
continue;
String keystr = a.getSourceType().convertToKey()
.concat(a.getType().convertToKey())
.concat(nodeType.convertToKey());
HashSet<GraphObject> anObjVec = new LinkedHashSet<GraphObject>(1);
anObjVec.add(a);
this.itsTypeObjectsMap.put(keystr, anObjVec);
// System.out.println("TypeGraph.extendTypeObjectsMap: "
// +a.getSourceType().getName()+" - "
// +a.getType().getName()+" -> "
// +nodeType.getName());
}
}
}
}
/**
* This method is not defined for this class.
*/
public boolean isUsingVariable(VarMember v) {
return false;
}
/**
* This method is not defined for this class.
*/
public synchronized boolean glue(GraphObject keep, GraphObject glue) {
return false;
}
/**
* This method is not defined for this class.
*/
public boolean isReadyForTransform() {
return false;
}
/**
* This method is not defined for this class.
*/
public boolean isReadyForTransform(Vector<GraphObject> storeOfFailedObjs) {
return false;
}
/**
* This method is not defined for this class.
*/
public OrdinaryMorphism isomorphicCopy() {
return null;
}
/**
* This method is not defined for this class.
*/
public OrdinaryMorphism isoToCopy() {
return null;
}
/**
* This method is not defined for this class.
*/
public OrdinaryMorphism isoToCopy(int n) {
return null;
}
/**
* This method is not defined for this class.
*/
public OrdinaryMorphism reverseIsomorphicCopy() {
return null;
}
/**
* This method is not defined for this class.
*/
public Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings(Graph g, boolean withIsomorphic) {
return null;
}
/**
* This method is not defined for this class.
*/
public Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings(Graph g, boolean disjunion,
boolean withIsomorphic) {
return null;
}
/**
* This method is not defined for this class.
*/
public Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings(Graph g, int sizeOfInclusions,
boolean withIsomorphic) {
return null;
}
/**
* This method is not defined for this class.
*/
public Enumeration<Pair<OrdinaryMorphism, OrdinaryMorphism>> getOverlappings(Graph g, int sizeOfInclusions,
boolean disjunion, boolean withIsomorphic) {
return null;
}
public void XwriteObject(XMLHelper h) {
h.openNewElem("Graph", this);
h.addAttr("name", getName());
if (!this.kind.equals(""))
h.addAttr("kind", this.kind);
if (!this.comment.equals(""))
h.addAttr("comment", this.comment);
if (!this.info.equals(""))
h.addAttr("info", this.info);
h.addIteration("", this.itsNodes.iterator(), true);
// multiplicity will be written by node
h.addIteration("", this.itsArcs.iterator(), true);
// multiplicity will be written by arc
h.close();
}
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("kind");
if (!str.equals(""))
this.kind = 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
// e.printStackTrace();
System.out.println("TypeGraph.XreadObject: cannot load a Node: "+e.getMessage());
}
// load multiplicity, if this is the type graph
// read the multiplicities
String m = h.readAttr("sourcemin");
if (!"".equals(m)) {
try {
t.setSourceMin(Integer.parseInt(m));
} catch (NumberFormatException e) {
t.setSourceMin(Type.UNDEFINED);
}
} else
t.setSourceMin(Type.UNDEFINED);
m = h.readAttr("sourcemax");
if (!"".equals(m)) {
try {
t.setSourceMax(Integer.parseInt(m));
} catch (NumberFormatException e) {
t.setSourceMax(Type.UNDEFINED);
}
} else
t.setSourceMax(Type.UNDEFINED);
}
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) {
Arc a = null;
try {
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("TypeGraph.XreadObject: cannot load an Arc: "+e.getMessage());
// e.printStackTrace();
}
// load multiplicity, if this is the type graph
Type sourceType = n1.getType();
Type targetType = n2.getType();
// read the multiplicities
String m = h.readAttr("sourcemin");
if (!"".equals(m)) {
try {
t.setSourceMin(sourceType, targetType, Integer
.parseInt(m));
} catch (NumberFormatException e) {
t.setSourceMin(sourceType, targetType, Type.UNDEFINED);
}
} else
t.setSourceMin(sourceType, targetType, Type.UNDEFINED);
m = h.readAttr("sourcemax");
if (!"".equals(m)) {
try {
t.setSourceMax(sourceType, targetType, Integer
.parseInt(m));
} catch (NumberFormatException e) {
t.setSourceMax(sourceType, targetType, Type.UNDEFINED);
}
} else
t.setSourceMax(sourceType, targetType, Type.UNDEFINED);
m = h.readAttr("targetmin");
if (!"".equals(m)) {
try {
t.setTargetMin(sourceType, targetType, Integer
.parseInt(m));
} catch (NumberFormatException e) {
t.setTargetMin(sourceType, targetType, Type.UNDEFINED);
}
} else
t.setTargetMin(sourceType, targetType, Type.UNDEFINED);
m = h.readAttr("targetmax");
if (!"".equals(m)) {
try {
t.setTargetMax(sourceType, targetType, Integer
.parseInt(m));
} catch (NumberFormatException e) {
t.setTargetMax(sourceType, targetType, Type.UNDEFINED);
}
} else
t.setTargetMax(sourceType, targetType, Type.UNDEFINED);
}
h.close();
}
h.close();
}
}
/**
* This method is not implemented for this class.
*/
public Vector<OrdinaryMorphism> generateAllSubgraphs(int sizeOfInclusions,
boolean union, boolean withIsomorphic) {
return null;
}
/**
* This method is not implemented for this class.
*/
public Vector<OrdinaryMorphism> generateAllSubgraphsWithInclusionsOfSize(
int i, Vector<GraphObject> itsGOSet, Vector<OrdinaryMorphism> inclusions, boolean withIsomorphic) {
return null;
}
/**
* Returns true.
*/
public boolean isTypeGraph() {
return true;
}
/**
* Returns false.
*/
public boolean isCompleteGraph() {
return false;
}
/**
* Returns false.
*/
public boolean isNacGraph() {
return false;
}
/**
* This method is not defined for this class.
*/
public Vector<String> getVariableNamesOfAttributes() {
return null;
}
/**
* This method is not defined for this class.
*/
public Vector<VarMember> getSameVariablesOfAttributes() {
return null;
}
/**
* This method is not defined for this class.
*/
public void unsetCriticalObjects() {
}
/**
* This method is not defined for this class.
*/
public void unsetTransientAttrValues() {
}
/**
* This method is not defined for this class.
*/
public Vector<Hashtable<GraphObject, GraphObject>> getPartialMorphismIntoSet(
Vector<GraphObject> set) {
return null;
}
}