Adds Entities.descendantsAndSelf(...)

Previously, the Entities.descendants() and Entities.ancestors() methods
returned the given entity as well. Those methods are now deprecated
because the method name does not imply that behaviour! Added 
descendantsAndSelf and ancestorsAndSelf methods to be explicit.

Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/41980adc
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/41980adc
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/41980adc

Branch: refs/heads/master
Commit: 41980adc3503b9d55c8d26cb189723e5acdb2c5f
Parents: 0fb22c5
Author: Aled Sage <[email protected]>
Authored: Mon Jul 4 10:29:56 2016 +0100
Committer: Aled Sage <[email protected]>
Committed: Mon Jul 4 10:29:56 2016 +0100

----------------------------------------------------------------------
 .../apache/brooklyn/core/entity/Entities.java   | 160 ++++++++++++++-----
 .../brooklyn/core/entity/EntitiesTest.java      |  46 +++++-
 2 files changed, 165 insertions(+), 41 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/41980adc/core/src/main/java/org/apache/brooklyn/core/entity/Entities.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/Entities.java 
b/core/src/main/java/org/apache/brooklyn/core/entity/Entities.java
index ca7f2a8..cffbaea 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/Entities.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/Entities.java
@@ -104,7 +104,6 @@ import com.google.common.base.Function;
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
 import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -618,26 +617,35 @@ public class Entities {
 
     /**
      * Return all descendants of given entity matching the given predicate and 
optionally the entity itself.
-     *
+     * 
      * @see {@link EntityPredicates} for useful second arguments.
      */
+    @SuppressWarnings("unused")
     public static Iterable<Entity> descendants(Entity root, Predicate<? super 
Entity> matching, boolean includeSelf) {
-        Iterable<Entity> descs = 
Iterables.concat(Iterables.transform(root.getChildren(), new 
Function<Entity,Iterable<Entity>>() {
-            @Override
-            public Iterable<Entity> apply(Entity input) {
-                return descendants(input);
-            }
-        }));
-        return Iterables.filter(Iterables.concat(descs, 
Collections.singleton(root)), matching);
+        if (false) {
+            // Keeping this unused code, so that anonymous inner class numbers 
don't change!
+            Iterable<Entity> descs = 
Iterables.concat(Iterables.transform(root.getChildren(), new 
Function<Entity,Iterable<Entity>>() {
+                @Override
+                public Iterable<Entity> apply(Entity input) {
+                    return descendants(input);
+                }
+            }));
+            return Iterables.filter(Iterables.concat(descs, 
Collections.singleton(root)), matching);
+        }
+        if (includeSelf) {
+            return descendantsAndSelf(root, matching);
+        } else {
+            return Iterables.filter(descendantsWithoutSelf(root), matching);
+        }
     }
 
     /**
-     * Returns the entity  matching the given predicate
+     * Returns the entities matching the given predicate.
      *
      * @see #descendants(Entity, Predicate, boolean)
      */
-    public static Iterable<Entity> descendants(Entity root, Predicate<? super 
Entity> matching) {
-        return descendants(root, matching, true);
+    public static Iterable<Entity> descendantsAndSelf(Entity root, Predicate<? 
super Entity> matching) {
+        return Iterables.filter(descendantsAndSelf(root), matching);
     }
 
     /**
@@ -645,8 +653,11 @@ public class Entities {
      *
      * @see #descendants(Entity, Predicate, boolean)
      */
-    public static Iterable<Entity> descendants(Entity root) {
-        return descendants(root, Predicates.alwaysTrue(), true);
+    public static Iterable<Entity> descendantsAndSelf(Entity root) {
+        Set<Entity> result = Sets.newLinkedHashSet();
+        result.add(root);
+        descendantsWithoutSelf(root, result);
+        return result;
     }
 
     /**
@@ -655,34 +666,107 @@ public class Entities {
      * @see #descendants(Entity)
      * @see Iterables#filter(Iterable, Class)
      */
-    public static <T extends Entity> Iterable<T> descendants(Entity root, 
Class<T> ofType) {
-        return Iterables.filter(descendants(root), ofType);
+    public static <T extends Entity> Iterable<T> descendantsAndSelf(Entity 
root, Class<T> ofType) {
+        return Iterables.filter(descendantsAndSelf(root), ofType);
     }
 
     /** Returns the entity, its parent, its parent, and so on. */
+    @SuppressWarnings("unused")
+    public static Iterable<Entity> ancestorsAndSelf(final Entity root) {
+        if (false) {
+            // Keeping this unused code, so that anonymous inner class numbers 
don't change!
+            return new Iterable<Entity>() {
+                @Override
+                public Iterator<Entity> iterator() {
+                    return new Iterator<Entity>() {
+                        Entity next = root;
+                        @Override
+                        public boolean hasNext() {
+                            return next!=null;
+                        }
+                        @Override
+                        public Entity next() {
+                            Entity result = next;
+                            next = next.getParent();
+                            return result;
+                        }
+                        @Override
+                        public void remove() {
+                            throw new UnsupportedOperationException();
+                        }
+                    };
+                }
+            };
+        }
+        Set<Entity> result = Sets.newLinkedHashSet();
+        Entity current = root;
+        while (current != null) {
+            result.add(current);
+            current = current.getParent();
+        }
+        return result;
+    }
+
+    private static Iterable<Entity> descendantsWithoutSelf(Entity root) {
+        Set<Entity> result = Sets.newLinkedHashSet();
+        descendantsWithoutSelf(root, result);
+        return result;
+    }
+    
+    /**
+     * Side-effects {@code result} to return descendants (not including {@code 
root}).
+     */
+    private static void descendantsWithoutSelf(Entity root, Collection<Entity> 
result) {
+        Stack<Entity> tovisit = new Stack<Entity>();
+        tovisit.add(root);
+
+        while (!tovisit.isEmpty()) {
+            Entity e = tovisit.pop();
+            result.addAll(e.getChildren());
+            tovisit.addAll(e.getChildren());
+        }
+    }
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    /**
+     * @deprecated since 0.10.0; see {@link #descendantsAndSelf(Entity, 
Predicate)}
+     */
+    public static Iterable<Entity> descendants(Entity root, Predicate<? super 
Entity> matching) {
+        return descendantsAndSelf(root, matching);
+    }
+
+    /**
+     * @deprecated since 0.10.0; see {@link #descendantsAndSelf(Entity)}
+     */
+    public static Iterable<Entity> descendants(Entity root) {
+        return descendantsAndSelf(root);
+    }
+
+    /**
+     * @deprecated since 0.10.0; see {@link #descendantsAndSelf(Entity)}
+     */
+    public static <T extends Entity> Iterable<T> descendants(Entity root, 
Class<T> ofType) {
+        return descendantsAndSelf(root, ofType);
+    }
+
+    /**
+     * @deprecated since 0.10.0; see {@link #ancestorsAndSelf(Entity)}
+     */
     public static Iterable<Entity> ancestors(final Entity root) {
-        return new Iterable<Entity>() {
-            @Override
-            public Iterator<Entity> iterator() {
-                return new Iterator<Entity>() {
-                    Entity next = root;
-                    @Override
-                    public boolean hasNext() {
-                        return next!=null;
-                    }
-                    @Override
-                    public Entity next() {
-                        Entity result = next;
-                        next = next.getParent();
-                        return result;
-                    }
-                    @Override
-                    public void remove() {
-                        throw new UnsupportedOperationException();
-                    }
-                };
-            }
-        };
+        return ancestorsAndSelf(root);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/41980adc/core/src/test/java/org/apache/brooklyn/core/entity/EntitiesTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/brooklyn/core/entity/EntitiesTest.java 
b/core/src/test/java/org/apache/brooklyn/core/entity/EntitiesTest.java
index b5d2099..34cddb4 100644
--- a/core/src/test/java/org/apache/brooklyn/core/entity/EntitiesTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/EntitiesTest.java
@@ -38,6 +38,7 @@ import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 
@@ -47,22 +48,61 @@ public class EntitiesTest extends 
BrooklynAppUnitTestSupport {
     
     private SimulatedLocation loc;
     private TestEntity entity;
+    private TestEntity entity2;
     
     @BeforeMethod(alwaysRun=true)
     @Override
     public void setUp() throws Exception {
         super.setUp();
         loc = 
app.getManagementContext().getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
-        entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+        entity = app.addChild(EntitySpec.create(TestEntity.class));
+        entity2 = app.addChild(EntitySpec.create(TestEntity.class));
         app.start(ImmutableList.of(loc));
     }
     
     @Test
+    @SuppressWarnings("deprecation")
     public void testDescendants() throws Exception {
-        Assert.assertEquals(Iterables.size(Entities.descendants(app)), 2);
-        Assert.assertEquals(Iterables.getOnlyElement(Entities.descendants(app, 
TestEntity.class)), entity);
+        Asserts.assertEqualsIgnoringOrder(Entities.descendantsAndSelf(app), 
ImmutableList.of(app, entity, entity2));
+        Asserts.assertEqualsIgnoringOrder(Entities.descendants(app), 
ImmutableList.of(app, entity, entity2));
+        
+        Asserts.assertEqualsIgnoringOrder(Entities.descendantsAndSelf(entity), 
ImmutableList.of(entity));
+        Asserts.assertEqualsIgnoringOrder(Entities.descendants(entity), 
ImmutableList.of(entity));
+    }
+    
+    @Test
+    @SuppressWarnings("deprecation")
+    public void testDescendantsFilteredByType() throws Exception {
+        Asserts.assertEqualsIgnoringOrder(Entities.descendantsAndSelf(app, 
TestEntity.class), ImmutableList.of(entity, entity2));
+        Asserts.assertEqualsIgnoringOrder(Entities.descendants(app, 
TestEntity.class), ImmutableList.of(entity, entity2));
+    }
+    
+    @Test
+    @SuppressWarnings("deprecation")
+    public void testDescendantsFilteredByPredicate() throws Exception {
+        Asserts.assertEqualsIgnoringOrder(Entities.descendantsAndSelf(app, 
Predicates.instanceOf(TestEntity.class)), ImmutableList.of(entity, entity2));
+        Asserts.assertEqualsIgnoringOrder(Entities.descendants(app, 
Predicates.instanceOf(TestEntity.class)), ImmutableList.of(entity, entity2));
+    }
+    
+    @Test
+    public void testDescendantsWithExplicitIncludeSelf() throws Exception {
+        Asserts.assertEqualsIgnoringOrder(Entities.descendants(app, 
Predicates.alwaysTrue(), true), ImmutableList.of(app, entity, entity2));
+        Asserts.assertEqualsIgnoringOrder(Entities.descendants(app, 
Predicates.alwaysTrue(), false), ImmutableList.of(entity, entity2));
+        
+        Asserts.assertEqualsIgnoringOrder(Entities.descendants(entity, 
Predicates.alwaysTrue(), true), ImmutableList.of(entity));
+        Asserts.assertEqualsIgnoringOrder(Entities.descendants(entity, 
Predicates.alwaysTrue(), false), ImmutableList.of());
+    }
+    
+    @Test
+    public void testAncestors() throws Exception {
+        Asserts.assertEqualsIgnoringOrder(Entities.ancestorsAndSelf(app), 
ImmutableList.of(app));
+        Asserts.assertEqualsIgnoringOrder(Entities.ancestors(app), 
ImmutableList.of(app));
+
+        Asserts.assertEqualsIgnoringOrder(Entities.ancestorsAndSelf(entity), 
ImmutableList.of(entity, app));
+        Asserts.assertEqualsIgnoringOrder(Entities.ancestors(entity), 
ImmutableList.of(entity, app));
     }
     
+    
     @Test
     public void testAttributeSupplier() throws Exception {
         entity.sensors().set(TestEntity.NAME, "myname");

Reply via email to