Added basic graph functionality as a first step towards simplifying the container...
authorerik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Fri, 16 May 2008 09:45:25 +0000 (09:45 +0000)
committererik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Fri, 16 May 2008 09:45:25 +0000 (09:45 +0000)
trunk/system/general/src/main/java/org/wamblee/system/graph/DefaultEdge.java [new file with mode: 0644]
trunk/system/general/src/main/java/org/wamblee/system/graph/DefaultNode.java [new file with mode: 0644]
trunk/system/general/src/main/java/org/wamblee/system/graph/Edge.java [new file with mode: 0644]
trunk/system/general/src/main/java/org/wamblee/system/graph/EdgeFactory.java [new file with mode: 0644]
trunk/system/general/src/main/java/org/wamblee/system/graph/Graph.java [new file with mode: 0644]
trunk/system/general/src/main/java/org/wamblee/system/graph/Node.java [new file with mode: 0644]
trunk/system/general/src/main/java/org/wamblee/system/graph/Visitor.java [new file with mode: 0644]
trunk/system/general/src/test/java/org/wamblee/system/graph/GraphTest.java [new file with mode: 0644]
trunk/system/general/src/test/java/org/wamblee/system/graph/MyEdgeFactory.java [new file with mode: 0644]
trunk/system/general/src/test/java/org/wamblee/system/graph/MyNode.java [new file with mode: 0644]

