[jboss-cvs] JBossAS SVN: r99149 - projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Fri Jan 8 05:06:19 EST 2010


Author: richard.opalka at jboss.com
Date: 2010-01-08 05:06:18 -0500 (Fri, 08 Jan 2010)
New Revision: 99149

Added:
   projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/DependenciesTopologicalDeployerSorter.java
Removed:
   projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/TopologicalOrderingDeployerSorter.java
Modified:
   projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/DeployerSorterFactory.java
Log:
[JBDEPLOY-229][JBDEPLOY-230][JBDEPLOY-233] refactoring, updating javadoc, improving exception message to print out deployers that are in cycle

Added: projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/DependenciesTopologicalDeployerSorter.java
===================================================================
--- projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/DependenciesTopologicalDeployerSorter.java	                        (rev 0)
+++ projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/DependenciesTopologicalDeployerSorter.java	2010-01-08 10:06:18 UTC (rev 99149)
@@ -0,0 +1,316 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright (c) 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This 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; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.deployers.plugins.sort;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.jboss.deployers.spi.Ordered;
+import org.jboss.deployers.spi.deployer.Deployer;
+
+/**
+ * Implements <a href="http://en.wikipedia.org/wiki/Topological_sorting">topological sorting</a> for acyclic graphs.
+ * The algorithm complexity is <b>O(m+n)</b>, where <b>m</b> is count of vertices and <b>n</b> is count of edges.
+ * However this complexity isn't true for this algorithm implementation because there's backward compatibility
+ * requirement that deployers have to be ordered by their relative number or name if they're on the same processing level.
+ * <b>IOW this backward compatible sorting requirement violates algorithm linear complexity</b>, see:
+ * <a href="https://jira.jboss.org/jira/browse/JBDEPLOY-233">JBDEPLOY-233</a>.
+ *
+ * @author <a href="mailto:ropalka at redhat.com">Richard Opalka</a>
+ */
+public class DependenciesTopologicalDeployerSorter implements DeployerSorter
+{
+
+   public List<Deployer> sortDeployers(List<Deployer> registeredDeployers, Deployer newDeployer)
+   {
+      return this.createOrientedGraph(registeredDeployers, newDeployer).sort();
+   }
+
+   private Graph createOrientedGraph(final List<Deployer> deployers, final Deployer newDeployer)
+   {
+      final Graph graph = new Graph();
+
+      for (final Deployer deployer : deployers)
+         graph.addVertex(deployer);
+
+      graph.addVertex(newDeployer);
+      graph.createEdges();
+
+      return graph;
+   }
+
+   private static class Graph
+   {
+      private Map<String, Dependency> dependencies = new HashMap<String, Dependency>();
+      private Set<Vertex> vertices = new HashSet<Vertex>();
+
+      public void addVertex(final Deployer deployer)
+      {
+         // create disjunct sets
+         final Set<String> inputs = new HashSet<String>();
+         inputs.addAll(deployer.getInputs());
+         final Set<String> outputs = new HashSet<String>();
+         outputs.addAll(deployer.getOutputs());
+         final Set<String> intersection = this.getIntersection(inputs, outputs);
+
+         // register vertex
+         final Vertex vertex = new Vertex(deployer);
+         this.vertices.add(vertex);
+
+         // register dependencies
+         Dependency dependency;
+         for (final String in : inputs)
+         {
+            dependency = this.getDependency(in);
+            dependency.consumers.add(vertex);
+         }
+
+         for (final String inOut : intersection)
+         {
+            dependency = this.getDependency(inOut);
+            dependency.modifiers.add(vertex);
+         }
+
+         for (final String out : outputs)
+         {
+            dependency = this.getDependency(out);
+            dependency.producers.add(vertex);
+         }
+      }
+
+      public List<Deployer> sort()
+      {
+         // L ← Empty list that will contain the sorted elements
+         List<Deployer> retVal = new LinkedList<Deployer>();
+         // S ← Set of all nodes with no incoming edges
+         List<Vertex> roots = this.getRoots();
+         // ensure backward compatibility
+         Collections.sort(roots, Ordered.COMPARATOR);
+
+         // while S is non-empty do
+         Vertex root;
+         Set<Vertex> nextLevel;
+         while(!roots.isEmpty())
+         {
+            // remove a node n from S
+            root = roots.remove(0);
+            // insert n into L
+            retVal.add(root.getDeployer());
+
+            // for each node m with an edge e from n to m do
+            if (root.hasConsumers())
+            {
+               // ensure backward compatibility
+               nextLevel = new TreeSet<Vertex>(Ordered.COMPARATOR);
+               for(final Vertex consumer : root.consumers)
+               {
+                  // remove edge e from the graph
+                  consumer.decrementDegree();
+                  // if m has no other incoming edges then insert m into S
+                  if (!consumer.hasProducers())
+                  {
+                     this.remove(consumer);
+                     nextLevel.add(consumer);
+                  }
+               }
+
+               // append to the end of list in sorted order
+               roots.addAll(nextLevel);
+            }
+         }
+
+         if (this.vertices.size() > 0)
+         {
+            // if graph has edges then graph has at least one cycle
+            throw new IllegalStateException("Cycle detected for deployers: " + this.vertices);
+         }
+         else
+         {
+            // topologically sorted order
+            return retVal;
+         }
+      }
+
+      private Set<String> getIntersection(final Set<String> inputs, final Set<String> outputs)
+      {
+         final Set<String> intersection = new HashSet<String>();
+
+         for (final String input : inputs)
+            for (final String output : outputs)
+               if (input.equals(output)) 
+                  intersection.add(input);
+
+         inputs.removeAll(intersection);
+         outputs.removeAll(intersection);
+
+         return intersection;
+      }
+
+      private Dependency getDependency(final String name)
+      {
+         if (this.dependencies.containsKey(name))
+         {
+            return this.dependencies.get(name);
+         }
+         else
+         {
+            final Dependency newDependency = new Dependency();
+            this.dependencies.put(name, newDependency);
+            return newDependency;
+         }
+      }
+
+      private void createEdges()
+      {
+         Dependency dependency;
+         boolean hasModifiers;
+
+         for (final String dependencyName : this.dependencies.keySet())
+         {
+            dependency = this.dependencies.get(dependencyName);
+            hasModifiers = dependency.modifiers.size() > 0;
+
+            if (hasModifiers)
+            {
+               this.createEdges(dependency.producers, dependency.modifiers);
+               this.createEdges(dependency.modifiers, dependency.consumers);
+            }
+            else
+            {
+               this.createEdges(dependency.producers, dependency.consumers);
+            }
+         }
+      }
+
+      private void createEdges(final List<Vertex> producers, final List<Vertex> consumers)
+      {
+         for (final Vertex producer : producers)
+            for (final Vertex consumer : consumers)
+            {
+               producer.addConsumer(consumer);
+               consumer.incrementDegree();
+            }
+      }
+
+      private List<Vertex> getRoots()
+      {
+         final List<Vertex> retVal = new LinkedList<Vertex>();
+
+         Vertex current;
+         for (final Iterator<Vertex> i = this.vertices.iterator(); i.hasNext(); )
+         {
+            current = i.next();
+            if (!current.hasProducers())
+            {
+               retVal.add(current);
+               i.remove();
+            }
+         }
+
+         return retVal;
+      }
+
+      private void remove(final Vertex v)
+      {
+         this.vertices.remove(v);
+      }
+
+      private static class Vertex implements Ordered
+      {
+         // Wrapped deployer
+         private Deployer deployer;
+         // Incoming edges
+         private int inDegree;
+         // Outgoing edges
+         private List<Vertex> consumers = new LinkedList<Vertex>();
+
+         public Vertex(final Deployer deployer)
+         {
+            this.deployer = deployer;
+         }
+
+         public void incrementDegree()
+         {
+            this.inDegree++;
+         }
+
+         public void decrementDegree()
+         {
+            this.inDegree--;
+         }
+
+         public boolean hasProducers()
+         {
+            return this.inDegree > 0;
+         }
+
+         public void addConsumer(final Vertex v)
+         {
+            this.consumers.add(v);
+         }
+
+         public boolean hasConsumers()
+         {
+            return this.consumers.size() > 0;
+         }
+
+         public Deployer getDeployer()
+         {
+            return this.deployer;
+         }
+
+         public int getRelativeOrder()
+         {
+            return this.deployer.getRelativeOrder();
+         }
+
+         public void setRelativeOrder(final int order)
+         {
+            throw new UnsupportedOperationException();
+         }
+
+         public String toString()
+         {
+            return this.deployer.toString();
+         }
+      }
+
+      private static class Dependency
+      {
+         // deployers creating this dependency
+         private List<Vertex> producers = new LinkedList<Vertex>();
+         // deployers modifying this dependency
+         private List<Vertex> modifiers = new LinkedList<Vertex>();
+         // deployers consuming this dependency
+         private List<Vertex> consumers = new LinkedList<Vertex>();
+      }
+
+   }
+
+}

