/* * (C) Copyright 2002 Arnaud Bailly (arnaud.oqube@gmail.com), * Yves Roos (yroos@lifl.fr) and others. * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package rationals.graph; import rationals.Automaton; import rationals.State; import rationals.Transition; import salvo.jesus.graph.*; import salvo.jesus.graph.algorithm.DepthFirstGraphTraversal; import salvo.jesus.graph.algorithm.GraphTraversal; import java.util.*; /** * An adapter class for encapsulating Automata objects as DirectedGraph * instances. * This adapter is useful for using display and output capabilities of * <a href="http://openjgraph.sourceforge.net">openjgraph</a> package * on automaton objects (without making jautomata core package dependant on * openjgraph). <br /> * <strong>WARNING</strong>: this implementation does not work. It is waiting * some refactoring of OpenJGraph API or some change in support package. * @author bailly@lifl.fr * @since 2.0 * @see rationals.Automaton */ public class AutomatonGraphAdapter implements DirectedGraph { private DirectedGraphImplFactory factory; private List addvertexlistener; private List addedgelistener; private List removevertexlistener; private List removeedgelistener; private GraphTraversal traversal; private Automaton auto; public Automaton getAutomaton() { return auto; } /** * Default constructor. * Creates an adapter that wraps the given automaton. * * @param auto the Automaton object to wrap. May not be null. */ public AutomatonGraphAdapter(Automaton auto) { this.auto = auto; /* graph initializations */ addvertexlistener = new ArrayList(10); addedgelistener = new ArrayList(10); removevertexlistener = new ArrayList(10); removeedgelistener = new ArrayList(10); this.factory = new DirectedGraphImplFactory(); traversal = new DepthFirstGraphTraversal(this); } ///////////////////////////////////////////////////// // GRAPH METHODS ///////////////////////////////////////////////////// /* * (non-Javadoc) * Passed object must a be a state of the underlying atuomaton. * @see salvo.jesus.graph.DirectedGraph#getOutgoingEdges(salvo.jesus.graph.Vertex) */ public List getOutgoingEdges(Object v) { List l = new ArrayList(); for(Iterator i = auto.delta((State)v).iterator();i.hasNext();) { Transition tr = (Transition)i.next(); DirectedEdgeImpl de = new DirectedEdgeImpl(tr.start(),tr.end(),tr); l.add(de); } return l; } /* * (non-Javadoc) * * @see salvo.jesus.graph.DirectedGraph#getIncomingEdges(salvo.jesus.graph.Vertex) */ public List getIncomingEdges(Object v) { List res = new ArrayList(); for(Iterator i = auto.deltaMinusOne((State)v).iterator();i.hasNext();) { Transition tr = (Transition)i.next(); DirectedEdgeImpl de = new DirectedEdgeImpl(tr.end(),tr.start(),tr); res.add(de); } return res; } /* * (non-Javadoc) * * @see salvo.jesus.graph.DirectedGraph#getOutgoingAdjacentVertices(salvo.jesus.graph.Vertex) */ public List getOutgoingAdjacentVertices(Object v) { List res = new ArrayList(); for(Iterator i = auto.delta((State)v).iterator();i.hasNext();) { Transition tr = (Transition)i.next(); res.add(tr.end()); } return res; } /* * (non-Javadoc) * * @see salvo.jesus.graph.DirectedGraph#getIncomingAdjacentVertices(salvo.jesus.graph.Vertex) */ public List getIncomingAdjacentVertices(Object v) { List res = new ArrayList(); for(Iterator i = auto.deltaMinusOne((State)v).iterator();i.hasNext();) { Transition tr = (Transition)i.next(); res.add(tr.end()); } return res; } /* * (non-Javadoc) * * @see salvo.jesus.graph.DirectedGraph#getEdge(salvo.jesus.graph.Vertex, * salvo.jesus.graph.Vertex) */ public DirectedEdge getEdge(Object fromvertex, Object tovertex) { List outIncidentEdges; Iterator iterator; DirectedEdge edge; // Get the adjacent edge set of the from vertex outIncidentEdges = this.getOutgoingEdges(fromvertex); // Find the edge where the direction is to the tovertex iterator = outIncidentEdges.iterator(); while (iterator.hasNext()) { edge = (DirectedEdge) iterator.next(); if (edge.getSink() == tovertex) { // Edge is found. iterator = null; return edge; } } return null; } /* * (non-Javadoc) * * @see salvo.jesus.graph.DirectedGraph#isPath(salvo.jesus.graph.Vertex, * salvo.jesus.graph.Vertex) */ public boolean isPath(Object fromVertex, Object toVertex) { List visited = new ArrayList(10); this.getTraversal().traverse(fromVertex, visited, new StopAtVisitor(toVertex)); if (toVertex == visited.get(visited.size() - 1)) return true; else return false; } /* * (non-Javadoc) * * @see salvo.jesus.graph.DirectedGraph#isCycle(salvo.jesus.graph.Vertex) */ public boolean isCycle(Object fromVertex) { List outedges = this.getOutgoingEdges(fromVertex); Iterator iterator = outedges.iterator(); DirectedEdge dedge; Object adjacentVertex; // For each outgoing edge of the vertex ... while (iterator.hasNext()) { dedge = (DirectedEdge) iterator.next(); // ... get the opposite vertex adjacentVertex = dedge.getOppositeVertex(fromVertex); // .. and check if there is a path from the opposite vertex back to // the vertex if (this.isPath(adjacentVertex, fromVertex)) // There is a cycle return true; } // No cycle return false; } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#getVerticesCount() */ public int getVerticesCount() { return auto.states().size(); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#getGraphFactory() */ public GraphFactory getGraphFactory() { return this.factory; } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#setGraphFactory(salvo.jesus.graph.GraphFactory) */ public void setGraphFactory(GraphFactory factory) { this.factory = (DirectedGraphImplFactory) factory; } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#add(salvo.jesus.graph.Vertex) */ public void add(Object v) throws GraphException { throw new GraphModificationException( "Cannot add vertices : add states to automaton instead"); } /** * @param v */ private void notifyStateAdd(Object v) { GraphAddVertexListener listener; Iterator iterator = addvertexlistener.iterator(); while (iterator.hasNext()) { listener = (GraphAddVertexListener) iterator.next(); listener.vertexAdded(new GraphAddVertexEvent(this, v)); } } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#remove(salvo.jesus.graph.Vertex) */ public void remove(Object v) throws GraphException { throw new GraphModificationException( "Cannot modify this graph. Use automaton interface instead"); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#getVerticesIterator() */ public Iterator getVerticesIterator() { return auto.states().iterator(); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#cloneVertices() */ public List cloneVertices() { Iterator it = auto.states().iterator(); List vertices = new ArrayList(); while (it.hasNext()) { vertices.add((Object) it.next()); } return vertices; } /* * * (non-Javadoc) * * @see salvo.jesus.graph.Graph#getAllVertices() */ public List getAllVertices() { return cloneVertices(); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#getAllEdges() */ public Collection getAllEdges() { List l = new ArrayList(); for(Iterator i = auto.delta().iterator();i.hasNext();) { Transition tr = (Transition)i.next(); DirectedEdgeImpl de = new DirectedEdgeImpl(tr.start(),tr.end(),tr); l.add(de); } return l; } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#getEdgesCount() */ public int getEdgesCount() { return auto.delta().size(); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#createEdge(salvo.jesus.graph.Vertex, * salvo.jesus.graph.Vertex) */ public Edge createEdge(Object v1, Object v2) { return null; } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#addEdge(salvo.jesus.graph.Vertex, * salvo.jesus.graph.Vertex) */ public Edge addEdge(Object v1, Object v2) throws GraphException { throw new GraphModificationException( "Cannot modify this graph. Use automaton interface instead"); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#addEdge(salvo.jesus.graph.Edge) */ public void addEdge(Edge e) throws GraphException { throw new GraphModificationException( "Cannot modify this graph. Use automaton interface instead"); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#removeEdge(salvo.jesus.graph.Edge) */ public void removeEdge(Edge e) throws GraphException { throw new GraphModificationException( "Cannot modify this graph. Use automaton interface instead"); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#removeEdges(salvo.jesus.graph.Vertex) */ public void removeEdges(Object v) throws GraphException { throw new GraphModificationException( "Cannot modify this graph. Use automaton interface instead"); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#getDegree() */ public int getDegree() { State v; HashSet set; set = new HashSet(auto.states()); if (set.size() > 0) { v = (State) Collections.max(set, new Comparator() { public int compare(Object obj1, Object obj2) { Object v1 = (Object) obj1, v2 = (Object) obj2; int countv1 = getDegree(v1); int countv2 = getDegree(v2); if (countv1 < countv2) return -1; if (countv1 > countv2) return 1; else return 0; } public boolean equals(Object objcomparator) { return objcomparator.equals(this); } }); return this.getEdges((Object) v).size(); } else return 0; } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#getDegree(salvo.jesus.graph.Vertex) */ public int getDegree(Object v) { return this.getEdges(v).size(); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#getVertices(int) */ public Set getVertices(int degree) { Set verticesofsamedegree = new HashSet(); Iterator iterator; Object vertex; iterator = auto.states().iterator(); while (iterator.hasNext()) { vertex = (Object) iterator.next(); if (this.getAdjacentVertices(vertex).size() == degree) verticesofsamedegree.add(vertex); } return verticesofsamedegree; } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#getEdges(salvo.jesus.graph.Vertex) */ public List getEdges(Object v) { List l = getOutgoingEdges(v); // l.addAll(getIncomingEdges(v)); return l; } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#getAdjacentVertices(salvo.jesus.graph.Vertex) */ public List getAdjacentVertices(Object v) { List res = new ArrayList(); List out = getOutgoingAdjacentVertices(v); List in = getIncomingAdjacentVertices(v); res.addAll(out); res.addAll(in); return res; } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#getAdjacentVertices(java.util.List) */ public HashSet getAdjacentVertices(List vertices) { HashSet res = new HashSet(); Iterator it = vertices.iterator(); Object current; List adjv; Iterator adjvIt; while (it.hasNext()) { current = (Object) it.next(); adjv = this.getAdjacentVertices(current); adjvIt = adjv.iterator(); while (adjvIt.hasNext()) { res.add(adjvIt.next()); } } return res; } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#getConnectedSet() */ public List getConnectedSet() { ArrayList al = new ArrayList(); al.add(new ArrayList(auto.states())); return al; } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#getConnectedSet(salvo.jesus.graph.Vertex) */ public List getConnectedSet(Object v) { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#mergeconnectedSet(salvo.jesus.graph.Vertex, * salvo.jesus.graph.Vertex) */ public void mergeconnectedSet(Object v1, Object v2) { // TODO Auto-generated method stub } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#traverse(salvo.jesus.graph.Vertex) */ public List traverse(Object startat) { return traversal.traverse(startat); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#getTraversal() */ public GraphTraversal getTraversal() { return this.traversal; } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#setTraversal(salvo.jesus.graph.algorithm.GraphTraversal) */ public void setTraversal(GraphTraversal traversal) { this.traversal = traversal; } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#isConnected(salvo.jesus.graph.Vertex, * salvo.jesus.graph.Vertex) */ public boolean isConnected(Object v1, Object v2) { // TODO Auto-generated method stub return false; } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#addGraphAddVertexListener(salvo.jesus.graph.GraphAddVertexListener) */ public void addGraphAddVertexListener(GraphAddVertexListener listener) { addvertexlistener.add(listener); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#addGraphAddEdgeListener(salvo.jesus.graph.GraphAddEdgeListener) */ public void addGraphAddEdgeListener(GraphAddEdgeListener listener) { addedgelistener.add(listener); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#addGraphRemoveEdgeListener(salvo.jesus.graph.GraphRemoveEdgeListener) */ public void addGraphRemoveEdgeListener(GraphRemoveEdgeListener listener) { removeedgelistener.add(listener); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#addGraphRemoveVertexListener(salvo.jesus.graph.GraphRemoveVertexListener) */ public void addGraphRemoveVertexListener(GraphRemoveVertexListener listener) { removevertexlistener.add(listener); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#removeGraphAddVertexListener(salvo.jesus.graph.GraphAddVertexListener) */ public void removeGraphAddVertexListener(GraphAddVertexListener listener) { addvertexlistener.remove(listener); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#removeGraphAddEdgeListener(salvo.jesus.graph.GraphAddEdgeListener) */ public void removeGraphAddEdgeListener(GraphAddEdgeListener listener) { addedgelistener.remove(listener); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#removeGraphRemoveEdgeListener(salvo.jesus.graph.GraphRemoveEdgeListener) */ public void removeGraphRemoveEdgeListener(GraphRemoveEdgeListener listener) { removeedgelistener.remove(listener); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#removeGraphRemoveVertexListener(salvo.jesus.graph.GraphRemoveVertexListener) */ public void removeGraphRemoveVertexListener( GraphRemoveVertexListener listener) { removevertexlistener.remove(listener); } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#same() */ public Graph same() { Graph g = new GraphImpl(); g.setGraphFactory(this.getGraphFactory()); return g; } /* * (non-Javadoc) * * @see salvo.jesus.graph.Graph#findVertex(java.lang.Object) */ public Object findVertex(Object o) { return o; } }