diff --git a/trunk/system/general/src/main/java/org/wamblee/system/graph/DefaultEdge.java b/trunk/system/general/src/main/java/org/wamblee/system/graph/DefaultEdge.java
new file mode 100644 (file)
index 0000000..886186f
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2008 the original author or authors.
+ * 
+ * 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 org.wamblee.system.graph;
+
+public class DefaultEdge implements Edge {
+    
+    private Node _from; 
+    private Node _to; 
+    
+    public DefaultEdge(Node aFrom, Node aTo) { 
+        _from = aFrom;
+        _to = aTo; 
+    }
+
+    @Override
+    public Node getFrom() {
+        return _from;
+    }
+
+    @Override
+    public Node getTo() {
+        return _to; 
+    }
+
+}
diff --git a/trunk/system/general/src/main/java/org/wamblee/system/graph/DefaultNode.java b/trunk/system/general/src/main/java/org/wamblee/system/graph/DefaultNode.java
new file mode 100644 (file)
index 0000000..7a7ff3c
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2008 the original author or authors.
+ * 
+ * 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 org.wamblee.system.graph;
+
+public class DefaultNode implements Node {
+    
+    private String _name; 
+    
+    public DefaultNode(String aName) { 
+        _name = aName; 
+    }
+
+    @Override
+    public String getName() {
+        return _name;
+    }
+
+    @Override
+    public boolean equals(Object aObj) {
+        if ( !(aObj instanceof Node)) { 
+            return false; 
+        }
+        Node node = (Node)aObj;
+        return _name.equals(node.getName());
+    }
+    
+    @Override
+    public int hashCode() {
+        return _name.hashCode();
+    }
+}
diff --git a/trunk/system/general/src/main/java/org/wamblee/system/graph/Edge.java b/trunk/system/general/src/main/java/org/wamblee/system/graph/Edge.java
new file mode 100644 (file)
index 0000000..3aa0d84
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2008 the original author or authors.
+ * 
+ * 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 org.wamblee.system.graph;
+
+public interface Edge {
+
+    Node getFrom();
+    Node getTo();
+}
diff --git a/trunk/system/general/src/main/java/org/wamblee/system/graph/EdgeFactory.java b/trunk/system/general/src/main/java/org/wamblee/system/graph/EdgeFactory.java
new file mode 100644 (file)
index 0000000..32601e7
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2008 the original author or authors.
+ * 
+ * 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 org.wamblee.system.graph;
+
+import java.util.List;
+
+public interface EdgeFactory<NodeType extends Node> {
+    List<Edge> create(NodeType aFrom, NodeType aTo); 
+}
diff --git a/trunk/system/general/src/main/java/org/wamblee/system/graph/Graph.java b/trunk/system/general/src/main/java/org/wamblee/system/graph/Graph.java
new file mode 100644 (file)
index 0000000..5d6e6cc
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2008 the original author or authors.
+ * 
+ * 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 org.wamblee.system.graph;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Graph {
+
+    private List<Node> _nodes;
+    private List<Edge> _edges;
+
+    public Graph() {
+        _nodes = new ArrayList<Node>();
+        _edges = new ArrayList<Edge>();
+    }
+
+    public void addNode(Node aNode) {
+        if (_nodes.contains(aNode)) {
+            throw new IllegalArgumentException("Node '" + aNode.getName()
+                    + "' already exists");
+        }
+        _nodes.add(aNode);
+    }
+    
+    public Node findNode(String aName) { 
+        for (Node node: _nodes) { 
+            if ( node.getName().equals(aName)) { 
+                return node; 
+            }
+        }
+        return null; 
+    }
+
+    public boolean removeNode(Node aNode) {
+        if (!findOutgoing(aNode).isEmpty() || !findIncoming(aNode).isEmpty()) {
+            throw new IllegalArgumentException("Cannot remove node '"
+                    + aNode.getName()
+                    + "' because it is connected to one or more edges");
+        }
+        return _nodes.remove(aNode);
+    }
+
+    public void addNodes(List<Node> aNodes) {
+        for (Node node : aNodes) {
+            addNode(node);
+        }
+    }
+
+    public void addEdge(Edge aEdge) {
+        if (_edges.contains(aEdge)) {
+            throw new IllegalArgumentException("Edge '" + aEdge
+                    + "' already exists");
+        }
+        if (!_nodes.contains(aEdge.getFrom())) {
+            throw new IllegalArgumentException("From node '" + aEdge.getFrom()
+                    + "' from edge '" + aEdge + "' is not part of the graph");
+        }
+        if (!_nodes.contains(aEdge.getTo())) {
+            throw new IllegalArgumentException("To node '" + aEdge.getTo()
+                    + "' from edge '" + aEdge + "' is not part of the graph");
+        }
+        _edges.add(aEdge);
+    }
+
+    public boolean removeEdge(Edge aEdge) {
+        return _edges.remove(aEdge);
+    }
+
+    public void addEdges(List<Edge> aEdges) {
+        for (Edge edge : aEdges) {
+            addEdge(edge);
+        }
+    }
+
+    public List<Node> getNodes() {
+        return new ArrayList<Node>(_nodes);
+    }
+
+    public List<Edge> getEdges() {
+        return new ArrayList<Edge>(_edges);
+    }
+
+    public void extend(EdgeFactory aFactory) {
+        for (Node from : _nodes) {
+            for (Node to : _nodes) {
+                _edges.addAll(aFactory.create(from, to));
+            }
+        }
+    }
+
+    public List<Edge> findOutgoing(Node aNode) {
+        List<Edge> result = new ArrayList<Edge>();
+        for (Edge edge : _edges) {
+            if (edge.getFrom().getName().equals(aNode.getName())) {
+                result.add(edge);
+            }
+        }
+        return result;
+    }
+
+    public List<Edge> findIncoming(Node aNode) {
+        List<Edge> result = new ArrayList<Edge>();
+        for (Edge edge : _edges) {
+            if (edge.getTo().getName().equals(aNode.getName())) {
+                result.add(edge);
+            }
+        }
+        return result;
+    }
+
+    public void accept(Visitor aVisitor) {
+        List<Node> nodes = getNodes(); // copy to make sure the visitor can
+                                        // modify the
+        // list of nodes as part of the loop.
+        List<Edge> edges = getEdges(); // copy ..... (see above).
+
+        for (Node node : nodes) {
+            aVisitor.visitNode(node);
+        }
+        for (Edge edge : edges) {
+            aVisitor.visitEdge(edge);
+        }
+    }
+}
diff --git a/trunk/system/general/src/main/java/org/wamblee/system/graph/Node.java b/trunk/system/general/src/main/java/org/wamblee/system/graph/Node.java
new file mode 100644 (file)
index 0000000..0becfda
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2008 the original author or authors.
+ * 
+ * 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 org.wamblee.system.graph;
+
+public interface Node {
+    
+    String getName();
+
+}
diff --git a/trunk/system/general/src/main/java/org/wamblee/system/graph/Visitor.java b/trunk/system/general/src/main/java/org/wamblee/system/graph/Visitor.java
new file mode 100644 (file)
index 0000000..9c3240e
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2008 the original author or authors.
+ * 
+ * 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 org.wamblee.system.graph;
+
+public interface Visitor {
+
+    void visitNode(Node aNode); 
+    
+    void visitEdge(Edge aEdge); 
+}
diff --git a/trunk/system/general/src/test/java/org/wamblee/system/graph/GraphTest.java b/trunk/system/general/src/test/java/org/wamblee/system/graph/GraphTest.java
new file mode 100644 (file)
index 0000000..305765f
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2008 the original author or authors.
+ * 
+ * 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 org.wamblee.system.graph;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.easymock.classextension.EasyMock;
+import org.wamblee.test.AssertionUtils;
+
+import junit.framework.TestCase;
+
+public class GraphTest extends TestCase {
+
+    public void testNodeMgt() {
+        final Graph graph = new Graph();
+        assertTrue(graph.getNodes().isEmpty());
+        assertTrue(graph.getEdges().isEmpty());
+
+        final Node x = new DefaultNode("x");
+        graph.addNode(x);
+        assertEquals(Arrays.asList(new Node[] { x }), graph.getNodes());
+        assertSame(x, graph.findNode("x"));
+        assertNull(graph.findNode("y"));
+
+        assertTrue(graph.removeNode(x));
+        assertTrue(graph.getNodes().isEmpty());
+
+        // Empty node set. 
+        assertFalse(graph.removeNode(x));
+        
+        Node y = new DefaultNode("y"); 
+        graph.addNodes(Arrays.asList(new Node[] { x, y} ));
+        assertEquals(2, graph.getNodes().size());
+        
+        // duplicate node
+        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { 
+            @Override
+            public void run() throws Exception {
+                graph.addNode(new DefaultNode("x"));   
+            }
+        }, IllegalArgumentException.class);
+    }
+
+    public void testEdgeMgt() { 
+        final Graph graph = new Graph();
+        final Node x = new DefaultNode("x"); 
+        final Node y = new DefaultNode("y"); 
+        graph.addNode(x);
+        graph.addNode(y);
+        final Edge e = new DefaultEdge(x, y); 
+        graph.addEdge(e);
+        assertEquals(Arrays.asList(new Edge[] { e }), graph.getEdges());
+        
+        // duplicate edge.
+        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { 
+            @Override
+            public void run() throws Exception {
+                graph.addEdge(e);   
+            }
+        }, IllegalArgumentException.class);
+        
+        // Remove node when edge is still present
+        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { 
+            @Override
+            public void run() throws Exception {
+                graph.removeNode(x);
+            }
+        }, IllegalArgumentException.class);
+        
+        
+        Node a = new DefaultNode("a");
+        graph.addNode(a);
+        graph.addEdges(Arrays.asList(new Edge[] { new DefaultEdge(x, a), new DefaultEdge(y, a) }));
+        assertEquals(3, graph.getEdges().size());
+    }
+    
+    public void testExtend() { 
+        Graph graph = new Graph(); 
+        graph.addNode(new MyNode("x", new String[] { "a", "b"}));
+        graph.addNode(new MyNode("y", new String[] { "b", "c"}));
+        graph.addNode(new MyNode("z", new String[] { "a", "c"}));
+        graph.extend(new MyEdgeFactory());
+        
+        List<Edge> edges = graph.getEdges(); 
+        assertEquals(12, edges.size()); // 2 outgoing and 2 incoming nodes.
+    }
+    
+    public void testFindIncomingOutgoing() { 
+        Graph graph = new Graph();
+        Node x = new DefaultNode("x");
+        Node y = new DefaultNode("y"); 
+        graph.addNode(x);
+        graph.addNode(y);
+        Edge e = new DefaultEdge(x,y);
+        graph.addEdge(e);
+        
+        List<Edge> incoming = graph.findIncoming(x);
+        assertTrue(incoming.isEmpty()); 
+        List<Edge> outgoing = graph.findOutgoing(x);
+        assertEquals(1, outgoing.size());
+        assertSame(e, outgoing.get(0));
+        
+        incoming = graph.findIncoming(y);
+        assertEquals(1, incoming.size());
+        assertSame(e, incoming.get(0));
+           
+        outgoing = graph.findOutgoing(y);
+        assertTrue(outgoing.isEmpty()); 
+    }
+    
+    public void testAccept() {
+        Graph graph = new Graph(); 
+        Node x = new DefaultNode("x"); 
+        Node y = new DefaultNode("y"); 
+        Edge e = new DefaultEdge(x, y);
+        graph.addNode(x);
+        graph.addNode(y);
+        graph.addEdge(e);
+        Visitor visitor = EasyMock.createMock(Visitor.class);
+        visitor.visitNode(x);
+        visitor.visitNode(y);
+        visitor.visitEdge(e);
+        EasyMock.replay(visitor);
+        graph.accept(visitor);
+        EasyMock.verify(visitor);
+    }
+}
diff --git a/trunk/system/general/src/test/java/org/wamblee/system/graph/MyEdgeFactory.java b/trunk/system/general/src/test/java/org/wamblee/system/graph/MyEdgeFactory.java
new file mode 100644 (file)
index 0000000..daddccd
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2008 the original author or authors.
+ * 
+ * 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 org.wamblee.system.graph;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MyEdgeFactory implements EdgeFactory<MyNode> {
+    
+    public MyEdgeFactory() { 
+        // Empty.
+    }
+
+    @Override
+    public List<Edge> create(MyNode aFrom, MyNode aTo) {
+        List<Edge> result = new ArrayList<Edge>();
+        for (String fromPort: aFrom.getPorts()) { 
+            for (String toPort: aTo.getPorts()) { 
+                if ( fromPort.equals(toPort)) { 
+                    result.add(new DefaultEdge(aFrom, aTo));
+                }
+            }
+        }
+        
+        return result; 
+    }
+
+}
diff --git a/trunk/system/general/src/test/java/org/wamblee/system/graph/MyNode.java b/trunk/system/general/src/test/java/org/wamblee/system/graph/MyNode.java
new file mode 100644 (file)
index 0000000..0090c3f
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2008 the original author or authors.
+ * 
+ * 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 org.wamblee.system.graph;
+
+public class MyNode extends DefaultNode {
+
+    private String[] _ports;   
+    
+    public MyNode(String aName, String[] aPorts) {
+        super(aName);
+        _ports = aPorts; 
+    }
+    
+    public String[] getPorts() {
+        return _ports;
+    }
+}