Modified: projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/DeployerSorterFactory.java
===================================================================
--- projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/DeployerSorterFactory.java	2010-01-08 09:35:20 UTC (rev 99148)
+++ projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/DeployerSorterFactory.java	2010-01-08 10:06:18 UTC (rev 99149)
@@ -37,6 +37,6 @@
     */
    public static DeployerSorter newSorter()
    {
-      return new TopologicalOrderingDeployerSorter();      
+      return new DependenciesTopologicalDeployerSorter();      
    }
 }

Deleted: projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/TopologicalOrderingDeployerSorter.java
===================================================================
--- projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/TopologicalOrderingDeployerSorter.java	2010-01-08 09:35:20 UTC (rev 99148)
+++ projects/jboss-deployers/trunk/deployers-impl/src/main/java/org/jboss/deployers/plugins/sort/TopologicalOrderingDeployerSorter.java	2010-01-08 10:06:18 UTC (rev 99149)
@@ -1,315 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright (c) 2010, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This 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; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.deployers.plugins.sort;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-
-import org.jboss.deployers.spi.Ordered;
-import org.jboss.deployers.spi.deployer.Deployer;
-
-/**
- * Implements <a href="http://en.wikipedia.org/wiki/Topological_sorting">topological sorting</a> for acyclic graphs.
- * The algorithm complexity is O(m+n), where <b>m</b> = count of vertices and <b>n</b> = count of edges in general.
- * However this complexity isn't true for this algorithm implementation, because there's backward compatibility
- * requirement that deployers have to be ordered by their relative number or name if they're on the same processing level.
- * <b>IOW this backward compatible sorting requirement breaks linear algorithm complexity :(</b>.
- *
- * @author <a href="mailto:ropalka at redhat.com">Richard Opalka</a>
- */
-public class TopologicalOrderingDeployerSorter implements DeployerSorter
-{
-   /**
-    * @see {@link DeployerSorter#sortDeployers(List, Deployer)}
-    */
-   public List<Deployer> sortDeployers(List<Deployer> registeredDeployers, Deployer newDeployer)
-   {
-      return this.createOrientedGraph(registeredDeployers, newDeployer).sort();
-   }
-
-   private Graph createOrientedGraph(final List<Deployer> deployers, final Deployer newDeployer)
-   {
-      final Graph graph = new Graph();
-
-      for (final Deployer deployer : deployers)
-         graph.addVertex(deployer);
-
-      graph.addVertex(newDeployer);
-      graph.createEdges();
-
-      return graph;
-   }
-
-   private static class Graph
-   {
-      private Map<String, Dependency> dependencies = new HashMap<String, Dependency>();
-      private Set<Vertex> vertices = new HashSet<Vertex>();
-
-      public void addVertex(final Deployer deployer)
-      {
-         // create disjunct sets
-         final Set<String> inputs = new HashSet<String>();
-         inputs.addAll(deployer.getInputs());
-         final Set<String> outputs = new HashSet<String>();
-         outputs.addAll(deployer.getOutputs());
-         final Set<String> intersection = this.getIntersection(inputs, outputs);
-
-         // register vertex
-         final Vertex vertex = new Vertex(deployer);
-         this.vertices.add(vertex);
-
-         // register dependencies
-         Dependency dependency;
-         for (final String in : inputs)
-         {
-            dependency = this.getDependency(in);
-            dependency.consumers.add(vertex);
-         }
-
-         for (final String inOut : intersection)
-         {
-            dependency = this.getDependency(inOut);
-            dependency.modifiers.add(vertex);
-         }
-
-         for (final String out : outputs)
-         {
-            dependency = this.getDependency(out);
-            dependency.producers.add(vertex);
-         }
-      }
-
-      public List<Deployer> sort()
-      {
-         // L ← Empty list that will contain the sorted elements
-         List<Deployer> retVal = new LinkedList<Deployer>();
-         // S ← Set of all nodes with no incoming edges
-         List<Vertex> roots = this.getRoots();
-         // ensure backward compatibility
-         Collections.sort(roots, Ordered.COMPARATOR);
-
-         // while S is non-empty do
-         Vertex root;
-         Set<Vertex> nextLevel;
-         while(!roots.isEmpty())
-         {
-            // remove a node n from S
-            root = roots.remove(0);
-            // insert n into L
-            retVal.add(root.getDeployer());
-
-            // for each node m with an edge e from n to m do
-            if (root.hasConsumers())
-            {
-               // ensure backward compatibility
-               nextLevel = new TreeSet<Vertex>(Ordered.COMPARATOR);
-               for(final Vertex consumer : root.consumers)
-               {
-                  // remove edge e from the graph
-                  consumer.decrementDegree();
-                  // if m has no other incoming edges then insert m into S
-                  if (!consumer.hasProducers())
-                  {
-                     this.remove(consumer);
-                     nextLevel.add(consumer);
-                  }
-               }
-
-               // append to the end of list in sorted order
-               roots.addAll(nextLevel);
-            }
-         }
-
-         if (this.vertices.size() > 0)
-         {
-            // if graph has edges then graph has at least one cycle
-            throw new IllegalStateException("Cycle detected");
-         }
-         else
-         {
-            // topologically sorted order
-            return retVal;
-         }
-      }
-
-      private Set<String> getIntersection(final Set<String> inputs, final Set<String> outputs)
-      {
-         final Set<String> intersection = new HashSet<String>();
-
-         for (final String input : inputs)
-            for (final String output : outputs)
-               if (input.equals(output)) 
-                  intersection.add(input);
-
-         inputs.removeAll(intersection);
-         outputs.removeAll(intersection);
-
-         return intersection;
-      }
-
-      private Dependency getDependency(final String name)
-      {
-         if (this.dependencies.containsKey(name))
-         {
-            return this.dependencies.get(name);
-         }
-         else
-         {
-            final Dependency newDependency = new Dependency();
-            this.dependencies.put(name, newDependency);
-            return newDependency;
-         }
-      }
-
-      private void createEdges()
-      {
-         boolean hasModifiers;
-         Dependency dependency;
-
-         for (final String dependencyName : this.dependencies.keySet())
-         {
-            dependency = this.dependencies.get(dependencyName);
-            hasModifiers = dependency.modifiers.size() > 0;
-
-            if (hasModifiers)
-            {
-               this.createEdges(dependency.producers, dependency.modifiers);
-               this.createEdges(dependency.modifiers, dependency.consumers);
-            }
-            else
-            {
-               this.createEdges(dependency.producers, dependency.consumers);
-            }
-         }
-      }
-
-      private void createEdges(final List<Vertex> producers, final List<Vertex> consumers)
-      {
-         for (final Vertex producer : producers)
-            for (final Vertex consumer : consumers)
-            {
-               producer.addConsumer(consumer);
-               consumer.incrementDegree();
-            }
-      }
-
-      private List<Vertex> getRoots()
-      {
-         final LinkedList<Vertex> retVal = new LinkedList<Vertex>();
-
-         for (final Vertex current : this.vertices)
-            if (!current.hasProducers())
-               retVal.add(current);
-
-         for (final Vertex root : retVal)
-            this.remove(root);
-
-         return retVal;
-      }
-
-      private void remove(final Vertex v)
-      {
-         this.vertices.remove(v);
-      }
-
-      private static class Vertex implements Ordered
-      {
-         // Wrapped deployer
-         private Deployer deployer;
-         // Incoming edges
-         private int inDegree = 0;
-         // Outgoing edges
-         private List<Vertex> consumers = new LinkedList<Vertex>();
-
-         public Vertex(final Deployer deployer)
-         {
-            if (deployer == null)
-               throw new IllegalArgumentException();
-
-            this.deployer = deployer;
-         }
-
-         public void incrementDegree()
-         {
-            this.inDegree++;
-         }
-
-         public void decrementDegree()
-         {
-            this.inDegree--;
-         }
-
-         public void addConsumer(final Vertex v)
-         {
-            this.consumers.add(v);
-         }
-
-         public boolean hasProducers()
-         {
-            return this.inDegree > 0;
-         }
-
-         public boolean hasConsumers()
-         {
-            return this.consumers.size() > 0;
-         }
-
-         public Deployer getDeployer()
-         {
-            return this.deployer;
-         }
-
-         public int getRelativeOrder()
-         {
-            return this.deployer.getRelativeOrder();
-         }
-
-         public void setRelativeOrder(final int order)
-         {
-            throw new UnsupportedOperationException();
-         }
-
-         public String toString()
-         {
-            return this.deployer.toString();
-         }
-      }
-
-      private static class Dependency
-      {
-         // deployers creating this dependency
-         private List<Vertex> producers = new LinkedList<Vertex>();
-         // deployers modifying this dependency
-         private List<Vertex> modifiers = new LinkedList<Vertex>();
-         // deployers consuming this dependency
-         private List<Vertex> consumers= new LinkedList<Vertex>();
-      }
-
-   }
-
-}




More information about the jboss-cvs-commits mailing list