001    package org.apache.commons.graph.visit;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.util.HashSet;
023    import java.util.LinkedList;
024    import java.util.Set;
025    import java.util.Stack;
026    
027    import org.apache.commons.graph.Edge;
028    import org.apache.commons.graph.Graph;
029    import org.apache.commons.graph.Vertex;
030    
031    /**
032     * Contains different implementations of Graph visitor algorithms.
033     */
034    public final class Visit
035    {
036    
037        /**
038         * Breadth-first search algorithm implementation.
039         *
040         * @param <V> the Graph vertices type
041         * @param <E> the Graph edges type
042         * @param graph the Graph instance has to be visited
043         * @param source the root node the search begins from
044         */
045        public final <V extends Vertex, E extends Edge<V>> void breadthFirstSearch( Graph<V, E> graph, V source )
046        {
047            breadthFirstSearch( graph, source, null );
048        }
049    
050        /**
051         * Breadth-first search algorithm implementation.
052         *
053         * @param <V> the Graph vertices type
054         * @param <E> the Graph edges type
055         * @param graph the Graph instance has to be visited
056         * @param source the root node the search begins from
057         * @param handler the handler intercepts visit actions
058         */
059        public final <V extends Vertex, E extends Edge<V>> void breadthFirstSearch( Graph<V, E> graph, V source,
060                                                                                    GraphVisitHandler<V, E> handler )
061        {
062            if ( graph == null )
063            {
064                throw new IllegalArgumentException( "Graph has to be visited can not be null." );
065            }
066            if ( source == null )
067            {
068                throw new IllegalArgumentException( "Root node the search begins from can not be null." );
069            }
070    
071            if ( handler != null )
072            {
073                handler.discoverGraph( graph );
074            }
075    
076            LinkedList<V> vertexQueue = new LinkedList<V>();
077            vertexQueue.add( source );
078    
079            Set<V> visitedVetices = new HashSet<V>();
080            visitedVetices.add( source );
081    
082            while ( !vertexQueue.isEmpty() )
083            {
084                V v = vertexQueue.remove();
085    
086                if ( handler != null )
087                {
088                    handler.discoverVertex( v );
089                }
090    
091                for ( E e : graph.getEdges( v ) )
092                {
093                    V w = e.getTail();
094    
095                    if ( !visitedVetices.add( w ) )
096                    {
097                        if ( handler != null )
098                        {
099                            handler.discoverEdge( e );
100                        }
101    
102                        vertexQueue.addFirst( v );
103    
104                        if ( handler != null )
105                        {
106                            handler.finishEdge( e );
107                        }
108                    }
109                }
110    
111                if ( handler != null )
112                {
113                    handler.finishVertex( v );
114                }
115            }
116    
117            if ( handler != null )
118            {
119                handler.finishGraph( graph );
120            }
121        }
122    
123        /**
124         * Depth-first search algorithm implementation.
125         *
126         * @param <V> the Graph vertices type
127         * @param <E> the Graph edges type
128         * @param graph the Graph instance has to be visited
129         * @param source the root node the search begins from
130         */
131        public final <V extends Vertex, E extends Edge<V>> void depthFirstSearch( Graph<V, E> graph, V source )
132        {
133            depthFirstSearch( graph, source, null );
134        }
135    
136        /**
137         * Depth-first search algorithm implementation.
138         *
139         * @param <V> the Graph vertices type
140         * @param <E> the Graph edges type
141         * @param graph the Graph instance has to be visited
142         * @param source the root node the search begins from
143         * @param handler the handler intercepts visit actions
144         */
145        public final <V extends Vertex, E extends Edge<V>> void depthFirstSearch( Graph<V, E> graph, V source,
146                                                                                  GraphVisitHandler<V, E> handler )
147        {
148            if ( graph == null )
149            {
150                throw new IllegalArgumentException( "Graph has to be visited can not be null." );
151            }
152            if ( source == null )
153            {
154                throw new IllegalArgumentException( "Root node the search begins from can not be null." );
155            }
156    
157            if ( handler != null )
158            {
159                handler.discoverGraph( graph );
160            }
161    
162            Stack<V> vertexStack = new Stack<V>();
163            vertexStack.push( source );
164    
165            Set<V> visitedVetices = new HashSet<V>();
166            visitedVetices.add( source );
167    
168            while ( !vertexStack.isEmpty() )
169            {
170                V v = vertexStack.pop();
171    
172                if ( handler != null )
173                {
174                    handler.discoverVertex( v );
175                }
176    
177                for ( E e : graph.getEdges( v ) )
178                {
179                    V w = e.getTail();
180    
181                    if ( !visitedVetices.add( w ) )
182                    {
183                        if ( handler != null )
184                        {
185                            handler.discoverEdge( e );
186                        }
187    
188                        vertexStack.push( w );
189    
190                        if ( handler != null )
191                        {
192                            handler.finishEdge( e );
193                        }
194                    }
195                }
196    
197                if ( handler != null )
198                {
199                    handler.finishVertex( v );
200                }
201            }
202    
203            if ( handler != null )
204            {
205                handler.finishGraph( graph );
206            }
207        }
208    
209        /**
210         * Hidden constructor, this class can't be instantiated
211         */
212        private Visit()
213        {
214            // do nothing
215        }
216    
217    }