You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2015/09/23 12:51:53 UTC

[01/10] incubator-brooklyn git commit: Move EntityLocal.setDisplayName to Entity

Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master 93f6f0f6a -> f34f0433b


Move EntityLocal.setDisplayName to Entity


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/1a6c4e3f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/1a6c4e3f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/1a6c4e3f

Branch: refs/heads/master
Commit: 1a6c4e3f15be543db91fb3dd33d7dc5dea97b683
Parents: 2995471
Author: Aled Sage <al...@gmail.com>
Authored: Mon Sep 21 07:57:15 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Sep 23 10:28:57 2015 +0100

----------------------------------------------------------------------
 api/src/main/java/org/apache/brooklyn/api/entity/Entity.java   | 5 +++++
 .../main/java/org/apache/brooklyn/api/entity/EntityLocal.java  | 6 ------
 .../org/apache/brooklyn/rest/resources/EntityResource.java     | 2 +-
 3 files changed, 6 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1a6c4e3f/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
index 0e25abb..612ce29 100644
--- a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
+++ b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
@@ -109,6 +109,11 @@ public interface Entity extends BrooklynObject {
     Collection<Entity> getChildren();
     
     /**
+     * Sets the entity's display name.
+     */
+    void setDisplayName(String displayName);
+
+    /**
      * Sets the parent (i.e. "owner") of this entity. Returns this entity, for convenience.
      *
      * @see #getParent

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1a6c4e3f/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java b/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
index 7e5e963..b3fa078 100644
--- a/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
+++ b/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
@@ -50,12 +50,6 @@ public interface EntityLocal extends Entity {
     // Separate out what is specific to "local jvm", and what is here for an SPI rather than API.
 
     /**
-     * Sets the entity's display name.
-     * Must be called before the entity is managed.
-     */
-    void setDisplayName(String displayName);
-
-    /**
      * @deprecated since 0.7.0; use {@link #config()}, such as {@code entity.config().set(key, val)}
      */
     @Deprecated

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1a6c4e3f/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java
index 4ca5add..d1290d2 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java
@@ -179,7 +179,7 @@ public class EntityResource extends AbstractBrooklynRestResource implements Enti
 
     @Override
     public Response rename(String application, String entity, String newName) {
-        EntityLocal entityLocal = brooklyn().getEntity(application, entity);
+        Entity entityLocal = brooklyn().getEntity(application, entity);
         entityLocal.setDisplayName(newName);
         return status(Response.Status.OK).build();
     }


[07/10] incubator-brooklyn git commit: Move entityLocal.subscribe(map, …) to SubscriptionSupport

Posted by al...@apache.org.
Move entityLocal.subscribe(map, …) to SubscriptionSupport

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

Branch: refs/heads/master
Commit: ee52d48d6d2b82e45283d6fe56c70442064e7e71
Parents: 7708363
Author: Aled Sage <al...@gmail.com>
Authored: Wed Sep 23 10:40:43 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Sep 23 10:40:43 2015 +0100

----------------------------------------------------------------------
 .../org/apache/brooklyn/api/entity/EntityLocal.java    | 11 -----------
 .../org/apache/brooklyn/api/objs/BrooklynObject.java   | 10 ++++++++++
 .../apache/brooklyn/core/entity/AbstractEntity.java    | 12 +++++-------
 .../brooklyn/core/location/AbstractLocation.java       |  5 +++++
 .../brooklyn/core/objs/AbstractEntityAdjunct.java      | 13 ++++++-------
 .../apache/brooklyn/enricher/stock/UpdatingMap.java    |  2 +-
 .../brooklyn/core/entity/EntitySubscriptionTest.java   | 12 ++++++------
 .../core/policy/basic/PolicySubscriptionTest.java      |  4 ++--
 .../entity/software/base/SoftwareProcessImpl.java      |  4 ++--
 9 files changed, 37 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ee52d48d/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java b/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
index 0ecc73a..aeb7249 100644
--- a/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
+++ b/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
@@ -115,17 +115,6 @@ public interface EntityLocal extends Entity {
     <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener);
 
     /**
-     * Allow us to subscribe to data from a {@link Sensor} on another entity.
-     * 
-     * @return a subscription id which can be used to unsubscribe
-     *
-     * @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener)
-     */
-    // FIXME remove from interface?
-    @Beta
-    <T> SubscriptionHandle subscribe(Map<String, ?> flags, Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener);
- 
-    /**
      * @see SubscriptionManager#subscribeToChildren(Map, Entity, Sensor, SensorEventListener)
      * 
      * @deprecated since 0.9.0; see {@link SubscriptionSupport#subscribeToChildren(Entity, Sensor, SensorEventListener)}, e.g. with {@code subscriptions().subscribeToChildren(...)}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ee52d48d/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java b/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java
index 094586f..f3fcad4 100644
--- a/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java
+++ b/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java
@@ -99,6 +99,16 @@ public interface BrooklynObject extends Identifiable, Configurable {
         @Beta
         <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener);
      
+        /**
+         * Allow us to subscribe to data from a {@link Sensor} on another entity.
+         * 
+         * @return a subscription id which can be used to unsubscribe
+         *
+         * @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener)
+         */
+        @Beta
+        <T> SubscriptionHandle subscribe(Map<String, ?> flags, Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener);
+
         /** @see SubscriptionManager#subscribeToChildren(Map, Entity, Sensor, SensorEventListener) */
         @Beta
         <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ee52d48d/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
index 0084038..291389f 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
@@ -1410,6 +1410,11 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         }
 
         @Override
+        public <T> SubscriptionHandle subscribe(Map<String, ?> flags, Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+            return getSubscriptionTracker().subscribe(flags, producer, sensor, listener);
+        }
+
+        @Override
         public <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
             return getSubscriptionTracker().subscribeToChildren(parent, sensor, listener);
         }
@@ -1480,13 +1485,6 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         return subscriptions().subscribe(producer, sensor, listener);
     }
 
-    /** @see EntityLocal#subscribe */
-    @Override
-    @Beta
-    public <T> SubscriptionHandle subscribe(Map<String, ?> flags, Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
-        return getSubscriptionTracker().subscribe(flags, producer, sensor, listener);
-    }
-
     /**
      * @deprecated since 0.9.0; see {@code subscriptions().subscribeToChildren(parent, sensor, listener)}
      */

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ee52d48d/core/src/main/java/org/apache/brooklyn/core/location/AbstractLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/location/AbstractLocation.java b/core/src/main/java/org/apache/brooklyn/core/location/AbstractLocation.java
index b8859d6..26e58e1 100644
--- a/core/src/main/java/org/apache/brooklyn/core/location/AbstractLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/core/location/AbstractLocation.java
@@ -507,6 +507,11 @@ public abstract class AbstractLocation extends AbstractBrooklynObject implements
         }
 
         @Override
+        public <T> SubscriptionHandle subscribe(Map<String, ?> flags, Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+            return getSubscriptionTracker().subscribe(flags, producer, sensor, listener);
+        }
+
+        @Override
         public <T> SubscriptionHandle subscribeToMembers(Group producerGroup, Sensor<T> sensor, SensorEventListener<? super T> listener) {
             return getSubscriptionTracker().subscribeToMembers(producerGroup, sensor, listener);
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ee52d48d/core/src/main/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunct.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunct.java b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunct.java
index 814923a..69c52ff 100644
--- a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunct.java
+++ b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunct.java
@@ -213,6 +213,12 @@ public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject imple
         }
 
         @Override
+        public <T> SubscriptionHandle subscribe(Map<String, ?> flags, Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+            if (!checkCanSubscribe()) return null;
+            return getSubscriptionTracker().subscribe(flags, producer, sensor, listener);
+        }
+
+        @Override
         public <T> SubscriptionHandle subscribeToMembers(Group producerGroup, Sensor<T> sensor, SensorEventListener<? super T> listener) {
             if (!checkCanSubscribe(producerGroup)) return null;
             return getSubscriptionTracker().subscribeToMembers(producerGroup, sensor, listener);
@@ -481,13 +487,6 @@ public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject imple
         return getSubscriptionTracker().subscribe(producer, sensor, listener);
     }
 
-    @Beta
-    /** @see SubscriptionContext#subscribe(Map, Entity, Sensor, SensorEventListener) */
-    public <T> SubscriptionHandle subscribe(Map<String, ?> flags, Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
-        if (!checkCanSubscribe()) return null;
-        return getSubscriptionTracker().subscribe(flags, producer, sensor, listener);
-    }
-
     /**
      * @deprecated since 0.9.0; see {@link SubscriptionSupport#subscribeToMembers(Entity, Sensor, SensorEventListener)} and {@link BrooklynObject#subscriptions()}
      */

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ee52d48d/core/src/main/java/org/apache/brooklyn/enricher/stock/UpdatingMap.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/enricher/stock/UpdatingMap.java b/core/src/main/java/org/apache/brooklyn/enricher/stock/UpdatingMap.java
index 01084e1..d37bf06 100644
--- a/core/src/main/java/org/apache/brooklyn/enricher/stock/UpdatingMap.java
+++ b/core/src/main/java/org/apache/brooklyn/enricher/stock/UpdatingMap.java
@@ -122,7 +122,7 @@ public class UpdatingMap<S,TKey,TVal> extends AbstractEnricher implements Sensor
         this.computing = (Function) getRequiredConfig(COMPUTING);
         this.removingIfResultIsNull = getConfig(REMOVING_IF_RESULT_IS_NULL);
 
