/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.graph.traverse.standard; import java.util.Iterator; import junit.framework.TestCase; import org.geotools.graph.GraphTestUtil; import org.geotools.graph.build.GraphBuilder; import org.geotools.graph.build.basic.BasicGraphBuilder; import org.geotools.graph.structure.GraphVisitor; import org.geotools.graph.structure.Graphable; import org.geotools.graph.structure.Node; import org.geotools.graph.traverse.GraphTraversal; import org.geotools.graph.traverse.basic.BasicGraphTraversal; import org.geotools.graph.traverse.basic.CountingWalker; public class BreadthFirstTopologicalIteratorTest extends TestCase { private GraphBuilder m_builder; public BreadthFirstTopologicalIteratorTest(String name) { super(name); } protected void setUp() throws Exception { super.setUp(); m_builder = createBuilder(); } /** * Create a graph with no bifurcations and do a full traversal. <BR> * <BR> * Expected: 1. Nodes should be visited in order (1,n,2,n-2,...n/2). This * order can be reversed. */ public void test_0() { int nnodes = 9; //odd number so there is a middle node GraphTestUtil.buildNoBifurcations(builder(), nnodes); //note: traversal uses count and we are changing the count value here. // but it shouldn't matter because at the time of visitation, the traversal // no longer needs the counter value. CountingWalker walker = new CountingWalker() { public int visit(Graphable element, GraphTraversal traversal) { element.setCount(getCount()); return super.visit(element, traversal); } }; BreadthFirstTopologicalIterator iterator = createIterator(); BasicGraphTraversal traversal = new BasicGraphTraversal( builder().getGraph(), walker, iterator ); traversal.init(); traversal.traverse(); assertTrue(walker.getCount() == nnodes); boolean flip = false; for ( Iterator itr = builder().getGraph().getNodes().iterator(); itr.hasNext(); ) { Node node = (Node)itr.next(); if (node.getID() == 0 && node.getCount() != 0) { flip = true; break; } } final int size = builder().getGraph().getNodes().size(); for ( Iterator itr = builder().getGraph().getNodes().iterator(); itr.hasNext(); ) { Node node = (Node)itr.next(); int id = node.getID(); int expected = -1; if (id == (int)size/2) expected = size-1; else if (id < (int)size/2) { if (!flip) { expected = id*2; } else { expected = id*2 + 1; } } else { if (!flip) { expected = (size-1 - id)*2 + 1; } else { expected = (size-1 - id)*2; } } assertTrue(expected == node.getCount()); }; } /** * Create a balanced binary tree and do a full traversal. <BR> * <BR> * Expected: 1. Nodes in a lower level of the tree should be visited before * nodes in a higher level. */ public void test_1() { int k = 4; GraphTestUtil.buildPerfectBinaryTree(builder(), k); CountingWalker walker = new CountingWalker() { public int visit(Graphable element, GraphTraversal traversal) { element.setCount(getCount()); return super.visit(element, traversal); } }; BreadthFirstTopologicalIterator iterator = createIterator(); BasicGraphTraversal traversal = new BasicGraphTraversal( builder().getGraph(), walker, iterator ); traversal.init(); traversal.traverse(); //ensure that each node in lower level visited before node in higher level GraphVisitor visitor = new GraphVisitor() { public int visit(Graphable component) { String id = component.getObject().toString(); for( Iterator itr = builder().getGraph().getNodes().iterator(); itr.hasNext(); ) { Node other = (Node)itr.next(); if (other.getObject().toString().length() < id.length()) { assertTrue(other.getCount() > component.getCount()); } } return 0; } }; builder().getGraph().visitNodes(visitor); assertTrue(walker.getCount() == Math.pow(2,k+1)-1); } /** * Create a circular graph and do a full traversal. <BR> * <BR> * Expected: 1. No nodes should be visited. * */ public void test_2() { int nnodes = 100; GraphTestUtil.buildCircular(builder(), nnodes); CountingWalker walker = new CountingWalker(); BreadthFirstTopologicalIterator iterator = createIterator(); BasicGraphTraversal traversal = new BasicGraphTraversal( builder().getGraph(), walker, iterator ); traversal.init(); traversal.traverse(); GraphVisitor visitor = new GraphVisitor() { public int visit(Graphable component) { assertTrue(!component.isVisited()); return 0; } }; builder().getGraph().visitNodes(visitor); assertTrue(walker.getCount() == 0); } protected GraphBuilder createBuilder() { return(new BasicGraphBuilder()); } protected GraphBuilder builder() { return(m_builder); } protected BreadthFirstTopologicalIterator createIterator() { return(new BreadthFirstTopologicalIterator()); } }