package agg.xt_basis; import java.util.Collection; import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Vector; import java.util.Hashtable; import agg.attribute.AttrManager; import agg.attribute.impl.AttrTupleManager; import agg.attribute.impl.DeclTuple; import agg.attribute.impl.DeclMember; import agg.attribute.impl.ValueTuple; import agg.cons.AtomConstraint; import agg.util.Pair; /** * Manages the node/edge types of graphs. * Especially the rules and host graphs * of a graph transformation system (gratra) * should use the same type set. * * Implements methods for creation, deletion and manipulation * of node/edge types, a type graph, * inheritance relations between node types, * checking type validity. * * @version $Id: TypeSet.java,v 1.87 2010/12/02 19:37:59 olga Exp $ * @author $Author: olga $ */ public class TypeSet { /** Value for unknown level of type graph check */ public static final int UNDEFINED = -1; /** Level of type graph check to disable type graph */ public static final int DISABLED = 0; /** Level of type graph check to enable inheritance relation only */ public static final int ENABLED_INHERITANCE = 5; /** Level of type graph check to enable type graph and no multiplicity */ public static final int ENABLED = 10; /** Level of type graph check to enable type graph and max multiplicity */ public static final int ENABLED_MAX = 20; /** * Level of type graph check to enable type graph and max and min * multiplicity */ public static final int ENABLED_MAX_MIN = 30; /** Level of type graph check to enable type graph and min multiplicity */ public static final int ENABLED_MIN = 40; /** * returned instead of a list of {@link TypeError}s, * if there were none. */ private static final Collection<TypeError> SUCCESS = new Vector<TypeError>(0); /** * the types of the edges and nodes will be hold in this list */ private final Vector<Type> types = new Vector<Type>(); private boolean directed = true; private boolean parallel = true; private boolean emptyAttr = true; /** * dummy type for inheritance arcs, * which are always without attributes */ private final Type inheritanceType = new ArcTypeImpl(); /** * inheritance edges within the type graph */ private final Vector<Arc> inheritanceArcs = new Vector<Arc>(); /** * the graph describing combinations of node and edge types */ private TypeGraph typeGraph; /** * manager for attributes */ private final AttrManager attrManager = AttrTupleManager.getDefaultManager(); /** * is true, if a type graph exists and it was successfully checked * Only if true, a TypeSet is able to check the types of graphs. */ private boolean typeGraphIsProved = false; /** * holds the level of type graph check * Possible values: * {@link #DISABLED}, {@link #ENABLED}, * {@link #ENABLED_MAX}, {@link #ENABLED_MAX_MIN} */ private int typeGraphLevel = DISABLED; private boolean newTypeGraphObjectImported; protected String info = ""; /** * creates a new type manager. with no types defined and no type graph * given. */ public TypeSet() {} public TypeSet(boolean directedArcs, boolean parallelArcs) { this.directed = directedArcs; this.parallel = parallelArcs; } public void dispose() { if (this.typeGraph != null) { this.typeGraph.dispose(); } for (int j=0; j<this.types.size(); j++) { Type type = this.types.get(j); if (type.isArcType()) { type.dispose(); this.types.remove(j); j--; } } for (int j=0; j<this.types.size(); j++) { Type type = this.types.get(j); if (type.hasChild()) { List<Type> clan = type.getClan(); for (int i = 0; i < clan.size(); i++) { removeInheritanceRelation(clan.get(i), type); } } this.types.remove(j); type.dispose(); j--; } // at this point the types should be already empty! for (int j=0; j<this.types.size(); j++) { Type type = this.types.get(j); if (!type.hasChild()) { type.dispose(); this.types.remove(j); j--; } } this.typeGraph = null; } public void finalize() { } /** * Creates a new Type instance without attribute type. It is * useful for non-attributed graphs. * * @deprecated replaced by * <code>Type createNodeType(boolean withAttributes)</code> for node type * and * <code>Type createArcType(boolean withAttributes)</code> for edge type */ public final Type createType() { Type aType = createType(false); return aType; } /* * Creates a new Type object. If the specified parameter is * TRUE, the attribute type is created, too, otherwise the attribute type is * null. * * @deprecated replaced by * <code>Type createNodeType(boolean withAttributes)</code> for node type * and * <code>Type createArcType(boolean withAttributes)</code> for edge type */ @SuppressWarnings("deprecation") public final Type createType(final boolean withAttributes) { if (withAttributes) { Type aType = new TypeImpl(this.attrManager.newType()); this.types.add(aType); return aType; } Type aType = new TypeImpl(); this.types.add(aType); return aType; } public final Type createNodeType(final boolean withAttributes) { if (withAttributes) { Type aType = new NodeTypeImpl(this.attrManager.newType()); this.types.add(aType); return aType; } Type aType = new NodeTypeImpl(); this.types.add(aType); return aType; } public final Type createArcType(final boolean withAttributes) { if (withAttributes) { Type aType = new ArcTypeImpl(this.attrManager.newType()); this.types.add(aType); return aType; } Type aType = new ArcTypeImpl(); this.types.add(aType); return aType; } public boolean isEmpty() { return (this.types.size() == 0) ? true : false; } /** * Iterate through all the valid types that may be given to a * GraphObject. * Enumeration elements are of type <code>Type</code>. * * * @see agg.xt_basis.Type */ public final Enumeration<Type> getTypes() { return this.types.elements(); } public final int getTypesCount() { return this.types.size(); } /** * * @return a list with node/edge types */ public final List<Type> getTypeList() { return this.types; } /** * @deprecated replaced by List<Type> getTypeList() * @return a list with node/edge types */ public final Vector<Type> getTypesVec() { return this.types; } /** * Returns a set of inheritance edges. An inheritance edge is especial edge * kind. It is not in the edge set of a type graph and it cannot be get by * typeSet.getTypeGraph().getArcs(). */ public final Vector<Arc> getInheritanceArcs() { return this.inheritanceArcs; } public final Type getInheritanceType() { return this.inheritanceType; } /** * Returns true, if a type graph exists and it is a type graph with node * type inheritance, otherwise returns false. */ public boolean hasInheritance() { return !this.inheritanceArcs.isEmpty(); } /** * Returns true, if a type graph exists and it is a type graph with node * type inheritance, otherwise returns false. */ public boolean usesInheritance() { return !this.inheritanceArcs.isEmpty(); } /** * Returns a type with the specified name and additional graphical * representation if it is found, otherwise <code>null</code>. */ public Type getTypeByNameAndAdditionalRepr(final String name, final String addRepr) { for (int i = 0; i < this.types.size(); i++) { Type t = this.types.elementAt(i); if ((t.getStringRepr().equals(name) || ("unnamed".equals(name) && "".equals(t.getStringRepr()))) && t.getAdditionalRepr().equals(addRepr)) return t; } return null; } /** * Returns a type with the specified name if it is found, otherwise * <code>null</code> Here the graphical represantation of a node or edge * type is not taken in account. That can be a problem, when there exists a * node type and an edge type with equal names. The method <c>Type * getTypeByNameAndAdditionalRepr(String name, String addRepr)</c> should * be used. */ public Type getTypeByName(final String name) { for (int i = 0; i < this.types.size(); i++) { Type t = this.types.elementAt(i); if (t.getStringRepr().equals(name) || ("unnamed".equals(name) && "".equals(t.getStringRepr()))) { return t; } } return null; } /** * Returns a type with the specified name or <code>null</code> * * @deprecated <code>Type getTypeByName(String name)</code> should be used */ public Type getTypeForName(final String name) { for (int i = 0; i < this.types.size(); i++) { Type t = this.types.elementAt(i); if (t.getStringRepr().equals(name) || ("unnamed".equals(name) && "".equals(t.getStringRepr()))) return t; } return null; } /** * Returns a type which is similar to the specified type: the type names, * the graphical representation such as color, node shape of node type or * edge style of edge type, the number of attributes, the name and type of * attribute member should be equal, otherwise returns <code>null</code>. */ public Type getSimilarType(final Type t) { for (int i = 0; i < this.types.size(); i++) { Type ti = this.types.elementAt(i); if (ti.compareTo(t)) { return ti; } } return null; } /** * Returns the type graph node of the specified type or <code>null</code>. */ public Node getTypeGraphNode(final Type t) { return t.getTypeGraphNodeObject(); } /** * 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 getTypeGraphArcOLD(final Type t, final Type source, final Type target) { if (this.typeGraph == null) return null; Arc result = null; Vector<Type> parents = source.getAllParents(); for (int j = 0; j < parents.size(); j++) { Type p = parents.get(j); Iterator<Node> nodes = this.typeGraph.getNodesSet().iterator(); while (nodes.hasNext()) { Node n = nodes.next(); if (n.getType().compareTo(p)) { Iterator<Arc> outs = n.getOutgoingArcsSet().iterator(); while (outs.hasNext()) { Arc arc = outs.next(); if (arc.getType().compareTo(t)) { if (arc.getTarget().getType().isParentOf(target)) { result = arc; } } } } } } return result; } public Arc getTypeGraphArc(final Type t, final Type source, final Type target) { if (this.typeGraph == null) return null; return this.typeGraph.getTypeGraphArc(t, source, target); // Iterator<Arc> arcs = this.typeGraph.getArcsSet().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; } /** * Returns the type graph or <code>null</code>, * if no type graph was created before. */ public Graph getTypeGraph() { return this.typeGraph; } public void setArcDirected(boolean b) { this.directed = b; } public boolean isArcDirected() { return this.directed; } public void setArcParallel(boolean b) { this.parallel = b; } public boolean isArcParallel() { return this.parallel; } /* * Allows or prohibits empty attribute values of new objects * of the RHS of a rule and also of the host graphs. */ public void setAllowEmptyAttr(boolean b) { this.emptyAttr = b; } public boolean isEmptyAttrAllowed() { return this.emptyAttr; } /** * Set the specified graph to be the type graph. * The method {@link #checkTypeGraph} should be called before to use {@link #checkType}. * * @param tGraph * a Graph which uses <code>this</code> TypeSet and contains only one node of each type. * In case of <code>null</code>, the type graph check will not be longer used. */ public void setTypeGraph(final Graph tGraph) { if (tGraph != null) { if (!this.compareTo(tGraph.getTypeSet())) { throw new RuntimeException( "Setting type graph failed. The specified graph does not use the same types."); } if (this != tGraph.getTypeSet()) { tGraph.setTypeSet(this); } } this.typeGraph = (TypeGraph) tGraph; this.typeGraphIsProved = false; } public void removeTypeGraph() { this.typeGraphLevel = TypeSet.DISABLED; this.typeGraph = null; } public void destroyTypeGraph() { if (this.typeGraph != null) { this.typeGraphLevel = TypeSet.DISABLED; this.typeGraph.dispose(); this.typeGraph = null; } } /** * If the parameter <code>all</code> is true, then a copy * of each type of the <code>otherTypes</code> will be created, * otherwise only of the not found types. */ public void adaptTypes(final TypeSet otherTypes, final boolean all) { doAdaptTypes(otherTypes.getTypes(), all); } /** * If the parameter <code>all</code> is true, then a copy will be created * of each type of the <code>otherTypes</code>, * otherwise only of not found type. */ public void adaptTypes(final Enumeration<Type> otherTypes, final boolean all) { doAdaptTypes(otherTypes, all); } private void doAdaptTypes(final Enumeration<Type> otherTypes, final boolean all) { Vector<Pair<Type, Type>> v = new Vector<Pair<Type, Type>>(5); while (otherTypes.hasMoreElements()) { Type t = otherTypes.nextElement(); Type similar = getTypeByNameAndAdditionalRepr(t.getStringRepr(), t .getAdditionalRepr()); if (similar == null) { Type type = adoptType(t); for (int i = 0; i < t.getParents().size(); i++) { Type parType = t.getParents().get(i); if (parType != null) { v.add(new Pair<Type, Type>(type, parType)); } } } else { for (int i = 0; i < t.getParents().size(); i++) { Type parType = t.getParents().get(i); if (parType != null) { v.add(new Pair<Type, Type>(similar, parType)); } } if (all) { if (similar instanceof NodeTypeImpl) ((NodeTypeImpl) similar).adaptTypeAttribute(t); else if (similar instanceof ArcTypeImpl) ((ArcTypeImpl) similar).adaptTypeAttribute(t); } } } for (int i = 0; i < v.size(); i++) { Pair<Type, Type> pair = v.get(i); Type type = pair.first; Type parent = pair.second; Type itsParent = getTypeByNameAndAdditionalRepr(parent .getName(), parent.getAdditionalRepr()); if (itsParent != null) { // final TypeError error = addInheritanceRelation(type, itsParent); } } while (otherTypes.hasMoreElements()) { Type t = otherTypes.nextElement(); Type similar = getTypeByNameAndAdditionalRepr(t.getStringRepr(), t .getAdditionalRepr()); if (similar != null) { similar.adaptTypeAttribute(t); } else { System.out.println(this.getClass().getName()+".doAdaptTypes:: FAILED type: "+ t.getStringRepr()); } } } private void adaptTypeInheritance( final Graph tGraph, final Vector<Type> typesToAdapt, final Hashtable<Type, Vector<Type>> oldInheritance) { if (tGraph == null || this.typeGraph == null || !this.typeGraph.getNodesSet().iterator().hasNext() || typesToAdapt.isEmpty()) return; Iterator<Node> e = this.typeGraph.getNodesSet().iterator(); while (e.hasNext()) { Node n = e.next(); Type t = n.getType(); Type t1 = tGraph.getTypeSet().getTypeByName(t.getStringRepr()); // t.getName()); if (t1 != null && t1.isNodeType() && typesToAdapt.contains(t1)) { Node tn = tGraph.getTypeSet().getTypeGraphNode(t1); if (tn != null) { if (!t1.getParents().isEmpty()) { for (int i = 0; i < t1.getParents().size(); i++) { Type p1i = t1.getParents().get(i); addInheritanceRelation(t, getTypeByNameAndAdditionalRepr(p1i .getStringRepr(), p1i .getAdditionalRepr())); } } else if (oldInheritance.get(t) != null) { Vector<Type> v = oldInheritance.get(t); for (int i = 0; i < v.size(); i++) { Type pi = v.get(i); addInheritanceRelation(t, pi); } } else removeAllInheritanceRelations(t); if (n.getAttribute() != null) ((ValueTuple) n.getAttribute()).refreshParents(); } } } } private void adaptTypeMultiplicity(final Graph tGraph, final Vector<Type> typesToAdapt) { if (tGraph == null || this.typeGraph == null || !this.typeGraph.getNodesSet().iterator().hasNext() || typesToAdapt.isEmpty()) return; Iterator<?> e = this.typeGraph.getNodesSet().iterator(); while (e.hasNext()) { Node n = (Node) e.next(); Type t = n.getType(); Type t1 = tGraph.getTypeSet().getTypeByName(t.getStringRepr()); // getName()); if (t1 != null && t1.isNodeType() && typesToAdapt.contains(t1)) { if (t.getSourceMax() != -1) { if ((t1.getSourceMax() == -1) || (t1.getSourceMax() > t.getSourceMax())) t.setSourceMax(t1.getSourceMax()); } if (t.getSourceMin() != -1) { if ((t1.getSourceMin() != -1) || (t1.getSourceMin() > t.getSourceMin())) t.setSourceMin(t1.getSourceMin()); } } } e = this.typeGraph.getArcsSet().iterator(); while (e.hasNext()) { Arc a = (Arc) e.next(); Type t = a.getType(); Type src_t = a.getSource().getType(); Type tar_t = a.getTarget().getType(); TypeGraphArc subt = t.getTypeGraphArc(src_t, tar_t); Type t1 = tGraph.getTypeSet().getTypeByNameAndAdditionalRepr( t.getName(), t.getAdditionalRepr()); Type src_t1 = tGraph.getTypeSet().getTypeByNameAndAdditionalRepr( src_t.getName(), src_t.getAdditionalRepr()); Type tar_t1 = tGraph.getTypeSet().getTypeByNameAndAdditionalRepr( tar_t.getName(), tar_t.getAdditionalRepr()); if (t1 != null && src_t1 != null && tar_t1 != null && typesToAdapt.contains(t1)) { Arc a1 = this.getTypeGraphArc(t1, src_t1, tar_t1); if (a1 != null) { TypeGraphArc subt1 = t1.getTypeGraphArc(src_t1, tar_t1); if (subt1 != null) { if (subt.getSourceMin() != -1) { if ((subt1.getSourceMin() != -1) || (subt1.getSourceMin() > subt .getSourceMin())) subt.setSourceMin(subt1.getSourceMin()); } if (subt.getSourceMax() != -1) { if ((subt1.getSourceMax() != -1) || (subt1.getSourceMax() > subt .getSourceMax())) subt.setSourceMax(subt1.getSourceMax()); } if (subt.getTargetMin() != -1) { if ((subt1.getTargetMin() != -1) || (subt1.getTargetMin() > subt .getTargetMin())) subt.setTargetMin(subt1.getTargetMin()); } if (subt.getTargetMax() != -1) { if ((subt1.getTargetMax() != -1) || (subt1.getTargetMax() > subt .getTargetMax())) subt.setTargetMax(subt1.getTargetMax()); } } } } } } /** * Here the double attribute members of parent-child relation would be * checked. If two or more attribute members with the same name are found, * the name will be extended by "?". The double clan edges would be removed, * too. */ private void adaptClans() { if (this.typeGraph == null || !this.typeGraph.getNodesSet().iterator().hasNext()) { return; } // check clans Iterator<Node> e = this.typeGraph.getNodesSet().iterator(); while (e.hasNext()) { Node n = e.next(); Type t = n.getType(); List<Type> clan = t.getClan(); List<Node> clanNodes = new Vector<Node>(5); // check double attrs of the clan types for (int i = 0; i < clan.size(); i++) { Type ct = clan.get(i); ct.checkDoubleAttributeType(); Node cn = this.typeGraph.getTypeSet().getTypeGraphNode(ct); if (cn != null) clanNodes.add(cn); } // check edges of a clan Vector<Arc> clanArcs = new Vector<Arc>(5); for (int i = 0; i < clanNodes.size(); i++) { Node cn = clanNodes.get(i); Iterator<Arc> arcs = cn.getIncomingArcsSet().iterator(); while (arcs.hasNext()) { Arc a = arcs.next(); if (!a.isInheritance() && !clanArcs.contains(a)) { if (((Node) a.getSource() != n) && clanNodes.contains(a.getSource())) { clanArcs.add(a); } } } if (this.directed) { // check more arcs = cn.getOutgoingArcsSet().iterator(); while (arcs.hasNext()) { Arc a = arcs.next(); if (!a.isInheritance() && !clanArcs.contains(a)) { if (((Node) a.getTarget() != n) && clanNodes.contains(a.getTarget())) { clanArcs.add(a); } } } } } // find clan arcs with equal name Vector<Arc> arcsToDelete = new Vector<Arc>(5); int nn = clanArcs.size(); int k = 0; while (nn > 0 && k < nn) { Arc a = clanArcs.get(k); boolean found = false; for (int j = k + 1; j < clanArcs.size(); j++) { Arc aj = clanArcs.get(j); if (aj.getType().getName().equals(a.getType().getName())) { if ((a.getSource().getType().isParentOf(aj.getSource().getType()) && a.getTarget().getType().isParentOf(aj.getTarget().getType())) || (aj.getSource().getType().isParentOf(a.getSource().getType()) && aj.getTarget().getType().isParentOf(a.getTarget().getType()))) { found = true; arcsToDelete.add(aj); clanArcs.remove(aj); j--; } } } if (found) arcsToDelete.add(a); nn = clanArcs.size(); k++; } // store arc, source and target types of a clan arc, then destroy the arc Hashtable<Type, Vector<Pair<?,?>>> table = new Hashtable<Type, Vector<Pair<?,?>>>( 5, 5); for (int i = 0; i < arcsToDelete.size(); i++) { Arc a = arcsToDelete.get(i); TypeGraphArc subt = t.getTypeGraphArc(a.getSource().getType(), a.getTarget().getType()); if (subt != null) { Vector<Pair<?,?>> tmp = new Vector<Pair<?,?>>(3); Pair<Type, Type> srcTtarT = new Pair<Type, Type>(a.getSource() .getType(), a.getTarget().getType()); Pair<Integer, Integer> srcMult = new Pair<Integer, Integer>( Integer.valueOf(subt.getSourceMin()), Integer.valueOf(subt .getSourceMax())); Pair<Integer, Integer> tarMult = new Pair<Integer, Integer>( Integer.valueOf(subt.getTargetMin()), Integer.valueOf(subt .getTargetMax())); tmp.add(srcTtarT); tmp.add(srcMult); tmp.add(tarMult); table.put(a.getType(), tmp); } try { this.typeGraph.destroyArc(a, true, false); } catch (TypeException exc) {} } // create clan edges again if (!table.isEmpty()) { Enumeration<Type> keys = table.keys(); while (keys.hasMoreElements()) { Type arcT = keys.nextElement(); Vector<Pair<?,?>> tmp = table.get(arcT); Pair<?,?> srcTtarT = tmp.get(0); Pair<?,?> srcMult = tmp.get(1); Pair<?,?> tarMult = tmp.get(2); Type srcT = (Type) srcTtarT.first; Type tarT = (Type) srcTtarT.second; Node src = this.typeGraph.getTypeSet().getTypeGraphNode(srcT); Node tar = this.typeGraph.getTypeSet().getTypeGraphNode(tarT); try { this.typeGraph.createArc(arcT, src, tar); TypeGraphArc subt = arcT.getTypeGraphArc(src.getType(), tar.getType()); subt.setSourceMin(((Integer)srcMult.first).intValue()); subt.setSourceMax(((Integer)srcMult.second).intValue()); subt.setTargetMin(((Integer)tarMult.first).intValue()); subt.setTargetMax(((Integer)tarMult.second).intValue()); } catch (TypeException exc) { System.out.println("TypeSet.adaptClans:: TypeException for: " + arcT.getName()); } } } } } /** * Imports (integrates) the specified Graph tGraph into my type graph. The * tGraph has to be a type graph, too. If the parameter <code>rewrite</code> * is true, my types would be adapted to the types imported, otherwise they * have to be equal. Returns true, if the import was successful, otherwise * false. */ public boolean importTypeGraph(final Graph tGraph, final boolean rewrite) { // System.out.println("TypeSet.importTypeGraph rewrite: "+rewrite); final Vector<Type> differentAttribute = new Vector<Type>(5); final Vector<Type> differentInheritance = new Vector<Type>(5); final Hashtable<Type, Vector<Type>> oldInheritance = new Hashtable<Type, Vector<Type>>(5, 5); final Vector<Type> differentMultiplicity = new Vector<Type>(5); final Vector<Type> typesToAdd = new Vector<Type>(5); boolean conflicting = !compareTypes(tGraph.getTypeSet(), differentAttribute, differentInheritance, differentMultiplicity, typesToAdd); if (conflicting && this.typeGraphLevel != DISABLED) { return false; } boolean result = true; boolean all = true; if (this.typeGraph != null) { if (!rewrite) { if (!conflicting) { adaptTypes(tGraph.getTypeSet(), !all); if (this.typeGraph.addCopyOfGraph(tGraph)) { refreshInheritanceArcs(); } else { System.out .println("Import Type Graph failed! Something gone wrong!"); result = false; } } else { System.out .println("Import Type Graph failed \nbecause there are conflicts between the type graph objects!"); result = false; } } else if (rewrite) { // store inheritance relation of different types for (int i = 0; i < differentInheritance.size(); i++) { Type other_t = differentInheritance.get(i); Type t = getTypeByNameAndAdditionalRepr(other_t .getStringRepr(), other_t.getAdditionalRepr()); Vector<GraphObject> v = this.typeGraph .getElementsOfTypeAsVector(t); if (!v.isEmpty() && v.firstElement().isNode()) { if (!t.getParents().isEmpty()) { oldInheritance.put(t, t.getParents()); } } } // add new graph objects of the new types if (this.typeGraph.addCopyOfGraph(tGraph)) { adaptTypeInheritance(tGraph, differentInheritance, oldInheritance); adaptTypeMultiplicity(tGraph, differentMultiplicity); adaptClans(); adaptTypeAttribute(differentAttribute); } else { result = false; System.out .println("Import Type Graph failed! Something gone wrong!"); } } } else { if (!rewrite) { if (!conflicting) { adaptTypes(tGraph.getTypeSet(), !all); this.typeGraph = (TypeGraph) tGraph.copy(this); this.typeGraph.setName("TypeGraph"); refreshInheritanceArcs(); } else { System.out .println("Import Type Graph failed \nbecause there are conflicts between the type graph objects!"); result = false; } } else { createTypeGraph(); if (this.typeGraph.addCopyOfGraph(tGraph)) { adaptTypeAttribute(differentAttribute); } else { System.out .println("Import Type Graph failed! Something gone wrong!"); result = false; } } } return result; } /** * Creates an empty type graph. * Already existing type graph will be lost. */ public Graph createTypeGraph() { if (this.directed) this.typeGraph = new TypeGraph(this); else this.typeGraph = new UndirectedTypeGraph(this); this.typeGraph.setName("TypeGraph"); this.typeGraph.setKind(GraphKind.TG); agg.attribute.AttrContext aGraphContext = agg.attribute.impl.AttrTupleManager .getDefaultManager().newContext( agg.attribute.AttrMapping.GRAPH_MAP); this.typeGraph.setAttrContext(agg.attribute.impl.AttrTupleManager .getDefaultManager().newRightContext(aGraphContext)); this.typeGraphIsProved = false; this.checkTypeGraph(); return this.typeGraph; } /** * This method does only work if a type graph does not exist or empty, * otherwise returns existing type graph. <br> * Creates a new type graph, if it does not already exist. <br> * Tries to create a unique type graph node for each node of the specified node list. * If the node list is empty, tries to create a unique type graph node for each existing node type. * Creates an inheritance edge for already existing inheritance relations.<br> * Tries to create a unique type graph edge for each edge of the specified edge list. * If the edge list is empty, no edges are created.<br> * The level for the type graph check of the already existing type graph * should be set to <code>TypeSet.DISABLED</code>. * * @return type graph */ public Graph generateMinimalTypeGraph(final List<Node> nodes, final List<Arc> edges) { if (this.typeGraph == null) this.typeGraph = (TypeGraph) createTypeGraph(); else if (!this.typeGraph.isEmpty()) return this.typeGraph; this.typeGraphLevel = TypeSet.DISABLED; // first, create type graph nodes of existing and // already used node types if (nodes != null && nodes.isEmpty()) { for (int i = 0; i < nodes.size(); i++) { Node n = nodes.get(i); try { this.typeGraph.createNode(n.getType()); } catch (TypeException ex) {} } } else { for (int i = 0; i < this.types.size(); i++) { Type t = this.types.get(i); if (t.isNodeType()) { try { this.typeGraph.createNode(t); } catch (TypeException ex) {} } } } // generate node type inheritance relations refreshInheritance(); // now, create type graph edges of existing and // already used edge types if (edges != null && !edges.isEmpty()) { for (int i = 0; i < edges.size(); i++) { Arc a = edges.get(i); List<Node> vsrc = this.typeGraph.getNodes(a.getSource().getType()); List<Node> vtar = this.typeGraph.getNodes(a.getTarget().getType()); if (vsrc != null && vtar != null) { final GraphObject src = vsrc.get(0); final GraphObject tar = vtar.get(0); if (this.typeGraph.getArcs(a.getType(), src, tar) == null) { try { this.typeGraph.createArc(a.getType(), (Node) src, (Node) tar); } catch (TypeException ex) {} } } } } // refresh node type clans adaptClans(); return this.typeGraph; } /** * Creates a new type graph, if it does not already exist. <br> * Tries to create a unique type graph node for each node of the specified node list. * If the node list is empty, tries to create a unique type graph node for each existing node type. * Creates an inheritance edge for already existing inheritance relations.<br> * Tries to create a unique type graph edge for each edge of the specified edge list. * If the edge list is empty, no edges are created.<br> * The level for the type graph check of the already existing type graph * should be set to <code>TypeSet.DISABLED</code>. * * @return type graph */ public Graph extendTypeGraph(final Iterator<Node> nodes, final Iterator<Arc> edges) { if (this.typeGraph == null) this.typeGraph = (TypeGraph) createTypeGraph(); this.typeGraphLevel = TypeSet.DISABLED; // first, create type graph nodes of existing and // already used node types without an object in the type graph if (nodes != null) { while (nodes.hasNext()) { Node n = nodes.next(); Type t = n.getType(); if (this.typeGraph.getNodes(t) == null) { try { this.typeGraph.createNode(t); } catch (TypeException ex) {} } } } else { for (int i = 0; i < this.types.size(); i++) { Type t = this.types.get(i); if (t.isNodeType()) { if (this.typeGraph.getNodes(t) == null) { try { this.typeGraph.createNode(t); } catch (TypeException ex) {} } } } } // generate node type inheritance relations refreshInheritance(); // now, create type graph edges of existing and // already used edge types if (edges != null) { while (edges.hasNext()) { Arc a = edges.next(); Type t = a.getType(); if (t.getName().equals("next")) { System.out.println("###### next"); } List<Node> vsrc = this.typeGraph.getNodes(a.getSource().getType()); List<Node> vtar = this.typeGraph.getNodes(a.getTarget().getType()); if (vsrc != null && vtar != null) { final GraphObject src = vsrc.get(0); final GraphObject tar = vtar.get(0); if (this.typeGraph.getArcs(t, src, tar) == null) { try { this.typeGraph.createArc(t, (Node) src, (Node) tar); } catch (TypeException ex) {} } } } } // refresh node type clans adaptClans(); return this.typeGraph; } /** * Remove all nodes and arcs and inheritance relations of the type graph. */ public void clearTypeGraph() { if (this.typeGraph != null && !this.typeGraph.isEmpty() && this.typeGraphLevel == DISABLED) { Iterator<Node> e = this.typeGraph.getNodesSet().iterator(); while (e.hasNext()) { Node n = e.next(); removeAllInheritanceRelations(n.getType()); } this.inheritanceArcs.clear(); this.typeGraph.clear(); } } /** * Adds the given type to this type manager. This should only called with * independent types, types can't be part of two manager. */ public Type addType(final Type aType) { if (aType.isNodeType()) { if (//!aType.isTypeUsed() && !aType.hasTypeGraphNode()) { this.types.add(aType); return aType; } return adoptType(aType); } else if (aType.isArcType()) { if (//!aType.isTypeUsed() && !aType.isTypeGraphObjectDefined()) { this.types.add(aType); return aType; } return adoptType(aType); } else return null; } public Type adoptClan(final Type aType) { if (this.containsType(aType)) return aType; Type t = this.getSimilarType(aType); if (t == null) t = addType(aType); if (t.getAdditionalRepr().indexOf("[NODE]") == -1) t.setAdditionalRepr("[NODE]"); if (!aType.getParents().isEmpty()) { for (int i = 0; i < aType.getParents().size(); i++) { Type p = aType.getParents().get(i); Type type = adoptClan(p); t.addParent(type); } } return t; } /** * Creates a new type that is similar to the specified Type t. */ public Type adoptType(final Type t) { // System.out.println("TypeSet.adoptType: "+t.getName()); Type type = null; boolean failed = false; DeclTuple otherTuple = (DeclTuple) t.getAttrType(); // create a new type if (otherTuple != null) { if (t.isNodeType()) type = new NodeTypeImpl(this.attrManager.newType()); else if (t.isArcType()) type = new ArcTypeImpl(this.attrManager.newType()); if (type != null) { // create attribute members DeclTuple declTuple = (DeclTuple) type.getAttrType(); for (int i = 0; i < otherTuple.getSize(); i++) { DeclMember dm = (DeclMember) otherTuple.getMemberAt(i); if (dm.getHoldingTuple() == otherTuple) { Object dmnew = declTuple.addMember( agg.attribute.facade.impl.DefaultInformationFacade .self().getJavaHandler(), otherTuple .getTypeAsString(i), otherTuple .getNameAsString(i)); if (dmnew == null) { failed = true; break; } } } } } else if (t.isNodeType()) type = new NodeTypeImpl(); else if (t.isArcType()) type = new ArcTypeImpl(); if (type != null && !failed) { type.setAbstract(t.isAbstract()); type.setStringRepr(t.getStringRepr()); type.setAdditionalRepr(t.getAdditionalRepr()); this.types.add(type); } return type; } /** * Returns true if the attribute members of the specified Type type could be * added without a conflict to an existing type which has the same name. A * conflict could arise from the members which have an equal name but a * different type. In this case the name of an existing attribute member is * extended by "?", the new attribute member is added and the method returns * false. */ private boolean adaptTypeAttribute(final Type type) { Type myType = getTypeByName(type.getStringRepr()); // getName()); if (myType != null) { if ((type.isNodeType() && myType.isNodeType()) || (type.isArcType() && myType.isArcType())) myType.adaptTypeAttribute(type); } return true; } /** * The {@link #adaptTypeAttribute(Type type)} method will be aplied to each * element of the specified Vector typesToAdapt. */ private void adaptTypeAttribute(final Vector<Type> typesToAdapt) { for (int i = 0; i < typesToAdapt.size(); i++) { Type other_t = typesToAdapt.get(i); adaptTypeAttribute(other_t); } return; } /** * Returns true if the given type is managed by this object. */ public boolean containsType(final Type type) { if (this.types.contains(type)) return true; return false; } /** * Dispose the specified type. */ public void destroyType(final Type type) throws TypeException { // if (this.typeGraphLevel != DISABLED) { // if (type.isTypeGraphObjectDefined()) { // throw new TypeException(new TypeError(TypeError.TYPE_IS_IN_USE, // "There is at least one type graph object defined for \"" // + type.getName() + "\" type." // + "\nPlease remove it before you remove the type.", // type, this.getTypeGraph())); // } // } List<Type> clan = getClan(type); for (int i = 0; i < clan.size(); i++) { Type t = clan.get(i); removeInheritanceRelation(t, type); } this.types.remove(type); type.dispose(); } /** * Returns the AttrManager used to create attributed types */ public AttrManager getAttrManager() { return this.attrManager; } TypeError checkTypeInTypeGraph(final Graph g, final Type edgeType, final GraphObject src, final GraphObject tar, final int tgl) { return edgeType.checkIfEdgeCreatable(g, (Node) src, (Node) tar, tgl); } /** * Checks, if the specified Arc is valid typed as defined in the * type graph: existence and multiplicity constraints of its type edge. * The type graph must be proofed before. * * @param arc * an arc in a graph * @param tgl * the level to use. {@see #setTypegraphLevel()} * @return null * if the arc is valid typed, otherwise an error object */ TypeError checkTypeInTypeGraph(final Arc arc, final int tgl) { if (!arc.getType().hasTypeGraphArc()) { return new TypeError(TypeError.NO_SUCH_TYPE, "The type graph does not contain an edge type with name \"" + arc.getType().getName() + "\" \nbetween node type \"" + arc.getSourceType().getName() + "\" and \"" + arc.getTargetType().getName() + "\"" +"\n ( see graph: "+arc.getContext().getName()+" ).", arc, arc.getType()); } // delegate multiplicity check to arc type return arc.getType().check(arc, tgl); } /** * Checks, if the specified Node is valid typed as defined in the * type graph: existence and multiplicity constraints of its type node. * The type graph must be proofed before. * * @param node * a node in a graph * @param tgl * the level to use. {@see #setTypegraphLevel()} * @return null * if the node is valid typed, otherwise an error object */ TypeError checkTypeInTypeGraph(final Node node, final int tgl) { if (node.getType().getTypeGraphNodeObject() == null) { return new TypeError(TypeError.NO_SUCH_TYPE, "The type graph does not contain a node type with name \"" + node.getType().getName() + "\"" +"\n ( see graph: "+node.getContext().getName()+" ).", node, node.getType()); } return checkMultiplicity(node, tgl); } /** * Checks the type graph. The method must be called before edge type * multiplicity will be set and before this TypeSet will check graphs, * rules, etc. above the type graph. To turn off the type graph based checks * use the method turnTypeGraphCheckOff() * * @return An empty Collection if for all node types exists exactly one node * and for all edge/arc types exists at least one edge in the type * graph, but not more then one of a type between the same nodes. If * there were errors in the type graph a Collection with objects of * class agg.xt_basis.TypeError will returned. For each mismatch an * object will delivered. You can check if there were errors with * Collection.isEmpty. * * @see TypeError */ public Collection<TypeError> checkTypeGraph() { // set result to false while checking this.typeGraphIsProved = false; // use a Vector to create the Enumeration // containing all errors found Vector<TypeError> errors = new Vector<TypeError>(); // check if a type graph is defined if (this.typeGraph == null) { errors.add(new TypeError(TypeError.NO_TYPE_GRAPH, "The current grammar does not contain a type graph.")); return errors; } // link the objects in the type graph to the types // here will be all errors found // first disable all type graph objects of types Enumeration<Type> enTypes = this.types.elements(); Type actType; while (enTypes.hasMoreElements()) { actType = enTypes.nextElement(); actType.disableTypeGraphObject(); } // now propagate all graph objects from type graph // to its this.types Enumeration<GraphObject> en = this.typeGraph.getElements(); GraphObject actGraphObject; while (en.hasMoreElements()) { // link the type to the graph object actGraphObject = en.nextElement(); actType = actGraphObject.getType(); if (!actType.addTypeGraphObject(actGraphObject)) { // the adding wasn't successful TypeError newError; if (actGraphObject instanceof Node) { newError = new TypeError(TypeError.TYPE_ALREADY_DEFINED, "The type graph contains already a node type \"" + actType.getName() + "\".", actGraphObject, actType); } else { newError = new TypeError(TypeError.TYPE_ALREADY_DEFINED, "The type graph contains already an edge type \"" + actType.getName() + "\" between node types \"" + ((Arc) actGraphObject) .getSource().getType().getName() + "\" and \"" + ((Arc) actGraphObject) .getTarget().getType().getName() + "\".", actGraphObject, actType); } newError.setContainingGraph(this.typeGraph); errors.add(newError); } } /* enTypes = types.elements(); while (enTypes.hasMoreElements()) { actType = enTypes.nextElement(); // if (actType.isTypeUsed()) { if (actType instanceof NodeTypeImpl && !actType.hasTypeGraphNode()) { TypeError newError = new TypeError(TypeError.TYPE_UNDEFINED, "No type graph object exists of the node type: " +actType.getName(), null, actType); newError.setContainingGraph(this.typeGraph); errors.add(newError); } else if (actType instanceof ArcTypeImpl && !actType.hasTypeGraphArc()) { TypeError newError = new TypeError(TypeError.TYPE_UNDEFINED, "No type graph object exists of the edge type: " +actType.getName(), null, actType); newError.setContainingGraph(this.typeGraph); errors.add(newError); } } } */ if (errors.isEmpty()) this.typeGraphIsProved = true; return errors; } /** * checks this new graph object in the type graph. This method will only * find a wrong object, if the type graph was checked first (see * {@link #checkTypeGraph()}). This method is designed to use <I>before</I> * adding an object to the type graph, so the type graph will be used even * if the check found mismatches. * * @return An empty {@link Collection} if for all node types exists exactly * one node and for all edge/arc types exists at least one edge in * the type graph, but not more then one of a type between the same * nodes. If there were errors in the type graph a Collection with * objects of class {@link TypeError} will returned. For each * mismatch an object will delivered. You can check if there were * errors with {@link Collection#isEmpty}. * * @see TypeError */ public TypeError addTypeGraphObject(final GraphObject typeObject) { if (!this.typeGraphIsProved) return null; Type actType = typeObject.getType(); // check type and add new object if (!actType.addTypeGraphObject(typeObject)) { // the adding wasn't successful - so it was already defined TypeError error; if (typeObject instanceof Node) { error = new TypeError(TypeError.TYPE_ALREADY_DEFINED, "The type graph contains already a type node \"" + actType.getName() + "\".", typeObject, actType); error.setContainingGraph(this.typeGraph); } else { error = new TypeError(TypeError.TYPE_ALREADY_DEFINED, "The type graph contains already a type edge \"" + actType.getName() + "\" between the type node \"" + ((Arc) typeObject).getSource() .getType().getName() + "\" and the type node \"" + ((Arc) typeObject).getTarget() .getType().getName() + "\".", typeObject, actType); error.setContainingGraph(this.typeGraph); } return error; } return null; } /** * Returns an error in the following cases: parent already exists, reflexive * or cyclic inheritance, double attribute names when multiple inheritance * used, otherwise - null. * * @deprecated replaced by {@link #checkInheritanceValidity(Type, Type)} * */ public TypeError checkInheritanceValid(final Type child, final Type parent) { return checkInheritanceValidity(child, parent); } /** * Returns an error in the following cases: parent already exists, reflexive * or cyclic inheritance, double attribute names when multiple inheritance * used, otherwise - null. */ public TypeError checkInheritanceValidity(final Type child, final Type parent) { if (this.typeGraph == null || parent == null) return null; // don't allow reflexive inheritance relation if (child == parent) { TypeError error = new TypeError(TypeError.PARENT_NOT_ALLOWED, "reflexive inheritance relation is not allowed"); error.setContainingGraph(this.typeGraph); return error; } // the new parent is an ancestor of child, don't allow the new relation if (child.getAllParents().contains(parent)) { TypeError error = new TypeError(TypeError.PARENT_NOT_ALLOWED, "this parent is already an ancestor"); error.setContainingGraph(this.typeGraph); return error; } // cycles are not allowed List<Type> grandpars = parent.getParents(); for (int i = 0; i < grandpars.size(); i++) { Type pi = grandpars.get(i); if (pi.getAllParents().contains(child)) { TypeError error = new TypeError(TypeError.PARENT_NOT_ALLOWED, "cyclic inheritance relation is not allowed"); error.setContainingGraph(this.typeGraph); return error; } } // double names of attr members are not allowed removeDoubleAttributes(child, parent); return null; } private void removeDoubleAttributes(final Type child, final Type parent) { if (child.getAttrType() == null || parent.getAttrType() == null) return; DeclTuple myDecl = (DeclTuple) child.getAttrType(); DeclTuple otherDecl = (DeclTuple) parent.getAttrType(); for (int i = 0; i < otherDecl.getNumberOfEntries(); i++) { DeclMember mem = (DeclMember) otherDecl.getMemberAt(i); if (myDecl.isLegalName(mem.getName()) > 0) { if (mem.getHoldingTuple() != myDecl.getMemberAt(mem.getName()).getHoldingTuple()) { myDecl.deleteMemberAt(mem.getName()); } } } } public boolean isInheritanceArc(final Arc a) { if (a.getType() == this.inheritanceType && this.inheritanceArcs.contains(a)) return true; return false; } /** * To use this method, a type graph must to be created * and the method * <code>checkInheritanceValidity(Type child, Type parent)</code> * must be called before. */ public Arc addValidInheritanceRelation(final Type child, final Type parent) { if (this.typeGraph == null) return null; child.addParent(parent); Node childNode = null; Node parentNode = null; // choose the proper type graph nodes representing the correct type Iterator<Node> en = this.typeGraph.getNodesSet().iterator(); while (en.hasNext()) { Node currentNode = en.next(); if (currentNode.getType() == child) childNode = currentNode; else if (currentNode.getType() == parent) parentNode = currentNode; if(childNode != null && parentNode != null) break; } Arc inheritArc = null; if (childNode != null && parentNode != null) { // check it! // if (this.typeGraph.indexOf(parentNode) > this.typeGraph.indexOf(childNode)) { // this.typeGraph.moveTo(parentNode, this.typeGraph.indexOf(childNode)); // } inheritArc = new Arc(null, this.inheritanceType, childNode, parentNode, this.typeGraph); inheritArc.setInheritance(true); // add inherited edge to its type when it is not already done Vector<Arc> inheritedArcs = this.getInheritedArcs(parent); for (int i = 0; i < inheritedArcs.size(); i++) { GraphObject a = inheritedArcs.get(i); a.getType().addTypeGraphObject(a); } childNode.propagateAttrValueFromParentNode(); this.inheritanceArcs.add(inheritArc); refreshInheritanceClan(child, parent, true); checkOtherDirectParents(child, parent); this.typeGraph.extendTypeObjectsMap(child); this.typeGraph.propagateChange(new agg.util.Change(agg.util.Change.OBJECT_CREATED, inheritArc)); } return inheritArc; } /** * To use this method, a type graph must to be created before. */ public TypeError addInheritanceRelation(final Type child, final Type parent) { TypeError error = checkInheritanceValidity(child, parent); if (error == null) { if (addValidInheritanceRelation(child, parent) == null) { String childName = (child==null)? "NULL": child.getName(); String parentName = (parent==null)? "NULL": parent.getName(); return new TypeError(TypeError.UNKNOWN_ERROR, "The inharitance relation from type: " + childName + " to " + parentName + " " + "is not possible."); } return null; } return error; } private void checkOtherDirectParents(final Type child, final Type p) { for (int i = 1; i < p.getAllParents().size(); i++) { Type pi = p.getAllParents().get(i); if (child.getParents().contains(pi)) removeInheritanceRelation(child, pi); } } /** * Remove all direct inheritance relations of the specified type. */ public void removeAllInheritanceRelations(final Type child) { while (!child.getParents().isEmpty()) { Type p = child.getParents().firstElement(); removeInheritanceRelation(child, p); } } /** * Remove inheritance relation from the specified <code>child</code> type * to the specified direct <code>parent</code> type. */ public boolean removeInheritanceRelation(final Type child, final Type parent) { if (this.typeGraph == null || parent == null || child == parent) return false; // remove the inheritance arc representing the old child->parent // relation if (child.getParents().contains(parent)) { Arc inheritArc = null; for (int i = 0; i < this.inheritanceArcs.size(); i++) { Arc currentArc = this.inheritanceArcs.get(i); if (currentArc.getSource().getType() == child && currentArc.getTarget().getType() == parent) { inheritArc = currentArc; break; } } if (inheritArc != null) { Vector<Arc> inheritedArcs = this.getInheritedArcs(inheritArc.getTarget() .getType()); for (int i = 0; i < inheritedArcs.size(); i++) { Arc a = inheritedArcs.get(i); if (a.getSource().getType() == child) { if (!a.getType().removeTypeGraphObject(a)) { return false; } } } this.inheritanceArcs.remove(inheritArc); child.removeParent(parent); refreshInheritanceClan(child, parent, false); this.typeGraph.propagateChange(new agg.util.Change(agg.util.Change.OBJECT_DESTROYED, inheritArc)); inheritArc.dispose(); return true; } // a parent exists, but any inheritance arc does not exist, // do remove this parent from the parent list. child.removeParent(parent); refreshInheritanceClan(child, parent, false); return true; } return false; } /** * Reads my current inheritance data and updates the inheritance edges. */ public void refreshInheritanceArcs() { if (this.typeGraph == null) return; final Vector<Arc> oldInheritanceArcs = new Vector<Arc>(this.inheritanceArcs.size()); oldInheritanceArcs.addAll(this.inheritanceArcs); this.inheritanceArcs.clear(); Iterator<Node> en = this.typeGraph.getNodesSet().iterator(); while (en.hasNext()) { Node currentNode = en.next(); Type currentType = currentNode.getType(); for (int i = 0; i < currentType.getParents().size(); i++) { Type parentType = currentType.getParents().get(i); Iterator<Node> en2 = this.typeGraph.getNodesSet().iterator(); while (en2.hasNext()) { Node parentNode = en2.next(); if (parentNode.getType() == parentType) { boolean found = false; for (int j = 0; j < oldInheritanceArcs.size(); j++) { Arc inh = oldInheritanceArcs.get(j); if (inh.getSource() == currentNode && inh.getTarget() == parentNode) { found = true; this.inheritanceArcs.add(inh); break; } } if (!found) { Arc inheritArc = new Arc(null, this.inheritanceType, currentNode, parentNode, null); inheritArc.setInheritance(true); this.inheritanceArcs.add(inheritArc); } } } } } oldInheritanceArcs.clear(); } /** * Returns a set with all edges to inherit from the specified parent type, * or empty set. */ public Vector<Arc> getInheritedArcs(final Type parentType) { Vector<Arc> inheritedArcs = new Vector<Arc>(); Vector<Type> allparents = parentType.getAllParents(); for (int i = 0; i < allparents.size(); i++) { Type p = allparents.get(i); Node go = p.getTypeGraphNodeObject(); if (go != null) { Iterator<Arc> enOut = go.getOutgoingArcsSet().iterator(); while (enOut.hasNext()) { Arc a = enOut.next(); if (!a.isInheritance()) inheritedArcs.add(a); } Iterator<Arc> enIn = go.getIncomingArcsSet().iterator(); while (enIn.hasNext()) { Arc a = enIn.next(); if (!a.isInheritance()) inheritedArcs.add(a); } } } return inheritedArcs; } /** * Returns all child types of the given node type. * * @param t * The type which children should be found. * @return a list of child types. */ public List<Type> getClan(final Type t) { return t.getClan(); } public boolean isIncomingArcOfClan( final Type aTypeOfClan, final Type arcType, final Type sourceNodeType) { if (this.typeGraph != null) { String keystr = sourceNodeType.convertToKey() + arcType.convertToKey() + aTypeOfClan.convertToKey(); HashSet<GraphObject> list = this.typeGraph.getTypeObjectsMap().get(keystr); if (list != null && !list.isEmpty()) { if (((Arc)list.iterator().next()).getSource().getType().isInClanOf(sourceNodeType)) { return true; } } } return false; } public boolean isOutgoingArcOfClan( final Type aTypeOfClan, final Type arcType, final Type targetNodeType) { if (this.typeGraph != null) { String keystr = aTypeOfClan.convertToKey() + arcType.convertToKey() + targetNodeType.convertToKey(); HashSet<GraphObject> list = this.typeGraph.getTypeObjectsMap().get(keystr); if (list != null && !list.isEmpty()) { if (((Arc)list.iterator().next()).getSource().getType().isInClanOf(targetNodeType)) { return true; } } } return false; } private void refreshInheritanceClan(final Type t) { refreshInheritanceClan(t, null, false); } private void refreshInheritanceClan(final Type t, final Type p, final boolean afterAdd) { List<Type> clan = getClan(t); for (int i = 0; i < clan.size(); i++) { Type child = clan.get(i); if (child != t) { if (p != null && child.getParents().contains(p)) { removeInheritanceRelation(child, p); } if (child.getAttrType() != null) { DeclTuple myDeclTuple = (DeclTuple) child.getAttrType(); if (afterAdd) { myDeclTuple.refreshParentsAfterAdd(); } else { myDeclTuple.refreshParentsAfterRemove(); } } } } } public void refreshInheritanceClans() { for (int j = 0; j < this.types.size(); j++) { Type t = this.types.get(j); refreshInheritanceClan(t); } } public void refreshInheritance() { for (int j = 0; j < this.types.size(); j++) { Type t = this.types.get(j); refreshInheritanceClan(t); } refreshInheritanceArcs(); } public TypeError removeTypeGraphObject(final GraphObject tgo) { Type actType = tgo.getType(); if (!actType.removeTypeGraphObject(tgo)) { if (this.typeGraphLevel == DISABLED) return null; if ((tgo instanceof Arc) && this.inheritanceArcs.contains(tgo)) { } else {// send error TypeError error = new TypeError( TypeError.TYPE_IS_IN_USE, "\nThe type \"" + actType.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.", tgo, actType); error.setContainingGraph(this.typeGraph); return error; } } return null; } public TypeError forceRemoveTypeGraphObject(final GraphObject tgo) { Type actType = tgo.getType(); if (!actType.removeTypeGraphObject(tgo, true)) { if (this.typeGraphLevel == DISABLED) return null; if ((tgo instanceof Arc) && this.inheritanceArcs.contains(tgo)) { } else {// send error TypeError error = new TypeError( TypeError.TYPE_IS_IN_USE, "\nThe type \"" + actType.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.", tgo, actType); error.setContainingGraph(this.typeGraph); return error; } } return null; } /** * checks the given graph, if it is valid typed. If the TypeSet of the graph * is not this object, the types of the nodes and edges must be also defined * here. If in this TypeSet a proofed type graph is used, there must be a * morphism from the given graph into the type graph (But a different * algorithmus will be used). * * @param graph * the graph to check * @return an empty {@link Collection} if the given graph is valid typed. If * there were type errors in the graph a Collection with objects of * class {@link TypeError} will returned. For each mismatch an error * object will delivered. You can check if there were some errors * {@link Collection#isEmpty}. * * @see #checkTypeGraph */ public Collection<TypeError> checkType(final Graph graph) { // count the type mismatches Vector<TypeError> errors = new Vector<TypeError>(); // the given graph has another TypeSet checkTypeSet(graph, errors); if ((this.typeGraph == null) || (this.typeGraphLevel <= TypeSet.ENABLED)) { // == DISABLED)) { // no type graph is defined/used // or the type graph is not proofed return errors; } if (graph.isEmpty() && this.typeGraphLevel <= TypeSet.ENABLED_MAX) return errors; // check with type graph // disable min check, if not host graph int actTypeGraphLevel = this.typeGraphLevel; if (!graph.isCompleteGraph() && this.typeGraphLevel >= ENABLED_MAX_MIN) { actTypeGraphLevel = ENABLED_MAX; } // now checks the nodes // checkNodes(graph, actTypeGraphLevel, errors); // now checks nodes about max/min multiplicity of type graph nodes this.checkNodesOverTypeGraph(graph, actTypeGraphLevel, errors); // checks arcs about max/min multiplicity of type graph edges this.checkArcsOverTypeGraph(graph, actTypeGraphLevel, errors); return errors; } // the given graph has another TypeSet private Vector<TypeError> checkTypeSet(final Graph graph, final Vector<TypeError> errors) { if (!this.equals(graph.getTypeSet())) { // checks all edges/arcs Iterator<?> en = graph.getArcsSet().iterator(); GraphObject act; while (en.hasNext()) { act = (GraphObject) en.next(); if (!this.types.contains(act.getType())) { // if the type of this object is // not defined here, increment the error counter errors.add(new TypeError( TypeError.TYPE_UNKNOWN_HERE, "The edge type \"" + act.getType().getName() + "\" used is not part of the grammars type set ( graph \"" + graph.getName() + "\" ).", act .getType())); } } // check all nodes en = graph.getNodesSet().iterator(); while (en.hasNext()) { act = (GraphObject) en.next(); if (!this.types.contains(act.getType())) { // if the type of this object is // not defined here, increment the error counter errors.add(new TypeError( TypeError.TYPE_UNKNOWN_HERE, "The node type \"" + act.getType().getName() + "\" used is not part of the grammars type set ( graph \"" + graph.getName() + "\" ).", act .getType())); } } } return errors; } /** * Returns an error object if the type multiplicity check failed after a node of * the specified type created, otherwise - null. */ public TypeError canCreateNode( final Graph g, final Type nodeType, final int currentTypeGraphLevel) { if (currentTypeGraphLevel >= ENABLED_MAX) { List<Type> parents = nodeType.getAllParents(); for (int i = 0; i < parents.size(); i++) { Type t = parents.get(i); int count = 0; int maxValue = t.getSourceMax(); HashSet<GraphObject> set = g.getTypeObjectsMap().get(nodeType.convertToKey()); if (set != null && !set.isEmpty()) { count = g.getTypeObjectsMap().get(nodeType.convertToKey()).size(); } if ((maxValue > 0) && (count + 1 > maxValue)) { TypeError actError = new TypeError(TypeError.TO_MUCH_NODES, "Too many nodes of type \"" + t.getName() + "\".\nThere are only " + maxValue + " allowed.", t); actError.setContainingGraph(g); return actError; } else if (currentTypeGraphLevel == ENABLED_MAX_MIN) { List<String> arctypes = nodeTypeRequiresArcType(nodeType, currentTypeGraphLevel); if (arctypes != null && arctypes.size() > 0) { TypeError actError = new TypeError(TypeError.TO_LESS_ARCS, "Node type " + "\""+t.getName()+ "\" \n" + "requires edge(s) of type: \n" + arctypes.toString(), t); actError.setContainingGraph(g); return actError; } } } } return null; } /** * Checks whether the given node type requires an outgoing resp. incoming edge type * with respect to the current type graph. * * @return a list with name of required arc type(s), otherwise null */ public List<String> nodeTypeRequiresArcType(final Type nodeType, final int currentTypeGraphLevel) { if (this.typeGraph == null || currentTypeGraphLevel != ENABLED_MAX_MIN) return null; List<String> arcTypes = new Vector<String>(); final List<Type> parents = nodeType.getAllParents(); if (parents.size() > 0) { for (int i=parents.size()-1; i>=0; i--) { final List<Node> list = this.typeGraph.getNodes(parents.get(i)); Node n = list != null? list.get(0): null; if (n == null) continue; // check target min multiplicity == 1, here n is the source node Iterator<Arc> arcs = n.getOutgoingArcsSet().iterator(); while (arcs.hasNext()) { final Arc arc = arcs.next(); if (getMinTargetMultiplicity(arc.getType(), n.getType(), arc.getTargetType()) == 1) { arcTypes.add(arc.getType().getName()); } } // check source min multiplicity == 1, here n is the target node arcs = n.getIncomingArcsSet().iterator(); while (arcs.hasNext()) { final Arc arc = arcs.next(); if (getMinSourceMultiplicity(arc.getType(), arc.getSourceType(), n.getType()) == 1) { arcTypes.add(arc.getType().getName()); } } } } return arcTypes; } /** * Checks whether the given node type requires an outgoing resp. incoming edge type * with respect to the current type graph. * * @return a list with name of required arc type(s), otherwise null */ public List<String> nodeTypeRequiresArcType( final Type nodeType, final Type arcType, final Type srcNodeType, final int currentTypeGraphLevel) { if (this.typeGraph == null || currentTypeGraphLevel != ENABLED_MAX_MIN) return null; List<String> arcTypes = new Vector<String>(); final List<Type> parents = nodeType.getAllParents(); if (parents.size() > 0) { for (int i=0; i<parents.size(); i++) { final List<Node> list = this.typeGraph.getNodes(parents.get(i)); Node n = list != null? list.get(0): null; if (n == null) continue; // check target min multiplicity == 1, here n is the source node Iterator<Arc> arcs = n.getOutgoingArcsSet().iterator(); while (arcs.hasNext()) { final Arc arc = arcs.next(); if (getMinTargetMultiplicity(arc.getType(), n.getType(), arc.getTargetType()) == 1) { arcTypes.add(arc.getType().getName()); } } // check source min multiplicity == 1, here n is the target node arcs = n.getIncomingArcsSet().iterator(); while (arcs.hasNext()) { final Arc arc = arcs.next(); if (getMinSourceMultiplicity(arc.getType(), arc.getSourceType(), n.getType()) == 1) { if (!arc.getType().compareTo(arcType) // || !arc.getSourceType().compareTo(srcNodeType) ) arcTypes.add(arc.getType().getName()); } } } } return arcTypes; } public List<String> nodeRequiresArc(final Node node) { List<String> arcTypes = null; final List<Type> parents = node.getType().getAllParents(); if (parents.size() > 0) { List<Arc> outcoms = new Vector<Arc>(node.getOutgoingArcsSet()); List<Arc> incoms = new Vector<Arc>(node.getIncomingArcsSet()); for (int i=0; i<parents.size(); i++) { List<Node> list = this.typeGraph.getNodes(parents.get(i)); Node n = list != null? list.get(0): null; if (n == null) continue; // check target min multiplicity == 1, here n is the source node Iterator<Arc> arcs = n.getOutgoingArcsSet().iterator(); while (arcs.hasNext()) { final Arc arc = arcs.next(); if (getMinTargetMultiplicity(arc.getType(), n.getType(), arc.getTargetType()) == 1) { boolean ok = false; for (int j=0; j<outcoms.size(); j++) { final Arc out = outcoms.get(j); if (out.getType().compareTo(arc.getType())) { ok = true; break; } } if (!ok) { if (arcTypes == null) arcTypes = new Vector<String>(); arcTypes.add(arc.getType().getName()); } } } // check source min multiplicity == 1, here n is the target node arcs = n.getIncomingArcsSet().iterator(); while (arcs.hasNext()) { final Arc arc = arcs.next(); if (getMinSourceMultiplicity(arc.getType(), arc.getSourceType(), n.getType()) == 1) { boolean ok = false; for (int j=0; j<incoms.size(); j++) { final Arc in= incoms.get(j); if (in.getType().compareTo(arc.getType())) { ok = true; break; } } if (!ok) { if (arcTypes == null) arcTypes = new Vector<String>(); arcTypes.add(arc.getType().getName()); } } } } } return arcTypes; } /** * Returns an error object if the type multiplicity check failed after an edge of * the specified type created, otherwise - null. */ public TypeError canCreateArc( final Graph g, final Type edgeType, final Node source, final Node target, final int currentTypeGraphLevel) { return checkTypeInTypeGraph(g, edgeType, source, target, currentTypeGraphLevel); } /** * Checks edges of the specified graph due to * type arc multiplicity of the specified type arc. * * @param typearc * type arc of the current type graph * @param graph * a graph to check (not a type graph) * @param currentTypeGraphLevel * @return null * if multiplicity is satisfied, otherwise an error object */ public TypeError checkEdgeTypeMultiplicity( final Arc typearc, final Graph graph, final int currentTypeGraphLevel) { final Enumeration<GraphObject> list = graph.getElementsOfType( typearc.getType(), typearc.getSourceType(), typearc.getTargetType()); while (list.hasMoreElements()) { final Arc arc = (Arc) list.nextElement(); // delegate multiplicity check to arc type final TypeError error = arc.getType().check(arc, currentTypeGraphLevel); if (error != null) return error; } return null; } /** * Checks node type multiplicity of the specified node Type of the nodes * of the specified Graph. * * @param nodeType * node type of the current type graph * @param graph * a graph to check * @param currentTypeGraphLevel * @return null * if multiplicity is satisfied, otherwise an error object */ public TypeError checkNodeTypeMultiplicity( final Type nodeType, final Graph graph, final int currentTypeGraphLevel) { TypeError actError = null; if (currentTypeGraphLevel > ENABLED) { HashSet<GraphObject> set = graph.getTypeObjectsMap().get(nodeType.convertToKey()); if (set != null && !set.isEmpty()) { int nc = graph.getTypeObjectsMap().get(nodeType.convertToKey()).size(); int maxValue = nodeType.getSourceMax(); if ((maxValue != UNDEFINED) && (nc > maxValue)) { actError = new TypeError(TypeError.TO_MUCH_NODES, "Too many ("+nc+") nodes of type \"" + nodeType.getName() + "\".\nThere are only " + maxValue + " allowed ( graph \"" + graph.getName() + "\" ).", graph); return actError; } if (currentTypeGraphLevel == ENABLED_MAX_MIN && graph.isCompleteGraph()) { int minValue = nodeType.getSourceMin(); if (minValue > 0 && nc < minValue) { actError = new TypeError(TypeError.TO_LESS_NODES, "Not enough ("+nc+") nodes of type \"" + nodeType.getName() + "\".\nThere are at least " + minValue + " needed ( graph \"" + graph.getName() + "\" ).", graph); return actError; } } } } /* for (int i = 0; i < nodeType.getAllParents().size(); i++) { Type t = nodeType.getAllParents().get(i); int nc = 0; int minValue = t.getSourceMin(); int maxValue = t.getSourceMax(); List<Type> clan = getClan(t); for (Iterator<Type> it = clan.iterator(); it.hasNext();) { Type clanMember = it.next(); if (clanMember.getTypeGraphNode() != null) { List<Node> list = graph.getNodes(clanMember); if (list != null) nc += list.size(); } } if (currentTypeGraphLevel >= ENABLED_MAX) { if ((maxValue != UNDEFINED) && (nc > maxValue)) { actError = new TypeError(TypeError.TO_MUCH_NODES, "Too many ("+nc+") nodes of type \"" + t.getName() + "\".\nThere are only " + maxValue + " allowed ( graph \"" + graph.getName() + "\" ).", graph); return actError; } } if (currentTypeGraphLevel == ENABLED_MAX_MIN && graph.isCompleteGraph()) { if (minValue > 0 && nc < minValue) { actError = new TypeError(TypeError.TO_LESS_NODES, "Not enough ("+nc+") nodes of type \"" + t.getName() + "\".\nThere are at least " + minValue + " needed ( graph \"" + graph.getName() + "\" ).", graph); return actError; } } } */ return null; } /** * Check node type multiplicity for the specified Node. * The specified Node can be a new created node. * @param n * @param currentTypeGraphLevel * @return null * if node type multiplicity satisfied otherwise an error object */ private TypeError checkMultiplicity(final Node n, final int currentTypeGraphLevel) { TypeError actError = null; if (currentTypeGraphLevel >= ENABLED_MAX) { Type nodeType = n.getType(); List<Type> parents = nodeType.getAllParents(); for (int i = 0; i < parents.size(); i++) { Type t = parents.get(i); int count = 0; int minValue = t.getSourceMin(); int maxValue = t.getSourceMax(); HashSet<GraphObject> set = n.getContext().getTypeObjectsMap().get(t.convertToKey()); if (set != null && !set.isEmpty()) { count = n.getContext().getTypeObjectsMap().get(t.convertToKey()).size(); } // List<Type> clan = getClan(t); // for (Iterator<Type> it = clan.iterator(); it.hasNext();) { // Type member = it.next(); // if (member.getTypeGraphNode() != null) { // List<Node> list = n.getContext().getNodes(member); // if (list != null) // count += list.size(); // } // } if(!n.getContext().isNode(n)) count++; // a node is created and should be added to nodes of a graph if ((maxValue != UNDEFINED) && (count > maxValue)) { actError = new TypeError(TypeError.TO_MUCH_NODES, "Too many ("+count+") nodes of type \"" + t.getName() + "\".\nThere are only " + maxValue + " allowed ( graph \"" + n.getContext().getName() + "\" ).", n, t); actError.setContainingGraph(n.getContext()); return actError; } if (currentTypeGraphLevel == ENABLED_MAX_MIN && n.getContext().isCompleteGraph()) { if (minValue > 0 && count < minValue) { actError = new TypeError(TypeError.TO_LESS_NODES, "Not enough ("+count+") nodes of type \"" + t.getName() + "\".\nThere are at least " + minValue + " needed ( graph \"" + n.getContext().getName() + "\" ).", n, t); actError.setContainingGraph(n.getContext()); return actError; } } } } return null; } // now checks the nodes about min/max multiplicity of the type graph nodes /* private Vector<TypeError> checkTypeGraph(final Graph graph, final int actTypeGraphLevel, final Vector<TypeError> errors) { TypeError actError = null; if ((actTypeGraphLevel == ENABLED_MAX) || (actTypeGraphLevel == ENABLED_MAX_MIN)) { Iterator<Node> en = this.typeGraph.getNodesSet().iterator(); Node actNode = null; while (en.hasNext()) { actNode = en.next(); actError = checkMultiplicity(actNode, actTypeGraphLevel); if (actError != null) errors.add(actError); } return errors; } return errors; } */ /** * Checks nodes of the specified graph over the type nodes (multiplicity constraint) * of the type graph. * * @param graph * @param actTypeGraphLevel * @param errors * @return errors */ private Vector<TypeError> checkNodesOverTypeGraph( final Graph graph, final int actTypeGraphLevel, final Vector<TypeError> errors) { boolean localresult = true; Iterator<Node> nodesTG = this.typeGraph.getNodesSet().iterator(); while (nodesTG.hasNext() && localresult) { Node n = nodesTG.next(); TypeError err = checkNodeTypeMultiplicity(n.getType(), graph, actTypeGraphLevel); if (err != null) { errors.add(err); localresult = false; } } if (localresult) { TypeError err = graph.checkNodeRequiresArc(actTypeGraphLevel); if (err != null) { errors.add(err); } } return errors; } // not used currently /* private Vector<TypeError> checkNodes(final Graph graph, final int actTypeGraphLevel, final Vector<TypeError> errors) { TypeError actError = null; final List<Type> checkedTypes = new Vector<Type>(); Iterator<Node> en = graph.getNodesSet().iterator(); Node actNode; while (en.hasNext()) { actNode = en.next(); if (!checkedTypes.contains(actNode.getType())) { checkedTypes.add(actNode.getType()); // check the actual node actError = this.checkTypeInTypeGraph(actNode, actTypeGraphLevel); if (actError != null) { actError.setContainingGraph(graph); errors.add(actError); } } } checkedTypes.clear(); return errors; } */ /** * Checks edges of the specified graph over the type edges (multiplicity constraint) * of the type graph. * * @param graph * @param actTypeGraphLevel * @param errors * @return errors */ private Vector<TypeError> checkArcsOverTypeGraph( final Graph graph, final int actTypeGraphLevel, Vector<TypeError> errors) { TypeError actError = null; final Iterator<Arc> en = graph.getArcsSet().iterator(); Arc actArc; while (en.hasNext()) { actArc = en.next(); actError = this.checkTypeInTypeGraph(actArc, actTypeGraphLevel); if (actError != null) { actError.setContainingGraph(graph); errors.add(actError); } } return errors; } /** * checks the given graph, if it is valid typed. The TypeSet of the graph * has to be this object. * * @param graph * the graph to check * @param typeGraphCheckLevel * the level of the check * @return An empty {@link Collection} if the given graph is valid typed. If * there were type errors in the graph a Collection with objects of * class {@link TypeError} will returned. For each mismatch an * object will delivered. You can check if there were errors with * {@link Collection#isEmpty}. * * @see #checkTypeGraph */ public Collection<TypeError> checkType(final Graph graph, final int typeGraphCheckLevel) { // count the type mismatches Vector<TypeError> errors = new Vector<TypeError>(); // check with type graph if ((this.typeGraph == null) || (typeGraphCheckLevel == DISABLED)) { return errors; } // disable min check, if not working graph int actTypeGraphLevel = typeGraphCheckLevel; if ((typeGraphCheckLevel >= ENABLED_MAX_MIN) && (!graph.isCompleteGraph())) { actTypeGraphLevel = ENABLED_MAX; } // now checks the nodes // checkNodes(graph, actTypeGraphLevel, errors); this.checkNodesOverTypeGraph(graph, actTypeGraphLevel, errors); // checks all arcs in the graph this.checkArcsOverTypeGraph(graph, actTypeGraphLevel, errors); return errors; } public TypeError checkTypeMaxMultiplicity(final Graph graph, int typeGraphCheckLevel) { if ((this.typeGraph == null) || (typeGraphCheckLevel <= TypeSet.ENABLED)) { return null; } int actTypeGraphLevel = ENABLED_MAX; final List<Type> checkedTypes = new Vector<Type>(); Node n; TypeError actError; // checks all nodes in the graph final Iterator<Node> en = graph.getNodesSet().iterator(); while (en.hasNext()) { n = en.next(); if (!checkedTypes.contains(n.getType())) { checkedTypes.add(n.getType()); if (!n.getType().hasTypeGraphNode()) { actError = new TypeError(TypeError.NO_SUCH_TYPE, "No type node with name \"" + n.getType().getName()+ "\"" +"\n ( see graph: "+graph.getName()+" ).", graph); return actError; } actError = this.checkNodeTypeMultiplicity(n.getType(), graph, actTypeGraphLevel); if (actError != null) { return actError; } } } checkedTypes.clear(); // checks all arcs in the graph final Iterator<Arc> en1 = graph.getArcsSet().iterator(); Arc a; while (en1.hasNext()) { a = en1.next(); if (!a.getType().hasTypeGraphArc()) { actError = new TypeError(TypeError.NO_SUCH_TYPE, "No type edge with name \"" + a.getType().getName() + "\" \nbetween node \"" + a.getSourceType() + "\" and \"" + a.getTargetType() + "\"" +"\n ( see graph: "+graph.getName()+" ).", graph); return actError; } actError = a.getType().checkSourceMax(graph, (Node)a.getSource(), (Node)a.getTarget()); if (actError != null) { actError.setContainingGraph(graph); return actError; } actError = a.getType().checkTargetMax(graph, (Node)a.getSource(), (Node)a.getTarget()); if (actError != null) { actError.setContainingGraph(graph); return actError; } } return null; } /** * checks the given rule, if it is valid typed. If the TypeSet of the * contained graphs is not this object, the types of the nodes and edges * must be also defined here. If in this TypeSet a proofed type graph is * used, there must be a morphism from the given graphs into the type graph. * * @param rule * the rule to check. The original and image graphs of the rule * and of all NACs will be checked. * @return An empty {@link Collection} if the given rule is valid typed. If * there were type errors in the rule a Collection with objects of * class {@link TypeError} will returned. For each mismatch an * object will delivered. You can check if there were errors with * {@link Collection#isEmpty}. * * @see #checkTypeGraph */ public Collection<TypeError> checkType(final Rule rule) { // count the type mismatches Vector<TypeError> errors = new Vector<TypeError>(); // check LHS errors.addAll(checkType(rule.getOriginal())); // check RHS errors.addAll(checkType(rule.getImage())); // check all NACs final List<OrdinaryMorphism> nacs = rule.getNACsList(); for (int l=0; l<nacs.size(); l++) { final OrdinaryMorphism nac = nacs.get(l); // check original (LHS) // errors.addAll(checkType(nac.getOriginal())); // check image errors.addAll(checkType(nac.getImage())); } // check all PACs final List<OrdinaryMorphism> pacs = rule.getPACsList(); for (int l=0; l<pacs.size(); l++) { final OrdinaryMorphism pac = pacs.get(l); // check original (LHS) // errors.addAll(checkType(pac.getOriginal())); // check image errors.addAll(checkType(pac.getImage())); } return errors; } /** * checks the given atomic, if it is valid typed. If the TypeSet of the * contained graphs is not this object, the types of the nodes and edges * must be also defined here. If in this TypeSet a proofed type graph is * used, there must be a morphism from the given graphs into the type graph. * * @param atomic * the atomic to check. * @return An empty {@link Collection} if the given atomic is valid typed. * If there were type errors in the atomic a Collection with objects * of class {@link TypeError} will returned. For each mismatch an * object will delivered. You can check if there were errors with * {@link Collection#isEmpty}. * * @see #checkTypeGraph */ public Collection<TypeError> checkType(final AtomConstraint atomic) { // count the type mismatches Vector<TypeError> errors = new Vector<TypeError>(); // check left side / original errors.addAll(checkType(atomic.getOriginal())); // check all right sides / conclusions Enumeration<AtomConstraint> cons = atomic.getConclusions(); OrdinaryMorphism actCon; while (cons.hasMoreElements()) { actCon = cons.nextElement(); // the left side is always the same // check image errors.addAll(checkType(actCon.getImage())); } return errors; }// checkType(Rule) /** * checks the given morphism, if it is valid typed. If the TypeSet of the * contained graph is not this object, the types of the nodes and edges must * be also defined here. If in this TypeSet a proofed type graph is used, * there must be a morphism from the given graphs into the type graph. * * @param morphism * the morphism to check. The image and the original grpah of the * morphism will be checked. * @return An empty {@link Collection} if the given morphism is valid typed. * If there were type errors in the morphism a Collection with * objects of class {@link TypeError} will returned. For each * mismatch an object will delivered. You can check if there were * errors with {@link Collection#isEmpty}. * * @see #checkTypeGraph */ public Collection<TypeError> checkType(final OrdinaryMorphism morphism) { // count the type mismatches Vector<TypeError> errors = new Vector<TypeError>(); // check left side / original errors.addAll(checkType(morphism.getOriginal())); // check right side / image errors.addAll(checkType(morphism.getImage())); // return the errors return errors; }// checkType(OrinaryMorphism) /** * checks the given arc, if it is valid typed. The TypeSet of the graph * which contains the arc must be this object. If in this TypeSet a proofed * type graph is used, this arc must be represented there. * * @param arc * the arc to check. * @return An empty {@link Collection} if the given arc is valid typed. If * there were type errors in the arc a Collection with objects of * class {@link TypeError} will returned. For each mismatch an * object will delivered. You can check if there were errors with * {@link Collection#isEmpty}. * * @see #checkTypeGraph */ public TypeError checkType(final Arc arc, final boolean isComplete) { // check if the type graph is validated if (this.typeGraphLevel <= DISABLED) return null; if (isComplete && this.typeGraphLevel >= ENABLED_MAX) return checkTypeInTypeGraph(arc, this.typeGraphLevel); else if (!isComplete && this.typeGraphLevel >= ENABLED_MAX) return checkTypeInTypeGraph(arc, ENABLED_MAX); else return null; } /** * checks the given node, if it is valid typed. The TypeSet of the graph * which contains the node must be this object. If in this TypeSet a proofed * type graph is used, this node must be represented there. * * @param node * the node to check. * @param isComplete * true, if the containing graph is not a subgraph so we will * also check for minimum multiplicity if activated. * @return An empty {@link Collection} if the given node is valid typed. If * there were type errors in the node a Collection with objects of * class {@link TypeError} will returned. For each mismatch an * object will delivered. You can check if there were errors with * {@link Collection#isEmpty}. * * @see #checkTypeGraph */ public TypeError checkType(final Node node, final boolean isComplete) { // check if the type graph is validated if (this.typeGraphLevel == DISABLED) return null; if (this.typeGraphLevel >= ENABLED_MAX) { if (isComplete) return checkTypeInTypeGraph(node, this.typeGraphLevel); return checkTypeInTypeGraph(node, ENABLED_MAX); } return null; } /** * checks the given graph object, if it is valid typed. The TypeSet of the * graph which contains the object must be this object. If in this TypeSet a * proofed type graph is used, this object must be represented there. * * @param object * the object to check. * @return An empty {@link Collection} if the given object is valid typed. * If there were type errors in the arc a Collection with objects of * class {@link TypeError} will returned. For each mismatch an * object will delivered. You can check if there were errors with * {@link Collection#isEmpty}. * * @see #checkTypeGraph */ public TypeError checkType(final GraphObject object) { if (object instanceof Node) { return checkType((Node) object, false); } else if (object instanceof Arc) { return checkType((Arc) object, false); } else { return null; } } /** * changes the behavior of the type graph check and defines, how the type * graph is used. * * @param level * <table> * <tr> * <td>{@link #DISABLED}</td> * <td>The type graph will be ignored, so all graphs can contain * objects with types undefined in the type graph. Multiplicity * will be also ignored.</td> * </tr> * <tr> * <td>{@link #ENABLED}</td> * <td>The type graph will be basicaly used, so all graphs can * only contain objects with types defined in the type graph. But * the multiplicity will not be checked.</td> * </tr> * <tr> * <td>{@link #ENABLED_MAX}</td> * <td>The type graph will be basically used, so all graphs can * only contain objects with types defined in the type graph. * Multiplicity in all graphs should satisfy the defined * maximum constraints.</td> * </tr> * <tr> * <td>{@link #ENABLED_MAX_MIN}</td> * <td>The type graph will be used, so all graphs can only * contain objects with types defined in the type graph. * Multiplicity in all graphs must satisfy the defined maximum * constraints and the working graph must</td> * </tr> * </table> * * @return {@link #SUCCESS} (an empty Collection), if the type graph is * defined and is usable as type graph. Otherwise you get a * Collection of {@link TypeError}. */ public Collection<TypeError> setLevelOfTypeGraphCheck(final int level) { // if the type graph is not proofed, check it if (level != DISABLED && (!this.typeGraphIsProved || this.typeGraphLevel == DISABLED)) { Collection<TypeError> errors = this.checkTypeGraph(); if (!errors.isEmpty()) return errors; } this.typeGraphLevel = level; return SUCCESS; } /** * Set the level of the type graph without checking * whether the type multiplicity constraints are satisfied. * * @param level */ public void setLevelOfTypeGraph(final int level) { this.typeGraphLevel = level; } /** * Returns the level of the type graph. * * @return <table> * <tr> * <td>{@link #DISABLED}</td> * <td>The type graph will be ignored, so all graphs can contain * objects with types undefined in the type graph.</td> * </tr> * <tr> * <td>{@link #ENABLED}</td> * <td>The type graph is used, so all graphs can only * contain objects with types defined in the type graph. * Multiplicity constraints will not be checked.</td> * </tr> * <tr> * <td>{@link #ENABLED_MAX}</td> * <td>The type graph is used, so all graphs can only * contain objects with types defined in the type graph. * Multiplicity constraints max will be checked.</td> * </tr> * <tr> * <td>{@link #ENABLED_MAX_MIN}</td> * <td>The type graph will be used, so all graphs can only contain * objects with types defined in the type graph. * Multiplicity constraints min, max will be checked.</td> * </tr> * </table> */ public int getLevelOfTypeGraphCheck() { return this.typeGraphLevel; } /** * marks the type graph as unchecked, so no longer the type graph will be * used for type checks. Use {@link #checkTypeGraph()} to turn the type * graph based checks on. * * @deprecated use {@link #setLevelOfTypeGraphCheck} */ public void disableTypeGraphCheck() { this.setLevelOfTypeGraphCheck(DISABLED); }// turnTypeGraphCheckOff /** * marks the type graph as checked, so no longer the type graph will be used * for type checks. Use {@link #checkTypeGraph()} to turn the type graph * based checks on. * * @deprecated use {@link #setLevelOfTypeGraphCheck} */ public Collection<TypeError> enableTypeGraphCheck() { return this.setLevelOfTypeGraphCheck(ENABLED_MAX); }// turnTypeGraphCheckOff public boolean compareTo(final TypeSet ts) { if (ts == this) return true; // compare types size Enumeration<Type> e = ts.getTypes(); Vector<Type> another = new Vector<Type>(); while (e.hasMoreElements()) { another.add(e.nextElement()); } if (this.types.size() != another.size()) return false; // compare this.types for (int i = 0; i < this.types.size(); i++) { Type t = this.types.elementAt(i); for (int j = another.size() - 1; j >= 0; j--) { Type t1 = another.elementAt(j); if (t.compareTo(t1)) { another.remove(t1); break; } } } if (another.size() != 0) return false; // compare type graph if ((this.typeGraph == null) && (ts.getTypeGraph() == null)) return true; if ((this.typeGraph != null) && (ts.getTypeGraph() == null)) return false; if ((this.typeGraph == null) && (ts.getTypeGraph() != null)) return false; if (!this.typeGraph.compareTo(ts.getTypeGraph())) return false; return true; } /** * Compare my types with the types of the specified TypeSet ts. Returns * true, if the types are compatible, otherwise false. */ public boolean compareTypes(final TypeSet ts) { if (String.valueOf(ts.hashCode()).equals(this.info)){ return true; } return compareTypes(ts, new Vector<Type>(), new Vector<Type>(), new Vector<Type>(), new Vector<Type>()); } /** * Compare my types with the types of the specified TypeSet ts. Fill the * specified container with types that have equal name but different * attributes, inheritance, multiplicity. Returns true, if the types are * compatible, otherwise false. */ public boolean compareTypes(final TypeSet ts, final Vector<Type> differentAttribute, final Vector<Type> differentInheritance, final Vector<Type> differentMultiplicity) { return compareTypes(ts, differentAttribute, differentInheritance, differentMultiplicity, new Vector<Type>()); } public boolean isNewTypeGraphObjectImported() { return this.newTypeGraphObjectImported; } /** * Compare my types with the types of the specified TypeSet ts. Fill the * specified container with types that have equal name but different * attributes, inheritance, multiplicity, also not existing types. Returns * true, if the types are compatible, otherwise false. */ private boolean compareTypes(final TypeSet ts, final Vector<Type> differentAttribute, final Vector<Type> differentInheritance, final Vector<Type> differentMultiplicity, final Vector<Type> typesToAdd) { if (ts == this || String.valueOf(ts.hashCode()).equals(this.info)) { return true; } // hier multiple inheritance einbauen!! differentInheritance.clear(); differentAttribute.clear(); differentMultiplicity.clear(); typesToAdd.clear(); boolean conflict = false; Vector<Type> another = new Vector<Type>(ts.getTypeList()); // compare types for (int i = 0; i < this.types.size(); i++) { Type t = this.types.elementAt(i); for (int j = 0; j < another.size(); j++) { Type t1 = another.elementAt(j); if (t.getStringRepr().equals(t1.getStringRepr())) { if ((t.isNodeType() && t1.isNodeType()) || (t.isArcType() && t1.isArcType())) { // check attribute list if (!t.compareTo(t1)) { if (!differentAttribute.contains(t1)) differentAttribute.add(t1); conflict = true; } // check node type graph object if (t.getTypeGraphNodeObject() != null && t1.getTypeGraphNodeObject() != null) { // check inheritance if (!t1.getParents().isEmpty()) { if (!t.getParents().isEmpty()) { Vector<Type> tParents = t.getAllParents(); Vector<Type> t1Parents = t1.getAllParents(); if (!compareParents(tParents, t1Parents)) { conflict = true; if (!differentInheritance.contains(t1)) { differentInheritance.add(t1); } } } else { conflict = true; if (!differentInheritance.contains(t1)) { differentInheritance.add(t1); } } } // check multiplicity of node type if (t.getSourceMax() != t1.getSourceMax()) { conflict = true; if (!differentMultiplicity.contains(t1)) differentMultiplicity.add(t1); } else if (t.getSourceMin() != t1.getSourceMin()) { conflict = true; if (!differentMultiplicity.contains(t1)) differentMultiplicity.add(t1); } } else if (t.hasTypeGraphArc() && t1.hasTypeGraphArc()) { // check arc embedding into the type graph if (!t.compareTypeGraphArcs(t1)) { if (!typesToAdd.contains(t1)) typesToAdd.add(t1); } // check multiplicity of arc type graph object if (!t.compareTypeGraphArcsMultiplicity(t1)) { conflict = true; if (!differentMultiplicity.contains(t1)) differentMultiplicity.add(t1); } } else { if (t1.hasTypeGraphNode()) { if (!typesToAdd.contains(t1)) typesToAdd.add(t1); } else if (t1.hasTypeGraphArc()) { if (!typesToAdd.contains(t1)) typesToAdd.add(t1); } } another.remove(t1); break; } } } } if (typesToAdd.isEmpty()) { for (int j = 0; j < another.size(); j++) { Type t1 = another.elementAt(j); if (t1.hasTypeGraphNode()) { if (!typesToAdd.contains(t1)) typesToAdd.add(t1); } else if (t1.hasTypeGraphArc()) { if (!typesToAdd.contains(t1)) typesToAdd.add(t1); } } } this.newTypeGraphObjectImported = !typesToAdd.isEmpty(); return !conflict; } private boolean compareParents(final Vector<Type> allParents1, final Vector<Type> allParents2) { int nm = allParents1.size(); int i = 1; while (i < nm) { Type p1 = allParents1.get(i); Type p2 = allParents2.get(i); if (!p1.compareTo(p2)) return false; i++; } return true; } public boolean contains(final TypeSet ts) { if (ts == this || String.valueOf(ts.hashCode()).equals(this.info)) { return true; } // compare types if (this.types.size() < ts.getTypesCount()) { return false; } int count = 0; for (int i = 0; i < this.types.size(); i++) { Type ti = this.types.elementAt(i); for (int j = 0; j < ts.getTypeList().size(); j++) { Type tj = ts.getTypeList().get(j); if (ti.compareTo(tj)) { count++; break; } } } if (count != ts.getTypeList().size()) { return false; } // compare type graph if (this.typeGraph != null && ts.getTypeGraph() != null && !this.typeGraph.contains(ts.getTypeGraph())) { return false; } return true; } /** * returns, if the given node could be removed from its actual graph. * * @param node * the node to check * @return null, if the removing is allowed otherwise a {@link TypeError} */ public TypeError checkIfRemovable(final Node node) { if (this.typeGraphLevel < ENABLED_MAX_MIN) { return null; } TypeError error = node.getType().checkIfRemovable(node, this.typeGraphLevel); return error; } /** * Checks if the given edge could be removed from its source and target. * * @param arc * the edge to check * @return null, if edge type multiplicity has not failed, otherwise {@link TypeError} * */ public TypeError checkIfRemovable(final Arc arc) { if (this.typeGraphLevel != ENABLED_MAX_MIN) { return null; } GraphObject node = arc.getSource(); TypeError error = node.getType().checkIfRemovableFromSource(node, arc, this.typeGraphLevel); if (error != null) { return error; } node = arc.getTarget(); error = node.getType().checkIfRemovableFromTarget(node, arc, this.typeGraphLevel); return error; } /** * Checks if the given edge could be removed from its source and target * with respect to source and target to delete. * * @param arc edge to delete * @param deleteSrc true if the source node will be deleted * @param deleteTar true if the target node will be deleted * * @return null if edge type multiplicity has not failed, otherwise a type error {@link TypeError} */ public TypeError checkIfRemovable(final Arc arc, boolean deleteSrc, boolean deleteTar) { if (this.typeGraphLevel != ENABLED_MAX_MIN) { return null; } TypeError error = null; if (!deleteTar) { GraphObject node = arc.getSource(); error = node.getType().checkIfRemovableFromSource(node, arc, deleteSrc, deleteTar, this.typeGraphLevel); } if ((error == null) && !deleteSrc) { GraphObject node = arc.getTarget(); error = node.getType().checkIfRemovableFromTarget(node, arc, deleteSrc, deleteTar, this.typeGraphLevel); } return error; } /** * Checks if the given arc could be removed from its source. This * method ignores the multiplicity constraints of the target node. It * should be only used when the target node should be destroyed. * * @param arc * the edge to check * @return null, if the removing is allowed otherwise a {@link TypeError} */ public TypeError checkIfRemovableFromSource(final Arc arc) { if (this.typeGraphLevel != ENABLED_MAX_MIN) { return null; } GraphObject node = arc.getSource(); TypeError error = node.getType().checkIfRemovableFromSource(node, arc, this.typeGraphLevel); return error; } /** * Checks if the given arc could be removed from its target. This * method ignores the multiplicity constraints of the source node. It * should be only used when the source node should be destroyed. * * @param arc * the arc to check * @return null, if the removing is allowed otherwise a {@link TypeError} */ public TypeError checkIfRemovableFromTarget(final Arc arc) { if (this.typeGraphLevel != ENABLED_MAX_MIN) { return null; } GraphObject node = arc.getTarget(); TypeError error = node.getType().checkIfRemovableFromTarget(node, arc, this.typeGraphLevel); return error; } public TypeError checkIfEdgeCreatable(final Type type, final Node src, final Node tar) { if ((this.typeGraphLevel == DISABLED) || (this.typeGraphLevel == ENABLED)) return null; return type.checkIfEdgeCreatable(src, tar, this.typeGraphLevel); } public int getMaxMultiplicity(final Type type) { return type.getSourceMax(); } public int getMinMultiplicity(final Type type) { return type.getSourceMin(); } public int getMaxSourceMultiplicity(final Type type, final Type srctype, final Type tartype) { return type.getSourceMax(srctype, tartype); } public int getMinSourceMultiplicity(final Type type, final Type srctype, final Type tartype) { return type.getSourceMin(srctype, tartype); } public int getMaxTargetMultiplicity(final Type type, final Type srctype, final Type tartype) { return type.getTargetMax(srctype, tartype); } public int getMinTargetMultiplicity(final Type type, final Type srctype, final Type tartype) { return type.getTargetMin(srctype, tartype); } public String showTypes() { String out = "Types:" + "\n"; for (int i = 0; i < this.types.size(); i++) { Type t = this.types.get(i); out = out + t.getName() + t.getAdditionalRepr() + "\n"; } return out; } public String showNodeTypes() { String out = "Types:" + "\n"; for (int i = 0; i < this.types.size(); i++) { Type t = this.types.get(i); if (t.getAdditionalRepr().indexOf("NODE") >= 0) out = out + t.getName() + t.getAdditionalRepr() + "\n"; } return out; } public String showArcTypes() { String out = "Types:" + "\n"; for (int i = 0; i < this.types.size(); i++) { Type t = this.types.get(i); if (t.getAdditionalRepr().indexOf("EDGE") >= 0) out = out + t.getName() + t.getAdditionalRepr() + "\n"; } return out; } public void refreshTypeGraphObjects() { if (this.typeGraph == null) return; this.refreshInheritance(); /* Vector<Arc> checkedArcs = new Vector<Arc>(); Enumeration<Node> en = this.typeGraph.getNodes(); while (en.hasMoreElements()) { Node tnode = en.nextElement(); Enumeration<Arc> inArcs = tnode.getIncomingArcs(); while (inArcs.hasMoreElements()) { Arc inarc = inArcs.nextElement(); if (inarc.getType() != this.inheritanceType || checkedArcs.contains(inarc)) continue; checkedArcs.add(inarc); } Enumeration<Arc> outArcs = tnode.getOutgoingArcs(); while (outArcs.hasMoreElements()) { Arc outarc = outArcs.nextElement(); if (outarc.getType() != this.inheritanceType || checkedArcs.contains(outarc)) continue; checkedArcs.add(outarc); } } checkedArcs.clear(); */ } /* * Remove all type users which are destroyed by <code>Node.disposeFast()</ode> * resp. <code>Arc.disposeFast()</code>. * The type of these edges is already null. */ // public void refreshTypeUsers() { // for (int i=0; i<this.types.size(); i++) { // Type t = this.types.get(i); // if (t instanceof NodeTypeImpl) { // ((NodeTypeImpl)t).refreshTypeUsers(); // } else if (t instanceof ArcTypeImpl) { // ((ArcTypeImpl)t).refreshTypeUsers(); // } // } // } public void setHelpInfo(final String str) { this.info = str; } public String getHelpInfo() { return this.info; } /** * Trims the capacity of used vectors to be the vector's current * size. */ public void trimToSize() { if (this.typeGraph != null) this.typeGraph.trimToSize(); this.types.trimToSize(); this.inheritanceArcs.trimToSize(); } } // $Log: TypeSet.java,v $ // Revision 1.87 2010/12/02 19:37:59 olga // import type graph - bug fixed // // Revision 1.86 2010/10/19 19:04:51 olga // tuning // // Revision 1.85 2010/10/18 15:00:51 olga // import type graph - bug fixed // // Revision 1.84 2010/10/16 22:46:11 olga // improved undo for RuleScheme graph objects // // Revision 1.83 2010/10/07 20:04:26 olga // bug fixed- multiplicity bug after disable-enable the type graph // // Revision 1.82 2010/09/23 08:27:32 olga // tuning // // Revision 1.81 2010/08/09 13:58:50 olga // tuning // // Revision 1.80 2010/03/08 15:51:40 olga // code optimizing // // Revision 1.79 2010/03/04 14:17:13 olga // code optimizing // // Revision 1.78 2010/02/22 14:42:07 olga // code optimizing // // Revision 1.77 2009/10/05 08:53:09 olga // RSA check - bug fixed // // Revision 1.76 2009/09/21 13:56:40 olga // type graph check improved // // Revision 1.75 2009/08/03 16:54:52 olga // CPA , essential pairs - bug fixed // // Revision 1.74 2009/07/29 09:32:05 olga // Match with PACs - bug fixed // ARS - code tuning // // Revision 1.73 2009/07/14 12:16:30 olga // Multiplicity bug fixed // // Revision 1.72 2009/07/13 07:26:22 olga // ARS: further development // // Revision 1.71 2009/06/02 12:39:22 olga // Min Multiplicity check - bug fixed // // Revision 1.70 2009/05/12 10:36:42 olga // CPA: bug fixed // Applicability of Rule Seq. : bug fixed // // Revision 1.69 2009/04/14 09:18:35 olga // Edge Type Multiplicity check - bug fixed // // Revision 1.68 2009/03/30 13:50:48 olga // some tests // // Revision 1.67 2009/03/12 10:57:48 olga // some changes in CPA of managing names of the attribute variables. // // Revision 1.66 2009/02/26 16:31:41 olga // Code tuning // // Revision 1.65 2009/01/14 10:51:41 olga // - Import of TypeGraph with NTI in an existing TypeGraph without NTI, // attribute member overlapping with parent attribute - bug fixed // - Edge type Multiplicity check (target min, source min) during manual graph editing - bug fixed // - Edge type Multiplicity check (target min, source min) during graph matching - improved // // Revision 1.64 2008/12/17 09:37:37 olga // Import of TypeGraph from grammar (.ggx) - bug fixed // // Revision 1.63 2008/11/13 08:26:20 olga // some tests // // Revision 1.62 2008/10/15 14:58:38 olga // - Bug fixed: import type graph with inheritance // - Bug fixed: edge type Multiplicity check in CPA // // Revision 1.61 2008/09/04 08:17:01 olga // Inheritance events added // // Revision 1.60 2008/08/21 13:08:13 jurack // Benachrichtigung an Observer, wenn Inheritance hinzugef�gt wird // // Revision 1.59 2008/07/09 13:34:26 olga // Applicability of RS - bug fixed // Delete not used node/edge type - bug fixed // AGG help - extended // // Revision 1.58 2008/04/21 09:32:18 olga // Visualization of inheritance edge - bugs fixed // Graph layout tuning // // Revision 1.57 2008/04/17 10:11:08 olga // Undo, redo edit and graph layout tuning, // // Revision 1.56 2008/04/10 14:57:24 olga // code tuning // // Revision 1.55 2008/04/09 10:29:37 olga // Bug fixed - import graph type with abstract types // // Revision 1.54 2008/04/09 07:38:52 olga // Bug fixed during loading of grammar // // Revision 1.53 2008/04/07 09:36:54 olga // Code tuning: refactoring + profiling // Extension: CPA - two new options added // // Revision 1.52 2008/02/18 09:37:11 olga // - an extention of rule dependency check is implemented; // - some bugs fixed; // - editing of graphs improved // // Revision 1.51 2007/12/17 08:33:29 olga // Editing inheritance relations - bug fixed; // CPA: dependency of rules - bug fixed // // Revision 1.50 2007/12/03 08:35:12 olga // - Some bugs fixed in visualization of morphism mappings after deleting and // creating // nodes, edges // - implemented: matching with non-injective NAC and Match morphism // // Revision 1.49 2007/11/21 09:59:44 olga // Update V1.6.2.1: // new features: - default attr value can be set in a type graph and used during // transformation (experimental phase) // - currently selected node and edge type are shown in the bottom right corner // of the AGG GUI // - Critical pair analysis for grammar with node type inheritance (experimental // phase) // // Revision 1.48 2007/11/19 08:48:40 olga // Some GUI usability mistakes fixed. // Default values in node/edge of a type graph implemented. // Code tuning. // // Revision 1.47 2007/11/14 08:53:42 olga // code tuning // // Revision 1.46 2007/11/12 08:48:55 olga // Code tuning // // Revision 1.45 2007/11/08 12:57:00 olga // working on CPA inconsistency for rules with pacs and inheritance // bugs are possible // // Revision 1.44 2007/11/05 09:18:21 olga // code tuning // // Revision 1.43 2007/11/01 09:58:16 olga // Code refactoring: generic types- done // // Revision 1.42 2007/10/10 14:30:32 olga // Enumeration typing // // Revision 1.41 2007/10/04 10:56:04 olga // Code tuning // // Revision 1.40 2007/10/04 07:44:28 olga // Code tuning // // Revision 1.39 2007/10/01 12:48:54 olga // test: in Graph, TypeGraph, GraphObject - DList replaced by Vector // // Revision 1.38 2007/09/27 08:42:47 olga // CPA: new option -ignore pairs with same rules and same matches- // // Revision 1.37 2007/09/24 09:42:36 olga // AGG transformation engine tuning // // Revision 1.36 2007/09/10 13:05:37 olga // In this update: // - package xerces2.5.0 is not used anymore; // - class com.objectspace.jgl.Pair is replaced by the agg own generic class // agg.util.Pair; // - bugs fixed in: usage of PACs in rules; match completion; // usage of static method calls in attr. conditions // - graph editing: added some new features // // Revision 1.35 2007/07/09 08:00:16 olga // GUI tuning // // Revision 1.34 2007/06/25 08:28:26 olga // Tuning and Docu update // // Revision 1.33 2007/06/18 08:15:56 olga // New extentions by drawing edge. // // Revision 1.32 2007/06/13 08:33:03 olga // Update: V161 // // Revision 1.31 2007/04/30 10:39:46 olga // tests // // Revision 1.30 2007/04/19 14:50:01 olga // Loading grammar - tuning // // Revision 1.29 2007/04/19 07:52:41 olga // Tuning of: Undo/Redo, Graph layouter, loading grammars // // Revision 1.28 2007/04/11 10:03:38 olga // Undo, Redo tuning, // Simple Parser- bug fixed // // Revision 1.27 2007/03/28 10:01:08 olga // - extensive changes of Node/Edge Type Editor, // - first Undo implementation for graphs and Node/edge Type editing and // transformation, // - new / reimplemented options for layered transformation, for graph layouter // - enable / disable for NACs, attr conditions, formula // - GUI tuning // // Revision 1.26 2007/02/05 12:33:46 olga // CPA: chengeAttribute conflict/dependency : attributes with constants // bug fixed, but the critical pairs computation has still a gap. // // Revision 1.25 2007/01/31 09:19:20 olga // Bug fixed in case of transformating attributed grammar with inheritance and // non-injective match // // Revision 1.24 2007/01/29 09:44:27 olga // Bugs fiixed, that occur during the extension a non-attributed grammar by // attributes. // // Revision 1.23 2007/01/22 08:28:26 olga // GUI bugs fixed // // Revision 1.22 2006/11/15 09:00:32 olga // Transform with input parameter : bug fixed // // Revision 1.21 2006/11/09 10:31:05 olga // Matching error fixed // // Revision 1.20 2006/11/06 10:09:36 olga // Type editor GUI tuning // // Revision 1.19 2006/11/01 11:17:30 olga // Optimized agg sources of CSP algorithm, match usability, // graph isomorphic copy, // node/edge type multiplicity check for injective rule and match // // Revision 1.18 2006/08/03 17:10:28 olga // Java docu // // Revision 1.17 2006/08/02 09:00:57 olga // Preliminary version 1.5.0 with // - multiple node type inheritance, // - new implemented evolutionary graph layouter for // graph transformation sequences // // Revision 1.16 2006/05/29 07:59:42 olga // GUI, undo delete - tuning. // // Revision 1.15 2006/05/08 08:24:12 olga // Some extentions of GUI: - Undo Delete button of tool bar to undo deletions // if grammar elements like rule, NAC, graph constraints; // - the possibility to add a new graph to a grammar or a copy of the current // host graph; // - to set one or more layer for consistency constraints. // Also some bugs fixed of matching and some optimizations of CSP algorithmus // done. // // Revision 1.14 2006/04/12 14:54:07 olga // Restore attr. values of attr. type observers after type graph imported. // // Revision 1.13 2006/04/12 09:01:57 olga // Layered graph constraints tuning // // Revision 1.12 2006/04/10 09:19:30 olga // Import Type Graph, Import Graph - tuning. // Attr. member type check: if class does not exist. // Graph constraints for a layer of layered grammar. // // Revision 1.11 2006/04/06 15:27:29 olga // Import Type Graph and Type Graph tuning // // Revision 1.10 2006/04/06 09:28:52 olga // Tuning of Import Type Graph and Import Graph // // Revision 1.9 2006/04/03 08:57:50 olga // New: Import Type Graph // and some bugs fixed // // Revision 1.8 2006/03/01 09:55:47 olga // - new CPA algorithm, new CPA GUI // // Revision 1.7 2005/10/24 09:04:49 olga // GUI tuning // // Revision 1.6 2005/10/17 12:32:28 enrico // Multiplicity check for node instances // // Revision 1.5 2005/09/26 08:35:15 olga // CPA graph frames; bugs // // Revision 1.4 2005/09/08 16:25:02 olga // Improved: editing attr. condition, importing graph, sorting node/edge types // // Revision 1.3 2005/09/05 10:06:45 olga // Deleting type graph object - fixed. // // Revision 1.2 2005/09/01 08:22:14 olga // Adaptation inheritance version to AGG standard: // - remove type graph nodes/arcs, // - GUI conformance. // // Revision 1.1 2005/08/25 11:56:54 enrico // *** empty log message *** // // Revision 1.2.2.2 2005/08/16 09:56:04 enrico // implemented method getClan // // Revision 1.2.2.1 2005/07/04 11:41:37 enrico // basic support for inheritance // // Revision 1.2 2005/06/20 13:37:03 olga // Up to now the version 1.2.8 will be prepared. // // Revision 1.1 2005/05/30 12:58:02 olga // Version with Eclipse // // Revision 1.31 2005/04/21 15:48:04 olga // Fehler in PACs korregiert. Graph constraints (formulae) mit Verneinung // koennen nicht vollstaendig korrekt getestet werden. Nur positive // constraints werden richtig geprueft. Attribute Kontext kann aber noch // Probleme berreiten. // CVSr ---------------------------------------------------------------------- // // Revision 1.30 2005/03/16 12:02:10 olga // // only little changes // // Revision 1.29 2005/02/09 15:08:15 olga // Interface Type erweitert; TypeImpl ist jetzt public class. // CiVS: ---------------------------------------------------------------------- // // Revision 1.28 2005/01/28 14:02:32 olga // -Fehlerbehandlung beim Typgraph check // -Erweiterung CP GUI / CP Menu // -Fehlerbehandlung mit identification option // -Fehlerbehandlung bei Rule PAC // // Revision 1.27 2005/01/05 08:56:13 olga // Source tuning // // Revision 1.26 2004/12/20 14:53:49 olga // Changes because of matching optimisation. // // Revision 1.25 2004/11/15 17:50:39 olga // Jetzt das Kombinieren von Grammars moeglich. // // Revision 1.24 2004/05/13 17:54:10 olga // Fehlerbehandlung // // Revision 1.23 2004/04/19 11:39:30 olga // Graphname als String ohne Blanks // // Revision 1.22 2004/04/15 10:49:48 olga // Kommentare // // Revision 1.21 2004/02/25 16:35:46 olga // Testausgaben aus. // // Revision 1.20 2004/01/28 17:58:39 olga // Errors suche // // Revision 1.19 2003/12/18 16:27:46 olga // Tests. // // Revision 1.18 2003/06/05 15:07:55 olga // delete type angepasst // // Revision 1.17 2003/06/05 07:43:26 olga // Dokumentation // // Revision 1.16 2003/05/30 13:43:17 olga // Multiplicity Max-check ist jetzt in Step.execute. // Multiplicity Min-check ist in Match.isValid // // Revision 1.15 2003/05/28 11:50:41 olga // Min/Max Multiplicity check Test und Aenderung // // Revision 1.14 2003/05/23 11:33:31 komm // new check function for dangling arcs // // Revision 1.13 2003/05/14 17:56:47 komm // Added minimum multiplicity and removed TODOs // // Revision 1.12 2003/04/10 08:51:23 olga // Tests mit serializable Ausgabe // // Revision 1.11 2003/03/31 10:33:36 olga // Min-Multiplicity check nur fuer Work Graph // // Revision 1.10 2003/03/20 13:36:10 olga // Delete TypeGraph neu // // Revision 1.9 2003/03/05 13:28:55 komm // method of type graph activation changed to type graph level // // Revision 1.8 2003/02/24 11:20:28 komm // appereance changed // // Revision 1.7 2003/02/03 17:49:52 olga // new : compareTo(..) // // Revision 1.6 2002/12/18 11:38:24 komm // remove of type error marks works now // // Revision 1.5 2002/12/16 13:43:59 komm // renamed methods for turning off type graph check // // Revision 1.4 2002/11/11 10:37:19 komm // multiplicity check added // // Revision 1.3 2002/09/30 10:12:55 komm // dynamic type check expanded // // Revision 1.2 2002/09/23 12:24:14 komm // added type graph in xt_basis, editor and GUI // // Revision 1.1.1.1 2002/07/11 12:17:27 olga // Imported sources // // Revision 1.6 2001/02/22 12:35:02 olga // Alle ALR Objecte werden mit einem "default" Typ aus der BaseFactory kreiert. // // Revision 1.5 2001/02/16 14:52:04 olga // Type Fehler korregiert. // // Revision 1.4 2001/02/15 16:02:37 olga // Fehlerbehebung wegen XML; // Aenderungen bei TypeSet. // // Revision 1.3 1999/06/28 16:41:46 shultzke // Hoffentlich erzeigen wir eine uebersetzungsfaehige Version // // Revision 1.2 1998/09/03 13:14:42 mich // Updated for use with JGL V3.1. // // Revision 1.1 1998/05/27 17:29:02 mich // Initial revision //