package agg.xt_basis;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Vector;
import agg.attribute.impl.ValueTuple;
import agg.util.Change;
public class UndirectedTypeGraph extends TypeGraph {
public UndirectedTypeGraph(TypeSet aTypeSet) {
super(aTypeSet);
}
/**
* 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) {
TypeError error = this.itsTypes.canCreateArc(
this, edgeType, source, target, currentTypeGraphLevel);
if (error != null)
error = this.itsTypes.canCreateArc(
this, edgeType, target, source, currentTypeGraphLevel);
return error;
}
/**
* Checks if the specified edge to create is allowed.
*/
public TypeError checkConnectValid(Type edgeType, Node source, Node target) {
if (this.itsTypes.getTypeGraph() == null
|| this.itsTypes.getLevelOfTypeGraphCheck() == TypeSet.DISABLED
|| this.itsTypes.getLevelOfTypeGraphCheck() == TypeSet.ENABLED_INHERITANCE)
return null;
Arc typearc = this.itsTypes.getTypeGraphArc(edgeType, source.getType(), target.getType());
if (typearc == null)
typearc = this.itsTypes.getTypeGraphArc(edgeType, target.getType(), source.getType());
if (typearc != null)
return null;
return new TypeError(TypeError.NO_SUCH_TYPE,
"The edge of the type \"" + edgeType.getName()
+ "\" is not allowed between node type \""
+ source.getType().getName() + "\" and \""
+ target.getType().getName() + "\".");
}
//???
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;
}
/**
* Creates and add a new UndirectedArc 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("UndirectedGraph.createArc:: Cannot create an UndirectedArc of type : "+type.getStringRepr()+" Source or target node is null!");
} else if (!this.isNode(src) || !this.isNode(tar)) {
throw new TypeException("UndirectedGraph.createArc:: Cannot create an UndirectedArc of type : "+type.getStringRepr()+" Source or target does not belong to this graph!");
}
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);
}
// TypeError typeError = this.checkConnectValid(t, src, tar);
// if (typeError != null) {
// throw new TypeException(typeError);
// }
Arc anArc = newArc(t, src, tar);
return anArc;
}
/**
* Creates a new UndirectedArc 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 {
UndirectedArc arc = null;
try {
arc = (UndirectedArc)this.createArc(orig.getType(), src, tar);
if (arc != null) {
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 UndirectedArc 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;
}
/**
* 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 UndirectedArc anArc = new UndirectedArc(t, src, tar, this);
TypeError typeError = this.itsTypes.addTypeGraphObject(anArc);
if (typeError != null) {
anArc.dispose();
throw new TypeException(typeError);
}
this.attributed = this.attributed || anArc.getAttribute() != null;
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;}
}
/**
* 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)) {
if (a.getSource().getType().isParentOf(source)
&& a.getTarget().getType().isParentOf(target))
return a;
else if (a.getSource().getType().isParentOf(target)
&& a.getTarget().getType().isParentOf(source))
return a;
}
}
return null;
}
protected void removeArc(final Arc a) {
if (a.getContext() == this) {
// remove arc from its source / target
((Node)a.getSource()).removeOut(a);
((Node)a.getTarget()).removeOut(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;
}
}
protected void removeArcFromTypeObjectsMap(final Arc arc) {
if (arc.getSource() != null
&& arc.getTarget() != null) {
if (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();
String keystr2 = tarParents.get(i).convertToKey()
+ arc.getType().convertToKey()
+ srcParents.get(j).convertToKey();
HashSet<GraphObject> objSet = this.itsTypeObjectsMap.get(keystr);
if (objSet == null) {
// look for inverse arc key
objSet = this.itsTypeObjectsMap.get(keystr2);
}
if (objSet != null) {
objSet.remove(arc);
}
}
}
} else {
String keystr = arc.convertToKey();
String keystr2 = ((UndirectedArc)arc).convertToInverseKey();
HashSet<GraphObject> objSet = this.itsTypeObjectsMap.get(keystr);
if (objSet == null) {
// look for inverse arc key
objSet = this.itsTypeObjectsMap.get(keystr2);
}
if (objSet != null) {
objSet.remove(arc);
}
}
}
}
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();
String keystr2 = tarParents.get(i).convertToKey()
+ arc.getType().convertToKey()
+ srcParents.get(j).convertToKey();
HashSet<GraphObject> objSet = this.itsTypeObjectsMap.get(keystr);
if (objSet == null) {
// look for inverse arc key
objSet = this.itsTypeObjectsMap.get(keystr2);
}
if (objSet == null) {
objSet = new LinkedHashSet<GraphObject>();
this.itsTypeObjectsMap.put(keystr, objSet);
}
objSet.add(arc);
}
}
} else {
String keystr = arc.convertToKey();
String keystr2 = ((UndirectedArc)arc).convertToInverseKey();
HashSet<GraphObject> objSet = this.itsTypeObjectsMap.get(keystr);
if (objSet == null) {
// look for inverse arc key
objSet = this.itsTypeObjectsMap.get(keystr2);
}
if (objSet == null) {
objSet = new LinkedHashSet<GraphObject>();
this.itsTypeObjectsMap.put(keystr, objSet);
}
objSet.add(arc);
}
}
}