-        subscribe(ImmutableMap.of("notifyOfInitialValue", true), entity, sourceSensor, this);
+        subscriptions().subscribe(ImmutableMap.of("notifyOfInitialValue", true), entity, sourceSensor, this);
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ee52d48d/core/src/test/java/org/apache/brooklyn/core/entity/EntitySubscriptionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/EntitySubscriptionTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/EntitySubscriptionTest.java
index 620d8e0..38848ef 100644
--- a/core/src/test/java/org/apache/brooklyn/core/entity/EntitySubscriptionTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/EntitySubscriptionTest.java
@@ -246,8 +246,8 @@ public class EntitySubscriptionTest {
         observedEntity.sensors().set(TestEntity.SEQUENCE, 123);
         observedEntity.sensors().set(TestEntity.NAME, "myname");
         
-        entity.subscribe(ImmutableMap.of("notifyOfInitialValue", true), observedEntity, TestEntity.SEQUENCE, listener);
-        entity.subscribe(ImmutableMap.of("notifyOfInitialValue", true), observedEntity, TestEntity.NAME, listener);
+        entity.subscriptions().subscribe(ImmutableMap.of("notifyOfInitialValue", true), observedEntity, TestEntity.SEQUENCE, listener);
+        entity.subscriptions().subscribe(ImmutableMap.of("notifyOfInitialValue", true), observedEntity, TestEntity.NAME, listener);
         
         Asserts.succeedsEventually(new Runnable() {
             @Override public void run() {
@@ -275,9 +275,9 @@ public class EntitySubscriptionTest {
     // TODO A visual inspection test that we get a log.warn telling us we can't get the initial-value
     @Test
     public void testSubscriptionForInitialValueWhenNotValid() {
-        entity.subscribe(ImmutableMap.of("notifyOfInitialValue", true), observedEntity, TestEntity.MY_NOTIF, listener);
-        entity.subscribe(ImmutableMap.of("notifyOfInitialValue", true), observedEntity, null, listener);
-        entity.subscribe(ImmutableMap.of("notifyOfInitialValue", true), null, TestEntity.NAME, listener);
-        entity.subscribe(ImmutableMap.of("notifyOfInitialValue", true), null, null, listener);
+        entity.subscriptions().subscribe(ImmutableMap.of("notifyOfInitialValue", true), observedEntity, TestEntity.MY_NOTIF, listener);
+        entity.subscriptions().subscribe(ImmutableMap.of("notifyOfInitialValue", true), observedEntity, null, listener);
+        entity.subscriptions().subscribe(ImmutableMap.of("notifyOfInitialValue", true), null, TestEntity.NAME, listener);
+        entity.subscriptions().subscribe(ImmutableMap.of("notifyOfInitialValue", true), null, null, listener);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ee52d48d/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicySubscriptionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicySubscriptionTest.java b/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicySubscriptionTest.java
index ab5bc4a..0a7b003 100644
--- a/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicySubscriptionTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/policy/basic/PolicySubscriptionTest.java
@@ -126,8 +126,8 @@ public class PolicySubscriptionTest extends BrooklynAppUnitTestSupport {
         entity.sensors().set(TestEntity.SEQUENCE, 123);
         entity.sensors().set(TestEntity.NAME, "myname");
         
-        policy.subscribe(ImmutableMap.of("notifyOfInitialValue", true), entity, TestEntity.SEQUENCE, listener);
-        policy.subscribe(ImmutableMap.of("notifyOfInitialValue", true), entity, TestEntity.NAME, listener);
+        policy.subscriptions().subscribe(ImmutableMap.of("notifyOfInitialValue", true), entity, TestEntity.SEQUENCE, listener);
+        policy.subscriptions().subscribe(ImmutableMap.of("notifyOfInitialValue", true), entity, TestEntity.NAME, listener);
         
         Asserts.succeedsEventually(new Runnable() {
             @Override public void run() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ee52d48d/software/base/src/main/java/org/apache/brooklyn/entity/software/base/SoftwareProcessImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/software/base/SoftwareProcessImpl.java b/software/base/src/main/java/org/apache/brooklyn/entity/software/base/SoftwareProcessImpl.java
index b635242..7f4658c 100644
--- a/software/base/src/main/java/org/apache/brooklyn/entity/software/base/SoftwareProcessImpl.java
+++ b/software/base/src/main/java/org/apache/brooklyn/entity/software/base/SoftwareProcessImpl.java
@@ -157,8 +157,8 @@ public abstract class SoftwareProcessImpl extends AbstractEntity implements Soft
             if (!(entity instanceof SoftwareProcess)) {
                 throw new IllegalArgumentException("Expected SoftwareProcess, but got entity "+entity);
             }
-            subscribe(ImmutableMap.of("notifyOfInitialValue", true), entity, Attributes.SERVICE_STATE_ACTUAL, this);
-            subscribe(ImmutableMap.of("notifyOfInitialValue", true), entity, Attributes.SERVICE_UP, this);
+            subscriptions().subscribe(ImmutableMap.of("notifyOfInitialValue", true), entity, Attributes.SERVICE_STATE_ACTUAL, this);
+            subscriptions().subscribe(ImmutableMap.of("notifyOfInitialValue", true), entity, Attributes.SERVICE_UP, this);
         }
 
         @Override


[05/10] incubator-brooklyn git commit: Adds Entity.groups(), for group-related methods

Posted by al...@apache.org.
Adds Entity.groups(), for group-related methods


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/7708363a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/7708363a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/7708363a

Branch: refs/heads/master
Commit: 7708363a26dc50c747ea980e600a9a3e01530ac7
Parents: 4ad6cc9
Author: Aled Sage <al...@gmail.com>
Authored: Mon Sep 21 10:14:14 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Sep 23 10:33:50 2015 +0100

----------------------------------------------------------------------
 .../org/apache/brooklyn/api/entity/Entity.java  | 39 +++++++++
 .../brooklyn/core/entity/AbstractEntity.java    | 91 +++++++++++++++-----
 2 files changed, 109 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7708363a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
index dd141f0..d302cff 100644
--- a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
+++ b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
@@ -178,7 +178,10 @@ public interface Entity extends BrooklynObject {
      * The {@link Collection} of {@link Group}s that this entity is a member of.
      *
      * Groupings can be used to allow easy management/monitoring of a group of entities.
+     * 
+     * @deprecated since 0.9.0; see {@link GroupSupport#getGroups()} and {@link #groups()}
      */
+    @Deprecated
     Collection<Group> getGroups();
 
     /**
@@ -187,7 +190,10 @@ public interface Entity extends BrooklynObject {
      * Users should call {@link Group#addMember(Entity)} instead; this method will then 
      * automatically be called. However, the reverse is not true (calling this method will 
      * not tell the group; this behaviour may change in a future release!)
+     * 
+     * @deprecated since 0.9.0; see {@link GroupSupport#getGroups()} and {@link #groups()}
      */
+    @Deprecated
     void addGroup(Group group);
 
     /**
@@ -196,7 +202,10 @@ public interface Entity extends BrooklynObject {
      * Users should call {@link Group#removeMember(Entity)} instead; this method will then 
      * automatically be called. However, the reverse is not true (calling this method will 
      * not tell the group; this behaviour may change in a future release!)
+     * 
+     * @deprecated since 0.9.0; see {@link GroupSupport#getGroups()} and {@link #groups()}
      */
+    @Deprecated
     void removeGroup(Group group);
 
     /**
@@ -305,6 +314,8 @@ public interface Entity extends BrooklynObject {
 
     EnricherSupport enrichers();
 
+    GroupSupport groups();
+
     @Beta
     public interface SensorSupport {
 
@@ -398,4 +409,32 @@ public interface Entity extends BrooklynObject {
          */
         boolean removeEnricher(Enricher enricher);
     }
+    
+    @Beta
+    public interface GroupSupport {
+        /**
+         * The {@link Collection} of {@link Group}s that this entity is a member of.
+         *
+         * Groupings can be used to allow easy management/monitoring of a group of entities.
+         */
+        Collection<Group> getGroups();
+
+        /**
+         * Add this entity as a member of the given {@link Group}. Called by framework.
+         * <p>
+         * Users should call {@link Group#addMember(Entity)} instead; this method will then 
+         * automatically be called. However, the reverse is not true (calling this method will 
+         * not tell the group; this behaviour may change in a future release!)
+         */
+        void addGroup(Group group);
+
+        /**
+         * Removes this entity as a member of the given {@link Group}. Called by framework.
+         * <p>
+         * Users should call {@link Group#removeMember(Entity)} instead; this method will then 
+         * automatically be called. However, the reverse is not true (calling this method will 
+         * not tell the group; this behaviour may change in a future release!)
+         */
+        void removeGroup(Group group);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7708363a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
index 48a07a4..0084038 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
@@ -190,7 +190,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     // then we need temp vals here. When setManagementContext is called, we'll switch these out for the read-deal;
     // i.e. for the values backed by storage
     private Reference<Entity> parent = new BasicReference<Entity>();
-    private Set<Group> groups = Sets.newLinkedHashSet();
+    private Set<Group> groupsInternal = Sets.newLinkedHashSet();
     private Set<Entity> children = Sets.newLinkedHashSet();
     private Reference<List<Location>> locations = new BasicReference<List<Location>>(ImmutableList.<Location>of()); // dups removed in addLocations
     private Reference<Long> creationTimeUtc = new BasicReference<Long>(System.currentTimeMillis());
@@ -226,6 +226,8 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
 
     private final BasicEnricherSupport enrichers = new BasicEnricherSupport();
 
+    private final BasicGroupSupport groups = new BasicGroupSupport();
+
     /**
      * The config values of this entity. Updating this map should be done
      * via getConfig/setConfig.
@@ -467,7 +469,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
 
         if (BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_USE_BROOKLYN_LIVE_OBJECTS_DATAGRID_STORAGE)) {
             Entity oldParent = parent.get();
-            Set<Group> oldGroups = groups;
+            Set<Group> oldGroups = groupsInternal;
             Set<Entity> oldChildren = children;
             List<Location> oldLocations = locations.get();
             EntityConfigMap oldConfig = configsInternal;
@@ -477,7 +479,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
             String oldIconUrl = iconUrl.get();
 
             parent = managementContext.getStorage().getReference(getId()+"-parent");
-            groups = SetFromLiveMap.create(managementContext.getStorage().<Group,Boolean>getMap(getId()+"-groups"));
+            groupsInternal = SetFromLiveMap.create(managementContext.getStorage().<Group,Boolean>getMap(getId()+"-groups"));
             children = SetFromLiveMap.create(managementContext.getStorage().<Entity,Boolean>getMap(getId()+"-children"));
             locations = managementContext.getStorage().getNonConcurrentList(getId()+"-locations");
             creationTimeUtc = managementContext.getStorage().getReference(getId()+"-creationTime");
@@ -491,7 +493,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
             // before setting the parent etc. However, for backwards compatibility we still support some
             // things calling the entity's constructor directly.
             if (oldParent != null) parent.set(oldParent);
-            if (oldGroups.size() > 0) groups.addAll(oldGroups);
+            if (oldGroups.size() > 0) groupsInternal.addAll(oldGroups);
             if (oldChildren.size() > 0) children.addAll(oldChildren);
             if (oldLocations.size() > 0) locations.set(ImmutableList.copyOf(oldLocations));
             if (creationTimeUtc.isNull()) creationTimeUtc.set(oldCreationTimeUtc);
@@ -685,26 +687,78 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         return changed;
     }
 
-    @Override
-    public void addGroup(Group group) {
-        boolean changed = groups.add(group);
-        getApplication();
+    // -------- GROUPS --------------
+
+    @Override 
+    @Beta
+    // the concrete type rather than an interface is returned because Groovy subclasses
+    // complain (incorrectly) if we return EnricherSupportInternal
+    // TODO revert to EnricherSupportInternal when groovy subclasses work without this (eg new groovy version)
+    public BasicGroupSupport groups() {
+        return groups;
+    }
+
+    /**
+     * Direct use of this class is strongly discouraged. It will become private in a future release,
+     * once {@link #groups()} is reverted to return {@link {GroupSupport} instead of
+     * {@link BasicGroupSupport}.
+     */
+    @Beta
+    // TODO revert to private when groups() is reverted to return GroupSupport
+    public class BasicGroupSupport implements GroupSupport {
+        @Override
+        public void addGroup(Group group) {
+            boolean changed = groupsInternal.add(group);
+            getApplication();
+            
+            if (changed) {
+                emit(AbstractEntity.GROUP_ADDED, group);
+            }
+        }
+
+        @Override
+        public void removeGroup(Group group) {
+            boolean changed = groupsInternal.remove(group);
+            getApplication();
+            
+            if (changed) {
+                emit(AbstractEntity.GROUP_REMOVED, group);
+            }
+        }
         
-        if (changed) {
-            emit(AbstractEntity.GROUP_ADDED, group);
+        @Override
+        public Collection<Group> getGroups() { 
+            return ImmutableList.copyOf(groupsInternal);
         }
     }
+    
+    /**
+     * @deprecated since 0.9.0; see {@link #groups()} and {@link GroupSupport#addGroup(Group)}
+     */
+    @Override
+    @Deprecated
+    public void addGroup(Group group) {
+        groups().addGroup(group);
+    }
 
+    /**
+     * @deprecated since 0.9.0; see {@link #groups()} and {@link GroupSupport#removeGroup(Group)}
+     */
     @Override
+    @Deprecated
     public void removeGroup(Group group) {
-        boolean changed = groups.remove(group);
-        getApplication();
-        
-        if (changed) {
-            emit(AbstractEntity.GROUP_REMOVED, group);
-        }
+        groups().removeGroup(group);
     }
 
+    /**
+     * @deprecated since 0.9.0; see {@link #groups()} and {@link GroupSupport#getGroups()}
+     */
+    @Override
+    @Deprecated
+    public Collection<Group> getGroups() { 
+        return groups().getGroups();
+    }
+    
     @Override
     public Entity getParent() {
         return parent.get();
@@ -715,11 +769,6 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         return ImmutableList.copyOf(children);
     }
     
-    @Override
-    public Collection<Group> getGroups() { 
-        return ImmutableList.copyOf(groups);
-    }
-
     /**
      * Returns the application, looking it up if not yet known (registering if necessary)
      */


[06/10] incubator-brooklyn git commit: Move subscriptions() from Entity to BrooklynObject

Posted by al...@apache.org.
Move subscriptions() from Entity to BrooklynObject

- Add support for subscriptions to Location (and test)
- For CatalogItem.subscriptions(), throw UnsupportedOperationException
- Deprecate methods on AbstractEntityAdjunct, in preference for
  AbstractEntityAdjunct.subscriptions().*


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/4ad6cc96
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/4ad6cc96
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/4ad6cc96

Branch: refs/heads/master
Commit: 4ad6cc967730001715ac3a97661106b5ed1b6c67
Parents: 2b29795
Author: Aled Sage <al...@gmail.com>
Authored: Mon Sep 21 10:05:11 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Sep 23 10:33:50 2015 +0100

----------------------------------------------------------------------
 .../brooklyn/api/catalog/CatalogItem.java       |  12 +
 .../org/apache/brooklyn/api/entity/Entity.java  |  51 ----
 .../brooklyn/api/mgmt/ManagementContext.java    |   9 +
 .../brooklyn/api/objs/BrooklynObject.java       |  63 ++++-
 .../core/catalog/internal/CatalogItemDo.java    |  11 +-
 .../internal/CatalogItemDtoAbstract.java        |  14 +-
 .../brooklyn/core/entity/EntityInternal.java    |   8 -
 .../core/location/AbstractLocation.java         |  79 +++++-
 .../access/PortForwardManagerClient.java        |   5 +
 .../internal/AbstractManagementContext.java     |  11 +-
 .../mgmt/internal/BasicSubscriptionContext.java |   3 +-
 .../NonDeploymentManagementContext.java         |   7 +
 .../core/objs/AbstractEntityAdjunct.java        | 164 ++++++++++---
 .../core/objs/BrooklynObjectInternal.java       |   9 +
 .../core/location/LocationSubscriptionTest.java | 241 +++++++++++++++++++
 15 files changed, 580 insertions(+), 107 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4ad6cc96/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java b/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
index 3758d08..bf806aa 100644
--- a/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
+++ b/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
@@ -48,6 +48,18 @@ public interface CatalogItem<T,SpecT> extends BrooklynObject, Rebindable {
         public boolean isNamed();
     }
 
+    /**
+     * @throws UnsupportedOperationException; config not supported for catalog items
+     */
+    @Override
+    ConfigurationSupport config();
+
+    /**
+     * @throws UnsupportedOperationException; subscriptions are not supported for catalog items
+     */
+    @Override
+    SubscriptionSupport subscriptions();
+    
     @Deprecated
     public static interface CatalogItemLibraries {
         Collection<String> getBundles();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4ad6cc96/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
index 795218c..dd141f0 100644
--- a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
+++ b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
@@ -301,8 +301,6 @@ public interface Entity extends BrooklynObject {
     
     SensorSupport sensors();
 
-    SubscriptionSupport subscriptions();
-
     PolicySupport policies();
 
     EnricherSupport enrichers();
@@ -354,55 +352,6 @@ public interface Entity extends BrooklynObject {
     }
     
     @Beta
-    public interface SubscriptionSupport {
-        /**
-         * Allow us to subscribe to data from a {@link Sensor} on another entity.
-         * 
-         * @return a subscription id which can be used to unsubscribe
-         *
-         * @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener)
-         */
-        // FIXME remove from interface?
-        @Beta
-        <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener);
-     
-        /** @see SubscriptionManager#subscribeToChildren(Map, Entity, Sensor, SensorEventListener) */
-        // FIXME remove from interface?
-        @Beta
-        <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener);
-     
-        /** @see SubscriptionManager#subscribeToMembers(Group, Sensor, SensorEventListener) */
-        // FIXME remove from interface?
-        @Beta
-        <T> SubscriptionHandle subscribeToMembers(Group group, Sensor<T> sensor, SensorEventListener<? super T> listener);
-
-        /**
-         * Unsubscribes from the given producer.
-         *
-         * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
-         */
-        @Beta
-        boolean unsubscribe(Entity producer);
-
-        /**
-         * Unsubscribes the given handle.
-         *
-         * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
-         */
-        @Beta
-        boolean unsubscribe(Entity producer, SubscriptionHandle handle);
-        
-        /**
-         * Unsubscribes the given handle.
-         * 
-         * It is (currently) more efficient to also pass in the producer -
-         * see {@link BasicSubscriptionSupport#unsubscribe(Entity, SubscriptionHandle)} 
-         */
-        @Beta
-        boolean unsubscribe(SubscriptionHandle handle);
-    }
-
-    @Beta
     public interface PolicySupport {
         /**
          * @return an immutable thread-safe view of the policies.

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4ad6cc96/api/src/main/java/org/apache/brooklyn/api/mgmt/ManagementContext.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/ManagementContext.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/ManagementContext.java
index ac4924e..f809fb2 100644
--- a/api/src/main/java/org/apache/brooklyn/api/mgmt/ManagementContext.java
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/ManagementContext.java
@@ -28,6 +28,7 @@ import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.drivers.DriverDependentEntity;
 import org.apache.brooklyn.api.entity.drivers.EntityDriverManager;
 import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolverManager;
+import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.location.LocationRegistry;
 import org.apache.brooklyn.api.mgmt.entitlement.EntitlementManager;
 import org.apache.brooklyn.api.mgmt.ha.HighAvailabilityManager;
@@ -156,6 +157,14 @@ public interface ManagementContext {
      */
     SubscriptionContext getSubscriptionContext(Entity entity);
 
+    /**
+     * Returns a {@link SubscriptionContext} instance representing subscriptions
+     * (from the {@link SubscriptionManager}) associated with this location, and capable 
+     * of conveniently subscribing on behalf of that location  
+     */
+    @Beta
+    SubscriptionContext getSubscriptionContext(Location location);
+
     @Beta // method may move to an internal interface; brooklyn users should not need to call this directly
     RebindManager getRebindManager();
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4ad6cc96/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java b/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java
index c932f02..094586f 100644
--- a/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java
+++ b/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java
@@ -18,10 +18,20 @@
  */
 package org.apache.brooklyn.api.objs;
 
+import java.util.Map;
 import java.util.Set;
 
 import javax.annotation.Nonnull;
 
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.Group;
+import org.apache.brooklyn.api.mgmt.SubscriptionContext;
+import org.apache.brooklyn.api.mgmt.SubscriptionHandle;
+import org.apache.brooklyn.api.mgmt.SubscriptionManager;
+import org.apache.brooklyn.api.sensor.Sensor;
+import org.apache.brooklyn.api.sensor.SensorEventListener;
+
+import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableMap;
 
 /**
@@ -53,7 +63,13 @@ public interface BrooklynObject extends Identifiable, Configurable {
      * and they should be amenable to our persistence (on-disk serialization) and our JSON serialization in the REST API.
      */
     TagSupport tags();
-    
+
+    /**
+     * Subscriptions are the mechanism for receiving notifications of sensor-events (e.g. attribute-changed) from 
+     * other entities.
+     */
+    SubscriptionSupport subscriptions();
+
     public interface TagSupport {
         /**
          * @return An immutable copy of the set of tags on this entity. 
@@ -70,4 +86,49 @@ public interface BrooklynObject extends Identifiable, Configurable {
         
         boolean removeTag(@Nonnull Object tag);
     }
+    
+    @Beta
+    public interface SubscriptionSupport {
+        /**
+         * Allow us to subscribe to data from a {@link Sensor} on another entity.
+         * 
+         * @return a subscription id which can be used to unsubscribe
+         *
+         * @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener)
+         */
+        @Beta
+        <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener);
+     
+        /** @see SubscriptionManager#subscribeToChildren(Map, Entity, Sensor, SensorEventListener) */
+        @Beta
+        <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener);
+     
+        /** @see SubscriptionManager#subscribeToMembers(Group, Sensor, SensorEventListener) */
+        @Beta
+        <T> SubscriptionHandle subscribeToMembers(Group group, Sensor<T> sensor, SensorEventListener<? super T> listener);
+
+        /**
+         * Unsubscribes from the given producer.
+         *
+         * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+         */
+        @Beta
+        boolean unsubscribe(Entity producer);
+
+        /**
+         * Unsubscribes the given handle.
+         *
+         * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+         */
+        @Beta
+        boolean unsubscribe(Entity producer, SubscriptionHandle handle);
+        
+        /**
+         * Unsubscribes the given handle.
+         * 
+         * It is (currently) more efficient to also pass in the producer -
+         * see {@link SubscriptionSupport#unsubscribe(Entity, SubscriptionHandle)} 
+         */
+        boolean unsubscribe(SubscriptionHandle handle);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4ad6cc96/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
index 5029d8d..0545a06 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
@@ -25,6 +25,7 @@ import javax.annotation.Nullable;
 
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
+import org.apache.brooklyn.core.objs.BrooklynObjectInternal.SubscriptionSupportInternal;
 import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
@@ -49,13 +50,21 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT>, BrooklynObj
     }
     
     /**
-     * Config not supported for catalog item. See {@link #getPlanYaml()}.
+     * @throws UnsupportedOperationException; Config not supported for catalog item. See {@link #getPlanYaml()}.
      */
     @Override
     public ConfigurationSupportInternal config() {
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * @throws UnsupportedOperationException; subscriptions are not supported for catalog items
+     */
+    @Override
+    public SubscriptionSupportInternal subscriptions() {
+        throw new UnsupportedOperationException();
+    }
+    
     @Override
     public <U> U setConfig(ConfigKey<U> key, U val) {
         return config().set(key, val);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4ad6cc96/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
index b281941..c950b7b 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
@@ -26,8 +26,6 @@ import java.util.Set;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.CatalogItemMemento;
@@ -37,6 +35,8 @@ import org.apache.brooklyn.core.objs.AbstractBrooklynObject;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.core.flags.FlagUtils;
 import org.apache.brooklyn.util.core.flags.SetFromFlag;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Objects;
 import com.google.common.collect.ImmutableList;
@@ -66,13 +66,21 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
     private @SetFromFlag boolean disabled;
 
     /**
-     * Config not supported for catalog item. See {@link #getPlanYaml()}.
+     * @throws UnsupportedOperationException; Config not supported for catalog item. See {@link #getPlanYaml()}.
      */
     @Override
     public ConfigurationSupportInternal config() {
         throw new UnsupportedOperationException();
     }
     
+    /**
+     * @throws UnsupportedOperationException; subscriptions are not supported for catalog items
+     */
+    @Override
+    public SubscriptionSupportInternal subscriptions() {
+        throw new UnsupportedOperationException();
+    }
+    
     @Override
     public <U> U setConfig(ConfigKey<U> key, U val) {
         return config().set(key, val);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4ad6cc96/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java b/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
index 4fa9c67..49dfa00 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
@@ -184,9 +184,6 @@ public interface EntityInternal extends BrooklynObjectInternal, EntityLocal, Reb
     SensorSupportInternal sensors();
 
     @Override
-    SubscriptionSupportInternal subscriptions();
-
-    @Override
     PolicySupportInternal policies();
 
     @Override
@@ -230,11 +227,6 @@ public interface EntityInternal extends BrooklynObjectInternal, EntityLocal, Reb
     }
     
     @Beta
-    public interface SubscriptionSupportInternal extends Entity.SubscriptionSupport {
-        public void unsubscribeAll();
-    }
-    
-    @Beta
     public interface PolicySupportInternal extends Entity.PolicySupport {
         /**
          * Removes all policy from this entity. 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4ad6cc96/core/src/main/java/org/apache/brooklyn/core/location/AbstractLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/location/AbstractLocation.java b/core/src/main/java/org/apache/brooklyn/core/location/AbstractLocation.java
index 507e7f5..b8859d6 100644
--- a/core/src/main/java/org/apache/brooklyn/core/location/AbstractLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/core/location/AbstractLocation.java
@@ -29,12 +29,18 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.Group;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.mgmt.SubscriptionContext;
+import org.apache.brooklyn.api.mgmt.SubscriptionHandle;
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.LocationMemento;
 import org.apache.brooklyn.api.objs.Configurable;
+import org.apache.brooklyn.api.sensor.Sensor;
+import org.apache.brooklyn.api.sensor.SensorEventListener;
 import org.apache.brooklyn.config.ConfigInheritance;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
@@ -50,17 +56,19 @@ import org.apache.brooklyn.core.location.internal.LocationDynamicType;
 import org.apache.brooklyn.core.location.internal.LocationInternal;
 import org.apache.brooklyn.core.mgmt.internal.LocalLocationManager;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.mgmt.internal.SubscriptionTracker;
 import org.apache.brooklyn.core.mgmt.rebind.BasicLocationRebindSupport;
 import org.apache.brooklyn.core.objs.AbstractBrooklynObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.apache.brooklyn.util.collections.SetFromLiveMap;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.core.flags.FlagUtils;
 import org.apache.brooklyn.util.core.flags.TypeCoercions;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.stream.Streams;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import com.google.common.annotations.Beta;
 import com.google.common.base.Objects;
 import com.google.common.base.Objects.ToStringHelper;
 import com.google.common.base.Splitter;
@@ -110,8 +118,13 @@ public abstract class AbstractLocation extends AbstractBrooklynObject implements
 
     private BasicConfigurationSupport config = new BasicConfigurationSupport();
     
+    private BasicSubscriptionSupport subscriptions = new BasicSubscriptionSupport();
+    
     private ConfigBag configBag = new ConfigBag();
 
+    /** not for direct access; refer to as 'subscriptionTracker' via getter so that it is initialized */
+    protected transient SubscriptionTracker _subscriptionTracker;
+
     private volatile boolean managed;
 
     private boolean inConstruction;
@@ -354,7 +367,16 @@ public abstract class AbstractLocation extends AbstractBrooklynObject implements
 
     @Override
     public ConfigurationSupportInternal config() {
-        return config ;
+        return config;
+    }
+
+    // the concrete type rather than an interface is returned because Groovy subclasses
+    // complain (incorrectly) if we return SubscriptionSupportInternal
+    // TODO revert to SubscriptionSupportInternal when groovy subclasses work without this (eg new groovy version)
+    @Override
+    @Beta
+    public BasicSubscriptionSupport subscriptions() {
+        return subscriptions;
     }
 
     private class BasicConfigurationSupport implements ConfigurationSupportInternal {
@@ -478,6 +500,57 @@ public abstract class AbstractLocation extends AbstractBrooklynObject implements
         }
     }
     
+    public class BasicSubscriptionSupport implements SubscriptionSupportInternal {
+        @Override
+        public <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+            return getSubscriptionTracker().subscribe(producer, sensor, listener);
+        }
+
+        @Override
+        public <T> SubscriptionHandle subscribeToMembers(Group producerGroup, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+            return getSubscriptionTracker().subscribeToMembers(producerGroup, sensor, listener);
+        }
+
+        @Override
+        public <T> SubscriptionHandle subscribeToChildren(Entity producerParent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+            return getSubscriptionTracker().subscribeToChildren(producerParent, sensor, listener);
+        }
+        
+        @Override
+        public boolean unsubscribe(Entity producer) {
+            return getSubscriptionTracker().unsubscribe(producer);
+        }
+
+        @Override
+        public boolean unsubscribe(Entity producer, SubscriptionHandle handle) {
+            return getSubscriptionTracker().unsubscribe(producer, handle);
+        }
+
+        @Override
+        public boolean unsubscribe(SubscriptionHandle handle) {
+            return getSubscriptionTracker().unsubscribe(handle);
+        }
+
+        @Override
+        public void unsubscribeAll() {
+            getSubscriptionTracker().unsubscribeAll();
+        }
+
+        protected SubscriptionTracker getSubscriptionTracker() {
+            synchronized (AbstractLocation.this) {
+                if (_subscriptionTracker!=null) return _subscriptionTracker;
+                _subscriptionTracker = new SubscriptionTracker(newSubscriptionContext());
+                return _subscriptionTracker;
+            }
+        }
+        
+        private SubscriptionContext newSubscriptionContext() {
+            synchronized (AbstractLocation.this) {
+                return getManagementContext().getSubscriptionContext(AbstractLocation.this);
+            }
+        }
+    }
+    
     @Override
     public <T> T getConfig(HasConfigKey<T> key) {
         return config().get(key);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4ad6cc96/core/src/main/java/org/apache/brooklyn/core/location/access/PortForwardManagerClient.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/location/access/PortForwardManagerClient.java b/core/src/main/java/org/apache/brooklyn/core/location/access/PortForwardManagerClient.java
index 12e15aa..d0199a0 100644
--- a/core/src/main/java/org/apache/brooklyn/core/location/access/PortForwardManagerClient.java
+++ b/core/src/main/java/org/apache/brooklyn/core/location/access/PortForwardManagerClient.java
@@ -402,4 +402,9 @@ public class PortForwardManagerClient implements PortForwardManager {
     public ConfigurationSupport config() {
         return getDelegate().config();
     }
+    
+    @Override
+    public SubscriptionSupport subscriptions() {
+        return getDelegate().subscriptions();
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4ad6cc96/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java
index 76871cd..343528d 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java
@@ -32,14 +32,13 @@ import java.util.concurrent.atomic.AtomicLong;
 
 import javax.annotation.Nullable;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.apache.brooklyn.api.catalog.BrooklynCatalog;
 import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.effector.Effector;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.drivers.EntityDriverManager;
 import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolverManager;
+import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.location.LocationRegistry;
 import org.apache.brooklyn.api.mgmt.ExecutionContext;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
@@ -78,6 +77,8 @@ import org.apache.brooklyn.util.core.task.BasicExecutionContext;
 import org.apache.brooklyn.util.core.task.Tasks;
 import org.apache.brooklyn.util.groovy.GroovyJavaMethods;
 import org.apache.brooklyn.util.guava.Maybe;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Function;
 import com.google.common.base.Objects;
@@ -260,6 +261,12 @@ public abstract class AbstractManagementContext implements ManagementContextInte
     }
 
     @Override
+    public SubscriptionContext getSubscriptionContext(Location loc) {
+        // BSC is a thin wrapper around SM so fine to create a new one here
+        return new BasicSubscriptionContext(getSubscriptionManager(), loc);
+    }
+
+    @Override
     public EntityDriverManager getEntityDriverManager() {
         return entityDriverManager;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4ad6cc96/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/BasicSubscriptionContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/BasicSubscriptionContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/BasicSubscriptionContext.java
index d821c4e..57d4712 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/BasicSubscriptionContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/BasicSubscriptionContext.java
@@ -19,7 +19,6 @@
 package org.apache.brooklyn.core.mgmt.internal;
 
 import static org.apache.brooklyn.util.JavaGroovyEquivalents.mapOf;
-import groovy.lang.Closure;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -42,6 +41,8 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Maps;
 
+import groovy.lang.Closure;
+
 /**
  * A {@link SubscriptionContext} for an entity or other user of a {@link SubscriptionManager}.
  */

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4ad6cc96/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/NonDeploymentManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/NonDeploymentManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/NonDeploymentManagementContext.java
index 87e8f84..1f62add 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/NonDeploymentManagementContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/NonDeploymentManagementContext.java
@@ -241,6 +241,13 @@ public class NonDeploymentManagementContext implements ManagementContextInternal
     }
 
     @Override
+    public synchronized SubscriptionContext getSubscriptionContext(Location loc) {
+        // Should never be called; the NonDeploymentManagementContext is associated with a particular entity, whereas
+        // the #getSubscriptionContext(loc) should only be called in the context of a location.
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public ExecutionContext getExecutionContext(Entity entity) {
         if (!this.entity.equals(entity)) throw new IllegalStateException("Non-deployment context "+this+" can only use a single Entity: has "+this.entity+", but passed "+entity);
         if (mode==NonDeploymentManagementContextMode.MANAGEMENT_STOPPED)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4ad6cc96/core/src/main/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunct.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunct.java b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunct.java
index fb71901..814923a 100644
--- a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunct.java
+++ b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunct.java
@@ -32,17 +32,17 @@ import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntityLocal;
 import org.apache.brooklyn.api.entity.Group;
 import org.apache.brooklyn.api.mgmt.ExecutionContext;
-import org.apache.brooklyn.api.mgmt.SubscriptionContext;
 import org.apache.brooklyn.api.mgmt.SubscriptionHandle;
 import org.apache.brooklyn.api.mgmt.Task;
+import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.objs.Configurable;
 import org.apache.brooklyn.api.objs.EntityAdjunct;
 import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.api.sensor.Sensor;
 import org.apache.brooklyn.api.sensor.SensorEventListener;
 import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.config.ConfigMap;
 import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
+import org.apache.brooklyn.config.ConfigMap;
 import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.enricher.AbstractEnricher;
 import org.apache.brooklyn.core.entity.Entities;
@@ -58,7 +58,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.annotations.Beta;
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableSet;
@@ -82,7 +81,9 @@ public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject imple
     protected transient ExecutionContext execution;
 
     private final BasicConfigurationSupport config = new BasicConfigurationSupport();
-    
+
+    private final BasicSubscriptionSupport subscriptions = new BasicSubscriptionSupport();
+
     /**
      * The config values of this entity. Updating this map should be done
      * via {@link #config()}.
@@ -199,6 +200,89 @@ public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject imple
         return config;
     }
 
+    @Override
+    public BasicSubscriptionSupport subscriptions() {
+        return subscriptions;
+    }
+
+    public class BasicSubscriptionSupport implements SubscriptionSupportInternal {
+        @Override
+        public <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+            if (!checkCanSubscribe()) return null;
+            return getSubscriptionTracker().subscribe(producer, sensor, listener);
+        }
+
+        @Override
+        public <T> SubscriptionHandle subscribeToMembers(Group producerGroup, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+            if (!checkCanSubscribe(producerGroup)) return null;
+            return getSubscriptionTracker().subscribeToMembers(producerGroup, sensor, listener);
+        }
+
+        @Override
+        public <T> SubscriptionHandle subscribeToChildren(Entity producerParent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+            if (!checkCanSubscribe(producerParent)) return null;
+            return getSubscriptionTracker().subscribeToChildren(producerParent, sensor, listener);
+        }
+        
+        @Override
+        public boolean unsubscribe(Entity producer) {
+            if (destroyed.get()) return false;
+            return getSubscriptionTracker().unsubscribe(producer);
+        }
+
+        @Override
+        public boolean unsubscribe(Entity producer, SubscriptionHandle handle) {
+            if (destroyed.get()) return false;
+            return getSubscriptionTracker().unsubscribe(producer, handle);
+        }
+
+        @Override
+        public boolean unsubscribe(SubscriptionHandle handle) {
+            if (destroyed.get()) return false;
+            return getSubscriptionTracker().unsubscribe(handle);
+        }
+
+        @Override
+        public void unsubscribeAll() {
+            if (destroyed.get()) return;
+            getSubscriptionTracker().unsubscribeAll();
+        }
+
+        protected SubscriptionTracker getSubscriptionTracker() {
+            synchronized (AbstractEntityAdjunct.this) {
+                if (_subscriptionTracker!=null) return _subscriptionTracker;
+                if (entity==null) return null;
+                _subscriptionTracker = new SubscriptionTracker(((EntityInternal)entity).getManagementSupport().getSubscriptionContext());
+                return _subscriptionTracker;
+            }
+        }
+        
+        /** returns false if deleted, throws exception if invalid state, otherwise true.
+         * okay if entity is not yet managed (but not if entity is no longer managed). */
+        protected boolean checkCanSubscribe(Entity producer) {
+            if (destroyed.get()) return false;
+            if (producer==null) throw new IllegalStateException(this+" given a null target for subscription");
+            if (entity==null) throw new IllegalStateException(this+" cannot subscribe to "+producer+" because it is not associated to an entity");
+            if (((EntityInternal)entity).getManagementSupport().isNoLongerManaged()) throw new IllegalStateException(this+" cannot subscribe to "+producer+" because the associated entity "+entity+" is no longer managed");
+            return true;
+        }
+        
+        protected boolean checkCanSubscribe() {
+            if (destroyed.get()) return false;
+            if (entity==null) throw new IllegalStateException(this+" cannot subscribe because it is not associated to an entity");
+            if (((EntityInternal)entity).getManagementSupport().isNoLongerManaged()) throw new IllegalStateException(this+" cannot subscribe because the associated entity "+entity+" is no longer managed");
+            return true;
+        }
+
+        /**
+         * @return a list of all subscription handles
+         */
+        protected Collection<SubscriptionHandle> getAllSubscriptions() {
+            SubscriptionTracker tracker = getSubscriptionTracker();
+            return (tracker != null) ? tracker.getAllSubscriptions() : Collections.<SubscriptionHandle>emptyList();
+        }
+    }
+    
     private class BasicConfigurationSupport implements ConfigurationSupportInternal {
 
         @Override
@@ -377,6 +461,10 @@ public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject imple
         }
     }
 
+    /**
+     * @deprecated since 0.9.0; for internal use only
+     */
+    @Deprecated
     protected synchronized SubscriptionTracker getSubscriptionTracker() {
         if (_subscriptionTracker!=null) return _subscriptionTracker;
         if (entity==null) return null;
@@ -384,14 +472,15 @@ public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject imple
         return _subscriptionTracker;
     }
     
-    @VisibleForTesting //intended as protected, meant for subclasses
-    /** @see SubscriptionContext#subscribe(Entity, Sensor, SensorEventListener) */
+    /**
+     * @deprecated since 0.9.0; see {@link SubscriptionSupport#subscribe(Entity, Sensor, SensorEventListener)} and {@link BrooklynObject#subscriptions()}
+     */
+    @Deprecated
     public <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
         if (!checkCanSubscribe()) return null;
         return getSubscriptionTracker().subscribe(producer, sensor, listener);
     }
 
-    @VisibleForTesting //intended as protected, meant for subclasses
     @Beta
     /** @see SubscriptionContext#subscribe(Map, Entity, Sensor, SensorEventListener) */
     public <T> SubscriptionHandle subscribe(Map<String, ?> flags, Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
@@ -399,67 +488,68 @@ public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject imple
         return getSubscriptionTracker().subscribe(flags, producer, sensor, listener);
     }
 
-    @VisibleForTesting //intended as protected, meant for subclasses
-    /** @see SubscriptionContext#subscribe(Entity, Sensor, SensorEventListener) */
+    /**
+     * @deprecated since 0.9.0; see {@link SubscriptionSupport#subscribeToMembers(Entity, Sensor, SensorEventListener)} and {@link BrooklynObject#subscriptions()}
+     */
+    @Deprecated
     public <T> SubscriptionHandle subscribeToMembers(Group producerGroup, Sensor<T> sensor, SensorEventListener<? super T> listener) {
         if (!checkCanSubscribe(producerGroup)) return null;
         return getSubscriptionTracker().subscribeToMembers(producerGroup, sensor, listener);
     }
 
-    @VisibleForTesting //intended as protected, meant for subclasses 
-    /** @see SubscriptionContext#subscribe(Entity, Sensor, SensorEventListener) */
+    /**
+     * @deprecated since 0.9.0; see {@link SubscriptionSupport#subscribeToChildren(Entity, Sensor, SensorEventListener)} and {@link BrooklynObject#subscriptions()}
+     */
+    @Deprecated
     public <T> SubscriptionHandle subscribeToChildren(Entity producerParent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
         if (!checkCanSubscribe(producerParent)) return null;
         return getSubscriptionTracker().subscribeToChildren(producerParent, sensor, listener);
     }
 
-    /** @deprecated since 0.7.0 use {@link #checkCanSubscribe(Entity)} */
+    /**
+     * @deprecated since 0.7.0 use {@link BasicSubscriptionSupport#checkCanSubscribe(Entity)
+     */
     @Deprecated
     protected boolean check(Entity requiredEntity) {
         return checkCanSubscribe(requiredEntity);
     }
-    /** returns false if deleted, throws exception if invalid state, otherwise true.
-     * okay if entity is not yet managed (but not if entity is no longer managed). */
+    
+    /**
+     * @deprecated since 0.9.0; for internal use only
+     */
+    @Deprecated
     protected boolean checkCanSubscribe(Entity producer) {
-        if (destroyed.get()) return false;
-        if (producer==null) throw new IllegalStateException(this+" given a null target for subscription");
-        if (entity==null) throw new IllegalStateException(this+" cannot subscribe to "+producer+" because it is not associated to an entity");
-        if (((EntityInternal)entity).getManagementSupport().isNoLongerManaged()) throw new IllegalStateException(this+" cannot subscribe to "+producer+" because the associated entity "+entity+" is no longer managed");
-        return true;
+        return subscriptions().checkCanSubscribe(producer);
     }
+    
+    /**
+     * @deprecated since 0.9.0; for internal use only
+     */
+    @Deprecated
     protected boolean checkCanSubscribe() {
-        if (destroyed.get()) return false;
-        if (entity==null) throw new IllegalStateException(this+" cannot subscribe because it is not associated to an entity");
-        if (((EntityInternal)entity).getManagementSupport().isNoLongerManaged()) throw new IllegalStateException(this+" cannot subscribe because the associated entity "+entity+" is no longer managed");
-        return true;
+        return subscriptions().checkCanSubscribe();
     }
         
     /**
-     * Unsubscribes the given producer.
-     *
-     * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+     * @deprecated since 0.9.0; see {@link SubscriptionSupport#unsubscribe(Entity)} and {@link BrooklynObject#subscriptions()}
      */
-    @VisibleForTesting //intended as protected, meant for subclasses
+    @Deprecated
     public boolean unsubscribe(Entity producer) {
-        if (destroyed.get()) return false;
-        return getSubscriptionTracker().unsubscribe(producer);
+        return subscriptions().unsubscribe(producer);
     }
 
     /**
-     * Unsubscribes the given producer.
-     *
-     * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+     * @deprecated since 0.9.0; see {@link SubscriptionSupport#unsubscribe(Entity, SubscriptionHandle)} and {@link BrooklynObject#subscriptions()}
      */
-    @VisibleForTesting //intended as protected, meant for subclasses
+    @Deprecated
     public boolean unsubscribe(Entity producer, SubscriptionHandle handle) {
-        if (destroyed.get()) return false;
-        return getSubscriptionTracker().unsubscribe(producer, handle);
+        return subscriptions().unsubscribe(producer, handle);
     }
 
     /**
-     * @return a list of all subscription handles
+     * @deprecated since 0.9.0; for internal use only
      */
-    @VisibleForTesting //intended as protected, meant for subclasses
+    @Deprecated
     protected Collection<SubscriptionHandle> getAllSubscriptions() {
         SubscriptionTracker tracker = getSubscriptionTracker();
         return (tracker != null) ? tracker.getAllSubscriptions() : Collections.<SubscriptionHandle>emptyList();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4ad6cc96/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectInternal.java b/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectInternal.java
index ad2cca1..d076f4e 100644
--- a/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectInternal.java
+++ b/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectInternal.java
@@ -38,8 +38,12 @@ public interface BrooklynObjectInternal extends BrooklynObject, Rebindable {
     @SuppressWarnings("rawtypes")  // subclasses typically apply stronger typing
     RebindSupport getRebindSupport();
     
+    @Override
     ConfigurationSupportInternal config();
 
+    @Override
+    SubscriptionSupportInternal subscriptions();
+
     @Beta
     public interface ConfigurationSupportInternal extends Configurable.ConfigurationSupport {
         
@@ -100,4 +104,9 @@ public interface BrooklynObjectInternal extends BrooklynObject, Rebindable {
         @Beta
         void refreshInheritedConfigOfChildren();
     }
+    
+    @Beta
+    public interface SubscriptionSupportInternal extends BrooklynObject.SubscriptionSupport {
+        public void unsubscribeAll();
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4ad6cc96/core/src/test/java/org/apache/brooklyn/core/location/LocationSubscriptionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/location/LocationSubscriptionTest.java b/core/src/test/java/org/apache/brooklyn/core/location/LocationSubscriptionTest.java
new file mode 100644
index 0000000..30352c7
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/location/LocationSubscriptionTest.java
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.brooklyn.core.location;
+
+import static org.testng.Assert.assertEquals;
+
+import org.apache.brooklyn.api.entity.EntityLocal;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.mgmt.SubscriptionHandle;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.RecordingSensorEventListener;
+import org.apache.brooklyn.core.location.SimulatedLocation;
+import org.apache.brooklyn.core.sensor.BasicSensorEvent;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.entity.group.BasicGroup;
+import org.apache.brooklyn.test.Asserts;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+public class LocationSubscriptionTest {
+
+    // TODO Duplication between this and PolicySubscriptionTest
+    
+    private SimulatedLocation loc;
+    private TestApplication app;
+    private TestEntity observedEntity;
+    private BasicGroup observedGroup;
+    private TestEntity observedChildEntity;
+    private TestEntity observedMemberEntity;
+    private TestEntity otherEntity;
+    private RecordingSensorEventListener<Object> listener;
+    
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() {
+        app = TestApplication.Factory.newManagedInstanceForTests();
+        loc = app.newSimulatedLocation();
+        observedEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+        observedChildEntity = observedEntity.createAndManageChild(EntitySpec.create(TestEntity.class));
+
+        observedGroup = app.createAndManageChild(EntitySpec.create(BasicGroup.class));
+        observedMemberEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+        observedGroup.addMember(observedMemberEntity);
+        
+        otherEntity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+        
+        listener = new RecordingSensorEventListener<>();
+        
+        app.start(ImmutableList.of(loc));
+    }
+    
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() {
+        if (app != null) Entities.destroyAll(app.getManagementContext());
+    }
+    
+    @Test
+    public void testSubscriptionReceivesEvents() {
+        loc.subscriptions().subscribe(observedEntity, TestEntity.SEQUENCE, listener);
+        loc.subscriptions().subscribe(observedEntity, TestEntity.NAME, listener);
+        loc.subscriptions().subscribe(observedEntity, TestEntity.MY_NOTIF, listener);
+        
+        otherEntity.sensors().set(TestEntity.SEQUENCE, 123);
+        observedEntity.sensors().set(TestEntity.SEQUENCE, 123);
+        observedEntity.sensors().set(TestEntity.NAME, "myname");
+        observedEntity.sensors().emit(TestEntity.MY_NOTIF, 456);
+        
+        Asserts.succeedsEventually(new Runnable() {
+            @Override public void run() {
+                assertEquals(listener.getEvents(), ImmutableList.of(
+                        new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, observedEntity, 123),
+                        new BasicSensorEvent<String>(TestEntity.NAME, observedEntity, "myname"),
+                        new BasicSensorEvent<Integer>(TestEntity.MY_NOTIF, observedEntity, 456)));
+            }});
+    }
+    
+    @Test
+    public void testSubscriptionToAllReceivesEvents() {
+        loc.subscriptions().subscribe(null, TestEntity.SEQUENCE, listener);
+        
+        observedEntity.sensors().set(TestEntity.SEQUENCE, 123);
+        otherEntity.sensors().set(TestEntity.SEQUENCE, 456);
+        
+        Asserts.succeedsEventually(new Runnable() {
+            @Override public void run() {
+                assertEquals(listener.getEvents(), ImmutableList.of(
+                        new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, observedEntity, 123),
+                        new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, otherEntity, 456)));
+            }});
+    }
+    
+    @Test
+    public void testSubscribeToChildrenReceivesEvents() {
+        loc.subscriptions().subscribeToChildren(observedEntity, TestEntity.SEQUENCE, listener);
+        
+        observedChildEntity.sensors().set(TestEntity.SEQUENCE, 123);
+        observedEntity.sensors().set(TestEntity.SEQUENCE, 456);
+        
+        Asserts.succeedsEventually(new Runnable() {
+            @Override public void run() {
+                assertEquals(listener.getEvents(), ImmutableList.of(
+                        new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, observedChildEntity, 123)));
+            }});
+    }
+    
+    @Test
+    public void testSubscribeToChildrenReceivesEventsForDynamicallyAddedChildren() {
+        loc.subscriptions().subscribeToChildren(observedEntity, TestEntity.SEQUENCE, listener);
+        
+        final TestEntity observedChildEntity2 = observedEntity.createAndManageChild(EntitySpec.create(TestEntity.class));
+        observedChildEntity2.sensors().set(TestEntity.SEQUENCE, 123);
+        
+        Asserts.succeedsEventually(new Runnable() {
+            @Override public void run() {
+                assertEquals(listener.getEvents(), ImmutableList.of(
+                        new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, observedChildEntity2, 123)));
+            }});
+    }
+    
+    @Test
+    public void testSubscribeToMembersReceivesEvents() {
+        loc.subscriptions().subscribeToMembers(observedGroup, TestEntity.SEQUENCE, listener);
+        
+        observedMemberEntity.sensors().set(TestEntity.SEQUENCE, 123);
+        observedGroup.sensors().set(TestEntity.SEQUENCE, 456);
+        
+        Asserts.succeedsEventually(new Runnable() {
+            @Override public void run() {
+                assertEquals(listener.getEvents(), ImmutableList.of(
+                        new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, observedMemberEntity, 123)));
+            }});
+    }
+    
+    @Test
+    public void testSubscribeToMembersReceivesEventsForDynamicallyAddedMembers() {
+        loc.subscriptions().subscribeToMembers(observedGroup, TestEntity.SEQUENCE, listener);
+        
+        final TestEntity observedMemberEntity2 = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+        observedGroup.addMember(observedMemberEntity2);
+        observedMemberEntity2.sensors().set(TestEntity.SEQUENCE, 123);
+        
+        Asserts.succeedsEventually(new Runnable() {
+            @Override public void run() {
+                assertEquals(listener.getEvents(), ImmutableList.of(
+                        new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, observedMemberEntity2, 123)));
+            }});
+    }
+    
+    @Test(groups="Integration")
+    public void testSubscribeToMembersIgnoresEventsForDynamicallyRemovedMembers() {
+        loc.subscriptions().subscribeToMembers(observedGroup, TestEntity.SEQUENCE, listener);
+        
+        observedGroup.removeMember(observedMemberEntity);
+        
+        observedMemberEntity.sensors().set(TestEntity.SEQUENCE, 123);
+        
+        Asserts.succeedsEventually(new Runnable() {
+            @Override public void run() {
+                assertEquals(listener.getEvents(), ImmutableList.of());
+            }});
+    }
+    
+    @Test
+    public void testUnsubscribeRemovesAllSubscriptionsForThatEntity() {
+        loc.subscriptions().subscribe(observedEntity, TestEntity.SEQUENCE, listener);
+        loc.subscriptions().subscribe(observedEntity, TestEntity.NAME, listener);
+        loc.subscriptions().subscribe(observedEntity, TestEntity.MY_NOTIF, listener);
+        loc.subscriptions().subscribe(otherEntity, TestEntity.SEQUENCE, listener);
+        loc.subscriptions().unsubscribe(observedEntity);
+        
+        observedEntity.sensors().set(TestEntity.SEQUENCE, 123);
+        observedEntity.sensors().set(TestEntity.NAME, "myname");
+        observedEntity.sensors().emit(TestEntity.MY_NOTIF, 123);
+        otherEntity.sensors().set(TestEntity.SEQUENCE, 456);
+        
+        Asserts.succeedsEventually(new Runnable() {
+            @Override public void run() {
+                assertEquals(listener.getEvents(), ImmutableList.of(
+                        new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, otherEntity, 456)));
+            }});
+    }
+    
+    @Test
+    public void testUnsubscribeUsingHandleStopsEvents() {
+        SubscriptionHandle handle1 = loc.subscriptions().subscribe(observedEntity, TestEntity.SEQUENCE, listener);
+        SubscriptionHandle handle2 = loc.subscriptions().subscribe(observedEntity, TestEntity.NAME, listener);
+        SubscriptionHandle handle3 = loc.subscriptions().subscribe(otherEntity, TestEntity.SEQUENCE, listener);
+        
+        loc.subscriptions().unsubscribe(observedEntity, handle2);
+        
+        observedEntity.sensors().set(TestEntity.SEQUENCE, 123);
+        observedEntity.sensors().set(TestEntity.NAME, "myname");
+        otherEntity.sensors().set(TestEntity.SEQUENCE, 456);
+        
+        Asserts.succeedsEventually(new Runnable() {
+            @Override public void run() {
+                assertEquals(listener.getEvents(), ImmutableList.of(
+                        new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, observedEntity, 123),
+                        new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, otherEntity, 456)));
+            }});
+    }
+    
+    @Test
+    public void testSubscriptionReceivesEventsInOrder() {
+        final int NUM_EVENTS = 100;
+        loc.subscriptions().subscribe(observedEntity, TestEntity.MY_NOTIF, listener);
+
+        for (int i = 0; i < NUM_EVENTS; i++) {
+            observedEntity.sensors().emit(TestEntity.MY_NOTIF, i);
+        }
+        
+        Asserts.succeedsEventually(new Runnable() {
+            @Override public void run() {
+                assertEquals(Iterables.size(listener.getEvents()), NUM_EVENTS);
+                for (int i = 0; i < NUM_EVENTS; i++) {
+                    assertEquals(Iterables.get(listener.getEvents(), i).getValue(), i);
+                }
+            }});
+    }
+
+}


[10/10] incubator-brooklyn git commit: This closes #911

Posted by al...@apache.org.
This closes #911


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

Branch: refs/heads/master
Commit: f34f0433bd945dd09f054639b6e3ba00dbefa0b9
Parents: 93f6f0f a63b8cf
Author: Aled Sage <al...@gmail.com>
Authored: Wed Sep 23 11:51:39 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Sep 23 11:51:39 2015 +0100

----------------------------------------------------------------------
 .../brooklyn/api/catalog/CatalogItem.java       |  12 +
 .../org/apache/brooklyn/api/entity/Entity.java  | 124 ++++-
 .../apache/brooklyn/api/entity/EntityLocal.java |  45 +-
 .../brooklyn/api/mgmt/ManagementContext.java    |   9 +
 .../brooklyn/api/objs/BrooklynObject.java       |  73 ++-
 .../core/catalog/internal/CatalogItemDo.java    |  11 +-
 .../internal/CatalogItemDtoAbstract.java        |  14 +-
 .../brooklyn/core/entity/AbstractEntity.java    | 504 ++++++++++++++-----
 .../brooklyn/core/entity/EntityInternal.java    |  60 ++-
 .../core/location/AbstractLocation.java         |  84 +++-
 .../access/PortForwardManagerClient.java        |   5 +
 .../internal/AbstractManagementContext.java     |  11 +-
 .../mgmt/internal/BasicSubscriptionContext.java |   3 +-
 .../NonDeploymentManagementContext.java         |   7 +
 .../core/mgmt/internal/SubscriptionTracker.java |  16 +
 .../core/objs/AbstractEntityAdjunct.java        | 177 +++++--
 .../core/objs/BrooklynObjectInternal.java       |   9 +
 .../core/sensor/DependentConfiguration.java     |   8 +-
 .../brooklyn/enricher/stock/UpdatingMap.java    |   2 +-
 .../core/entity/EntitySubscriptionTest.java     |  12 +-
 .../brooklyn/core/entity/EntityTypeTest.java    |   4 +-
 .../core/entity/hello/LocalEntitiesTest.java    |   8 +-
 .../core/location/LocationSubscriptionTest.java | 241 +++++++++
 .../policy/basic/PolicySubscriptionTest.java    |   4 +-
 .../core/test/entity/TestApplicationImpl.java   |   2 +-
 .../software/base/SoftwareProcessImpl.java      |   4 +-
 .../entity/proxy/nginx/UrlMappingImpl.java      |   4 +-
 .../AbstractWebAppFixtureIntegrationTest.java   |   5 +-
 .../brooklyn/rest/resources/EntityResource.java |   2 +-
 29 files changed, 1234 insertions(+), 226 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f34f0433/software/base/src/main/java/org/apache/brooklyn/entity/software/base/SoftwareProcessImpl.java
----------------------------------------------------------------------


[04/10] incubator-brooklyn git commit: Deleted EntityInternal.getSubscriptionContext

Posted by al...@apache.org.
Deleted EntityInternal.getSubscriptionContext

- Added Entity.subscriptions().unsubscribe(handle)
- Added EntityInternal.subscriptions().unsubscribeAll()


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/2b29795b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/2b29795b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/2b29795b

Branch: refs/heads/master
Commit: 2b29795b6ef9c37cb14242ccc28249b16a708c68
Parents: e48bdaa
Author: Aled Sage <al...@gmail.com>
Authored: Mon Sep 21 09:22:24 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Sep 23 10:32:56 2015 +0100

----------------------------------------------------------------------
 .../org/apache/brooklyn/api/entity/Entity.java  |  9 +++++++
 .../brooklyn/core/entity/AbstractEntity.java    | 28 ++++++++++++--------
 .../brooklyn/core/entity/EntityInternal.java    | 14 +---------
 .../core/mgmt/internal/SubscriptionTracker.java | 16 +++++++++++
 .../core/sensor/DependentConfiguration.java     |  8 +++---
 .../brooklyn/core/entity/EntityTypeTest.java    |  4 +--
 .../core/entity/hello/LocalEntitiesTest.java    |  8 +++---
 .../core/test/entity/TestApplicationImpl.java   |  2 +-
 .../entity/proxy/nginx/UrlMappingImpl.java      |  4 +--
 .../AbstractWebAppFixtureIntegrationTest.java   |  5 ++--
 10 files changed, 58 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2b29795b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
index 4df913b..795218c 100644
--- a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
+++ b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
@@ -391,6 +391,15 @@ public interface Entity extends BrooklynObject {
          */
         @Beta
         boolean unsubscribe(Entity producer, SubscriptionHandle handle);
+        
+        /**
+         * Unsubscribes the given handle.
+         * 
+         * It is (currently) more efficient to also pass in the producer -
+         * see {@link BasicSubscriptionSupport#unsubscribe(Entity, SubscriptionHandle)} 
+         */
+        @Beta
+        boolean unsubscribe(SubscriptionHandle handle);
     }
 
     @Beta

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2b29795b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
index 13079d3..48a07a4 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
@@ -1069,7 +1069,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
             if (getManagementSupport().isNoLongerManaged())
                 throw new IllegalStateException("Entity "+AbstractEntity.this+" is no longer managed, when trying to publish "+sensor+" "+val);
 
-            SubscriptionContext subsContext = getSubscriptionContext();
+            SubscriptionContext subsContext = subscriptions().getSubscriptionContext();
             if (subsContext != null) subsContext.publish(sensor.newEvent(getProxyIfAvailable(), val));
         }
     }
@@ -1390,8 +1390,23 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
             return getSubscriptionTracker().unsubscribe(producer, handle);
         }
 
+        /**
+         * Unsubscribes the given handle.
+         * 
+         * It is (currently) more efficient to also pass in the producer -
+         * see {@link BasicSubscriptionSupport#unsubscribe(Entity, SubscriptionHandle)} 
+         */
         @Override
-        public SubscriptionContext getSubscriptionContext() {
+        public boolean unsubscribe(SubscriptionHandle handle) {
+            return getSubscriptionTracker().unsubscribe(handle);
+        }
+
+        @Override
+        public void unsubscribeAll() {
+            getSubscriptionTracker().unsubscribeAll();
+        }
+        
+        protected SubscriptionContext getSubscriptionContext() {
             synchronized (AbstractEntity.this) {
                 return getManagementSupport().getSubscriptionContext();
             }
@@ -1460,15 +1475,6 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     }
 
     /**
-     * @deprecated since 0.9.0; see {@code subscriptions().getSubscriptionContext()}
-     */
-    @Override
-    @Deprecated
-    public synchronized SubscriptionContext getSubscriptionContext() {
-        return subscriptions().getSubscriptionContext();
-    }
-
-    /**
      * @deprecated since 0.9.0; for internal use only
      */
     @Deprecated

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2b29795b/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java b/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
index 04fa88b..4fa9c67 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
@@ -24,25 +24,19 @@ import java.util.Map;
 import org.apache.brooklyn.api.effector.Effector;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntityLocal;
-import org.apache.brooklyn.api.entity.Entity.SensorSupport;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.mgmt.ExecutionContext;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
-import org.apache.brooklyn.api.mgmt.SubscriptionContext;
 import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
 import org.apache.brooklyn.api.mgmt.rebind.Rebindable;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.EntityMemento;
-import org.apache.brooklyn.api.objs.Configurable;
 import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.api.sensor.Feed;
 import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
 import org.apache.brooklyn.core.entity.internal.EntityConfigMap;
 import org.apache.brooklyn.core.mgmt.internal.EntityManagementSupport;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
-import org.apache.brooklyn.core.objs.BrooklynObjectInternal.ConfigurationSupportInternal;
 import org.apache.brooklyn.util.core.config.ConfigBag;
-import org.apache.brooklyn.util.guava.Maybe;
 
 import com.google.common.annotations.Beta;
 
@@ -152,12 +146,6 @@ public interface EntityInternal extends BrooklynObjectInternal, EntityLocal, Reb
      */    
     ExecutionContext getExecutionContext();
 
-    /**
-     * @deprecated since 0.9.0; see {@link SubscriptionSupportInternal#getSubscriptionContext()}, e.g. with {@code subscriptions().getSubscriptionContext()}
-     */
-    @Deprecated
-    SubscriptionContext getSubscriptionContext();
-    
     /** returns the dynamic type corresponding to the type of this entity instance */
     @Beta
     EntityDynamicType getMutableEntityType();
@@ -243,7 +231,7 @@ public interface EntityInternal extends BrooklynObjectInternal, EntityLocal, Reb
     
     @Beta
     public interface SubscriptionSupportInternal extends Entity.SubscriptionSupport {
-        SubscriptionContext getSubscriptionContext();
+        public void unsubscribeAll();
     }
     
     @Beta

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2b29795b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/SubscriptionTracker.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/SubscriptionTracker.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/SubscriptionTracker.java
index 3d5793c..bafa150 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/SubscriptionTracker.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/SubscriptionTracker.java
@@ -27,6 +27,7 @@ import org.apache.brooklyn.api.mgmt.SubscriptionContext;
 import org.apache.brooklyn.api.mgmt.SubscriptionHandle;
 import org.apache.brooklyn.api.sensor.Sensor;
 import org.apache.brooklyn.api.sensor.SensorEventListener;
+import org.apache.brooklyn.core.entity.AbstractEntity.BasicSubscriptionSupport;
 
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.ImmutableList;
@@ -121,6 +122,21 @@ public class SubscriptionTracker {
        return context.unsubscribe(handle);
    }
 
+   /**
+   * Unsubscribes the given handle.
+   * 
+   * It is (currently) more efficient to also pass in the producer -
+   * see {@link BasicSubscriptionSupport#unsubscribe(Entity, SubscriptionHandle)}
+   *
+   * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+   */
+  public boolean unsubscribe(SubscriptionHandle handle) {
+      synchronized (subscriptions) {
+          subscriptions.values().remove(handle);
+      }
+      return context.unsubscribe(handle);
+  }
+
     /**
     * @return an ordered list of all subscription handles
     */

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2b29795b/core/src/main/java/org/apache/brooklyn/core/sensor/DependentConfiguration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/sensor/DependentConfiguration.java b/core/src/main/java/org/apache/brooklyn/core/sensor/DependentConfiguration.java
index 01e3426..ddca05c 100644
--- a/core/src/main/java/org/apache/brooklyn/core/sensor/DependentConfiguration.java
+++ b/core/src/main/java/org/apache/brooklyn/core/sensor/DependentConfiguration.java
@@ -274,13 +274,13 @@ public class DependentConfiguration {
             List<SubscriptionHandle> abortSubscriptions = Lists.newArrayList();
             
             try {
-                subscription = ((EntityInternal)entity).getSubscriptionContext().subscribe(source, sensor, new SensorEventListener<T>() {
+                subscription = entity.subscriptions().subscribe(source, sensor, new SensorEventListener<T>() {
                     @Override public void onEvent(SensorEvent<T> event) {
                         synchronized (publishedValues) { publishedValues.add(event.getValue()); }
                         semaphore.release();
                     }});
                 for (final AttributeAndSensorCondition abortCondition : abortSensorConditions) {
-                    abortSubscriptions.add(((EntityInternal)entity).getSubscriptionContext().subscribe(abortCondition.source, abortCondition.sensor, new SensorEventListener<Object>() {
+                    abortSubscriptions.add(entity.subscriptions().subscribe(abortCondition.source, abortCondition.sensor, new SensorEventListener<Object>() {
                         @Override public void onEvent(SensorEvent<Object> event) {
                             if (abortCondition.predicate.apply(event.getValue())) {
                                 abortionExceptions.add(new Exception("Abort due to "+abortCondition.source+" -> "+abortCondition.sensor));
@@ -354,10 +354,10 @@ public class DependentConfiguration {
                 throw Exceptions.propagate(e);
             } finally {
                 if (subscription != null) {
-                    ((EntityInternal)entity).getSubscriptionContext().unsubscribe(subscription);
+                    entity.subscriptions().unsubscribe(subscription);
                 }
                 for (SubscriptionHandle handle : abortSubscriptions) {
-                    ((EntityInternal)entity).getSubscriptionContext().unsubscribe(handle);
+                    entity.subscriptions().unsubscribe(handle);
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2b29795b/core/src/test/java/org/apache/brooklyn/core/entity/EntityTypeTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/EntityTypeTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/EntityTypeTest.java
index 5851c35..130327f 100644
--- a/core/src/test/java/org/apache/brooklyn/core/entity/EntityTypeTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/EntityTypeTest.java
@@ -87,8 +87,8 @@ public class EntityTypeTest extends BrooklynAppUnitTestSupport {
         super.setUp();
         entity = (EntityInternal) app.createAndManageChild(EntitySpec.create(Entity.class, EmptyEntityForTesting.class));
         listener = new RecordingSensorEventListener<>();
-        app.getSubscriptionContext().subscribe(entity, SENSOR_ADDED, listener);
-        app.getSubscriptionContext().subscribe(entity, SENSOR_REMOVED, listener);
+        app.subscriptions().subscribe(entity, SENSOR_ADDED, listener);
+        app.subscriptions().subscribe(entity, SENSOR_REMOVED, listener);
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2b29795b/core/src/test/java/org/apache/brooklyn/core/entity/hello/LocalEntitiesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/hello/LocalEntitiesTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/hello/LocalEntitiesTest.java
index 28ee8c1..6d64d2b 100644
--- a/core/src/test/java/org/apache/brooklyn/core/entity/hello/LocalEntitiesTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/hello/LocalEntitiesTest.java
@@ -94,7 +94,7 @@ public class LocalEntitiesTest extends BrooklynAppUnitTestSupport {
         final AtomicReference<SensorEvent<?>> evt = new AtomicReference<SensorEvent<?>>();
         final CountDownLatch latch = new CountDownLatch(1);
         
-        app.getSubscriptionContext().subscribe(h, HelloEntity.AGE, new SensorEventListener<Integer>() {
+        app.subscriptions().subscribe(h, HelloEntity.AGE, new SensorEventListener<Integer>() {
             @Override public void onEvent(SensorEvent<Integer> event) {
                 evt.set(event);
                 latch.countDown();
@@ -121,7 +121,7 @@ public class LocalEntitiesTest extends BrooklynAppUnitTestSupport {
         app.start(ImmutableList.of(loc));
         
         final AtomicReference<SensorEvent<?>> evt = new AtomicReference<SensorEvent<?>>();
-        app.getSubscriptionContext().subscribe(h, HelloEntity.ITS_MY_BIRTHDAY, new SensorEventListener<Object>() {
+        app.subscriptions().subscribe(h, HelloEntity.ITS_MY_BIRTHDAY, new SensorEventListener<Object>() {
             @Override public void onEvent(SensorEvent<Object> event) {
                 evt.set(event);
                 synchronized (evt) {
@@ -149,7 +149,7 @@ public class LocalEntitiesTest extends BrooklynAppUnitTestSupport {
         final List<Integer> data = Lists.newArrayList();
         final CountDownLatch latch = new CountDownLatch(5);
         
-        app.getSubscriptionContext().subscribe(h, HelloEntity.AGE, new SensorEventListener<Integer>() {
+        app.subscriptions().subscribe(h, HelloEntity.AGE, new SensorEventListener<Integer>() {
             @Override public void onEvent(SensorEvent<Integer> event) {
                 data.add(event.getValue());
                 Time.sleep((int)(20*Math.random()));
@@ -163,7 +163,7 @@ public class LocalEntitiesTest extends BrooklynAppUnitTestSupport {
         }
         assertTrue(latch.await(5000, TimeUnit.MILLISECONDS));
 
-        app.getSubscriptionContext().unsubscribeAll();
+        app.subscriptions().unsubscribeAll();
         h.setAge(6);
         long totalTime = stopwatch.elapsed(TimeUnit.MILLISECONDS);
         

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2b29795b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestApplicationImpl.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/entity/TestApplicationImpl.java b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestApplicationImpl.java
index 47faafd..7ce08d3 100644
--- a/core/src/test/java/org/apache/brooklyn/core/test/entity/TestApplicationImpl.java
+++ b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestApplicationImpl.java
@@ -63,7 +63,7 @@ public class TestApplicationImpl extends AbstractApplication implements TestAppl
     
     @Override
     public <T> SubscriptionHandle subscribeToMembers(Group parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
-        return getSubscriptionContext().subscribeToMembers(parent, sensor, listener);
+        return subscriptions().subscribeToMembers(parent, sensor, listener);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2b29795b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/UrlMappingImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/UrlMappingImpl.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/UrlMappingImpl.java
index 98d0de2..121219a 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/UrlMappingImpl.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/UrlMappingImpl.java
@@ -184,8 +184,8 @@ public class UrlMappingImpl extends AbstractGroupImpl implements UrlMapping {
 
     @Override
     public synchronized void recompute() {
-        if (subscriptionHandle != null) getSubscriptionContext().unsubscribe(subscriptionHandle);
-        if (subscriptionHandle2 != null) getSubscriptionContext().unsubscribe(subscriptionHandle2);
+        if (subscriptionHandle != null) subscriptions().unsubscribe(subscriptionHandle);
+        if (subscriptionHandle2 != null) subscriptions().unsubscribe(subscriptionHandle2);
 
         Entity t = getTarget();
         if (t != null) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2b29795b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java
index 7a66c87..9c77b45 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/AbstractWebAppFixtureIntegrationTest.java
@@ -369,11 +369,10 @@ public abstract class AbstractWebAppFixtureIntegrationTest {
         Entities.start(entity.getApplication(), ImmutableList.of(loc));
         
         SubscriptionHandle subscriptionHandle = null;
-        SubscriptionContext subContext = ((EntityInternal)entity).getSubscriptionContext();
 
         try {
             final List<SensorEvent> events = new CopyOnWriteArrayList<SensorEvent>();
-            subscriptionHandle = subContext.subscribe(entity, WebAppService.REQUESTS_PER_SECOND_IN_WINDOW, new SensorEventListener<Double>() {
+            subscriptionHandle = entity.subscriptions().subscribe(entity, WebAppService.REQUESTS_PER_SECOND_IN_WINDOW, new SensorEventListener<Double>() {
                 public void onEvent(SensorEvent<Double> event) {
                     log.info("publishesRequestsPerSecondMetricRepeatedly.onEvent: {}", event);
                     events.add(event);
@@ -395,7 +394,7 @@ public abstract class AbstractWebAppFixtureIntegrationTest {
                     }
                 }});
         } finally {
-            if (subscriptionHandle != null) subContext.unsubscribe(subscriptionHandle);
+            if (subscriptionHandle != null) entity.subscriptions().unsubscribe(subscriptionHandle);
             entity.stop();
         }
     }


[09/10] incubator-brooklyn git commit: entity.policies() etc returns an Iterable

Posted by al...@apache.org.
entity.policies() etc returns an Iterable

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

Branch: refs/heads/master
Commit: a63b8cf13ed62decb136bccd20eb35df706d5046
Parents: ebe942b
Author: Aled Sage <al...@gmail.com>
Authored: Wed Sep 23 11:10:04 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Sep 23 11:10:04 2015 +0100

----------------------------------------------------------------------
 .../org/apache/brooklyn/api/entity/Entity.java  | 89 ++++++++++----------
 .../brooklyn/core/entity/AbstractEntity.java    | 40 ++++++---
 .../brooklyn/core/entity/EntityInternal.java    | 22 +++++
 3 files changed, 92 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a63b8cf1/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
index 32f9c00..eb9f907 100644
--- a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
+++ b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
@@ -19,17 +19,16 @@
 package org.apache.brooklyn.api.entity;
 
 import java.util.Collection;
+import java.util.Iterator;
 import java.util.Map;
 
 import javax.annotation.Nullable;
 
 import org.apache.brooklyn.api.effector.Effector;
 import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.mgmt.SubscriptionContext;
-import org.apache.brooklyn.api.mgmt.SubscriptionHandle;
-import org.apache.brooklyn.api.mgmt.SubscriptionManager;
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.api.objs.EntityAdjunct;
 import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.api.policy.PolicySpec;
 import org.apache.brooklyn.api.sensor.AttributeSensor;
@@ -38,7 +37,6 @@ import org.apache.brooklyn.api.sensor.EnricherSpec;
 import org.apache.brooklyn.api.sensor.Feed;
 import org.apache.brooklyn.api.sensor.Sensor;
 import org.apache.brooklyn.api.sensor.SensorEvent;
-import org.apache.brooklyn.api.sensor.SensorEventListener;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
 import org.apache.brooklyn.util.guava.Maybe;
@@ -362,79 +360,80 @@ public interface Entity extends BrooklynObject {
         <T> void emit(Sensor<T> sensor, T value);
     }
     
-    @Beta
-    public interface PolicySupport {
+    public interface AdjunctSupport<T extends EntityAdjunct> extends Iterable<T> {
         /**
-         * @return an immutable thread-safe view of the policies.
+         * @return A read-only thread-safe iterator over all the instances.
          */
-        Collection<Policy> getPolicies();
+        Iterator<T> iterator();
         
         /**
-         * Adds the given policy to this entity. Also calls policy.setEntity if available.
+         * Adds an instance.
          */
-        void add(Policy policy);
+        void add(T val);
         
         /**
+         * Removes an instance.
+         */
+        boolean remove(T val);
+    }
+    
+    @Beta
+    public interface PolicySupport extends AdjunctSupport<Policy> {
+        /**
          * Adds the given policy to this entity. Also calls policy.setEntity if available.
          */
-        <T extends Policy> T add(PolicySpec<T> enricher);
+        @Override
+        void add(Policy policy);
         
         /**
          * Removes the given policy from this entity. 
          * @return True if the policy existed at this entity; false otherwise
          */
+        @Override
         boolean remove(Policy policy);
+        
+        /**
+         * Adds the given policy to this entity. Also calls policy.setEntity if available.
+         */
+        <T extends Policy> T add(PolicySpec<T> enricher);
     }
     
     @Beta
-    public interface EnricherSupport {
-        /**
-         * @return an immutable thread-safe view of the enrichers.
-         */
-        Collection<Enricher> getEnrichers();
-        
+    public interface EnricherSupport extends AdjunctSupport<Enricher> {
         /**
          * Adds the given enricher to this entity. Also calls enricher.setEntity if available.
          */
+        @Override
         void add(Enricher enricher);
         
         /**
-         * Adds the given enricher to this entity. Also calls enricher.setEntity if available.
-         */
-        <T extends Enricher> T add(EnricherSpec<T> enricher);
-        
-        /**
          * Removes the given enricher from this entity. 
          * @return True if the policy enricher at this entity; false otherwise
          */
+        @Override
         boolean remove(Enricher enricher);
-    }
-    
-    @Beta
-    public interface GroupSupport {
-        /**
-         * The {@link Collection} of {@link Group}s that this entity is a member of.
-         *
-         * Groupings can be used to allow easy management/monitoring of a group of entities.
-         */
-        Collection<Group> getGroups();
-
+        
         /**
-         * Add this entity as a member of the given {@link Group}. Called by framework.
-         * <p>
-         * Users should call {@link Group#addMember(Entity)} instead; this method will then 
-         * automatically be called. However, the reverse is not true (calling this method will 
-         * not tell the group; this behaviour may change in a future release!)
+         * Adds the given enricher to this entity. Also calls enricher.setEntity if available.
          */
-        void add(Group group);
+        <T extends Enricher> T add(EnricherSpec<T> enricher);
+    }
 
+    /**
+     * For managing/querying the group membership of this entity. 
+     * 
+     * Groupings can be used to allow easy management/monitoring of a group of entities.
+     * 
+     * To add/remove this entity from a group, users should call {@link Group#addMember(Entity)} 
+     * and {@link Group#removeMember(Entity)}. In a future release, add/remove methods may be
+     * added here.
+     */
+    @Beta
+    public interface GroupSupport extends Iterable<Group> {
         /**
-         * Removes this entity as a member of the given {@link Group}. Called by framework.
-         * <p>
-         * Users should call {@link Group#removeMember(Entity)} instead; this method will then 
-         * automatically be called. However, the reverse is not true (calling this method will 
-         * not tell the group; this behaviour may change in a future release!)
+         * A read-only thread-safe iterator over all the {@link Group}s that this entity is a member of.
          */
-        void remove(Group group);
+        @Override
+        Iterator<Group> iterator();
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a63b8cf1/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
index 08b25f2..e432717 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
@@ -705,7 +705,16 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
      */
     @Beta
     // TODO revert to private when groups() is reverted to return GroupSupport
-    public class BasicGroupSupport implements GroupSupport {
+    public class BasicGroupSupport implements GroupSupportInternal {
+        @Override
+        public Iterator<Group> iterator() { 
+            return asList().iterator();
+        }
+        
+        protected List<Group> asList() { 
+            return ImmutableList.copyOf(groupsInternal);
+        }
+        
         @Override
         public void add(Group group) {
             boolean changed = groupsInternal.add(group);
@@ -725,11 +734,6 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
                 emit(AbstractEntity.GROUP_REMOVED, group);
             }
         }
-        
-        @Override
-        public Collection<Group> getGroups() { 
-            return ImmutableList.copyOf(groupsInternal);
-        }
     }
     
     /**
@@ -751,12 +755,12 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     }
 
     /**
-     * @deprecated since 0.9.0; see {@link #groups()} and {@link GroupSupport#getGroups()}
+     * @deprecated since 0.9.0; see {@link #groups()} and {@link GroupSupport#iterator()}
      */
     @Override
     @Deprecated
     public Collection<Group> getGroups() { 
-        return groups().getGroups();
+        return groups().asList();
     }
     
     @Override
@@ -1607,7 +1611,11 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     public class BasicPolicySupport implements PolicySupportInternal {
         
         @Override
-        public Collection<Policy> getPolicies() {
+        public Iterator<Policy> iterator() {
+            return asList().iterator();
+        }
+
+        protected List<Policy> asList() {
             return ImmutableList.<Policy>copyOf(policiesInternal);
         }
 
@@ -1666,7 +1674,11 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     // TODO revert to private when config() is reverted to return SensorSupportInternal
     public class BasicEnricherSupport implements EnricherSupportInternal {
         @Override
-        public Collection<Enricher> getEnrichers() {
+        public Iterator<Enricher> iterator() {
+            return asList().iterator();
+        }
+
+        protected List<Enricher> asList() {
             return ImmutableList.<Enricher>copyOf(enrichersInternal);
         }
 
@@ -1716,12 +1728,12 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     }
     
     /**
-     * @deprecated since 0.9.0; see {@link BasicPolicySupport#getPolicies()}; e.g. {@code policies().getPolicies()}
+     * @deprecated since 0.9.0; see {@link BasicPolicySupport#iterator()}; e.g. {@code policies().iterator()}
      */
     @Override
     @Deprecated
     public Collection<Policy> getPolicies() {
-        return policies().getPolicies();
+        return policies().asList();
     }
 
     /**
@@ -1770,12 +1782,12 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     }
     
     /**
-     * @deprecated since 0.9.0; see {@link BasicEnricherSupport#getEnrichers()}; e.g. {@code enrichers().getEnrichers()}
+     * @deprecated since 0.9.0; see {@link BasicEnricherSupport#iterator()}; e.g. {@code enrichers().iterator()}
      */
     @Override
     @Deprecated
     public Collection<Enricher> getEnrichers() {
-        return enrichers().getEnrichers();
+        return enrichers().asList();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a63b8cf1/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java b/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
index c0eca7e..27b09a4 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
@@ -24,6 +24,7 @@ import java.util.Map;
 import org.apache.brooklyn.api.effector.Effector;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntityLocal;
+import org.apache.brooklyn.api.entity.Group;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.mgmt.ExecutionContext;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
@@ -244,4 +245,25 @@ public interface EntityInternal extends BrooklynObjectInternal, EntityLocal, Reb
          */
         boolean removeAll();
     }
+    
+    @Beta
+    public interface GroupSupportInternal extends Entity.GroupSupport {
+        /**
+         * Add this entity as a member of the given {@link Group}. Called by framework.
+         * <p>
+         * Users should call {@link Group#addMember(Entity)} instead; this method will then 
+         * automatically be called. However, the reverse is not true (calling this method will 
+         * not tell the group; this behaviour may change in a future release!)
+         */
+        void add(Group group);
+
+        /**
+         * Removes this entity as a member of the given {@link Group}. Called by framework.
+         * <p>
+         * Users should call {@link Group#removeMember(Entity)} instead; this method will then 
+         * automatically be called. However, the reverse is not true (calling this method will 
+         * not tell the group; this behaviour may change in a future release!)
+         */
+        void remove(Group group);
+    }
 }


[02/10] incubator-brooklyn git commit: Create entity.enrichers() and entity.policies()

Posted by al...@apache.org.
Create entity.enrichers() and entity.policies()

- deprecate methods Entity.*enricher*() and Entity.*policy*(),
  instead to use those on EnricherSupport / PolicySupport.
- added to EntityInternal.enrichers()/policies() the methods
  removeAllEnrichers() and removeAllPolicies().
- deprecate those last methods of EntityLocal
- deprecate EntityLocal


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

Branch: refs/heads/master
Commit: e48bdaa73ab7cd85ac3b1aa42b6f1637c6dab0f9
Parents: 3e46621
Author: Aled Sage <al...@gmail.com>
Authored: Mon Sep 21 08:51:18 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Sep 23 10:32:55 2015 +0100

----------------------------------------------------------------------
 .../org/apache/brooklyn/api/entity/Entity.java  |  78 +++++-
 .../apache/brooklyn/api/entity/EntityLocal.java |   8 +
 .../brooklyn/core/entity/AbstractEntity.java    | 255 ++++++++++++++-----
 .../brooklyn/core/entity/EntityInternal.java    |  27 ++
 4 files changed, 305 insertions(+), 63 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e48bdaa7/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
index 8388d28..4df913b 100644
--- a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
+++ b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
@@ -160,12 +160,18 @@ public interface Entity extends BrooklynObject {
     
     /**
      * @return an immutable thread-safe view of the policies.
+     * 
+     * @deprecated since 0.9.0; see {@link PolicySupport#getPolicies()}
      */
+    @Deprecated
     Collection<Policy> getPolicies();
     
     /**
      * @return an immutable thread-safe view of the enrichers.
+     * 
+     * @deprecated since 0.9.0; see {@link EnricherSupport#getEnrichers()}
      */
+    @Deprecated
     Collection<Enricher> getEnrichers();
     
     /**
@@ -240,34 +246,52 @@ public interface Entity extends BrooklynObject {
     
     /**
      * Adds the given policy to this entity. Also calls policy.setEntity if available.
+     * 
+     * @deprecated since 0.9.0; see {@link PolicySupport#addPolicy(Policy)}
      */
+    @Deprecated
     void addPolicy(Policy policy);
     
     /**
      * Adds the given policy to this entity. Also calls policy.setEntity if available.
+     * 
+     * @deprecated since 0.9.0; see {@link PolicySupport#addPolicy(PolicySpec)}
      */
+    @Deprecated
     <T extends Policy> T addPolicy(PolicySpec<T> enricher);
     
     /**
      * Removes the given policy from this entity. 
      * @return True if the policy existed at this entity; false otherwise
+     * 
+     * @deprecated since 0.9.0; see {@link PolicySupport#removePolicy(Policy)}
      */
+    @Deprecated
     boolean removePolicy(Policy policy);
     
     /**
      * Adds the given enricher to this entity. Also calls enricher.setEntity if available.
+     * 
+     * @deprecated since 0.9.0; see {@link EnricherSupport#addEnricher(Enricher)}
      */
+    @Deprecated
     void addEnricher(Enricher enricher);
     
     /**
      * Adds the given enricher to this entity. Also calls enricher.setEntity if available.
+     * 
+     * @deprecated since 0.9.0; see {@link EnricherSupport#addEnricher(EnricherSpec)}
      */
+    @Deprecated
     <T extends Enricher> T addEnricher(EnricherSpec<T> enricher);
     
     /**
      * Removes the given enricher from this entity. 
      * @return True if the policy enricher at this entity; false otherwise
+     * 
+     * @deprecated since 0.9.0; see {@link EnricherSupport#removeEnricher(Enricher)}
      */
+    @Deprecated
     boolean removeEnricher(Enricher enricher);
     
     /**
@@ -278,7 +302,11 @@ public interface Entity extends BrooklynObject {
     SensorSupport sensors();
 
     SubscriptionSupport subscriptions();
-    
+
+    PolicySupport policies();
+
+    EnricherSupport enrichers();
+
     @Beta
     public interface SensorSupport {
 
@@ -364,4 +392,52 @@ public interface Entity extends BrooklynObject {
         @Beta
         boolean unsubscribe(Entity producer, SubscriptionHandle handle);
     }
+
+    @Beta
+    public interface PolicySupport {
+        /**
+         * @return an immutable thread-safe view of the policies.
+         */
+        Collection<Policy> getPolicies();
+        
+        /**
+         * Adds the given policy to this entity. Also calls policy.setEntity if available.
+         */
+        void addPolicy(Policy policy);
+        
+        /**
+         * Adds the given policy to this entity. Also calls policy.setEntity if available.
+         */
+        <T extends Policy> T addPolicy(PolicySpec<T> enricher);
+        
+        /**
+         * Removes the given policy from this entity. 
+         * @return True if the policy existed at this entity; false otherwise
+         */
+        boolean removePolicy(Policy policy);
+    }
+    
+    @Beta
+    public interface EnricherSupport {
+        /**
+         * @return an immutable thread-safe view of the enrichers.
+         */
+        Collection<Enricher> getEnrichers();
+        
+        /**
+         * Adds the given enricher to this entity. Also calls enricher.setEntity if available.
+         */
+        void addEnricher(Enricher enricher);
+        
+        /**
+         * Adds the given enricher to this entity. Also calls enricher.setEntity if available.
+         */
+        <T extends Enricher> T addEnricher(EnricherSpec<T> enricher);
+        
+        /**
+         * Removes the given enricher from this entity. 
+         * @return True if the policy enricher at this entity; false otherwise
+         */
+        boolean removeEnricher(Enricher enricher);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e48bdaa7/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java b/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
index c0b7a42..0ecc73a 100644
--- a/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
+++ b/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
@@ -43,6 +43,8 @@ import com.google.common.base.Function;
  * of sub-types.
  * FIXME Add {@link setAttribute(AttributeSensorAndConfigKey<?,T>)} back in if/when move it back,
  * or if we extract an interface for AttributeSensorAndConfigKey.
+ * 
+ * @deprecated since 0.9.0; use {@link Entity} or {@link org.apache.brooklyn.core.entity.EntityInternal}
  */
 public interface EntityLocal extends Entity {
     
@@ -166,13 +168,19 @@ public interface EntityLocal extends Entity {
     /**
      * Removes all policy from this entity. 
      * @return True if any policies existed at this entity; false otherwise
+     * 
+     * @deprecated since 0.9.0; see {@link PolicySupportInternal#removeAllPolicies()}, e.g. {@code ((EntityInternal)entity).policies().removeAllPolicies()}
      */
+    @Deprecated
     boolean removeAllPolicies();
     
     /**
      * Removes all enricher from this entity.
      * Use with caution as some entities automatically register enrichers; this will remove those enrichers as well.
      * @return True if any enrichers existed at this entity; false otherwise
+     * 
+     * @deprecated since 0.9.0; see {@link EnricherSupportInternal#removeAllEnrichers()}, e.g. {@code ((EntityInternal)entity).enrichers().removeAllEnrichers()}
      */
+    @Deprecated
     boolean removeAllEnrichers();
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e48bdaa7/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
index 7a626a4..13079d3 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
@@ -198,8 +198,8 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     private Reference<String> iconUrl = new BasicReference<String>();
 
     Map<String,Object> presentationAttributes = Maps.newLinkedHashMap();
-    Collection<AbstractPolicy> policies = Lists.newCopyOnWriteArrayList();
-    Collection<AbstractEnricher> enrichers = Lists.newCopyOnWriteArrayList();
+    private Collection<AbstractPolicy> policiesInternal = Lists.newCopyOnWriteArrayList();
+    private Collection<AbstractEnricher> enrichersInternal = Lists.newCopyOnWriteArrayList();
     Collection<Feed> feeds = Lists.newCopyOnWriteArrayList();
 
     // FIXME we do not currently support changing parents, but to implement a cluster that can shrink we need to support at least
@@ -221,7 +221,11 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     private final BasicSensorSupport sensors = new BasicSensorSupport();
 
     private final BasicSubscriptionSupport subscriptions = new BasicSubscriptionSupport();
-    
+
+    private final BasicPolicySupport policies = new BasicPolicySupport();
+
+    private final BasicEnricherSupport enrichers = new BasicEnricherSupport();
+
     /**
      * The config values of this entity. Updating this map should be done
      * via getConfig/setConfig.
@@ -1522,82 +1526,212 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     
     // -------- POLICIES --------------------
 
+    @Override 
+    @Beta
+    // the concrete type rather than an interface is returned because Groovy subclasses
+    // complain (incorrectly) if we return PolicySupportInternal
+    // TODO revert to PolicySupportInternal when groovy subclasses work without this (eg new groovy version)
+    public BasicPolicySupport policies() {
+        return policies;
+    }
+
+    @Override 
+    @Beta
+    // the concrete type rather than an interface is returned because Groovy subclasses
+    // complain (incorrectly) if we return EnricherSupportInternal
+    // TODO revert to EnricherSupportInternal when groovy subclasses work without this (eg new groovy version)
+    public BasicEnricherSupport enrichers() {
+        return enrichers;
+    }
+
+    /**
+     * Direct use of this class is strongly discouraged. It will become private in a future release,
+     * once {@link #policies()} is reverted to return {@link {PolicySupportInternal} instead of
+     * {@link BasicPolicySupport}.
+     */
+    @Beta
+    // TODO revert to private when config() is reverted to return SensorSupportInternal
+    public class BasicPolicySupport implements PolicySupportInternal {
+        
+        @Override
+        public Collection<Policy> getPolicies() {
+            return ImmutableList.<Policy>copyOf(policiesInternal);
+        }
+
+        @Override
+        public void addPolicy(Policy policy) {
+            Policy old = findApparentlyEqualAndWarnIfNotSameUniqueTag(policiesInternal, policy);
+            if (old!=null) {
+                LOG.debug("Removing "+old+" when adding "+policy+" to "+AbstractEntity.this);
+                removePolicy(old);
+            }
+            
+            CatalogUtils.setCatalogItemIdOnAddition(AbstractEntity.this, policy);
+            policiesInternal.add((AbstractPolicy)policy);
+            ((AbstractPolicy)policy).setEntity(AbstractEntity.this);
+            
+            getManagementSupport().getEntityChangeListener().onPolicyAdded(policy);
+            emit(AbstractEntity.POLICY_ADDED, new PolicyDescriptor(policy));
+        }
+
+        @Override
+        public <T extends Policy> T addPolicy(PolicySpec<T> spec) {
+            T policy = getManagementContext().getEntityManager().createPolicy(spec);
+            addPolicy(policy);
+            return policy;
+        }
+        
+        @Override
+        public boolean removePolicy(Policy policy) {
+            ((AbstractPolicy)policy).destroy();
+            boolean changed = policiesInternal.remove(policy);
+            
+            if (changed) {
+                getManagementSupport().getEntityChangeListener().onPolicyRemoved(policy);
+                emit(AbstractEntity.POLICY_REMOVED, new PolicyDescriptor(policy));
+            }
+            return changed;
+        }
+        
+        @Override
+        public boolean removeAllPolicies() {
+            boolean changed = false;
+            for (Policy policy : policiesInternal) {
+                removePolicy(policy);
+                changed = true;
+            }
+            return changed;
+        }
+    }
+
+    /**
+     * Direct use of this class is strongly discouraged. It will become private in a future release,
+     * once {@link #enrichers()} is reverted to return {@link EnricherSupportInternal} instead of
+     * {@link BasicEnricherSupport}.
+     */
+    @Beta
+    // TODO revert to private when config() is reverted to return SensorSupportInternal
+    public class BasicEnricherSupport implements EnricherSupportInternal {
+        @Override
+        public Collection<Enricher> getEnrichers() {
+            return ImmutableList.<Enricher>copyOf(enrichersInternal);
+        }
+
+        @Override
+        public <T extends Enricher> T addEnricher(EnricherSpec<T> spec) {
+            T enricher = getManagementContext().getEntityManager().createEnricher(spec);
+            addEnricher(enricher);
+            return enricher;
+        }
+
+        @Override
+        public void addEnricher(Enricher enricher) {
+            Enricher old = findApparentlyEqualAndWarnIfNotSameUniqueTag(enrichersInternal, enricher);
+            if (old!=null) {
+                LOG.debug("Removing "+old+" when adding "+enricher+" to "+AbstractEntity.this);
+                removeEnricher(old);
+            }
+            
+            CatalogUtils.setCatalogItemIdOnAddition(AbstractEntity.this, enricher);
+            enrichersInternal.add((AbstractEnricher) enricher);
+            ((AbstractEnricher)enricher).setEntity(AbstractEntity.this);
+            
+            getManagementSupport().getEntityChangeListener().onEnricherAdded(enricher);
+            // TODO Could add equivalent of AbstractEntity.POLICY_ADDED for enrichers; no use-case for that yet
+        }
+        
+        @Override
+        public boolean removeEnricher(Enricher enricher) {
+            ((AbstractEnricher)enricher).destroy();
+            boolean changed = enrichersInternal.remove(enricher);
+            
+            if (changed) {
+                getManagementSupport().getEntityChangeListener().onEnricherRemoved(enricher);
+            }
+            return changed;
+
+        }
+
+        @Override
+        public boolean removeAllEnrichers() {
+            boolean changed = false;
+            for (AbstractEnricher enricher : enrichersInternal) {
+                changed = removeEnricher(enricher) || changed;
+            }
+            return changed;
+        }
+    }
+    
+    /**
+     * @deprecated since 0.9.0; see {@link BasicPolicySupport#getPolicies()}; e.g. {@code policies().getPolicies()}
+     */
     @Override
+    @Deprecated
     public Collection<Policy> getPolicies() {
-        return ImmutableList.<Policy>copyOf(policies);
+        return policies().getPolicies();
     }
 
+    /**
+     * @deprecated since 0.9.0; see {@link BasicPolicySupport#addPolicy(Policy)}; e.g. {@code policies().addPolicy(policy)}
+     */
     @Override
+    @Deprecated
     public void addPolicy(Policy policy) {
-        Policy old = findApparentlyEqualAndWarnIfNotSameUniqueTag(policies, policy);
-        if (old!=null) {
-            LOG.debug("Removing "+old+" when adding "+policy+" to "+this);
-            removePolicy(old);
-        }
-        
-        CatalogUtils.setCatalogItemIdOnAddition(this, policy);
-        policies.add((AbstractPolicy)policy);
-        ((AbstractPolicy)policy).setEntity(this);
-        
-        getManagementSupport().getEntityChangeListener().onPolicyAdded(policy);
-        emit(AbstractEntity.POLICY_ADDED, new PolicyDescriptor(policy));
+        policies().addPolicy(policy);
     }
 
+    /**
+     * @deprecated since 0.9.0; see {@link BasicPolicySupport#addPolicy(PolicySpec)}; e.g. {@code policies().addPolicy(spec)}
+     */
     @Override
+    @Deprecated
     public <T extends Policy> T addPolicy(PolicySpec<T> spec) {
-        T policy = getManagementContext().getEntityManager().createPolicy(spec);
-        addPolicy(policy);
-        return policy;
+        return policies().addPolicy(spec);
     }
 
+    /**
+     * @deprecated since 0.9.0; see {@link BasicEnricherSupport#; e.g. {@code enrichers().addEnricher(spec)}
+     */
     @Override
+    @Deprecated
     public <T extends Enricher> T addEnricher(EnricherSpec<T> spec) {
-        T enricher = getManagementContext().getEntityManager().createEnricher(spec);
-        addEnricher(enricher);
-        return enricher;
+        return enrichers().addEnricher(spec);
     }
 
+    /**
+     * @deprecated since 0.9.0; see {@link BasicPolicySupport#removePolicy(Policy)}; e.g. {@code policies().removePolicy(policy)}
+     */
     @Override
+    @Deprecated
     public boolean removePolicy(Policy policy) {
-        ((AbstractPolicy)policy).destroy();
-        boolean changed = policies.remove(policy);
-        
-        if (changed) {
-            getManagementSupport().getEntityChangeListener().onPolicyRemoved(policy);
-            emit(AbstractEntity.POLICY_REMOVED, new PolicyDescriptor(policy));
-        }
-        return changed;
+        return policies().removePolicy(policy);
     }
     
+    /**
+     * @deprecated since 0.9.0; see {@link BasicPolicySupport#removeAllPolicies()}; e.g. {@code policies().removeAllPolicies()}
+     */
     @Override
+    @Deprecated
     public boolean removeAllPolicies() {
-        boolean changed = false;
-        for (Policy policy : policies) {
-            removePolicy(policy);
-            changed = true;
-        }
-        return changed;
+        return policies().removeAllPolicies();
     }
     
+    /**
+     * @deprecated since 0.9.0; see {@link BasicEnricherSupport#getEnrichers()}; e.g. {@code enrichers().getEnrichers()}
+     */
     @Override
+    @Deprecated
     public Collection<Enricher> getEnrichers() {
-        return ImmutableList.<Enricher>copyOf(enrichers);
+        return enrichers().getEnrichers();
     }
 
+    /**
+     * @deprecated since 0.9.0; see {@link BasicEnricherSupport#addEnricher(Enricher)}; e.g. {@code enrichers().addEnricher(enricher)}
+     */
     @Override
+    @Deprecated
     public void addEnricher(Enricher enricher) {
-        Enricher old = findApparentlyEqualAndWarnIfNotSameUniqueTag(enrichers, enricher);
-        if (old!=null) {
-            LOG.debug("Removing "+old+" when adding "+enricher+" to "+this);
-            removeEnricher(old);
-        }
-        
-        CatalogUtils.setCatalogItemIdOnAddition(this, enricher);
-        enrichers.add((AbstractEnricher) enricher);
-        ((AbstractEnricher)enricher).setEntity(this);
-        
-        getManagementSupport().getEntityChangeListener().onEnricherAdded(enricher);
-        // TODO Could add equivalent of AbstractEntity.POLICY_ADDED for enrichers; no use-case for that yet
+        enrichers().addEnricher(enricher);
     }
     
     private <T extends EntityAdjunct> T findApparentlyEqualAndWarnIfNotSameUniqueTag(Collection<? extends T> items, T newItem) {
@@ -1677,25 +1811,22 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         return null;
     }
 
+    /**
+     * @deprecated since 0.9.0; see {@link BasicEnricherSupport#removeEnricher(Enricher)}; e.g. {@code enrichers().removeEnricher(enricher)}
+     */
     @Override
+    @Deprecated
     public boolean removeEnricher(Enricher enricher) {
-        ((AbstractEnricher)enricher).destroy();
-        boolean changed = enrichers.remove(enricher);
-        
-        if (changed) {
-            getManagementSupport().getEntityChangeListener().onEnricherRemoved(enricher);
-        }
-        return changed;
-
+        return enrichers().removeEnricher(enricher);
     }
 
+    /**
+     * @deprecated since 0.9.0; see {@link BasicEnricherSupport#removeAllEnrichers()}; e.g. {@code enrichers().removeAllEnrichers()}
+     */
     @Override
+    @Deprecated
     public boolean removeAllEnrichers() {
-        boolean changed = false;
-        for (AbstractEnricher enricher : enrichers) {
-            changed = removeEnricher(enricher) || changed;
-        }
-        return changed;
+        return enrichers().removeAllEnrichers();
     }
     
     // -------- FEEDS --------------------

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e48bdaa7/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java b/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
index 1ebcaf1..04fa88b 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
@@ -192,10 +192,18 @@ public interface EntityInternal extends BrooklynObjectInternal, EntityLocal, Reb
      */
     void requestPersist();
     
+    @Override
     SensorSupportInternal sensors();
 
+    @Override
     SubscriptionSupportInternal subscriptions();
 
+    @Override
+    PolicySupportInternal policies();
+
+    @Override
+    EnricherSupportInternal enrichers();
+
     @Beta
     public interface SensorSupportInternal extends Entity.SensorSupport {
         /**
@@ -237,4 +245,23 @@ public interface EntityInternal extends BrooklynObjectInternal, EntityLocal, Reb
     public interface SubscriptionSupportInternal extends Entity.SubscriptionSupport {
         SubscriptionContext getSubscriptionContext();
     }
+    
+    @Beta
+    public interface PolicySupportInternal extends Entity.PolicySupport {
+        /**
+         * Removes all policy from this entity. 
+         * @return True if any policies existed at this entity; false otherwise
+         */
+        boolean removeAllPolicies();
+    }
+    
+    @Beta
+    public interface EnricherSupportInternal extends Entity.EnricherSupport {
+        /**
+         * Removes all enricher from this entity.
+         * Use with caution as some entities automatically register enrichers; this will remove those enrichers as well.
+         * @return True if any enrichers existed at this entity; false otherwise
+         */
+        boolean removeAllEnrichers();
+    }
 }


[08/10] incubator-brooklyn git commit: Simplify PolicySupport etc method names

Posted by al...@apache.org.
Simplify PolicySupport etc method names

e.g. policies().addPolicy(...) becomes policies().add(...)

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

Branch: refs/heads/master
Commit: ebe942be06a417cc00d442472ca7219ec8125c21
Parents: ee52d48
Author: Aled Sage <al...@gmail.com>
Authored: Wed Sep 23 10:51:07 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Sep 23 10:51:07 2015 +0100

----------------------------------------------------------------------
 .../org/apache/brooklyn/api/entity/Entity.java  | 32 ++++++-------
 .../brooklyn/core/entity/AbstractEntity.java    | 48 ++++++++++----------
 .../brooklyn/core/entity/EntityInternal.java    |  2 +-
 3 files changed, 41 insertions(+), 41 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ebe942be/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
index d302cff..32f9c00 100644
--- a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
+++ b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
@@ -191,7 +191,7 @@ public interface Entity extends BrooklynObject {
      * automatically be called. However, the reverse is not true (calling this method will 
      * not tell the group; this behaviour may change in a future release!)
      * 
-     * @deprecated since 0.9.0; see {@link GroupSupport#getGroups()} and {@link #groups()}
+     * @deprecated since 0.9.0; see {@link GroupSupport#add()} and {@link #groups()}
      */
     @Deprecated
     void addGroup(Group group);
@@ -203,7 +203,7 @@ public interface Entity extends BrooklynObject {
      * automatically be called. However, the reverse is not true (calling this method will 
      * not tell the group; this behaviour may change in a future release!)
      * 
-     * @deprecated since 0.9.0; see {@link GroupSupport#getGroups()} and {@link #groups()}
+     * @deprecated since 0.9.0; see {@link GroupSupport#remove()} and {@link #groups()}
      */
     @Deprecated
     void removeGroup(Group group);
@@ -256,7 +256,7 @@ public interface Entity extends BrooklynObject {
     /**
      * Adds the given policy to this entity. Also calls policy.setEntity if available.
      * 
-     * @deprecated since 0.9.0; see {@link PolicySupport#addPolicy(Policy)}
+     * @deprecated since 0.9.0; see {@link PolicySupport#add(Policy)}
      */
     @Deprecated
     void addPolicy(Policy policy);
@@ -264,7 +264,7 @@ public interface Entity extends BrooklynObject {
     /**
      * Adds the given policy to this entity. Also calls policy.setEntity if available.
      * 
-     * @deprecated since 0.9.0; see {@link PolicySupport#addPolicy(PolicySpec)}
+     * @deprecated since 0.9.0; see {@link PolicySupport#add(PolicySpec)}
      */
     @Deprecated
     <T extends Policy> T addPolicy(PolicySpec<T> enricher);
@@ -273,7 +273,7 @@ public interface Entity extends BrooklynObject {
      * Removes the given policy from this entity. 
      * @return True if the policy existed at this entity; false otherwise
      * 
-     * @deprecated since 0.9.0; see {@link PolicySupport#removePolicy(Policy)}
+     * @deprecated since 0.9.0; see {@link PolicySupport#remove(Policy)}
      */
     @Deprecated
     boolean removePolicy(Policy policy);
@@ -281,7 +281,7 @@ public interface Entity extends BrooklynObject {
     /**
      * Adds the given enricher to this entity. Also calls enricher.setEntity if available.
      * 
-     * @deprecated since 0.9.0; see {@link EnricherSupport#addEnricher(Enricher)}
+     * @deprecated since 0.9.0; see {@link EnricherSupport#add(Enricher)}
      */
     @Deprecated
     void addEnricher(Enricher enricher);
@@ -289,7 +289,7 @@ public interface Entity extends BrooklynObject {
     /**
      * Adds the given enricher to this entity. Also calls enricher.setEntity if available.
      * 
-     * @deprecated since 0.9.0; see {@link EnricherSupport#addEnricher(EnricherSpec)}
+     * @deprecated since 0.9.0; see {@link EnricherSupport#add(EnricherSpec)}
      */
     @Deprecated
     <T extends Enricher> T addEnricher(EnricherSpec<T> enricher);
@@ -298,7 +298,7 @@ public interface Entity extends BrooklynObject {
      * Removes the given enricher from this entity. 
      * @return True if the policy enricher at this entity; false otherwise
      * 
-     * @deprecated since 0.9.0; see {@link EnricherSupport#removeEnricher(Enricher)}
+     * @deprecated since 0.9.0; see {@link EnricherSupport#remove(Enricher)}
      */
     @Deprecated
     boolean removeEnricher(Enricher enricher);
@@ -372,18 +372,18 @@ public interface Entity extends BrooklynObject {
         /**
          * Adds the given policy to this entity. Also calls policy.setEntity if available.
          */
-        void addPolicy(Policy policy);
+        void add(Policy policy);
         
         /**
          * Adds the given policy to this entity. Also calls policy.setEntity if available.
          */
-        <T extends Policy> T addPolicy(PolicySpec<T> enricher);
+        <T extends Policy> T add(PolicySpec<T> enricher);
         
         /**
          * Removes the given policy from this entity. 
          * @return True if the policy existed at this entity; false otherwise
          */
-        boolean removePolicy(Policy policy);
+        boolean remove(Policy policy);
     }
     
     @Beta
@@ -396,18 +396,18 @@ public interface Entity extends BrooklynObject {
         /**
          * Adds the given enricher to this entity. Also calls enricher.setEntity if available.
          */
-        void addEnricher(Enricher enricher);
+        void add(Enricher enricher);
         
         /**
          * Adds the given enricher to this entity. Also calls enricher.setEntity if available.
          */
-        <T extends Enricher> T addEnricher(EnricherSpec<T> enricher);
+        <T extends Enricher> T add(EnricherSpec<T> enricher);
         
         /**
          * Removes the given enricher from this entity. 
          * @return True if the policy enricher at this entity; false otherwise
          */
-        boolean removeEnricher(Enricher enricher);
+        boolean remove(Enricher enricher);
     }
     
     @Beta
@@ -426,7 +426,7 @@ public interface Entity extends BrooklynObject {
          * automatically be called. However, the reverse is not true (calling this method will 
          * not tell the group; this behaviour may change in a future release!)
          */
-        void addGroup(Group group);
+        void add(Group group);
 
         /**
          * Removes this entity as a member of the given {@link Group}. Called by framework.
@@ -435,6 +435,6 @@ public interface Entity extends BrooklynObject {
          * automatically be called. However, the reverse is not true (calling this method will 
          * not tell the group; this behaviour may change in a future release!)
          */
-        void removeGroup(Group group);
+        void remove(Group group);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ebe942be/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
index 291389f..08b25f2 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
@@ -707,7 +707,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     // TODO revert to private when groups() is reverted to return GroupSupport
     public class BasicGroupSupport implements GroupSupport {
         @Override
-        public void addGroup(Group group) {
+        public void add(Group group) {
             boolean changed = groupsInternal.add(group);
             getApplication();
             
@@ -717,7 +717,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         }
 
         @Override
-        public void removeGroup(Group group) {
+        public void remove(Group group) {
             boolean changed = groupsInternal.remove(group);
             getApplication();
             
@@ -738,7 +738,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     @Override
     @Deprecated
     public void addGroup(Group group) {
-        groups().addGroup(group);
+        groups().add(group);
     }
 
     /**
@@ -747,7 +747,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     @Override
     @Deprecated
     public void removeGroup(Group group) {
-        groups().removeGroup(group);
+        groups().remove(group);
     }
 
     /**
@@ -1612,11 +1612,11 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         }
 
         @Override
-        public void addPolicy(Policy policy) {
+        public void add(Policy policy) {
             Policy old = findApparentlyEqualAndWarnIfNotSameUniqueTag(policiesInternal, policy);
             if (old!=null) {
                 LOG.debug("Removing "+old+" when adding "+policy+" to "+AbstractEntity.this);
-                removePolicy(old);
+                remove(old);
             }
             
             CatalogUtils.setCatalogItemIdOnAddition(AbstractEntity.this, policy);
@@ -1628,14 +1628,14 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         }
 
         @Override
-        public <T extends Policy> T addPolicy(PolicySpec<T> spec) {
+        public <T extends Policy> T add(PolicySpec<T> spec) {
             T policy = getManagementContext().getEntityManager().createPolicy(spec);
-            addPolicy(policy);
+            add(policy);
             return policy;
         }
         
         @Override
-        public boolean removePolicy(Policy policy) {
+        public boolean remove(Policy policy) {
             ((AbstractPolicy)policy).destroy();
             boolean changed = policiesInternal.remove(policy);
             
@@ -1650,7 +1650,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         public boolean removeAllPolicies() {
             boolean changed = false;
             for (Policy policy : policiesInternal) {
-                removePolicy(policy);
+                remove(policy);
                 changed = true;
             }
             return changed;
@@ -1671,18 +1671,18 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         }
 
         @Override
-        public <T extends Enricher> T addEnricher(EnricherSpec<T> spec) {
+        public <T extends Enricher> T add(EnricherSpec<T> spec) {
             T enricher = getManagementContext().getEntityManager().createEnricher(spec);
-            addEnricher(enricher);
+            add(enricher);
             return enricher;
         }
 
         @Override
-        public void addEnricher(Enricher enricher) {
+        public void add(Enricher enricher) {
             Enricher old = findApparentlyEqualAndWarnIfNotSameUniqueTag(enrichersInternal, enricher);
             if (old!=null) {
                 LOG.debug("Removing "+old+" when adding "+enricher+" to "+AbstractEntity.this);
-                removeEnricher(old);
+                remove(old);
             }
             
             CatalogUtils.setCatalogItemIdOnAddition(AbstractEntity.this, enricher);
@@ -1694,7 +1694,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         }
         
         @Override
-        public boolean removeEnricher(Enricher enricher) {
+        public boolean remove(Enricher enricher) {
             ((AbstractEnricher)enricher).destroy();
             boolean changed = enrichersInternal.remove(enricher);
             
@@ -1706,10 +1706,10 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         }
 
         @Override
-        public boolean removeAllEnrichers() {
+        public boolean removeAll() {
             boolean changed = false;
             for (AbstractEnricher enricher : enrichersInternal) {
-                changed = removeEnricher(enricher) || changed;
+                changed = remove(enricher) || changed;
             }
             return changed;
         }
@@ -1730,7 +1730,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     @Override
     @Deprecated
     public void addPolicy(Policy policy) {
-        policies().addPolicy(policy);
+        policies().add(policy);
     }
 
     /**
@@ -1739,7 +1739,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     @Override
     @Deprecated
     public <T extends Policy> T addPolicy(PolicySpec<T> spec) {
-        return policies().addPolicy(spec);
+        return policies().add(spec);
     }
 
     /**
@@ -1748,7 +1748,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     @Override
     @Deprecated
     public <T extends Enricher> T addEnricher(EnricherSpec<T> spec) {
-        return enrichers().addEnricher(spec);
+        return enrichers().add(spec);
     }
 
     /**
@@ -1757,7 +1757,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     @Override
     @Deprecated
     public boolean removePolicy(Policy policy) {
-        return policies().removePolicy(policy);
+        return policies().remove(policy);
     }
     
     /**
@@ -1784,7 +1784,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     @Override
     @Deprecated
     public void addEnricher(Enricher enricher) {
-        enrichers().addEnricher(enricher);
+        enrichers().add(enricher);
     }
     
     private <T extends EntityAdjunct> T findApparentlyEqualAndWarnIfNotSameUniqueTag(Collection<? extends T> items, T newItem) {
@@ -1870,7 +1870,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     @Override
     @Deprecated
     public boolean removeEnricher(Enricher enricher) {
-        return enrichers().removeEnricher(enricher);
+        return enrichers().remove(enricher);
     }
 
     /**
@@ -1879,7 +1879,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     @Override
     @Deprecated
     public boolean removeAllEnrichers() {
-        return enrichers().removeAllEnrichers();
+        return enrichers().removeAll();
     }
     
     // -------- FEEDS --------------------

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ebe942be/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java b/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
index 49dfa00..c0eca7e 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
@@ -242,6 +242,6 @@ public interface EntityInternal extends BrooklynObjectInternal, EntityLocal, Reb
          * Use with caution as some entities automatically register enrichers; this will remove those enrichers as well.
          * @return True if any enrichers existed at this entity; false otherwise
          */
-        boolean removeAllEnrichers();
+        boolean removeAll();
     }
 }


[03/10] incubator-brooklyn git commit: Create entity.subscriptions() for grouping

Posted by al...@apache.org.
Create entity.subscriptions() for grouping

- Deprecate EntityLocal.*subscri*()


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/3e46621c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/3e46621c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/3e46621c

Branch: refs/heads/master
Commit: 3e46621cf490569289954ffadc631e1b6e99df03
Parents: 1a6c4e3
Author: Aled Sage <al...@gmail.com>
Authored: Mon Sep 21 08:20:57 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Sep 23 10:32:55 2015 +0100

----------------------------------------------------------------------
 .../org/apache/brooklyn/api/entity/Entity.java  |  47 ++++++-
 .../apache/brooklyn/api/entity/EntityLocal.java |  28 ++++-
 .../brooklyn/core/entity/AbstractEntity.java    | 122 ++++++++++++++++---
 .../brooklyn/core/entity/EntityInternal.java    |  15 ++-
 4 files changed, 183 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3e46621c/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
index 612ce29..8388d28 100644
--- a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
+++ b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java
@@ -25,9 +25,11 @@ import javax.annotation.Nullable;
 
 import org.apache.brooklyn.api.effector.Effector;
 import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.mgmt.SubscriptionContext;
+import org.apache.brooklyn.api.mgmt.SubscriptionHandle;
+import org.apache.brooklyn.api.mgmt.SubscriptionManager;
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.api.objs.BrooklynObject;
-import org.apache.brooklyn.api.objs.Configurable.ConfigurationSupport;
 import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.api.policy.PolicySpec;
 import org.apache.brooklyn.api.sensor.AttributeSensor;
@@ -36,6 +38,7 @@ import org.apache.brooklyn.api.sensor.EnricherSpec;
 import org.apache.brooklyn.api.sensor.Feed;
 import org.apache.brooklyn.api.sensor.Sensor;
 import org.apache.brooklyn.api.sensor.SensorEvent;
+import org.apache.brooklyn.api.sensor.SensorEventListener;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
 import org.apache.brooklyn.util.guava.Maybe;
@@ -274,6 +277,8 @@ public interface Entity extends BrooklynObject {
     
     SensorSupport sensors();
 
+    SubscriptionSupport subscriptions();
+    
     @Beta
     public interface SensorSupport {
 
@@ -319,4 +324,44 @@ public interface Entity extends BrooklynObject {
          */
         <T> void emit(Sensor<T> sensor, T value);
     }
+    
+    @Beta
+    public interface SubscriptionSupport {
+        /**
+         * Allow us to subscribe to data from a {@link Sensor} on another entity.
+         * 
+         * @return a subscription id which can be used to unsubscribe
+         *
+         * @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener)
+         */
+        // FIXME remove from interface?
+        @Beta
+        <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener);
+     
+        /** @see SubscriptionManager#subscribeToChildren(Map, Entity, Sensor, SensorEventListener) */
+        // FIXME remove from interface?
+        @Beta
+        <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener);
+     
+        /** @see SubscriptionManager#subscribeToMembers(Group, Sensor, SensorEventListener) */
+        // FIXME remove from interface?
+        @Beta
+        <T> SubscriptionHandle subscribeToMembers(Group group, Sensor<T> sensor, SensorEventListener<? super T> listener);
+
+        /**
+         * Unsubscribes from the given producer.
+         *
+         * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+         */
+        @Beta
+        boolean unsubscribe(Entity producer);
+
+        /**
+         * Unsubscribes the given handle.
+         *
+         * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+         */
+        @Beta
+        boolean unsubscribe(Entity producer, SubscriptionHandle handle);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3e46621c/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java b/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
index b3fa078..c0b7a42 100644
--- a/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
+++ b/api/src/main/java/org/apache/brooklyn/api/entity/EntityLocal.java
@@ -105,8 +105,10 @@ public interface EntityLocal extends Entity {
      * @return a subscription id which can be used to unsubscribe
      *
      * @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener)
+     * 
+     * @deprecated since 0.9.0; see {@link SubscriptionSupportInternal#getSubscriptionContext()}, e.g. with {@code subscriptions().getSubscriptionContext()}
      */
-    // FIXME remove from interface?
+    @Deprecated
     @Beta
     <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener);
 
@@ -120,14 +122,22 @@ public interface EntityLocal extends Entity {
     // FIXME remove from interface?
     @Beta
     <T> SubscriptionHandle subscribe(Map<String, ?> flags, Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener);
-
-    /** @see SubscriptionManager#subscribeToChildren(Map, Entity, Sensor, SensorEventListener) */
-    // FIXME remove from interface?
+ 
+    /**
+     * @see SubscriptionManager#subscribeToChildren(Map, Entity, Sensor, SensorEventListener)
+     * 
+     * @deprecated since 0.9.0; see {@link SubscriptionSupport#subscribeToChildren(Entity, Sensor, SensorEventListener)}, e.g. with {@code subscriptions().subscribeToChildren(...)}
+     */
+    @Deprecated
     @Beta
     <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener);
  
-    /** @see SubscriptionManager#subscribeToMembers(Group, Sensor, SensorEventListener) */
-    // FIXME remove from interface?
+    /**
+     * @see SubscriptionManager#subscribeToMembers(Group, Sensor, SensorEventListener)
+     * 
+     * @deprecated since 0.9.0; see {@link SubscriptionSupport#subscribeToMembers(Entity, Sensor, SensorEventListener)}, e.g. with {@code subscriptions().subscribeToMembers(...)}
+     */
+    @Deprecated
     @Beta
     <T> SubscriptionHandle subscribeToMembers(Group group, Sensor<T> sensor, SensorEventListener<? super T> listener);
 
@@ -135,7 +145,10 @@ public interface EntityLocal extends Entity {
      * Unsubscribes from the given producer.
      *
      * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+     * 
+     * @deprecated since 0.9.0; see {@link SubscriptionSupport#unsubscribe(Entity)}, e.g. with {@code subscriptions().unsubscribe(...)}
      */
+    @Deprecated
     @Beta
     boolean unsubscribe(Entity producer);
 
@@ -143,7 +156,10 @@ public interface EntityLocal extends Entity {
      * Unsubscribes the given handle.
      *
      * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+     * 
+     * @deprecated since 0.9.0; see {@link SubscriptionSupport#unsubscribe(Entity, SubscriptionHandle)}, e.g. with {@code subscriptions().unsubscribe(...)}
      */
+    @Deprecated
     @Beta
     boolean unsubscribe(Entity producer, SubscriptionHandle handle);
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3e46621c/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
index 03254dd..7a626a4 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
@@ -220,6 +220,8 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
 
     private final BasicSensorSupport sensors = new BasicSensorSupport();
 
+    private final BasicSubscriptionSupport subscriptions = new BasicSubscriptionSupport();
+    
     /**
      * The config values of this entity. Updating this map should be done
      * via getConfig/setConfig.
@@ -1331,10 +1333,83 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     
     // -------- SUBSCRIPTIONS --------------
 
-    /** @see EntityLocal#subscribe */
+    @Override 
+    @Beta
+    // the concrete type rather than an interface is returned because Groovy subclasses
+    // complain (incorrectly) if we return SubscriptionSupportInternal
+    // TODO revert to SubscriptionSupportInternal when groovy subclasses work without this (eg new groovy version)
+    public BasicSubscriptionSupport subscriptions() {
+        return subscriptions;
+    }
+
+    /**
+     * Direct use of this class is strongly discouraged. It will become private in a future release,
+     * once {@link #subscriptions()} is reverted to return {@link SubscriptionSupportInternal} instead of
+     * {@link BasicSubscriptionSupport}.
+     */
+    @Beta
+    // TODO revert to private when config() is reverted to return SensorSupportInternal
+    public class BasicSubscriptionSupport implements SubscriptionSupportInternal {
+        
+        @Override
+        public <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+            return getSubscriptionTracker().subscribe(producer, sensor, listener);
+        }
+
+        @Override
+        public <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+            return getSubscriptionTracker().subscribeToChildren(parent, sensor, listener);
+        }
+
+        @Override
+        public <T> SubscriptionHandle subscribeToMembers(Group group, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+            return getSubscriptionTracker().subscribeToMembers(group, sensor, listener);
+        }
+
+        /**
+         * Unsubscribes the given producer.
+         *
+         * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+         */
+        @Override
+        public boolean unsubscribe(Entity producer) {
+            return getSubscriptionTracker().unsubscribe(producer);
+        }
+
+        /**
+         * Unsubscribes the given handle.
+         *
+         * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+         */
+        @Override
+        public boolean unsubscribe(Entity producer, SubscriptionHandle handle) {
+            return getSubscriptionTracker().unsubscribe(producer, handle);
+        }
+
+        @Override
+        public SubscriptionContext getSubscriptionContext() {
+            synchronized (AbstractEntity.this) {
+                return getManagementSupport().getSubscriptionContext();
+            }
+        }
+
+        protected SubscriptionTracker getSubscriptionTracker() {
+            synchronized (AbstractEntity.this) {
+                if (_subscriptionTracker == null) {
+                    _subscriptionTracker = new SubscriptionTracker(getSubscriptionContext());
+                }
+                return _subscriptionTracker;
+            }
+        }
+    }
+    
+    /**
+     * @deprecated since 0.9.0; see {@code subscriptions().subscribe(producer, sensor, listener)}
+     */
     @Override
+    @Deprecated
     public <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
-        return getSubscriptionTracker().subscribe(producer, sensor, listener);
+        return subscriptions().subscribe(producer, sensor, listener);
     }
 
     /** @see EntityLocal#subscribe */
@@ -1344,48 +1419,57 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         return getSubscriptionTracker().subscribe(flags, producer, sensor, listener);
     }
 
-    /** @see EntityLocal#subscribeToChildren */
+    /**
+     * @deprecated since 0.9.0; see {@code subscriptions().subscribeToChildren(parent, sensor, listener)}
+     */
     @Override
+    @Deprecated
     public <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
-        return getSubscriptionTracker().subscribeToChildren(parent, sensor, listener);
+        return subscriptions().subscribeToChildren(parent, sensor, listener);
     }
 
-    /** @see EntityLocal#subscribeToMembers */
+    /**
+     * @deprecated since 0.9.0; see {@code subscriptions().subscribeToMembers(producer, sensor, listener)}
+     */
     @Override
+    @Deprecated
     public <T> SubscriptionHandle subscribeToMembers(Group group, Sensor<T> sensor, SensorEventListener<? super T> listener) {
-        return getSubscriptionTracker().subscribeToMembers(group, sensor, listener);
+        return subscriptions().subscribeToMembers(group, sensor, listener);
     }
 
     /**
-     * Unsubscribes the given producer.
-     *
-     * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+     * @deprecated since 0.9.0; see {@code subscriptions().unsubscribe(producer)}
      */
     @Override
+    @Deprecated
     public boolean unsubscribe(Entity producer) {
-        return getSubscriptionTracker().unsubscribe(producer);
+        return subscriptions().unsubscribe(producer);
     }
 
     /**
-     * Unsubscribes the given handle.
-     *
-     * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+     * @deprecated since 0.9.0; see {@code subscriptions().unsubscribe(producer, handle)}
      */
     @Override
+    @Deprecated
     public boolean unsubscribe(Entity producer, SubscriptionHandle handle) {
-        return getSubscriptionTracker().unsubscribe(producer, handle);
+        return subscriptions().unsubscribe(producer, handle);
     }
 
+    /**
+     * @deprecated since 0.9.0; see {@code subscriptions().getSubscriptionContext()}
+     */
     @Override
+    @Deprecated
     public synchronized SubscriptionContext getSubscriptionContext() {
-        return getManagementSupport().getSubscriptionContext();
+        return subscriptions().getSubscriptionContext();
     }
 
+    /**
+     * @deprecated since 0.9.0; for internal use only
+     */
+    @Deprecated
     protected synchronized SubscriptionTracker getSubscriptionTracker() {
-        if (_subscriptionTracker == null) {
-            _subscriptionTracker = new SubscriptionTracker(getSubscriptionContext());
-        }
-        return _subscriptionTracker;
+        return subscriptions().getSubscriptionTracker();
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/3e46621c/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java b/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
index 3811ce8..1ebcaf1 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/EntityInternal.java
@@ -151,7 +151,11 @@ public interface EntityInternal extends BrooklynObjectInternal, EntityLocal, Reb
      * Do not cache this object; instead call getExecutionContext() each time you need to use it.
      */    
     ExecutionContext getExecutionContext();
-    
+
+    /**
+     * @deprecated since 0.9.0; see {@link SubscriptionSupportInternal#getSubscriptionContext()}, e.g. with {@code subscriptions().getSubscriptionContext()}
+     */
+    @Deprecated
     SubscriptionContext getSubscriptionContext();
     
     /** returns the dynamic type corresponding to the type of this entity instance */
@@ -190,6 +194,8 @@ public interface EntityInternal extends BrooklynObjectInternal, EntityLocal, Reb
     
     SensorSupportInternal sensors();
 
+    SubscriptionSupportInternal subscriptions();
+
     @Beta
     public interface SensorSupportInternal extends Entity.SensorSupport {
         /**
@@ -203,8 +209,6 @@ public interface EntityInternal extends BrooklynObjectInternal, EntityLocal, Reb
 
         @Beta
         void remove(AttributeSensor<?> attribute);
-
-
     }
 
     public interface FeedSupport {
@@ -228,4 +232,9 @@ public interface EntityInternal extends BrooklynObjectInternal, EntityLocal, Reb
          */
         boolean removeAllFeeds();
     }
+    
+    @Beta
+    public interface SubscriptionSupportInternal extends Entity.SubscriptionSupport {
+        SubscriptionContext getSubscriptionContext();
+    }
 }