You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by sv...@apache.org on 2015/10/27 15:48:23 UTC

[1/8] incubator-brooklyn git commit: Introduce relationships between brooklyn objects

Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master c6273b891 -> 52241ae61


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/test/java/org/apache/brooklyn/core/relations/RelationshipTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/relations/RelationshipTest.java b/core/src/test/java/org/apache/brooklyn/core/relations/RelationshipTest.java
new file mode 100644
index 0000000..ba114dd
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/relations/RelationshipTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.relations;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.basic.relations.Relationship;
+
+@Test
+public class RelationshipTest {
+
+    static Relationship<Entity, TestEntity> AUNTIE_OF = Relationships.newRelationshipPair(
+        "auntie", "aunties", Entity.class, "auntie_of_nephew",
+        "nephew", "nephews", TestEntity.class, "nephew_of_auntie");
+    
+    static Relationship<TestEntity, Entity> NEPHEW_OF = AUNTIE_OF.getInverseRelationship();
+    
+    public void testFields() {
+        Assert.assertEquals(AUNTIE_OF.getRelationshipTypeName(), "auntie_of_nephew");
+        Assert.assertEquals(AUNTIE_OF.getSourceType(), Entity.class);
+        Assert.assertEquals(AUNTIE_OF.getTargetType(), TestEntity.class);
+        Assert.assertEquals(AUNTIE_OF.getSourceName(), "auntie");
+        Assert.assertEquals(AUNTIE_OF.getTargetName(), "nephew");
+        Assert.assertEquals(AUNTIE_OF.getSourceNamePlural(), "aunties");
+        Assert.assertEquals(AUNTIE_OF.getTargetNamePlural(), "nephews");
+        
+        Assert.assertEquals(NEPHEW_OF.getRelationshipTypeName(), "nephew_of_auntie");
+        Assert.assertEquals(NEPHEW_OF.getSourceType(), TestEntity.class);
+        Assert.assertEquals(NEPHEW_OF.getTargetType(), Entity.class);
+        Assert.assertEquals(NEPHEW_OF.getSourceName(), "nephew");
+        Assert.assertEquals(NEPHEW_OF.getTargetName(), "auntie");
+        Assert.assertEquals(NEPHEW_OF.getSourceNamePlural(), "nephews");
+        Assert.assertEquals(NEPHEW_OF.getTargetNamePlural(), "aunties");
+        
+        Assert.assertEquals(NEPHEW_OF.getInverseRelationship(), AUNTIE_OF);
+        Assert.assertEquals(AUNTIE_OF.getInverseRelationship(), NEPHEW_OF);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/test/java/org/apache/brooklyn/util/core/internal/FlagUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/internal/FlagUtilsTest.java b/core/src/test/java/org/apache/brooklyn/util/core/internal/FlagUtilsTest.java
index 81c760e..a75db17 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/internal/FlagUtilsTest.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/internal/FlagUtilsTest.java
@@ -272,6 +272,11 @@ public class FlagUtilsTest {
             return configSupport;
         }
         
+        @Override
+        public <T> T getConfig(ConfigKey<T> key) {
+            return config().get(key);
+        }
+        
         public <T> T setConfig(ConfigKey<T> key, T val) {
             return config().set(key, val);
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
index b278f02..e16d825 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
@@ -97,6 +97,11 @@ public class ObjectsYamlTest extends AbstractYamlTest {
         public void setDouble(Double value) { this.value = value; }
 
         @Override
+        public <T> T getConfig(ConfigKey<T> key) {
+            return config().get(key);
+        }
+        
+        @Override
         public <T> T setConfig(ConfigKey<T> key, T value) {
             return config().set(key, value);
         }


[8/8] incubator-brooklyn git commit: This closes #987

Posted by sv...@apache.org.
This closes #987

Introduce relationships between brooklyn objects


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

Branch: refs/heads/master
Commit: 52241ae613db56707b21a50696c531dbf6780e89
Parents: c6273b8 05f91af
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Tue Oct 27 16:47:19 2015 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Tue Oct 27 16:47:19 2015 +0200

----------------------------------------------------------------------
 .../basic/relations/RelationshipType.java       |  38 ++++
 .../org/apache/brooklyn/api/entity/Entity.java  |  11 +-
 .../apache/brooklyn/api/location/Location.java  |  11 +-
 .../api/mgmt/rebind/RebindExceptionHandler.java |   5 +
 .../mementos/BrooklynMementoPersister.java      |   5 +-
 .../api/mgmt/rebind/mementos/Memento.java       |   4 +-
 .../brooklyn/api/objs/BrooklynObject.java       |  26 +++
 .../apache/brooklyn/api/objs/Configurable.java  |   6 +
 .../org/apache/brooklyn/api/policy/Policy.java  |   9 +-
 .../apache/brooklyn/api/sensor/Enricher.java    |  15 +-
 .../org/apache/brooklyn/api/sensor/Feed.java    |   4 +
 .../core/catalog/internal/CatalogItemDo.java    |  21 ++-
 .../internal/CatalogItemDtoAbstract.java        |  18 +-
 .../core/enricher/AbstractEnricher.java         |   6 +
 .../brooklyn/core/entity/AbstractEntity.java    |   9 +-
 .../brooklyn/core/entity/EntityInternal.java    |   3 +
 .../brooklyn/core/entity/EntityRelations.java   | 180 ++++++++++++++++++
 .../apache/brooklyn/core/feed/AbstractFeed.java |   6 +
 .../core/location/AbstractLocation.java         |   8 +-
 .../access/PortForwardManagerClient.java        |   5 +
 .../location/internal/LocationInternal.java     |   3 +
 .../AbstractBrooklynObjectRebindSupport.java    |  27 +++
 .../mgmt/rebind/RebindContextLookupContext.java |  18 ++
 .../mgmt/rebind/RebindExceptionHandlerImpl.java |  17 +-
 .../core/mgmt/rebind/dto/AbstractMemento.java   |  47 ++---
 .../mgmt/rebind/dto/BasicEnricherMemento.java   |   1 -
 .../mgmt/rebind/dto/BasicEntityMemento.java     |   2 -
 .../core/mgmt/rebind/dto/BasicFeedMemento.java  |   1 -
 .../mgmt/rebind/dto/BasicLocationMemento.java   |   1 -
 .../mgmt/rebind/dto/BasicPolicyMemento.java     |   1 -
 .../mgmt/rebind/dto/MementosGenerators.java     |  13 +-
 .../core/objs/AbstractBrooklynObject.java       |  25 ++-
 .../core/objs/AbstractEntityAdjunct.java        |   3 +-
 .../core/objs/BrooklynObjectInternal.java       |  11 +-
 .../brooklyn/core/policy/AbstractPolicy.java    |   6 +
 .../relations/AbstractBasicRelationSupport.java |  63 +++++++
 .../relations/ByObjectBasicRelationSupport.java | 104 ++++++++++
 .../core/relations/EmptyRelationSupport.java    |  60 ++++++
 .../core/relations/RelationshipTypes.java       | 188 +++++++++++++++++++
 .../stock/SensorPropagatingEnricher.java        |   2 +-
 .../entity/group/AbstractGroupImpl.java         |   2 +
 .../util/core/xstream/XmlSerializer.java        |   3 +-
 .../effector/EffectorSayHiGroovyTest.groovy     |   2 +-
 .../mgmt/persist/XmlMementoSerializerTest.java  |  23 ++-
 .../rebind/RebindClassInitializationTest.java   |  78 ++++++++
 .../core/mgmt/rebind/RebindEntityTest.java      |   3 +-
 .../relations/RelationsEntityBasicTest.java     |  55 ++++++
 .../relations/RelationsEntityRebindTest.java    |  51 +++++
 .../core/relations/RelationshipTest.java        |  58 ++++++
 .../util/core/internal/FlagUtilsTest.java       |   5 +
 .../VanillaSoftwareProcessIntegrationTest.java  |   2 +-
 .../brooklyn/camp/brooklyn/ObjectsYamlTest.java |   5 +
 52 files changed, 1181 insertions(+), 89 deletions(-)
----------------------------------------------------------------------



[5/8] incubator-brooklyn git commit: remove generics on BrooklynObject internal hierarchy

Posted by sv...@apache.org.
remove generics on BrooklynObject internal hierarchy

simplifies things a lot without much work needed to cast or add correct-generic-type methods so that API is natural.


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

Branch: refs/heads/master
Commit: 890c5c046d22612969ccb8876a070a4b15ccb316
Parents: ed113a3
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Oct 27 12:33:47 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Oct 27 12:33:47 2015 +0000

----------------------------------------------------------------------
 .../org/apache/brooklyn/api/entity/Entity.java  |  1 +
 .../apache/brooklyn/api/location/Location.java  |  4 ++++
 .../org/apache/brooklyn/api/policy/Policy.java  |  4 ++++
 .../apache/brooklyn/api/sensor/Enricher.java    |  3 +++
 .../org/apache/brooklyn/api/sensor/Feed.java    |  4 ++++
 .../core/catalog/internal/CatalogItemDo.java    |  2 +-
 .../internal/CatalogItemDtoAbstract.java        |  2 +-
 .../core/enricher/AbstractEnricher.java         |  8 +++++++-
 .../brooklyn/core/entity/AbstractEntity.java    |  8 +++++++-
 .../brooklyn/core/entity/EntityInternal.java    |  5 ++++-
 .../brooklyn/core/entity/EntityRelations.java   | 14 +++++++------
 .../apache/brooklyn/core/feed/AbstractFeed.java |  8 +++++++-
 .../core/location/AbstractLocation.java         |  8 +++++++-
 .../access/PortForwardManagerClient.java        |  2 +-
 .../location/internal/LocationInternal.java     |  5 ++++-
 .../AbstractBrooklynObjectRebindSupport.java    |  4 ++--
 .../core/objs/AbstractBrooklynObject.java       | 21 +++++++-------------
 .../core/objs/AbstractEntityAdjunct.java        |  8 ++++----
 .../brooklyn/core/objs/BrooklynDynamicType.java |  4 ++--
 .../core/objs/BrooklynObjectInternal.java       |  4 ++--
 .../brooklyn/core/policy/AbstractPolicy.java    |  8 +++++++-
 .../relations/AbstractBasicRelationSupport.java |  8 ++++++++
 22 files changed, 95 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/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 3b333e0..3bca701 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
@@ -308,6 +308,7 @@ public interface Entity extends BrooklynObject {
 
     GroupSupport groups();
 
+    @Override
     RelationSupport<Entity> relations();
     
     @Beta

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/api/src/main/java/org/apache/brooklyn/api/location/Location.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/location/Location.java b/api/src/main/java/org/apache/brooklyn/api/location/Location.java
index 84e371b..3ef9251 100644
--- a/api/src/main/java/org/apache/brooklyn/api/location/Location.java
+++ b/api/src/main/java/org/apache/brooklyn/api/location/Location.java
@@ -131,4 +131,8 @@ public interface Location extends Serializable, BrooklynObject {
      * @throws NullPointerException if extensionType is null
      */
     <T> T getExtension(Class<T> extensionType);
+    
+    @Override
+    RelationSupport<Location> relations();
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/api/src/main/java/org/apache/brooklyn/api/policy/Policy.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/policy/Policy.java b/api/src/main/java/org/apache/brooklyn/api/policy/Policy.java
index 0235bac..5b1e2fa 100644
--- a/api/src/main/java/org/apache/brooklyn/api/policy/Policy.java
+++ b/api/src/main/java/org/apache/brooklyn/api/policy/Policy.java
@@ -73,4 +73,8 @@ public interface Policy extends EntityAdjunct, Rebindable, Configurable {
     @Override
     @Beta
     RebindSupport<PolicyMemento> getRebindSupport();
+    
+    @Override
+    RelationSupport<Policy> relations();
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/api/src/main/java/org/apache/brooklyn/api/sensor/Enricher.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/sensor/Enricher.java b/api/src/main/java/org/apache/brooklyn/api/sensor/Enricher.java
index 7d34e6c..3fde2a5 100644
--- a/api/src/main/java/org/apache/brooklyn/api/sensor/Enricher.java
+++ b/api/src/main/java/org/apache/brooklyn/api/sensor/Enricher.java
@@ -55,4 +55,7 @@ public interface Enricher extends EntityAdjunct, Rebindable, Configurable {
     @Beta
     RebindSupport<EnricherMemento> getRebindSupport();
 
+    @Override
+    RelationSupport<Enricher> relations();
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/api/src/main/java/org/apache/brooklyn/api/sensor/Feed.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/sensor/Feed.java b/api/src/main/java/org/apache/brooklyn/api/sensor/Feed.java
index b07b5e3..d50e092 100644
--- a/api/src/main/java/org/apache/brooklyn/api/sensor/Feed.java
+++ b/api/src/main/java/org/apache/brooklyn/api/sensor/Feed.java
@@ -67,4 +67,8 @@ public interface Feed extends EntityAdjunct, Rebindable {
     @Override
     @Beta
     RebindSupport<FeedMemento> getRebindSupport();
+    
+    @Override
+    RelationSupport<Feed> relations();
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/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 a3ae36e..fedc37e 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
@@ -33,7 +33,7 @@ import org.apache.brooklyn.core.relations.EmptyRelationSupport;
 
 import com.google.common.base.Preconditions;
 
-public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT>, BrooklynObjectInternal<CatalogItem<T,SpecT>,CatalogItemDo<T,SpecT>> {
+public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT>, BrooklynObjectInternal {
 
     protected final CatalogDo catalog;
     protected final CatalogItemDtoAbstract<T,SpecT> itemDto;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/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 078cd27..47ce81d 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
@@ -44,7 +44,7 @@ import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
 
-public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynObject<CatalogItem<T, SpecT>, CatalogItemDtoAbstract<T, SpecT>> implements CatalogItem<T, SpecT> {
+public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynObject implements CatalogItem<T, SpecT> {
 
     private static Logger LOG = LoggerFactory.getLogger(CatalogItemDtoAbstract.class);
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/core/src/main/java/org/apache/brooklyn/core/enricher/AbstractEnricher.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/enricher/AbstractEnricher.java b/core/src/main/java/org/apache/brooklyn/core/enricher/AbstractEnricher.java
index 2597baa..5471c78 100644
--- a/core/src/main/java/org/apache/brooklyn/core/enricher/AbstractEnricher.java
+++ b/core/src/main/java/org/apache/brooklyn/core/enricher/AbstractEnricher.java
@@ -43,7 +43,7 @@ import com.google.common.collect.Maps;
 /**
 * Base {@link Enricher} implementation; all enrichers should extend this or its children
 */
-public abstract class AbstractEnricher extends AbstractEntityAdjunct<Enricher,AbstractEnricher> implements Enricher {
+public abstract class AbstractEnricher extends AbstractEntityAdjunct implements Enricher {
 
     public static final ConfigKey<Boolean> SUPPRESS_DUPLICATES = ConfigKeys.newBooleanConfigKey("enricher.suppressDuplicates",
         "Whether duplicate values published by this enricher should be suppressed");
@@ -70,6 +70,12 @@ public abstract class AbstractEnricher extends AbstractEntityAdjunct<Enricher,Ab
         return new BasicEnricherRebindSupport(this);
     }
     
+    @SuppressWarnings("unchecked")
+    @Override
+    public RelationSupportInternal<Enricher> relations() {
+        return (RelationSupportInternal<Enricher>) super.relations();
+    }
+    
     @Override
     public EnricherType getEnricherType() {
         return enricherType.getSnapshot();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/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 5b52321..c75c908 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
@@ -141,7 +141,7 @@ import com.google.common.collect.Sets;
  * The legacy (pre 0.5) mechanism for creating entities is for others to call the constructor directly.
  * This is now deprecated.
  */
-public abstract class AbstractEntity extends AbstractBrooklynObject<Entity,EntityInternal> implements EntityLocal, EntityInternal {
+public abstract class AbstractEntity extends AbstractBrooklynObject implements EntityLocal, EntityInternal {
     
     private static final Logger LOG = LoggerFactory.getLogger(AbstractEntity.class);
     
@@ -2082,5 +2082,11 @@ public abstract class AbstractEntity extends AbstractBrooklynObject<Entity,Entit
         super.onTagsChanged();
         getManagementSupport().getEntityChangeListener().onTagsChanged();
     }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public RelationSupportInternal<Entity> relations() {
+        return (RelationSupportInternal<Entity>) super.relations();
+    }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/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 af81c21..4056eca 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
@@ -46,7 +46,7 @@ import com.google.common.annotations.Beta;
  * for the brooklyn framework only).
  */
 @Beta
-public interface EntityInternal extends BrooklynObjectInternal<Entity,EntityInternal>, EntityLocal, Rebindable {
+public interface EntityInternal extends BrooklynObjectInternal, EntityLocal, Rebindable {
     
     void addLocations(Collection<? extends Location> locations);
 
@@ -175,6 +175,9 @@ public interface EntityInternal extends BrooklynObjectInternal<Entity,EntityInte
     @Beta
     RebindSupport<EntityMemento> getRebindSupport();
 
+    @Override
+    RelationSupportInternal<Entity> relations();
+    
     /**
      * Can be called to request that the entity be persisted.
      * This persistence may happen asynchronously, or may not happen at all if persistence is disabled.

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java b/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java
index 7dfa93e..4621a76 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java
@@ -137,24 +137,26 @@ public class EntityRelations<T extends BrooklynObject> {
     
     @SuppressWarnings({ "rawtypes", "unchecked" })
     public static <T extends BrooklynObject> Set<Relationship<? super T,? extends BrooklynObject>> getRelationships(T source) {
-        return ((BrooklynObjectInternal)source).relations().getLocalBackingStore().getRelationships();
+        return (Set) ((BrooklynObjectInternal)source).relations().getLocalBackingStore().getRelationships();
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
     public static <T extends BrooklynObject,U extends BrooklynObject> Set<U> getRelations(Relationship<? super T,U> relationship, T source) {
-        return ((BrooklynObjectInternal)source).relations().getLocalBackingStore().getRelations(relationship);
+        return (Set) ((BrooklynObjectInternal)source).relations().getLocalBackingStore().getRelations((Relationship)relationship);
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
     public static <T extends BrooklynObject,U extends BrooklynObject> void add(T source, Relationship<? super T,? super U> relationship, U target) {
-        ((BrooklynObjectInternal)source).relations().getLocalBackingStore().add(relationship, target);
-        ((BrooklynObjectInternal)target).relations().getLocalBackingStore().add(relationship.getInverseRelationship(), source);
+        ((BrooklynObjectInternal)source).relations().getLocalBackingStore().add((Relationship)relationship, target);
+        if (relationship.getInverseRelationship()!=null)
+            ((BrooklynObjectInternal)target).relations().getLocalBackingStore().add((Relationship)relationship.getInverseRelationship(), source);
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
     public static <T extends BrooklynObject,U extends BrooklynObject> void remove(T source, Relationship<? super T,? super U> relationship, U target) {
-        ((BrooklynObjectInternal)source).relations().getLocalBackingStore().remove(relationship, target);
-        ((BrooklynObjectInternal)target).relations().getLocalBackingStore().remove(relationship.getInverseRelationship(), source);
+        ((BrooklynObjectInternal)source).relations().getLocalBackingStore().remove((Relationship)relationship, target);
+        if (relationship.getInverseRelationship()!=null)
+            ((BrooklynObjectInternal)target).relations().getLocalBackingStore().remove((Relationship)relationship.getInverseRelationship(), source);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/core/src/main/java/org/apache/brooklyn/core/feed/AbstractFeed.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/feed/AbstractFeed.java b/core/src/main/java/org/apache/brooklyn/core/feed/AbstractFeed.java
index 64320cd..5b057dd 100644
--- a/core/src/main/java/org/apache/brooklyn/core/feed/AbstractFeed.java
+++ b/core/src/main/java/org/apache/brooklyn/core/feed/AbstractFeed.java
@@ -42,7 +42,7 @@ import org.slf4j.LoggerFactory;
  * These generally poll or subscribe to get sensor values for an entity.
  * They make it easy to poll over http, jmx, etc.
  */
-public abstract class AbstractFeed extends AbstractEntityAdjunct<Feed,AbstractFeed> implements Feed {
+public abstract class AbstractFeed extends AbstractEntityAdjunct implements Feed {
 
     private static final Logger log = LoggerFactory.getLogger(AbstractFeed.class);
 
@@ -208,6 +208,12 @@ public abstract class AbstractFeed extends AbstractEntityAdjunct<Feed,AbstractFe
         return new BasicFeedRebindSupport(this);
     }
 
+    @SuppressWarnings("unchecked")
+    @Override
+    public RelationSupportInternal<Feed> relations() {
+        return (RelationSupportInternal<Feed>) super.relations();
+    }
+    
     @Override
     protected void onChanged() {
         // TODO Auto-generated method stub

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/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 996b1a0..c14472d 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
@@ -94,7 +94,7 @@ import com.google.common.reflect.TypeToken;
  * 
  * Override {@link #configure(Map)} to add special initialization logic.
  */
-public abstract class AbstractLocation extends AbstractBrooklynObject<Location,LocationInternal> implements LocationInternal, HasHostGeoInfo, Configurable {
+public abstract class AbstractLocation extends AbstractBrooklynObject implements LocationInternal, HasHostGeoInfo, Configurable {
     
     private static final long serialVersionUID = -7495805474138619830L;
 
@@ -755,6 +755,12 @@ public abstract class AbstractLocation extends AbstractBrooklynObject<Location,L
         return new BasicLocationRebindSupport(this);
     }
     
+    @SuppressWarnings("unchecked")
+    @Override
+    public RelationSupportInternal<Location> relations() {
+        return (RelationSupportInternal<Location>) super.relations();
+    }
+    
     @Override
     public boolean hasExtension(Class<?> extensionType) {
         return extensions.get().containsKey(checkNotNull(extensionType, "extensionType"));

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/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 d312f53..f2b9662 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
@@ -394,7 +394,7 @@ public class PortForwardManagerClient implements PortForwardManager {
     }
 
     @Override
-    public RelationSupport<?> relations() {
+    public RelationSupport<Location> relations() {
         return getDelegate().relations();
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/core/src/main/java/org/apache/brooklyn/core/location/internal/LocationInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/location/internal/LocationInternal.java b/core/src/main/java/org/apache/brooklyn/core/location/internal/LocationInternal.java
index fe9f669..5c83f2d 100644
--- a/core/src/main/java/org/apache/brooklyn/core/location/internal/LocationInternal.java
+++ b/core/src/main/java/org/apache/brooklyn/core/location/internal/LocationInternal.java
@@ -35,7 +35,7 @@ import com.google.common.annotations.Beta;
 /**
  * Information about locations private to Brooklyn.
  */
-public interface LocationInternal extends BrooklynObjectInternal<Location,LocationInternal>, Location {
+public interface LocationInternal extends BrooklynObjectInternal, Location {
 
     @Beta
     public static final ConfigKey<String> ORIGINAL_SPEC = ConfigKeys.newStringConfigKey("spec.original", "The original spec used to instantiate a location");
@@ -89,5 +89,8 @@ public interface LocationInternal extends BrooklynObjectInternal<Location,Locati
     @Beta
     RebindSupport<LocationMemento> getRebindSupport();
     
+    @Override
+    RelationSupportInternal<Location> relations();
+    
     ManagementContext getManagementContext();
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java
index 414cdbe..b56d8c6 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java
@@ -40,9 +40,9 @@ public abstract class AbstractBrooklynObjectRebindSupport<T extends Memento> imp
 
     private static final Logger LOG = LoggerFactory.getLogger(AbstractBrooklynObjectRebindSupport.class);
     
-    private final AbstractBrooklynObject<?,?> instance;
+    private final AbstractBrooklynObject instance;
     
-    public AbstractBrooklynObjectRebindSupport(AbstractBrooklynObject<?,?> instance) {
+    public AbstractBrooklynObjectRebindSupport(AbstractBrooklynObject instance) {
         this.instance = instance;
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java
index a0e02c5..d6ed647 100644
--- a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java
+++ b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java
@@ -24,7 +24,6 @@ import java.util.Set;
 
 import org.apache.brooklyn.api.internal.ApiObjectsFactory;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
-import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.core.entity.AbstractEntity;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.mgmt.rebind.RebindManagerImpl;
@@ -41,7 +40,7 @@ import com.google.common.collect.Iterables;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 
-public abstract class AbstractBrooklynObject<PublicSelfType extends BrooklynObject,InternalSelfType extends BrooklynObjectInternal<PublicSelfType,InternalSelfType>> implements BrooklynObjectInternal<PublicSelfType,InternalSelfType> {
+public abstract class AbstractBrooklynObject implements BrooklynObjectInternal {
 
     private static final Logger log = LoggerFactory.getLogger(AbstractBrooklynObject.class);
 
@@ -57,18 +56,11 @@ public abstract class AbstractBrooklynObject<PublicSelfType extends BrooklynObje
     @SetFromFlag(value = "tags")
     private final Set<Object> tags = Sets.newLinkedHashSet();
 
-    private RelationSupportInternal<PublicSelfType> relations = new ByObjectBasicRelationSupport<PublicSelfType>(getPublicThis(), new RelationChangedCallback());
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private RelationSupportInternal relations = new ByObjectBasicRelationSupport(this, new RelationChangedCallback());
     
     private volatile ManagementContext managementContext;
     
-    @SuppressWarnings("unchecked")
-    /** returns this cast to T, e.g. EntityInternal */
-    protected InternalSelfType getThis() { return (InternalSelfType)this; }
-    
-    /** returns this cast to PublicT, e.g. Entity */
-    @SuppressWarnings("unchecked")
-    protected PublicSelfType getPublicThis() { return (PublicSelfType)this; }
-    
     public abstract void setDisplayName(String newName);
 
     public AbstractBrooklynObject() {
@@ -98,7 +90,7 @@ public abstract class AbstractBrooklynObject<PublicSelfType extends BrooklynObje
      * @deprecated since 0.7.0; only used for legacy brooklyn types where constructor is called directly
      */
     @Deprecated
-    protected InternalSelfType configure() {
+    protected BrooklynObjectInternal configure() {
         return configure(Collections.emptyMap());
     }
 
@@ -117,7 +109,7 @@ public abstract class AbstractBrooklynObject<PublicSelfType extends BrooklynObje
      * @deprecated since 0.7.0; only used for legacy brooklyn types where constructor is called directly
      */
     @Deprecated
-    protected abstract InternalSelfType configure(Map<?, ?> flags);
+    protected abstract BrooklynObjectInternal configure(Map<?, ?> flags);
 
     protected boolean isLegacyConstruction() {
         return _legacyConstruction;
@@ -257,8 +249,9 @@ public abstract class AbstractBrooklynObject<PublicSelfType extends BrooklynObje
         }
     }
 
+    // XXX always override to get casting correct
     @Override
-    public RelationSupportInternal<PublicSelfType> relations() {
+    public RelationSupportInternal<?> relations() {
         return relations;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/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 9089095..d3bd9a8 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
@@ -67,7 +67,7 @@ import com.google.common.collect.Maps;
 /**
  * Common functionality for policies and enrichers
  */
-public abstract class AbstractEntityAdjunct<PublicSelfType extends BrooklynObject,InternalSelfType extends AbstractEntityAdjunct<PublicSelfType,InternalSelfType>> extends AbstractBrooklynObject<PublicSelfType,InternalSelfType> implements BrooklynObjectInternal<PublicSelfType,InternalSelfType>, EntityAdjunct, Configurable {
+public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject implements BrooklynObjectInternal, EntityAdjunct, Configurable {
     private static final Logger log = LoggerFactory.getLogger(AbstractEntityAdjunct.class);
 
     private boolean _legacyNoConstructionInit;
@@ -121,7 +121,7 @@ public abstract class AbstractEntityAdjunct<PublicSelfType extends BrooklynObjec
         _legacyNoConstructionInit = (properties != null) && Boolean.TRUE.equals(properties.get("noConstructionInit"));
         
         if (isLegacyConstruction()) {
-            InternalSelfType checkWeGetThis = configure(properties);
+            AbstractEntityAdjunct checkWeGetThis = configure(properties);
             assert this.equals(checkWeGetThis) : this+" configure method does not return itself; returns "+checkWeGetThis+" instead of "+this;
 
             boolean deferConstructionChecks = (properties.containsKey("deferConstructionChecks") && TypeCoercions.coerce(properties.get("deferConstructionChecks"), Boolean.class));
@@ -137,7 +137,7 @@ public abstract class AbstractEntityAdjunct<PublicSelfType extends BrooklynObjec
     @Override
     @Deprecated
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    public InternalSelfType configure(Map flags) {
+    public AbstractEntityAdjunct configure(Map flags) {
         // TODO only set on first time through
         boolean isFirstTime = true;
         
@@ -178,7 +178,7 @@ public abstract class AbstractEntityAdjunct<PublicSelfType extends BrooklynObjec
             }
         }
         
-        return (InternalSelfType) this;
+        return this;
     }
     
     /**

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynDynamicType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynDynamicType.java b/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynDynamicType.java
index d7c73dd..3642448 100644
--- a/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynDynamicType.java
+++ b/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynDynamicType.java
@@ -55,7 +55,7 @@ import com.google.common.collect.Lists;
  * for this reason it does *not* implement BrooklynType, but 
  * callers can call {@link #getSnapshot()} to get a snapshot such instance.  
  */
-public abstract class BrooklynDynamicType<T extends BrooklynObject, AbstractT extends AbstractBrooklynObject<T,?>> {
+public abstract class BrooklynDynamicType<T extends BrooklynObject, AbstractT extends AbstractBrooklynObject> {
 
     private static final Logger LOG = LoggerFactory.getLogger(BrooklynDynamicType.class);
 
@@ -144,7 +144,7 @@ public abstract class BrooklynDynamicType<T extends BrooklynObject, AbstractT ex
      * Prefers keys which overwrite other keys, and prefers keys which are lower in the hierarchy;
      * logs warnings if there are two conflicting keys which don't have an overwriting relationship.
      */
-    protected static void buildConfigKeys(Class<? extends BrooklynObject> clazz, AbstractBrooklynObject<?,?> optionalInstance, 
+    protected static void buildConfigKeys(Class<? extends BrooklynObject> clazz, AbstractBrooklynObject optionalInstance, 
             Map<String, FieldAndValue<ConfigKey<?>>> configKeys) {
         ListMultimap<String,FieldAndValue<ConfigKey<?>>> configKeysAll = 
                 ArrayListMultimap.<String, FieldAndValue<ConfigKey<?>>>create();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/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 658a9da..2da7463 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
@@ -31,7 +31,7 @@ import org.apache.brooklyn.util.guava.Maybe;
 
 import com.google.common.annotations.Beta;
 
-public interface BrooklynObjectInternal<PublicSelfType extends BrooklynObject, InternalSelfType extends BrooklynObjectInternal<PublicSelfType,InternalSelfType>> extends BrooklynObject, Rebindable {
+public interface BrooklynObjectInternal extends BrooklynObject, Rebindable {
     
     void setCatalogItemId(String id);
     
@@ -124,7 +124,7 @@ public interface BrooklynObjectInternal<PublicSelfType extends BrooklynObject, I
         public void unsubscribeAll();
     }
     
-    RelationSupportInternal<PublicSelfType> relations();
+    RelationSupportInternal<?> relations();
     
     public interface RelationSupportInternal<T extends BrooklynObject> extends BrooklynObject.RelationSupport<T> {
         @Beta

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/core/src/main/java/org/apache/brooklyn/core/policy/AbstractPolicy.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/policy/AbstractPolicy.java b/core/src/main/java/org/apache/brooklyn/core/policy/AbstractPolicy.java
index 3cb39e9..3af8176 100644
--- a/core/src/main/java/org/apache/brooklyn/core/policy/AbstractPolicy.java
+++ b/core/src/main/java/org/apache/brooklyn/core/policy/AbstractPolicy.java
@@ -37,7 +37,7 @@ import com.google.common.base.Objects;
 /**
  * Base {@link Policy} implementation; all policies should extend this or its children
  */
-public abstract class AbstractPolicy extends AbstractEntityAdjunct<Policy,AbstractPolicy> implements Policy, Configurable {
+public abstract class AbstractPolicy extends AbstractEntityAdjunct implements Policy, Configurable {
     @SuppressWarnings("unused")
     private static final Logger log = LoggerFactory.getLogger(AbstractPolicy.class);
 
@@ -109,6 +109,12 @@ public abstract class AbstractPolicy extends AbstractEntityAdjunct<Policy,Abstra
         return new BasicPolicyRebindSupport(this);
     }
 
+    @SuppressWarnings("unchecked")
+    @Override
+    public RelationSupportInternal<Policy> relations() {
+        return (RelationSupportInternal<Policy>) super.relations();
+    }
+    
     @Override
     public String toString() {
         return Objects.toStringHelper(getClass())

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/890c5c04/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java b/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java
index 3694fa8..6483e97 100644
--- a/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java
+++ b/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java
@@ -26,6 +26,14 @@ import org.apache.brooklyn.core.objs.BrooklynObjectInternal.RelationSupportInter
 
 import brooklyn.basic.relations.Relationship;
 
+/** This abstract impl delegates to {@link EntityRelations} for all changes, routing through a local backing store.
+ * This allows us to make the changes in both directions simultaneously when a relationship is bi-directional,
+ * and should facilitate changing a backing datastore or remote instances when that is supported.
+ * <p>
+ * Currently it can be implemented without it, simplifying things a bit (avoiding the double dispatch)
+ * apart from the {@link #add(Relationship, BrooklynObject)} method triggering the reverse addition
+ * if it isn't already present. TBD which is better (and the internal call to get the backing store is 
+ * marked as Beta). */
 public abstract class AbstractBasicRelationSupport<SourceType extends BrooklynObject> implements RelationSupportInternal<SourceType> {
 
     final SourceType source;


[3/8] incubator-brooklyn git commit: Merge branch 'master' into relationships

Posted by sv...@apache.org.
Merge branch 'master' into relationships


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

Branch: refs/heads/master
Commit: 1b71134a4001a7d27a2b7ef1e13ae3a296ce681a
Parents: 772e707 8457515
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Oct 27 09:51:05 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Oct 27 09:51:05 2015 +0000

----------------------------------------------------------------------
 core/pom.xml                                    |  52 ++-
 .../apache/brooklyn/core/BrooklynVersion.java   | 188 +++++---
 .../brooklyn/core/mgmt/ha/OsgiManager.java      |  16 +-
 .../core/mgmt/persist/XmlMementoSerializer.java |  35 +-
 .../core/objs/AbstractEntityAdjunct.java        |  21 +-
 .../util/core/BrooklynLanguageExtensions.java   |   2 -
 .../brooklyn/util/core/ResourceUtils.java       |  32 +-
 .../brooklyn/util/core/internal/Repeater.java   |   3 -
 .../apache/brooklyn/util/core/osgi/Osgis.java   | 389 +++--------------
 .../brooklyn/util/core/task/DynamicTasks.java   |  17 +
 core/src/test/dependencies/osgi/README.md       |  33 --
 .../src/test/dependencies/osgi/entities/pom.xml |  84 ----
 .../test/osgi/entities/SimpleApplication.java   |  28 --
 .../osgi/entities/SimpleApplicationImpl.java    |  27 --
 .../test/osgi/entities/SimpleEntity.java        |  28 --
 .../test/osgi/entities/SimpleEntityImpl.java    |  26 --
 .../test/osgi/entities/SimpleLocation.java      |  35 --
 .../test/osgi/entities/SimplePolicy.java        |  36 --
 .../apache/brooklyn/test/osgi/entities/icon.gif | Bin 43 -> 0 bytes
 .../dependencies/osgi/more-entities-v1/pom.xml  |  82 ----
 .../test/osgi/entities/more/MoreEntity.java     |  37 --
 .../test/osgi/entities/more/MoreEntityImpl.java |  43 --
 .../test/osgi/entities/more/MoreLocation.java   |  24 --
 .../test/osgi/entities/more/MorePolicy.java     |  25 --
 .../test/osgi/entities/more/MoreTemplate.java   |  24 --
 .../osgi/more-entities-v2-evil-twin/pom.xml     |  88 ----
 .../test/osgi/entities/more/MoreEntity.java     |  37 --
 .../test/osgi/entities/more/MoreEntityImpl.java |  46 --
 .../dependencies/osgi/more-entities-v2/pom.xml  |  88 ----
 .../test/osgi/entities/more/MoreEntity.java     |  40 --
 .../test/osgi/entities/more/MoreEntityImpl.java |  46 --
 .../test/osgi/entities/more/MoreLocation.java   |  26 --
 .../test/osgi/entities/more/MorePolicy.java     |  29 --
 .../test/osgi/entities/more/MoreTemplate.java   |  26 --
 .../policy/basic/AbstractEntityAdjunctTest.java |  52 +++
 .../brooklyn/core/BrooklynVersionTest.java      |   2 +-
 .../core/mgmt/osgi/OsgiStandaloneTest.java      |  75 +---
 .../core/mgmt/osgi/OsgiTestResources.java       |  74 ----
 .../mgmt/osgi/OsgiVersionMoreEntityTest.java    |   6 +-
 .../mgmt/persist/XmlMementoSerializerTest.java  |   2 +-
 ...stomAggregatingEnricherDeprecatedTest.groovy | 368 ----------------
 ...CustomAggregatingEnricherDeprecatedTest.java | 405 ++++++++++++++++++
 .../TransformingEnricherDeprecatedTest.groovy   |  83 ----
 .../TransformingEnricherDeprecatedTest.java     |  92 ++++
 .../util/core/internal/RepeaterTest.groovy      | 256 -----------
 .../util/core/internal/RepeaterTest.java        | 251 +++++++++++
 .../brooklyn/util/core/osgi/OsgiTestBase.java   |  56 +++
 .../brooklyn/util/core/osgi/OsgisTest.java      |  41 --
 core/src/test/resources/brooklyn/osgi/README.md |  25 --
 .../osgi/brooklyn-osgi-test-a_0.1.0.jar         | Bin 2055 -> 0 bytes
 .../osgi/brooklyn-osgi-test-a_0.1.0.txt         |  26 --
 .../osgi/brooklyn-test-osgi-entities.jar        | Bin 14454 -> 0 bytes
 .../osgi/brooklyn-test-osgi-entities.txt        |  26 --
 .../brooklyn-test-osgi-more-entities_0.1.0.jar  | Bin 14964 -> 0 bytes
 .../brooklyn-test-osgi-more-entities_0.1.0.txt  |  26 --
 .../brooklyn-test-osgi-more-entities_0.2.0.jar  | Bin 15622 -> 0 bytes
 .../brooklyn-test-osgi-more-entities_0.2.0.txt  |  26 --
 ...-test-osgi-more-entities_evil-twin_0.2.0.jar | Bin 13922 -> 0 bytes
 ...-test-osgi-more-entities_evil-twin_0.2.0.txt |  26 --
 .../guide/ops/catalog/images/add-to-catalog.png | Bin 0 -> 4919 bytes
 docs/guide/ops/catalog/index.md                 |  13 +-
 docs/guide/ops/locations/index.md               |  33 +-
 docs/guide/ops/locations/vpc-issues.md          |  32 ++
 docs/guide/start/managing.md                    |   3 +
 docs/guide/yaml/winrm/index.md                  |   7 +-
 examples/simple-web-cluster/pom.xml             |   4 -
 .../demo/WebClusterDatabaseExampleGroovy.groovy |  92 ----
 karaf/apache-brooklyn/pom.xml                   | 124 ++++++
 .../filtered-resources/etc/branding.properties  |  35 ++
 .../src/main/resources/etc/custom.properties    | 120 ++++++
 .../resources/etc/org.ops4j.pax.logging.cfg     |  46 ++
 .../src/main/resources/etc/system.properties    | 133 ++++++
 karaf/commands/pom.xml                          |  77 ++++
 .../apache/brooklyn/karaf/commands/Catalog.java |  44 ++
 karaf/feature.xml                               |  51 +++
 karaf/features/pom.xml                          |  64 +++
 karaf/features/src/main/feature/feature.xml     |  89 ++++
 .../features/src/main/history/dependencies.xml  |  47 ++
 karaf/itest/pom.xml                             | 188 ++++++++
 .../java/org/apache/brooklyn/AssemblyTest.java  | 117 +++++
 karaf/itest/src/test/resources/exam.properties  |  21 +
 karaf/itest/src/test/resources/logback.xml      |  43 ++
 karaf/pom.xml                                   | 143 +++++++
 locations/jclouds/pom.xml                       |  21 -
 .../location/jclouds/JcloudsLocation.java       |  25 +-
 .../location/jclouds/JcloudsSuseLiveTest.java   | 102 +++++
 .../AwsEc2LocationWindowsLiveTest.groovy        |  94 ----
 .../provider/AwsEc2LocationWindowsLiveTest.java |  95 +++++
 .../provider/CarrenzaLocationLiveTest.groovy    | 132 ------
 .../provider/CarrenzaLocationLiveTest.java      | 135 ++++++
 .../provider/GoGridLocationLiveTest.groovy      |  52 ---
 .../provider/GoGridLocationLiveTest.java        |  52 +++
 parent/pom.xml                                  | 189 ++------
 policy/pom.xml                                  |  25 +-
 .../policy/enricher/DeltaEnrichersTests.groovy  | 123 ------
 .../policy/enricher/DeltaEnrichersTests.java    | 144 +++++++
 .../enricher/RollingMeanEnricherTest.groovy     | 105 -----
 .../enricher/RollingMeanEnricherTest.java       | 106 +++++
 .../RollingTimeWindowMeanEnricherTest.groovy    | 155 -------
 .../RollingTimeWindowMeanEnricherTest.java      | 156 +++++++
 pom.xml                                         | 118 ++++-
 sandbox/database/pom.xml                        |  17 -
 .../brooklyn/entity/database/Database.groovy    |  53 ---
 .../brooklyn/entity/database/Database.java      |  42 ++
 .../apache/brooklyn/entity/database/Schema.java |  37 ++
 sandbox/nosql/pom.xml                           |  12 -
 .../Infinispan5ServerIntegrationTest.groovy     | 103 -----
 .../Infinispan5ServerIntegrationTest.java       | 104 +++++
 software/base/pom.xml                           |   9 -
 .../entity/machine/SetHostnameCustomizer.java   |  48 ++-
 .../system_service/SystemServiceEnricher.java   |  12 +-
 .../machine/SetHostnameCustomizerTest.java      |  92 +++-
 software/database/pom.xml                       |  23 -
 .../entity/database/DatastoreMixins.java        |   5 +-
 .../database/mysql/InitSlaveTaskBody.java       | 426 +++++++++++++++++++
 .../entity/database/mysql/MySqlCluster.java     |  38 +-
 .../entity/database/mysql/MySqlClusterImpl.java | 225 ++++------
 .../database/mysql/MySqlClusterUtils.java       |  52 +++
 .../entity/database/mysql/MySqlDriver.java      |   7 +-
 .../entity/database/mysql/MySqlNode.java        |  43 +-
 .../database/mysql/MySqlNodeEffectors.java      |  87 ++++
 .../entity/database/mysql/MySqlNodeImpl.java    |   7 +-
 .../entity/database/mysql/MySqlSshDriver.java   |  67 ++-
 .../database/mysql/ReplicationSnapshot.java     |  58 +++
 .../entity/database/mysql/mysql_slave.conf      |  25 +-
 .../entity/database/VogellaExampleAccess.java   |  63 ++-
 .../mysql/MySqlClusterIntegrationTest.java      | 162 ++++++-
 .../database/mysql/MySqlClusterTestHelper.java  |  64 ++-
 software/messaging/pom.xml                      |   9 -
 software/nosql/pom.xml                          |   9 -
 .../nosql/couchdb/AbstractCouchDBNodeTest.java  |   5 -
 software/osgi/pom.xml                           |   4 -
 software/webapp/pom.xml                         |  18 -
 .../webapp/WebAppLiveIntegrationTest.groovy     | 101 -----
 .../webapp/WebAppLiveIntegrationTest.java       |  91 ++++
 ...namicWebAppClusterRebindIntegrationTest.java |   3 -
 usage/camp/pom.xml                              |   7 +
 .../catalog/AbstractCatalogXmlTest.java         |   2 +-
 .../brooklyn/catalog/CatalogYamlEntityTest.java |   2 +-
 .../brooklyn/catalog/CatalogYamlRebindTest.java |  24 +-
 .../catalog/CatalogYamlTemplateTest.java        |   2 +-
 usage/cli/pom.xml                               |  16 -
 usage/downstream-parent/pom.xml                 |   1 -
 usage/launcher/pom.xml                          |   4 -
 usage/qa/pom.xml                                |   4 -
 usage/rest-server/pom.xml                       |   4 -
 usage/test-support/pom.xml                      |   5 -
 .../org/apache/brooklyn/util/GenericTypes.java  |  37 ++
 .../brooklyn/util/exceptions/Exceptions.java    |   5 +
 .../brooklyn/util/text/StringEscapes.java       |  14 +-
 .../util/exceptions/ExceptionsTest.java         |  97 ++++-
 utils/groovy/pom.xml                            |  12 -
 .../util/groovy/FromCallableClosure.java        |  38 ++
 .../util/groovy/FromFunctionClosure.java        |  39 ++
 .../util/groovy/FromRunnableClosure.java        |  46 ++
 .../util/groovy/GroovyJavaMethods.groovy        | 146 -------
 .../brooklyn/util/groovy/GroovyJavaMethods.java | 200 +++++++++
 .../brooklyn/util/groovy/JavadocDummy.java      |  30 --
 .../brooklyn/util/groovy/LanguageUtils.groovy   | 383 -----------------
 .../brooklyn/util/groovy/TimeExtras.groovy      |  83 ----
 .../util/groovy/LanguageUtilsTest.groovy        | 152 -------
 .../brooklyn/util/groovy/TimeExtrasTest.groovy  |  49 ---
 utils/rt-felix/pom.xml                          |  61 +++
 .../rt/felix/EmbeddedFelixFramework.java        | 258 +++++++++++
 .../brooklyn/rt/felix/ManifestHelper.java       | 103 +++++
 .../rt/felix/EmbeddedFelixFrameworkTest.java    | 101 +++++
 utils/rt-osgi/pom.xml                           |  53 +++
 .../apache/brooklyn/util/osgi/OsgiUtils.java    | 101 +++++
 .../brooklyn/util/osgi/VersionedName.java       |  76 ++++
 .../brooklyn/util/osgi/OsgiTestResources.java   |  74 ++++
 .../apache/brooklyn/util/osgi/OsgisTest.java    |  39 ++
 .../src/test/resources/brooklyn/osgi/README.md  |  25 ++
 .../osgi/brooklyn-osgi-test-a_0.1.0.jar         | Bin 0 -> 2055 bytes
 .../osgi/brooklyn-osgi-test-a_0.1.0.txt         |  26 ++
 .../osgi/brooklyn-test-osgi-entities.jar        | Bin 0 -> 14454 bytes
 .../osgi/brooklyn-test-osgi-entities.txt        |  26 ++
 .../brooklyn-test-osgi-more-entities_0.1.0.jar  | Bin 0 -> 14964 bytes
 .../brooklyn-test-osgi-more-entities_0.1.0.txt  |  26 ++
 .../brooklyn-test-osgi-more-entities_0.2.0.jar  | Bin 0 -> 15622 bytes
 .../brooklyn-test-osgi-more-entities_0.2.0.txt  |  26 ++
 ...-test-osgi-more-entities_evil-twin_0.2.0.jar | Bin 0 -> 13922 bytes
 ...-test-osgi-more-entities_evil-twin_0.2.0.txt |  26 ++
 .../test/resources/dependencies/osgi/README.md  |  33 ++
 .../dependencies/osgi/entities/pom.xml          |  84 ++++
 .../test/osgi/entities/SimpleApplication.java   |  28 ++
 .../osgi/entities/SimpleApplicationImpl.java    |  27 ++
 .../test/osgi/entities/SimpleEntity.java        |  28 ++
 .../test/osgi/entities/SimpleEntityImpl.java    |  26 ++
 .../test/osgi/entities/SimpleLocation.java      |  35 ++
 .../test/osgi/entities/SimplePolicy.java        |  36 ++
 .../apache/brooklyn/test/osgi/entities/icon.gif | Bin 0 -> 43 bytes
 .../dependencies/osgi/more-entities-v1/pom.xml  |  82 ++++
 .../test/osgi/entities/more/MoreEntity.java     |  37 ++
 .../test/osgi/entities/more/MoreEntityImpl.java |  43 ++
 .../test/osgi/entities/more/MoreLocation.java   |  24 ++
 .../test/osgi/entities/more/MorePolicy.java     |  25 ++
 .../test/osgi/entities/more/MoreTemplate.java   |  24 ++
 .../osgi/more-entities-v2-evil-twin/pom.xml     |  88 ++++
 .../test/osgi/entities/more/MoreEntity.java     |  37 ++
 .../test/osgi/entities/more/MoreEntityImpl.java |  46 ++
 .../dependencies/osgi/more-entities-v2/pom.xml  |  88 ++++
 .../test/osgi/entities/more/MoreEntity.java     |  40 ++
 .../test/osgi/entities/more/MoreEntityImpl.java |  46 ++
 .../test/osgi/entities/more/MoreLocation.java   |  26 ++
 .../test/osgi/entities/more/MorePolicy.java     |  29 ++
 .../test/osgi/entities/more/MoreTemplate.java   |  26 ++
 206 files changed, 7482 insertions(+), 5006 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1b71134a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunct.java
----------------------------------------------------------------------


[7/8] incubator-brooklyn git commit: ensure all CatalogItem impls give no-op relations, and misc cleanup

Posted by sv...@apache.org.
ensure all CatalogItem impls give no-op relations, and misc cleanup

fixes bug where catalog items wouldn't rebind because the relations field is not set on deserialization; see discussion at https://github.com/apache/incubator-brooklyn/pull/987.

re cleanup, mainly removing in some places where i noticed XXX was used in addition to things i added during this dev work in order to test things, and some javadoc near where i've been working.


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

Branch: refs/heads/master
Commit: 05f91af1c95e2b235b3126ac06c045373a806d7a
Parents: 09aab58
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Oct 27 13:18:41 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Oct 27 13:18:41 2015 +0000

----------------------------------------------------------------------
 .../brooklyn/core/catalog/internal/CatalogItemDo.java    |  1 +
 .../core/catalog/internal/CatalogItemDtoAbstract.java    | 11 +++++++++++
 .../brooklyn/core/objs/AbstractBrooklynObject.java       |  6 +++---
 .../enricher/stock/SensorPropagatingEnricher.java        |  2 +-
 .../apache/brooklyn/util/core/xstream/XmlSerializer.java |  3 +--
 .../core/mgmt/persist/XmlMementoSerializerTest.java      |  5 +----
 .../base/VanillaSoftwareProcessIntegrationTest.java      |  2 +-
 7 files changed, 19 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/05f91af1/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 fedc37e..2aa8479 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
@@ -66,6 +66,7 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT>, BrooklynObj
     }
     
     /**
+     * Overrides the parent so that relations are not visible.
      * @return an immutable empty relation support object; relations are not supported,
      * but we do not throw on access to enable reads in a consistent manner
      */

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/05f91af1/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 47ce81d..6262508 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
@@ -32,6 +32,7 @@ import org.apache.brooklyn.api.mgmt.rebind.mementos.CatalogItemMemento;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.mgmt.rebind.BasicCatalogItemRebindSupport;
 import org.apache.brooklyn.core.objs.AbstractBrooklynObject;
+import org.apache.brooklyn.core.relations.EmptyRelationSupport;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.core.flags.FlagUtils;
 import org.apache.brooklyn.util.core.flags.SetFromFlag;
@@ -244,6 +245,16 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
         return new BasicCatalogItemRebindSupport(this);
     }
 
+    /**
+     * Overrides the parent so that relations are not visible.
+     * @return an immutable empty relation support object; relations are not supported,
+     * but we do not throw on access to enable reads in a consistent manner
+     */
+    @Override
+    public RelationSupportInternal<CatalogItem<T,SpecT>> relations() {
+        return new EmptyRelationSupport<CatalogItem<T,SpecT>>(this);
+    }
+
     @Override
     public void setDisplayName(String newName) {
         this.displayName = newName;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/05f91af1/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java
index d6ed647..e2592b9 100644
--- a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java
+++ b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java
@@ -52,12 +52,12 @@ public abstract class AbstractBrooklynObject implements BrooklynObjectInternal {
 
     private String catalogItemId;
 
-    /** subclasses should synchronize on this for all access */
+    /** callers (only in TagSupport) should synchronize on this for all access */
     @SetFromFlag(value = "tags")
     private final Set<Object> tags = Sets.newLinkedHashSet();
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    private RelationSupportInternal relations = new ByObjectBasicRelationSupport(this, new RelationChangedCallback());
+    private final RelationSupportInternal relations = new ByObjectBasicRelationSupport(this, new RelationChangedCallback());
     
     private volatile ManagementContext managementContext;
     
@@ -249,7 +249,7 @@ public abstract class AbstractBrooklynObject implements BrooklynObjectInternal {
         }
     }
 
-    // XXX always override to get casting correct
+    // always override to get casting correct
     @Override
     public RelationSupportInternal<?> relations() {
         return relations;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/05f91af1/core/src/main/java/org/apache/brooklyn/enricher/stock/SensorPropagatingEnricher.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/enricher/stock/SensorPropagatingEnricher.java b/core/src/main/java/org/apache/brooklyn/enricher/stock/SensorPropagatingEnricher.java
index f266a80..5f1b9ed 100644
--- a/core/src/main/java/org/apache/brooklyn/enricher/stock/SensorPropagatingEnricher.java
+++ b/core/src/main/java/org/apache/brooklyn/enricher/stock/SensorPropagatingEnricher.java
@@ -41,7 +41,7 @@ import com.google.common.collect.Sets;
  * an enricher policy which just listens for the target sensor(s) on a child entity and passes it up.
  * now superseded by syntax such as:
  * 
- * <pre>{@code Enrichers.builder().propagating(XXX).from(source).build()}</pre>
+ * <pre>{@code Enrichers.builder().propagating(sensor).from(source).build()}</pre>
  * 
  * @deprecated since 0.7.0; use {@link Enrichers#builder()}
  * 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/05f91af1/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlSerializer.java b/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlSerializer.java
index c83e25c..12561d3 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlSerializer.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/xstream/XmlSerializer.java
@@ -42,8 +42,7 @@ import com.thoughtworks.xstream.mapper.MapperWrapper;
 public class XmlSerializer<T> {
 
     private final Map<String, String> deserializingClassRenames;
-    // XXX protected
-    public final XStream xstream;
+    protected final XStream xstream;
 
     public XmlSerializer() {
         this(ImmutableMap.<String, String>of());

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/05f91af1/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
index 3ed5486..6bd850a 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
@@ -48,7 +48,6 @@ import org.apache.brooklyn.core.catalog.internal.CatalogItemDtoAbstract;
 import org.apache.brooklyn.core.catalog.internal.CatalogTestUtils;
 import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.location.SimulatedLocation;
-import org.apache.brooklyn.util.osgi.OsgiTestResources;
 import org.apache.brooklyn.core.mgmt.osgi.OsgiVersionMoreEntityTest;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
 import org.apache.brooklyn.core.test.entity.TestApplication;
@@ -60,6 +59,7 @@ import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.net.Networking;
 import org.apache.brooklyn.util.net.UserAndHostAndPort;
+import org.apache.brooklyn.util.osgi.OsgiTestResources;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.annotations.BeforeMethod;
@@ -71,7 +71,6 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Maps;
-import com.thoughtworks.xstream.converters.Converter;
 
 public class XmlMementoSerializerTest {
 
@@ -400,8 +399,6 @@ public class XmlMementoSerializerTest {
 
     @SuppressWarnings("unchecked")
     private <T> T assertSerializeAndDeserialize(T obj) throws Exception {
-Converter x = serializer.xstream.getConverterLookup().lookupConverterForType(Class.class);
-System.out.println("XXX: "+x);
         String serializedForm = serializer.toString(obj);
         LOG.info("serializedForm=" + serializedForm);
         Object deserialized = serializer.fromString(serializedForm);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/05f91af1/software/base/src/test/java/org/apache/brooklyn/entity/software/base/VanillaSoftwareProcessIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/VanillaSoftwareProcessIntegrationTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/VanillaSoftwareProcessIntegrationTest.java
index 141945b..082c4b1 100644
--- a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/VanillaSoftwareProcessIntegrationTest.java
+++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/VanillaSoftwareProcessIntegrationTest.java
@@ -188,7 +188,7 @@ public class VanillaSoftwareProcessIntegrationTest extends BrooklynAppLiveTestSu
         assertEquals(new String(Files.readAllBytes(runRecord)).trim(), "installCommand");
     }
 
-    // Installation creates a installs/VanillaSoftwareProcess_0.0.0_XXXX/BROOKLYN marker file.
+    // Installation creates a installs/VanillaSoftwareProcess_0.0.0_nnnnn/BROOKLYN marker file.
     // It indicates that installation has already been done successfully, so it is skipped the second time.
     // Assert it respects different values for the install script, to ensure each different VanillaSoftwareProcess
     // does get installed!


[2/8] incubator-brooklyn git commit: Introduce relationships between brooklyn objects

Posted by sv...@apache.org.
Introduce relationships between brooklyn objects

adds BrooklynObject.relations() and relationships such as MANAGER_OF and IN_GROUP.
includes tests, also convering persistence.
also adds self-bounding generics to BrooklynObject, and lifts getConfig(key) to Configurable to avoid generics conflicts (not sure why `public <T> T getConfig(ConfigKey<T> key)` declared in two interfaces is incompatible but it is apparently).

however there is much still to do:
* add relations to CAMP, and to the REST API and UI
* use relations for groups and children, and for locations, policies, etc (ensuring old persistence is still supported)


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

Branch: refs/heads/master
Commit: 772e707f81fd34e3db2eafca3067890f384cb9e1
Parents: e3553a1
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Jun 22 23:09:15 2015 -0700
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Oct 23 14:06:54 2015 +0100

----------------------------------------------------------------------
 .../brooklyn/basic/relations/Relationship.java  |  38 ++++
 .../org/apache/brooklyn/api/entity/Entity.java  |   2 +
 .../api/mgmt/rebind/mementos/Memento.java       |   5 +-
 .../brooklyn/api/objs/BrooklynObject.java       |  15 ++
 .../apache/brooklyn/api/objs/Configurable.java  |   5 +
 .../apache/brooklyn/api/sensor/Enricher.java    |  12 --
 .../core/catalog/internal/CatalogItemDo.java    |  20 +-
 .../internal/CatalogItemDtoAbstract.java        |   9 +-
 .../core/enricher/AbstractEnricher.java         |   2 +-
 .../brooklyn/core/entity/AbstractEntity.java    |   5 +-
 .../brooklyn/core/entity/EntityInternal.java    |   2 +-
 .../brooklyn/core/entity/EntityRelations.java   | 160 ++++++++++++++++
 .../apache/brooklyn/core/feed/AbstractFeed.java |   2 +-
 .../core/location/AbstractLocation.java         |   4 +-
 .../access/PortForwardManagerClient.java        |   5 +
 .../location/internal/LocationInternal.java     |   2 +-
 .../AbstractBrooklynObjectRebindSupport.java    |  23 ++-
 .../core/mgmt/rebind/dto/AbstractMemento.java   |  36 ++--
 .../mgmt/rebind/dto/BasicEnricherMemento.java   |   1 -
 .../mgmt/rebind/dto/BasicEntityMemento.java     |   2 -
 .../core/mgmt/rebind/dto/BasicFeedMemento.java  |   1 -
 .../mgmt/rebind/dto/BasicLocationMemento.java   |   1 -
 .../mgmt/rebind/dto/BasicPolicyMemento.java     |   1 -
 .../mgmt/rebind/dto/MementosGenerators.java     |  12 +-
 .../core/objs/AbstractBrooklynObject.java       |  32 +++-
 .../core/objs/AbstractEntityAdjunct.java        |   9 +-
 .../brooklyn/core/objs/BrooklynDynamicType.java |   4 +-
 .../core/objs/BrooklynObjectInternal.java       |  13 +-
 .../brooklyn/core/policy/AbstractPolicy.java    |   2 +-
 .../relations/AbstractBasicRelationSupport.java |  55 ++++++
 .../relations/ByObjectBasicRelationSupport.java | 103 ++++++++++
 .../brooklyn/core/relations/Relationships.java  | 188 +++++++++++++++++++
 .../entity/group/AbstractGroupImpl.java         |   2 +
 .../effector/EffectorSayHiGroovyTest.groovy     |   2 +-
 .../relations/RelationsEntityBasicTest.java     |  55 ++++++
 .../relations/RelationsEntityRebindTest.java    |  51 +++++
 .../core/relations/RelationshipTest.java        |  58 ++++++
 .../util/core/internal/FlagUtilsTest.java       |   5 +
 .../brooklyn/camp/brooklyn/ObjectsYamlTest.java |   5 +
 39 files changed, 876 insertions(+), 73 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/api/src/main/java/brooklyn/basic/relations/Relationship.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/basic/relations/Relationship.java b/api/src/main/java/brooklyn/basic/relations/Relationship.java
new file mode 100644
index 0000000..bc17e6a
--- /dev/null
+++ b/api/src/main/java/brooklyn/basic/relations/Relationship.java
@@ -0,0 +1,38 @@
+/*
+ * 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 brooklyn.basic.relations;
+
+import brooklyn.basic.relations.Relationship;
+
+
+public interface Relationship<SourceType,TargetType> {
+
+    public String getRelationshipTypeName();
+    public Class<SourceType> getSourceType();
+    public Class<TargetType> getTargetType();
+    
+    public String getSourceName();
+    public String getSourceNamePlural();
+
+    public String getTargetName();
+    public String getTargetNamePlural();
+
+    public Relationship<TargetType,SourceType> getInverseRelationship();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/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 e01d5e2..a15f4e1 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
@@ -314,6 +314,8 @@ public interface Entity extends BrooklynObject {
 
     GroupSupport groups();
 
+    RelationSupport<Entity> relations();
+    
     @Beta
     public interface SensorSupport {
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java
index 4a21117..b57780d 100644
--- a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java
@@ -21,9 +21,11 @@ package org.apache.brooklyn.api.mgmt.rebind.mementos;
 import java.io.Serializable;
 import java.util.Collection;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
+import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.objs.EntityAdjunct;
 
 /**
@@ -77,7 +79,8 @@ public interface Memento extends Serializable {
 
     public Collection<Object> getTags();
     
+    Map<String, Set<BrooklynObject>> getRelations();
+    
     /** Null for {@link Entity}, but important for adjuncts; see {@link EntityAdjunct#getUniqueTag()} */
     public String getUniqueTag();
-    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/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 f3fcad4..8648491 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
@@ -34,6 +34,8 @@ import org.apache.brooklyn.api.sensor.SensorEventListener;
 import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableMap;
 
+import brooklyn.basic.relations.Relationship;
+
 /**
  * Super-type of entity, location, policy and enricher.
  */
@@ -70,6 +72,12 @@ public interface BrooklynObject extends Identifiable, Configurable {
      */
     SubscriptionSupport subscriptions();
 
+    /**
+     * Relations specify a typed, directed connection between two entities.
+     * Generic type is overridden in sub-interfaces.
+     */
+    public RelationSupport<?> relations();
+    
     public interface TagSupport {
         /**
          * @return An immutable copy of the set of tags on this entity. 
@@ -141,4 +149,11 @@ public interface BrooklynObject extends Identifiable, Configurable {
          */
         boolean unsubscribe(SubscriptionHandle handle);
     }
+    
+    public interface RelationSupport<T extends BrooklynObject> {
+        public <U extends BrooklynObject> void add(Relationship<? super T,U> relationship, U target);
+        public <U extends BrooklynObject> void remove(Relationship<? super T,U> relationship, U target);
+        public Set<Relationship<? super T,? extends BrooklynObject>> getRelationships();
+        public <U extends BrooklynObject> Set<U> getRelations(Relationship<? super T,U> relationship);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java b/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java
index 513c8d7..5f1b294 100644
--- a/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java
+++ b/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java
@@ -41,6 +41,11 @@ public interface Configurable {
     @Deprecated
     public <T> T setConfig(ConfigKey<T> key, T val);
 
+    /**
+     * Convenience method for {@code config().get(key)}
+     */
+    <T> T getConfig(ConfigKey<T> key);
+
     ConfigurationSupport config();
     
     @Beta

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/api/src/main/java/org/apache/brooklyn/api/sensor/Enricher.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/sensor/Enricher.java b/api/src/main/java/org/apache/brooklyn/api/sensor/Enricher.java
index aaaecf0..7d34e6c 100644
--- a/api/src/main/java/org/apache/brooklyn/api/sensor/Enricher.java
+++ b/api/src/main/java/org/apache/brooklyn/api/sensor/Enricher.java
@@ -24,7 +24,6 @@ import org.apache.brooklyn.api.mgmt.rebind.mementos.EnricherMemento;
 import org.apache.brooklyn.api.objs.Configurable;
 import org.apache.brooklyn.api.objs.EntityAdjunct;
 import org.apache.brooklyn.api.policy.Policy;
-import org.apache.brooklyn.config.ConfigKey;
 
 import com.google.common.annotations.Beta;
 
@@ -48,17 +47,6 @@ public interface Enricher extends EntityAdjunct, Rebindable, Configurable {
     EnricherType getEnricherType();
 
     /**
-     * Convenience method for {@code config().get(key)}
-     */
-    <T> T getConfig(ConfigKey<T> key);
-    
-    /**
-     * @deprecated since 0.7.0; use {@link #config()}, such as {@code policy.config().setConfig(key, val)}
-     */
-    @Deprecated
-    <T> T setConfig(ConfigKey<T> key, T val);
-
-    /**
      * Users are strongly discouraged from calling or overriding this method.
      * It is for internal calls only, relating to persisting/rebinding entities.
      * This method may change (or be removed) in a future release without notice.

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/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 0545a06..7f3a54a 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
@@ -23,17 +23,16 @@ import java.util.Collection;
 import javax.annotation.Nonnull;
 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;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.CatalogItemMemento;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
 
 import com.google.common.base.Preconditions;
 
-public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT>, BrooklynObjectInternal {
+public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT>, BrooklynObjectInternal<CatalogItem<T,SpecT>,CatalogItemDo<T,SpecT>> {
 
     protected final CatalogDo catalog;
     protected final CatalogItemDtoAbstract<T,SpecT> itemDto;
@@ -65,6 +64,19 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT>, BrooklynObj
         throw new UnsupportedOperationException();
     }
     
+    /**
+     * @throws UnsupportedOperationException; relations are not supported for catalog items
+     */
+    @Override
+    public RelationSupportInternal<CatalogItem<T,SpecT>> relations() {
+        throw new UnsupportedOperationException();
+    }
+    
+    @Override
+    public <U> U getConfig(ConfigKey<U> key) {
+        return config().get(key);
+    }
+    
     @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/772e707f/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 c950b7b..078cd27 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
@@ -44,7 +44,7 @@ import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
 
-public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynObject implements CatalogItem<T, SpecT> {
+public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynObject<CatalogItem<T, SpecT>, CatalogItemDtoAbstract<T, SpecT>> implements CatalogItem<T, SpecT> {
 
     private static Logger LOG = LoggerFactory.getLogger(CatalogItemDtoAbstract.class);
 
@@ -82,6 +82,11 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
     }
     
     @Override
+    public <U> U getConfig(ConfigKey<U> key) {
+        return config().get(key);
+    }
+    
+    @Override
     public <U> U setConfig(ConfigKey<U> key, U val) {
         return config().set(key, val);
     }
@@ -245,7 +250,7 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
     }
 
     @Override
-    protected AbstractBrooklynObject configure(Map<?, ?> flags) {
+    protected CatalogItemDtoAbstract<T, SpecT> configure(Map<?, ?> flags) {
         FlagUtils.setFieldsFromFlags(flags, this);
         return this;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/enricher/AbstractEnricher.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/enricher/AbstractEnricher.java b/core/src/main/java/org/apache/brooklyn/core/enricher/AbstractEnricher.java
index 8c3f41e..2597baa 100644
--- a/core/src/main/java/org/apache/brooklyn/core/enricher/AbstractEnricher.java
+++ b/core/src/main/java/org/apache/brooklyn/core/enricher/AbstractEnricher.java
@@ -43,7 +43,7 @@ import com.google.common.collect.Maps;
 /**
 * Base {@link Enricher} implementation; all enrichers should extend this or its children
 */
-public abstract class AbstractEnricher extends AbstractEntityAdjunct implements Enricher {
+public abstract class AbstractEnricher extends AbstractEntityAdjunct<Enricher,AbstractEnricher> implements Enricher {
 
     public static final ConfigKey<Boolean> SUPPRESS_DUPLICATES = ConfigKeys.newBooleanConfigKey("enricher.suppressDuplicates",
         "Whether duplicate values published by this enricher should be suppressed");

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/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 65ec72f..5b52321 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
@@ -141,7 +141,7 @@ import com.google.common.collect.Sets;
  * The legacy (pre 0.5) mechanism for creating entities is for others to call the constructor directly.
  * This is now deprecated.
  */
-public abstract class AbstractEntity extends AbstractBrooklynObject implements EntityLocal, EntityInternal {
+public abstract class AbstractEntity extends AbstractBrooklynObject<Entity,EntityInternal> implements EntityLocal, EntityInternal {
     
     private static final Logger LOG = LoggerFactory.getLogger(AbstractEntity.class);
     
@@ -287,7 +287,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         entityType = new EntityDynamicType(this);
         
         if (isLegacyConstruction()) {
-            AbstractBrooklynObject checkWeGetThis = configure(flags);
+            AbstractEntity checkWeGetThis = configure(flags);
             assert this.equals(checkWeGetThis) : this+" configure method does not return itself; returns "+checkWeGetThis+" instead of "+this;
 
             boolean deferConstructionChecks = (flags.containsKey("deferConstructionChecks") && TypeCoercions.coerce(flags.get("deferConstructionChecks"), Boolean.class));
@@ -2082,4 +2082,5 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         super.onTagsChanged();
         getManagementSupport().getEntityChangeListener().onTagsChanged();
     }
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/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 27b09a4..af81c21 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
@@ -46,7 +46,7 @@ import com.google.common.annotations.Beta;
  * for the brooklyn framework only).
  */
 @Beta
-public interface EntityInternal extends BrooklynObjectInternal, EntityLocal, Rebindable {
+public interface EntityInternal extends BrooklynObjectInternal<Entity,EntityInternal>, EntityLocal, Rebindable {
     
     void addLocations(Collection<? extends Location> locations);
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java b/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java
new file mode 100644
index 0000000..7b20845
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java
@@ -0,0 +1,160 @@
+/*
+ * 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.entity;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.Group;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
+import org.apache.brooklyn.core.relations.Relationships;
+import org.apache.brooklyn.util.collections.MutableMap;
+
+import com.google.common.annotations.Beta;
+
+import brooklyn.basic.relations.Relationship;
+
+/** TODO these relations are not used yet; see issue where this is introduced and email thread */
+@Beta
+public class EntityRelations<T extends BrooklynObject> {
+
+    /** {@link #MANAGER_OF} indicates that one entity is the manager of another entity,
+     * in the internal Brooklyn management hierarchy model.
+     * Apart from root {@link Application} entities, every deployed entity must have exactly one manager.  
+     * The inverse relationship is {@link #MANAGED_BY}. */ 
+    public static final Relationship<Entity,Entity> MANAGER_OF = Relationships.newRelationshipPair(
+        "manager", "managers", Entity.class, "manager_of", 
+        "managed child", "managed children", Entity.class, "managed_by");
+    /** Inverse of {@link #MANAGER_OF}. */
+    public static final Relationship<Entity,Entity> MANAGED_BY = MANAGER_OF.getInverseRelationship();
+    
+    /** {@link #GROUP_CONTAINS} indicates that one entity, typically a {@link Group},
+     * has zero or more entities which are labelled as "members" of that group entity.
+     * What membership means will depend on the group entity.
+     * An entity may be a member of any number of other entities.  
+     * The inverse relationship is {@link #IN_GROUP}. */ 
+    public static final Relationship<Entity,Entity> GROUP_CONTAINS = Relationships.newRelationshipPair(
+        "group", "groups", Entity.class, "group_contains",
+        "member", "members", Entity.class, "in_group");
+    /** Inverse of {@link #GROUP_CONTAINS}. */
+    public static final Relationship<Entity,Entity> IN_GROUP = GROUP_CONTAINS.getInverseRelationship();
+
+    /** {@link #HAS_TARGET} indicates that one entity directs to one or more other entities.
+     * What this targeting relationship means depends on the targetter.
+     * The inverse relationship is {@link #TARGETTED_BY}. */
+    public static final Relationship<Entity,Entity> HAS_TARGET = Relationships.newRelationshipPair(
+        "targetter", "targetters", Entity.class, "has_target", 
+        "target", "targets", Entity.class, "targetted_by");
+    /** Inverse of {@link #HAS_TARGET}. */
+    public static final Relationship<Entity,Entity> TARGETTED_BY = HAS_TARGET.getInverseRelationship();
+
+    /** {@link #ACTIVE_PARENT_OF} indicates that one entity is should be considered as the logical parent of another,
+     * e.g. for presentation purposes to the end user.
+     * Frequently this relationship coincides with a {@link #MANAGED_BY} relationship, 
+     * but sometimes some managed children are there for purposes the designers consider less important,
+     * and they can choose to suppress the {@link #ACTIVE_PARENT_OF} relationship 
+     * so that the active children is a subset of the managed children.
+     * <p>
+     * One recommended consideration is whether the child should be shown in a default tree view.
+     * Whilst a user can always fina a way to see all managed children, 
+     * it may be the case that only some of those are of primary interest,
+     * and it is to identify those that this relationship exists.
+     * <p>
+     * It is permitted that an entity be an {@link #ACTIVE_PARENT_OF} an entity for which it is not a manager,
+     * but in most cases a different relationship type is more appropriate where there is not also a management relationship.
+     * <p> 
+     * The inverse relationship is {@link #ACTIVE_CHILD_OF},
+     * and an entity should normally be an {@link #ACTIVE_CHILD_OF} zero or one entities. */
+    public static final Relationship<Entity,Entity> ACTIVE_PARENT_OF = Relationships.newRelationshipPair(
+        "parent", "parents", Entity.class, "parent_of_active", 
+        "active child", "active children", Entity.class, "active_child_of");
+    /** Inverse of {@link #ACTIVE_PARENT_OF}. */
+    public static final Relationship<Entity,Entity> ACTIVE_CHILD_OF = ACTIVE_PARENT_OF.getInverseRelationship();
+    
+    /** {@link #HAS_POLICY} indicates that an entity has a policy associated to it.
+     * The inverse relationship is {@link #POLICY_FOR}. */
+    public static final Relationship<Entity,Policy> HAS_POLICY = Relationships.newRelationshipPair(
+        "entity", "entities", Entity.class, "has_policy", 
+        "policy", "policies", Policy.class, "policy_for");
+    /** Inverse of {@link #HAS_POLICY}. */
+    public static final Relationship<Policy,Entity> POLICY_FOR = HAS_POLICY.getInverseRelationship();
+
+    // ----
+    
+    // TODO replace by relations stored in catalog when catalog supports arbitrary types
+    private static Map<String,Relationship<? extends BrooklynObject, ? extends BrooklynObject>> KNOWN_RELATIONSHIPS = MutableMap.of();
+    private static void addRelationship(Relationship<? extends BrooklynObject, ? extends BrooklynObject> r) {
+        KNOWN_RELATIONSHIPS.put(r.getRelationshipTypeName(), r);
+        if (r.getInverseRelationship()!=null) {
+            KNOWN_RELATIONSHIPS.put(r.getInverseRelationship().getRelationshipTypeName(), r.getInverseRelationship());
+        }
+    }
+    static {
+        addRelationship(MANAGER_OF);
+        addRelationship(GROUP_CONTAINS);
+        addRelationship(HAS_TARGET);
+        addRelationship(HAS_POLICY);
+    }
+    
+    /** Find the typed Relationship instance for the given relationship name, if known;
+     * behaviour is not guaranteed by the API if not known (hence the Beta marker),
+     * it may fail fast or return null or create a poor-man's relationship instance. 
+     */
+    @Beta
+    public static Relationship<? extends BrooklynObject, ? extends BrooklynObject> lookup(ManagementContext mgmt, String relationshipTypeName) {
+        if (relationshipTypeName==null) return null;
+        Relationship<? extends BrooklynObject, ? extends BrooklynObject> result = KNOWN_RELATIONSHIPS.get(relationshipTypeName);
+        if (result!=null) return result;
+        
+        /* TODO ultimately we'd like to support arbitrary relationships via persistence and lookup against the catalog;
+         * however for now, so that we can persist nicely (without catalog items for relationships) 
+         * we are smart about the relationships defined here, and we return a poor-man's version for items elsewhere.
+         * 
+         * for now, a poor-man's relationship; if not in catalog ultimately we should fail. */
+        return Relationships.newRelationshipOneway("source", "sources", BrooklynObject.class, relationshipTypeName, "target", "targets", BrooklynObject.class);
+    }
+    
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public static <T extends BrooklynObject> Set<Relationship<? super T,? extends BrooklynObject>> getRelations(T source) {
+        return ((BrooklynObjectInternal)source).relations().getLocalBackingStore().getRelationships();
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public static <T extends BrooklynObject,U extends BrooklynObject> Set<U> getRelationships(Relationship<? super T,U> relationship, T source) {
+        return ((BrooklynObjectInternal)source).relations().getLocalBackingStore().getRelations(relationship);
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public static <T extends BrooklynObject,U extends BrooklynObject> void add(T source, Relationship<? super T,U> relationship, U target) {
+        ((BrooklynObjectInternal)source).relations().getLocalBackingStore().add(relationship, target);
+        ((BrooklynObjectInternal)target).relations().getLocalBackingStore().add(relationship.getInverseRelationship(), source);
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public static <T extends BrooklynObject,U extends BrooklynObject> void remove(T source, Relationship<? super T,U> relationship, U target) {
+        ((BrooklynObjectInternal)source).relations().getLocalBackingStore().remove(relationship, target);
+        ((BrooklynObjectInternal)target).relations().getLocalBackingStore().remove(relationship.getInverseRelationship(), source);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/feed/AbstractFeed.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/feed/AbstractFeed.java b/core/src/main/java/org/apache/brooklyn/core/feed/AbstractFeed.java
index a31b73e..64320cd 100644
--- a/core/src/main/java/org/apache/brooklyn/core/feed/AbstractFeed.java
+++ b/core/src/main/java/org/apache/brooklyn/core/feed/AbstractFeed.java
@@ -42,7 +42,7 @@ import org.slf4j.LoggerFactory;
  * These generally poll or subscribe to get sensor values for an entity.
  * They make it easy to poll over http, jmx, etc.
  */
-public abstract class AbstractFeed extends AbstractEntityAdjunct implements Feed {
+public abstract class AbstractFeed extends AbstractEntityAdjunct<Feed,AbstractFeed> implements Feed {
 
     private static final Logger log = LoggerFactory.getLogger(AbstractFeed.class);
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/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 b5a91c7..996b1a0 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
@@ -94,7 +94,7 @@ import com.google.common.reflect.TypeToken;
  * 
  * Override {@link #configure(Map)} to add special initialization logic.
  */
-public abstract class AbstractLocation extends AbstractBrooklynObject implements LocationInternal, HasHostGeoInfo, Configurable {
+public abstract class AbstractLocation extends AbstractBrooklynObject<Location,LocationInternal> implements LocationInternal, HasHostGeoInfo, Configurable {
     
     private static final long serialVersionUID = -7495805474138619830L;
 
@@ -175,7 +175,7 @@ public abstract class AbstractLocation extends AbstractBrooklynObject implements
         locationType = new LocationDynamicType(this);
         
         if (isLegacyConstruction()) {
-            AbstractBrooklynObject checkWeGetThis = configure(properties);
+            AbstractLocation checkWeGetThis = configure(properties);
             assert this.equals(checkWeGetThis) : this+" configure method does not return itself; returns "+checkWeGetThis+" instead of "+this;
 
             boolean deferConstructionChecks = (properties.containsKey("deferConstructionChecks") && TypeCoercions.coerce(properties.get("deferConstructionChecks"), Boolean.class));

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/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 fb27ada..d312f53 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
@@ -394,6 +394,11 @@ public class PortForwardManagerClient implements PortForwardManager {
     }
 
     @Override
+    public RelationSupport<?> relations() {
+        return getDelegate().relations();
+    }
+    
+    @Override
     public <T> T setConfig(ConfigKey<T> key, T val) {
         return getDelegate().config().set(key, val);
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/location/internal/LocationInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/location/internal/LocationInternal.java b/core/src/main/java/org/apache/brooklyn/core/location/internal/LocationInternal.java
index 18bceef..fe9f669 100644
--- a/core/src/main/java/org/apache/brooklyn/core/location/internal/LocationInternal.java
+++ b/core/src/main/java/org/apache/brooklyn/core/location/internal/LocationInternal.java
@@ -35,7 +35,7 @@ import com.google.common.annotations.Beta;
 /**
  * Information about locations private to Brooklyn.
  */
-public interface LocationInternal extends BrooklynObjectInternal, Location {
+public interface LocationInternal extends BrooklynObjectInternal<Location,LocationInternal>, Location {
 
     @Beta
     public static final ConfigKey<String> ORIGINAL_SPEC = ConfigKeys.newStringConfigKey("spec.original", "The original spec used to instantiate a location");

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java
index 326df67..74a7dca 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java
@@ -18,10 +18,15 @@
  */
 package org.apache.brooklyn.core.mgmt.rebind;
 
+import java.util.Map;
+import java.util.Set;
+
 import org.apache.brooklyn.api.mgmt.rebind.RebindContext;
 import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.Memento;
+import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.objs.EntityAdjunct;
+import org.apache.brooklyn.core.entity.EntityRelations;
 import org.apache.brooklyn.core.mgmt.rebind.dto.MementosGenerators;
 import org.apache.brooklyn.core.objs.AbstractBrooklynObject;
 import org.apache.brooklyn.core.objs.AbstractEntityAdjunct.AdjunctTagSupport;
@@ -29,13 +34,15 @@ import org.apache.brooklyn.util.text.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.basic.relations.Relationship;
+
 public abstract class AbstractBrooklynObjectRebindSupport<T extends Memento> implements RebindSupport<T> {
 
     private static final Logger LOG = LoggerFactory.getLogger(AbstractBrooklynObjectRebindSupport.class);
     
-    private final AbstractBrooklynObject instance;
+    private final AbstractBrooklynObject<?,?> instance;
     
-    public AbstractBrooklynObjectRebindSupport(AbstractBrooklynObject instance) {
+    public AbstractBrooklynObjectRebindSupport(AbstractBrooklynObject<?,?> instance) {
         this.instance = instance;
     }
     
@@ -55,6 +62,7 @@ public abstract class AbstractBrooklynObjectRebindSupport<T extends Memento> imp
         //catalogItemId already set when creating the object
         addConfig(rebindContext, memento);
         addTags(rebindContext, memento);
+        addRelations(rebindContext, memento);
         addCustoms(rebindContext, memento);
         
         doReconstruct(rebindContext, memento);
@@ -66,6 +74,7 @@ public abstract class AbstractBrooklynObjectRebindSupport<T extends Memento> imp
 
     protected abstract void addCustoms(RebindContext rebindContext, T memento);
     
+    @SuppressWarnings("rawtypes")
     protected void addTags(RebindContext rebindContext, T memento) {
         if (instance instanceof EntityAdjunct && Strings.isNonBlank(memento.getUniqueTag())) {
             ((AdjunctTagSupport)(instance.tags())).setUniqueTag(memento.getUniqueTag());
@@ -75,6 +84,16 @@ public abstract class AbstractBrooklynObjectRebindSupport<T extends Memento> imp
         }
     }
 
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    protected void addRelations(RebindContext rebindContext, T memento) {
+        for (Map.Entry<String,Set<BrooklynObject>> rEntry : memento.getRelations().entrySet()) {
+            Relationship<? extends BrooklynObject, ? extends BrooklynObject> r = EntityRelations.lookup(instance.getManagementContext(), rEntry.getKey());
+            if (r==null) throw new IllegalStateException("Unsupported relationship -- "+rEntry.getKey() + " -- in "+memento);
+            for (BrooklynObject item: rEntry.getValue())
+                instance.relations().add((Relationship)r, item);
+        }
+    }
+
     @Override
     public void addPolicies(RebindContext rebindContext, T Memento) {
         throw new UnsupportedOperationException();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java
index 77ebdbb..1fae585 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java
@@ -25,9 +25,9 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.brooklyn.api.mgmt.rebind.mementos.Memento;
+import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.core.BrooklynVersion;
 import org.apache.brooklyn.core.config.Sanitizer;
-import org.apache.brooklyn.core.entity.Entities;
 
 import com.google.common.base.Objects;
 import com.google.common.base.Objects.ToStringHelper;
@@ -47,6 +47,7 @@ public abstract class AbstractMemento implements Memento, Serializable {
         protected String catalogItemId;
         protected Map<String, Object> customFields = Maps.newLinkedHashMap();
         protected List<Object> tags = Lists.newArrayList();
+        protected Map<String,Set<BrooklynObject>> relations = Maps.newLinkedHashMap();
         
         // only supported for EntityAdjuncts
         protected String uniqueTag;
@@ -65,29 +66,10 @@ public abstract class AbstractMemento implements Memento, Serializable {
             catalogItemId = other.getCatalogItemId();
             customFields.putAll(other.getCustomFields());
             tags.addAll(other.getTags());
+            relations.putAll(other.getRelations());
             uniqueTag = other.getUniqueTag();
             return self();
         }
-        // this method set is incomplete; and they are not used, as the protected fields are set directly
-        // kept in case we want to expose this elsewhere, but we should complete the list
-//        public B brooklynVersion(String val) {
-//            brooklynVersion = val; return self();
-//        }
-//        public B id(String val) {
-//            id = val; return self();
-//        }
-//        public B type(String val) {
-//            type = val; return self();
-//        }
-//        public B typeClass(Class<?> val) {
-//            typeClass = val; return self();
-//        }
-//        public B displayName(String val) {
-//            displayName = val; return self();
-//        }
-//        public B catalogItemId(String val) {
-//            catalogItemId = val; return self();
-//        }
         
         /**
          * @deprecated since 0.7.0; use config/attributes so generic persistence will work, rather than requiring "custom fields"
@@ -104,6 +86,7 @@ public abstract class AbstractMemento implements Memento, Serializable {
     private String displayName;
     private String catalogItemId;
     private List<Object> tags;
+    private Map<String, Set<BrooklynObject>> relations;
     
     // for EntityAdjuncts; not used for entity
     private String uniqueTag;
@@ -124,6 +107,7 @@ public abstract class AbstractMemento implements Memento, Serializable {
         catalogItemId = builder.catalogItemId;
         setCustomFields(builder.customFields);
         tags = toPersistedList(builder.tags);
+        relations = toPersistedMap(builder.relations);
         uniqueTag = builder.uniqueTag;
     }
 
@@ -172,6 +156,11 @@ public abstract class AbstractMemento implements Memento, Serializable {
     }
 
     @Override
+    public Map<String, Set<BrooklynObject>> getRelations() {
+        return fromPersistedMap(relations);
+    }
+    
+    @Override
     public String getUniqueTag() {
         return uniqueTag;
     }
@@ -199,7 +188,10 @@ public abstract class AbstractMemento implements Memento, Serializable {
     
     protected ToStringHelper newVerboseStringHelper() {
         return Objects.toStringHelper(this).add("id", getId()).add("type", getType())
-                .add("displayName", getDisplayName()).add("customFields", Sanitizer.sanitize(getCustomFields()));
+                .add("displayName", getDisplayName())
+                .add("tags", getTags())
+                .add("relations", getRelations())
+                .add("customFields", Sanitizer.sanitize(getCustomFields()));
     }
     
     protected <T> List<T> fromPersistedList(List<T> l) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicEnricherMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicEnricherMemento.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicEnricherMemento.java
index 254b803..80c502d 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicEnricherMemento.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicEnricherMemento.java
@@ -23,7 +23,6 @@ import java.util.Map;
 
 import org.apache.brooklyn.api.mgmt.rebind.mementos.EnricherMemento;
 import org.apache.brooklyn.core.config.Sanitizer;
-import org.apache.brooklyn.core.entity.Entities;
 
 import com.google.common.base.Objects.ToStringHelper;
 import com.google.common.collect.Maps;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicEntityMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicEntityMemento.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicEntityMemento.java
index 7418813..8294562 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicEntityMemento.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicEntityMemento.java
@@ -90,7 +90,6 @@ public class BasicEntityMemento extends AbstractTreeNodeMemento implements Entit
             feeds.addAll(other.getFeeds());
             members.addAll(other.getMembers());
             effectors.addAll(other.getEffectors());
-            tags.addAll(other.getTags());
             return this;
         }
         public EntityMemento build() {
@@ -319,7 +318,6 @@ public class BasicEntityMemento extends AbstractTreeNodeMemento implements Entit
                 .add("attributes", Sanitizer.sanitize(getAttributes()))
                 .add("policies", getPolicies())
                 .add("enrichers", getEnrichers())
-                .add("tags", getTags())
                 .add("locations", getLocations());
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicFeedMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicFeedMemento.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicFeedMemento.java
index 2f07443..072756f 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicFeedMemento.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicFeedMemento.java
@@ -23,7 +23,6 @@ import java.util.Map;
 
 import org.apache.brooklyn.api.mgmt.rebind.mementos.FeedMemento;
 import org.apache.brooklyn.core.config.Sanitizer;
-import org.apache.brooklyn.core.entity.Entities;
 
 import com.google.common.base.Objects.ToStringHelper;
 import com.google.common.collect.Maps;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicLocationMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicLocationMemento.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicLocationMemento.java
index 16c9e92..71ddcaa 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicLocationMemento.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicLocationMemento.java
@@ -25,7 +25,6 @@ import java.util.Set;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.LocationMemento;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.TreeNode;
 import org.apache.brooklyn.core.config.Sanitizer;
-import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 
 import com.google.common.base.Objects.ToStringHelper;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicPolicyMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicPolicyMemento.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicPolicyMemento.java
index 31ce3b2..87a0dfb 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicPolicyMemento.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BasicPolicyMemento.java
@@ -23,7 +23,6 @@ import java.util.Map;
 
 import org.apache.brooklyn.api.mgmt.rebind.mementos.PolicyMemento;
 import org.apache.brooklyn.core.config.Sanitizer;
-import org.apache.brooklyn.core.entity.Entities;
 
 import com.google.common.base.Objects.ToStringHelper;
 import com.google.common.collect.Maps;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java
index e5d0359..6cfda79 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java
@@ -44,9 +44,9 @@ 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.sensor.AttributeSensor;
+import org.apache.brooklyn.api.sensor.AttributeSensor.SensorPersistenceMode;
 import org.apache.brooklyn.api.sensor.Enricher;
 import org.apache.brooklyn.api.sensor.Feed;
-import org.apache.brooklyn.api.sensor.AttributeSensor.SensorPersistenceMode;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.catalog.internal.CatalogItemDo;
 import org.apache.brooklyn.core.enricher.AbstractEnricher;
@@ -67,6 +67,8 @@ import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
 import com.google.common.base.Predicates;
 
+import brooklyn.basic.relations.Relationship;
+
 public class MementosGenerators {
 
     private MementosGenerators() {}
@@ -429,6 +431,7 @@ public class MementosGenerators {
         return builder.build();
     }
     
+    @SuppressWarnings({ "unchecked", "rawtypes" })
     private static void populateBrooklynObjectMementoBuilder(BrooklynObject instance, AbstractMemento.Builder<?> builder) {
         if (Proxy.isProxyClass(instance.getClass())) {
             throw new IllegalStateException("Attempt to create memento from proxy "+instance+" (would fail with wrong type)");
@@ -445,6 +448,13 @@ public class MementosGenerators {
         for (Object tag : instance.tags().getTags()) {
             builder.tags.add(tag); 
         }
+        if (!(instance instanceof CatalogItem)) {
+            // CatalogItem is a BrooklynObject so it can be persisted
+            // but it does not support relations
+            for (Relationship<?,? extends BrooklynObject> relationship: instance.relations().getRelationships()) {
+                builder.relations.put(relationship.getRelationshipTypeName(), instance.relations().getRelations((Relationship)relationship));
+            }
+        }
     }
 
     protected static Object configValueToPersistable(Object value) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java
index 385d279..a0e02c5 100644
--- a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java
+++ b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java
@@ -24,10 +24,12 @@ import java.util.Set;
 
 import org.apache.brooklyn.api.internal.ApiObjectsFactory;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.core.entity.AbstractEntity;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.mgmt.rebind.RebindManagerImpl;
 import org.apache.brooklyn.core.objs.proxy.InternalFactory;
+import org.apache.brooklyn.core.relations.ByObjectBasicRelationSupport;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.core.flags.SetFromFlag;
 import org.apache.brooklyn.util.text.Identifiers;
@@ -39,7 +41,7 @@ import com.google.common.collect.Iterables;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 
-public abstract class AbstractBrooklynObject implements BrooklynObjectInternal {
+public abstract class AbstractBrooklynObject<PublicSelfType extends BrooklynObject,InternalSelfType extends BrooklynObjectInternal<PublicSelfType,InternalSelfType>> implements BrooklynObjectInternal<PublicSelfType,InternalSelfType> {
 
     private static final Logger log = LoggerFactory.getLogger(AbstractBrooklynObject.class);
 
@@ -55,8 +57,18 @@ public abstract class AbstractBrooklynObject implements BrooklynObjectInternal {
     @SetFromFlag(value = "tags")
     private final Set<Object> tags = Sets.newLinkedHashSet();
 
+    private RelationSupportInternal<PublicSelfType> relations = new ByObjectBasicRelationSupport<PublicSelfType>(getPublicThis(), new RelationChangedCallback());
+    
     private volatile ManagementContext managementContext;
-
+    
+    @SuppressWarnings("unchecked")
+    /** returns this cast to T, e.g. EntityInternal */
+    protected InternalSelfType getThis() { return (InternalSelfType)this; }
+    
+    /** returns this cast to PublicT, e.g. Entity */
+    @SuppressWarnings("unchecked")
+    protected PublicSelfType getPublicThis() { return (PublicSelfType)this; }
+    
     public abstract void setDisplayName(String newName);
 
     public AbstractBrooklynObject() {
@@ -86,7 +98,7 @@ public abstract class AbstractBrooklynObject implements BrooklynObjectInternal {
      * @deprecated since 0.7.0; only used for legacy brooklyn types where constructor is called directly
      */
     @Deprecated
-    protected AbstractBrooklynObject configure() {
+    protected InternalSelfType configure() {
         return configure(Collections.emptyMap());
     }
 
@@ -105,7 +117,7 @@ public abstract class AbstractBrooklynObject implements BrooklynObjectInternal {
      * @deprecated since 0.7.0; only used for legacy brooklyn types where constructor is called directly
      */
     @Deprecated
-    protected abstract AbstractBrooklynObject configure(Map<?, ?> flags);
+    protected abstract InternalSelfType configure(Map<?, ?> flags);
 
     protected boolean isLegacyConstruction() {
         return _legacyConstruction;
@@ -245,4 +257,16 @@ public abstract class AbstractBrooklynObject implements BrooklynObjectInternal {
         }
     }
 
+    @Override
+    public RelationSupportInternal<PublicSelfType> relations() {
+        return relations;
+    }
+
+    private class RelationChangedCallback implements Runnable {
+        @Override
+        public void run() {
+            requestPersist();
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/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 3fc2839..63745d3 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
@@ -67,7 +67,7 @@ import com.google.common.collect.Maps;
 /**
  * Common functionality for policies and enrichers
  */
-public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject implements BrooklynObjectInternal, EntityAdjunct, Configurable {
+public abstract class AbstractEntityAdjunct<PublicSelfType extends BrooklynObject,InternalSelfType extends AbstractEntityAdjunct<PublicSelfType,InternalSelfType>> extends AbstractBrooklynObject<PublicSelfType,InternalSelfType> implements BrooklynObjectInternal<PublicSelfType,InternalSelfType>, EntityAdjunct, Configurable {
     private static final Logger log = LoggerFactory.getLogger(AbstractEntityAdjunct.class);
 
     private boolean _legacyNoConstructionInit;
@@ -121,7 +121,7 @@ public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject imple
         _legacyNoConstructionInit = (properties != null) && Boolean.TRUE.equals(properties.get("noConstructionInit"));
         
         if (isLegacyConstruction()) {
-            AbstractBrooklynObject checkWeGetThis = configure(properties);
+            InternalSelfType checkWeGetThis = configure(properties);
             assert this.equals(checkWeGetThis) : this+" configure method does not return itself; returns "+checkWeGetThis+" instead of "+this;
 
             boolean deferConstructionChecks = (properties.containsKey("deferConstructionChecks") && TypeCoercions.coerce(properties.get("deferConstructionChecks"), Boolean.class));
@@ -137,7 +137,7 @@ public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject imple
     @Override
     @Deprecated
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    public AbstractEntityAdjunct configure(Map flags) {
+    public InternalSelfType configure(Map flags) {
         // TODO only set on first time through
         boolean isFirstTime = true;
         
@@ -183,7 +183,7 @@ public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject imple
             }
         }
         
-        return this;
+        return (InternalSelfType) this;
     }
     
     /**
@@ -366,6 +366,7 @@ public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject imple
         }
     }
 
+    @Override
     public <T> T getConfig(ConfigKey<T> key) {
         return config().get(key);
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynDynamicType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynDynamicType.java b/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynDynamicType.java
index 3642448..d7c73dd 100644
--- a/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynDynamicType.java
+++ b/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynDynamicType.java
@@ -55,7 +55,7 @@ import com.google.common.collect.Lists;
  * for this reason it does *not* implement BrooklynType, but 
  * callers can call {@link #getSnapshot()} to get a snapshot such instance.  
  */
-public abstract class BrooklynDynamicType<T extends BrooklynObject, AbstractT extends AbstractBrooklynObject> {
+public abstract class BrooklynDynamicType<T extends BrooklynObject, AbstractT extends AbstractBrooklynObject<T,?>> {
 
     private static final Logger LOG = LoggerFactory.getLogger(BrooklynDynamicType.class);
 
@@ -144,7 +144,7 @@ public abstract class BrooklynDynamicType<T extends BrooklynObject, AbstractT ex
      * Prefers keys which overwrite other keys, and prefers keys which are lower in the hierarchy;
      * logs warnings if there are two conflicting keys which don't have an overwriting relationship.
      */
-    protected static void buildConfigKeys(Class<? extends BrooklynObject> clazz, AbstractBrooklynObject optionalInstance, 
+    protected static void buildConfigKeys(Class<? extends BrooklynObject> clazz, AbstractBrooklynObject<?,?> optionalInstance, 
             Map<String, FieldAndValue<ConfigKey<?>>> configKeys) {
         ListMultimap<String,FieldAndValue<ConfigKey<?>>> configKeysAll = 
                 ArrayListMultimap.<String, FieldAndValue<ConfigKey<?>>>create();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/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 6888c52..658a9da 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
@@ -31,12 +31,12 @@ import org.apache.brooklyn.util.guava.Maybe;
 
 import com.google.common.annotations.Beta;
 
-public interface BrooklynObjectInternal extends BrooklynObject, Rebindable {
+public interface BrooklynObjectInternal<PublicSelfType extends BrooklynObject, InternalSelfType extends BrooklynObjectInternal<PublicSelfType,InternalSelfType>> extends BrooklynObject, Rebindable {
     
     void setCatalogItemId(String id);
     
-    @SuppressWarnings("rawtypes")  // subclasses typically apply stronger typing
-    RebindSupport getRebindSupport();
+    // subclasses typically apply stronger typing
+    RebindSupport<?> getRebindSupport();
     
     @Override
     ConfigurationSupportInternal config();
@@ -123,4 +123,11 @@ public interface BrooklynObjectInternal extends BrooklynObject, Rebindable {
     public interface SubscriptionSupportInternal extends BrooklynObject.SubscriptionSupport {
         public void unsubscribeAll();
     }
+    
+    RelationSupportInternal<PublicSelfType> relations();
+    
+    public interface RelationSupportInternal<T extends BrooklynObject> extends BrooklynObject.RelationSupport<T> {
+        @Beta
+        RelationSupport<T> getLocalBackingStore();
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/policy/AbstractPolicy.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/policy/AbstractPolicy.java b/core/src/main/java/org/apache/brooklyn/core/policy/AbstractPolicy.java
index 1c9bb1c..3cb39e9 100644
--- a/core/src/main/java/org/apache/brooklyn/core/policy/AbstractPolicy.java
+++ b/core/src/main/java/org/apache/brooklyn/core/policy/AbstractPolicy.java
@@ -37,7 +37,7 @@ import com.google.common.base.Objects;
 /**
  * Base {@link Policy} implementation; all policies should extend this or its children
  */
-public abstract class AbstractPolicy extends AbstractEntityAdjunct implements Policy, Configurable {
+public abstract class AbstractPolicy extends AbstractEntityAdjunct<Policy,AbstractPolicy> implements Policy, Configurable {
     @SuppressWarnings("unused")
     private static final Logger log = LoggerFactory.getLogger(AbstractPolicy.class);
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java b/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java
new file mode 100644
index 0000000..e87d0ea
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java
@@ -0,0 +1,55 @@
+/*
+ * 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.relations;
+
+import java.util.Set;
+
+import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.core.entity.EntityRelations;
+import org.apache.brooklyn.core.objs.BrooklynObjectInternal.RelationSupportInternal;
+
+import brooklyn.basic.relations.Relationship;
+
+public abstract class AbstractBasicRelationSupport<SourceType extends BrooklynObject> implements RelationSupportInternal<SourceType> {
+
+    final SourceType source;
+    
+    public AbstractBasicRelationSupport(SourceType source) { this.source = source; }
+        
+    @Override
+    public Set<Relationship<? super SourceType, ? extends BrooklynObject>> getRelationships() {
+        return EntityRelations.getRelations(source);
+    }
+    
+    @Override
+    public <U extends BrooklynObject> Set<U> getRelations(Relationship<? super SourceType, U> relationship) {
+        return EntityRelations.getRelationships(relationship, source);
+    }
+
+    @Override
+    public <U extends BrooklynObject> void add(Relationship<? super SourceType, U> relationship, U target) {
+        EntityRelations.add(source, relationship, target);
+    }
+
+    @Override
+    public <U extends BrooklynObject> void remove(Relationship<? super SourceType, U> relationship, U target) {
+        EntityRelations.remove(source, relationship, target);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java b/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java
new file mode 100644
index 0000000..1152e85
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java
@@ -0,0 +1,103 @@
+/*
+ * 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.relations;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.api.objs.BrooklynObject.RelationSupport;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.collections.MutableSet;
+
+import com.google.common.base.Supplier;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+
+import brooklyn.basic.relations.Relationship;
+
+public class ByObjectBasicRelationSupport<SourceType extends BrooklynObject> extends AbstractBasicRelationSupport<SourceType> {
+
+    DataForBasicRelations<SourceType> data;
+    
+    public ByObjectBasicRelationSupport(SourceType source, Runnable relationChangeCallback) { 
+        super(source); 
+        data = new DataForBasicRelations<SourceType>(relationChangeCallback);
+    }
+    
+    @Override
+    public RelationSupport<SourceType> getLocalBackingStore() {
+        return data;
+    }
+
+    public static class DataForBasicRelations<T extends BrooklynObject> implements RelationSupport<T> {
+        
+        Runnable relationChangeCallback;
+        
+        public DataForBasicRelations(Runnable relationChangeCallback) {
+            this.relationChangeCallback = relationChangeCallback;
+        }
+        
+        // TODO for now, relationships are stored here (and persisted); ideally we'd look them up in catalog
+        private Map<String,Relationship<? super T,? extends BrooklynObject>> relationships = MutableMap.of();
+        
+        private Multimap<String,BrooklynObject> relations = Multimaps.newMultimap(MutableMap.<String,Collection<BrooklynObject>>of(), 
+            new Supplier<Collection<BrooklynObject>>() {
+                public Collection<BrooklynObject> get() {
+                    return MutableSet.of();
+                }
+            });
+
+        public Set<Relationship<? super T,? extends BrooklynObject>> getRelationships() {
+            synchronized (relations) {
+                return MutableSet.copyOf(relationships.values());
+            }
+        }
+        
+        @SuppressWarnings("unchecked") @Override 
+        public <U extends BrooklynObject> Set<U> getRelations(Relationship<? super T, U> relationship) {
+            synchronized (relations) {
+                return (Set<U>)MutableSet.copyOf(relations.get(relationship.getRelationshipTypeName()));
+            }
+        }
+
+        @Override
+        public <U extends BrooklynObject> void add(Relationship<? super T,U> relationship, U target) {
+            synchronized (relations) {
+                relationships.put(relationship.getRelationshipTypeName(), relationship);
+                relations.put(relationship.getRelationshipTypeName(), target);
+            }
+            onRelationsChanged();
+        }
+
+        @Override
+        public <U extends BrooklynObject> void remove(Relationship<? super T,U> relationship, U target) {
+            synchronized (relations) {
+                relations.remove(relationship.getRelationshipTypeName(), target);
+            }
+            onRelationsChanged();
+        }
+
+        protected void onRelationsChanged() {
+            if (relationChangeCallback!=null) relationChangeCallback.run();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/core/relations/Relationships.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/relations/Relationships.java b/core/src/main/java/org/apache/brooklyn/core/relations/Relationships.java
new file mode 100644
index 0000000..8f7ad54
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/relations/Relationships.java
@@ -0,0 +1,188 @@
+/*
+ * 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.relations;
+
+import com.google.common.base.Objects;
+
+import brooklyn.basic.relations.Relationship;
+
+public class Relationships {
+
+    private static abstract class AbstractBasicRelationship<SourceType,TargetType> implements Relationship<SourceType,TargetType> {
+        private final String relationshipTypeName;
+        private final String sourceName;
+        private final String sourceNamePlural;
+        private final Class<TargetType> targetType;
+        
+        private AbstractBasicRelationship(String relationshipTypeName, String sourceName, String sourceNamePlural, Class<TargetType> targetType) {
+            this.relationshipTypeName = relationshipTypeName;
+            this.sourceName = sourceName;
+            this.sourceNamePlural = sourceNamePlural;
+            this.targetType = targetType;
+        }
+
+        @Override
+        public String getRelationshipTypeName() {
+            return relationshipTypeName;
+        }
+
+        @Override
+        public String getSourceName() {
+            return sourceName;
+        }
+        
+        @Override
+        public String getSourceNamePlural() {
+            return sourceNamePlural;
+        }
+        
+        @Override
+        public Class<TargetType> getTargetType() {
+            return targetType;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) return true;
+            if (obj == null) return false;
+            if (!(obj instanceof AbstractBasicRelationship)) return false;
+            
+            @SuppressWarnings("rawtypes")
+            AbstractBasicRelationship other = (AbstractBasicRelationship) obj;
+
+            // only look at type name and class; name of source and target is informational
+            if (!Objects.equal(relationshipTypeName, other.relationshipTypeName)) return false;
+            if (!Objects.equal(getSourceType(), other.getSourceType())) return false;
+            if (!Objects.equal(targetType, other.targetType)) return false;
+
+            if (getInverseRelationship() == null) {
+                // require both null or...
+                if (other.getInverseRelationship() != null)
+                    return false;
+            } else {
+                // ... they have same type name
+                // (don't recurse as that sets up infinite loop)
+                if (other.getInverseRelationship() == null)
+                    return false;
+                if (!Objects.equal(getInverseRelationship().getRelationshipTypeName(), other.getInverseRelationship().getRelationshipTypeName())) return false;
+            }
+
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            // comments as per equals
+            return Objects.hashCode(relationshipTypeName, getSourceType(), targetType,
+                getInverseRelationship()!=null ? getInverseRelationship().getRelationshipTypeName() : null);
+        }
+        
+        @Override
+        public String toString() {
+            return relationshipTypeName;
+        }
+    }
+
+    private static class BasicRelationshipWithInverse<SourceType,TargetType> extends AbstractBasicRelationship<SourceType,TargetType> {
+        private BasicRelationshipWithInverse<TargetType,SourceType> inverseRelationship;
+        
+        private BasicRelationshipWithInverse(String relationshipTypeName, String sourceName, String sourceNamePlural, Class<TargetType> targetType) {
+            super(relationshipTypeName, sourceName, sourceNamePlural, targetType);
+        }
+
+        @Override
+        public Relationship<TargetType,SourceType> getInverseRelationship() {
+            return inverseRelationship;
+        }
+
+        @Override
+        public Class<SourceType> getSourceType() {
+            if (getInverseRelationship()==null) return null;
+            return getInverseRelationship().getTargetType();
+        }
+
+        @Override
+        public String getTargetName() {
+            if (getInverseRelationship()==null) return null;
+            return getInverseRelationship().getSourceName();
+        }
+
+        @Override
+        public String getTargetNamePlural() {
+            if (getInverseRelationship()==null) return null;
+            return getInverseRelationship().getSourceNamePlural();
+        }
+    }
+
+    private static class BasicRelationshipOneWay<SourceType,TargetType> extends AbstractBasicRelationship<SourceType,TargetType> {
+        
+        private final String targetName;
+        private final String targetNamePlural;
+        private final Class<SourceType> sourceType;
+
+        private BasicRelationshipOneWay(String sourceName, String sourceNamePlural, Class<SourceType> sourceType, String toTargetRelationshipTypeName, 
+                String targetName, String targetNamePlural, Class<TargetType> targetType) {
+            super(toTargetRelationshipTypeName, sourceName, sourceNamePlural, targetType);
+            this.targetName = targetName;
+            this.targetNamePlural = targetNamePlural;
+            this.sourceType = sourceType;
+        }
+
+        @Override
+        public Class<SourceType> getSourceType() {
+            return sourceType;
+        }
+
+        @Override
+        public String getTargetName() {
+            return targetName;
+        }
+
+        @Override
+        public String getTargetNamePlural() {
+            return targetNamePlural;
+        }
+
+        @Override
+        public Relationship<TargetType, SourceType> getInverseRelationship() {
+            return null;
+        }
+    }
+
+    public static <SourceType,TargetType> Relationship<SourceType,TargetType> newRelationshipPair(
+            String sourceName, String sourceNamePlural, Class<SourceType> sourceType, String toTargetRelationshipTypeName,   
+            String targetName, String targetNamePlural, Class<TargetType> targetType, String toSourceRelationshipTypeName) {
+        BasicRelationshipWithInverse<SourceType, TargetType> r1 = new BasicRelationshipWithInverse<SourceType, TargetType>(
+            toTargetRelationshipTypeName, sourceName, sourceNamePlural, targetType);
+        BasicRelationshipWithInverse<TargetType, SourceType> r2 = new BasicRelationshipWithInverse<TargetType, SourceType>(
+            toSourceRelationshipTypeName, targetName, targetNamePlural, sourceType);
+        r1.inverseRelationship = r2;
+        r2.inverseRelationship = r1;
+        return r1;
+    }
+
+    public static <SourceType,TargetType> Relationship<SourceType,TargetType> newRelationshipOneway(
+            String sourceName, String sourceNamePlural, Class<SourceType> sourceType, String toTargetRelationshipTypeName,   
+            String targetName, String targetNamePlural, Class<TargetType> targetType) {
+        return new BasicRelationshipOneWay<SourceType,TargetType>(
+            sourceName, sourceNamePlural, sourceType, toTargetRelationshipTypeName,
+            targetName, targetNamePlural, targetType);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/main/java/org/apache/brooklyn/entity/group/AbstractGroupImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/entity/group/AbstractGroupImpl.java b/core/src/main/java/org/apache/brooklyn/entity/group/AbstractGroupImpl.java
index 8108c9f..d8814bd 100644
--- a/core/src/main/java/org/apache/brooklyn/entity/group/AbstractGroupImpl.java
+++ b/core/src/main/java/org/apache/brooklyn/entity/group/AbstractGroupImpl.java
@@ -239,6 +239,8 @@ public abstract class AbstractGroupImpl extends AbstractEntity implements Abstra
 
     @Override
     public Collection<Entity> getMembers() {
+        // TODO use this instead; see issue and email thread where this comment was introduced
+//        relations().getRelations(EntityRelations.GROUP_CONTAINS);
         synchronized (members) {
             return ImmutableSet.<Entity>copyOf(members);
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/test/java/org/apache/brooklyn/core/effector/EffectorSayHiGroovyTest.groovy
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/effector/EffectorSayHiGroovyTest.groovy b/core/src/test/java/org/apache/brooklyn/core/effector/EffectorSayHiGroovyTest.groovy
index 5dd776e..02b1076 100644
--- a/core/src/test/java/org/apache/brooklyn/core/effector/EffectorSayHiGroovyTest.groovy
+++ b/core/src/test/java/org/apache/brooklyn/core/effector/EffectorSayHiGroovyTest.groovy
@@ -45,7 +45,7 @@ import org.testng.annotations.Test
 /**
  * Test the operation of the {@link Effector} implementations.
  *
- * TODO clarify test purpose
+ * TODO delete? the groovy causes compile errors, and EffectorSayHiTest does most of what this does
  */
 public class EffectorSayHiGroovyTest {
     private static final Logger log = LoggerFactory.getLogger(EffectorSayHiTest.class);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/test/java/org/apache/brooklyn/core/relations/RelationsEntityBasicTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/relations/RelationsEntityBasicTest.java b/core/src/test/java/org/apache/brooklyn/core/relations/RelationsEntityBasicTest.java
new file mode 100644
index 0000000..ea4bcb3
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/relations/RelationsEntityBasicTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.relations;
+
+import java.util.Collections;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.core.entity.EntityRelations;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.util.collections.MutableSet;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+@Test
+public class RelationsEntityBasicTest extends BrooklynAppUnitTestSupport {
+
+    @Override
+    protected void setUpApp() {
+        super.setUpApp();
+    }
+    
+    public void testCustomEntityRelation() {
+        TestEntity t1 = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+        TestEntity t2 = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+        
+        t1.relations().add(EntityRelations.HAS_TARGET, t2);
+        Assert.assertEquals(t1.relations().getRelations(EntityRelations.HAS_TARGET), Collections.singleton(t2));
+        Assert.assertEquals(t2.relations().getRelations(EntityRelations.HAS_TARGET), Collections.emptySet());
+        Assert.assertEquals(t2.relations().getRelations(EntityRelations.TARGETTED_BY), Collections.singleton(t1));
+        
+        t1.relations().add(EntityRelations.HAS_TARGET, t2);
+        Assert.assertEquals(t1.relations().getRelations(EntityRelations.HAS_TARGET), Collections.singleton(t2));
+        
+        t1.relations().add(EntityRelations.HAS_TARGET, t1);
+        Assert.assertEquals(t1.relations().getRelations(EntityRelations.HAS_TARGET), MutableSet.of(t1, t2));
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/772e707f/core/src/test/java/org/apache/brooklyn/core/relations/RelationsEntityRebindTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/relations/RelationsEntityRebindTest.java b/core/src/test/java/org/apache/brooklyn/core/relations/RelationsEntityRebindTest.java
new file mode 100644
index 0000000..544794d
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/relations/RelationsEntityRebindTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.relations;
+
+import java.util.Collections;
+import java.util.Iterator;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.core.entity.EntityRelations;
+import org.apache.brooklyn.core.mgmt.rebind.RebindTestFixtureWithApp;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+@Test
+public class RelationsEntityRebindTest extends RebindTestFixtureWithApp {
+
+    public void testCustomEntityRelation() throws Exception {
+        TestEntity origT1 = origApp.createAndManageChild(EntitySpec.create(TestEntity.class));
+        TestEntity origT2 = origApp.createAndManageChild(EntitySpec.create(TestEntity.class));
+        origT1.relations().add(EntityRelations.HAS_TARGET, origT2);
+        
+        TestApplication newApp = rebind();
+        Iterator<Entity> ci = newApp.getChildren().iterator();
+        Entity t1 = ci.next();
+        Entity t2 = ci.next();
+        
+        Assert.assertEquals(t1.relations().getRelations(EntityRelations.HAS_TARGET), Collections.singleton(t2));
+        Assert.assertEquals(t2.relations().getRelations(EntityRelations.HAS_TARGET), Collections.emptySet());
+        Assert.assertEquals(t2.relations().getRelations(EntityRelations.TARGETTED_BY), Collections.singleton(t1));
+    }
+    
+}


[4/8] incubator-brooklyn git commit: address most review comments on relations

Posted by sv...@apache.org.
address most review comments on relations


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

Branch: refs/heads/master
Commit: ed113a348dbf214a2d8977e6179d5c0ebbf8c439
Parents: 1b71134
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Oct 27 11:29:00 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Oct 27 11:51:42 2015 +0000

----------------------------------------------------------------------
 .../org/apache/brooklyn/api/entity/Entity.java  |  8 +-
 .../apache/brooklyn/api/location/Location.java  |  7 --
 .../api/mgmt/rebind/RebindExceptionHandler.java |  5 ++
 .../mementos/BrooklynMementoPersister.java      |  5 +-
 .../api/mgmt/rebind/mementos/Memento.java       |  3 +-
 .../brooklyn/api/objs/BrooklynObject.java       |  4 +-
 .../apache/brooklyn/api/objs/Configurable.java  |  3 +-
 .../org/apache/brooklyn/api/policy/Policy.java  |  5 --
 .../core/catalog/internal/CatalogItemDo.java    |  6 +-
 .../brooklyn/core/entity/EntityRelations.java   |  8 +-
 .../AbstractBrooklynObjectRebindSupport.java    | 14 +++-
 .../mgmt/rebind/RebindContextLookupContext.java | 18 +++++
 .../mgmt/rebind/RebindExceptionHandlerImpl.java | 17 ++++-
 .../core/mgmt/rebind/dto/AbstractMemento.java   | 19 +++--
 .../mgmt/rebind/dto/MementosGenerators.java     | 15 ++--
 .../relations/AbstractBasicRelationSupport.java |  8 +-
 .../relations/ByObjectBasicRelationSupport.java |  7 +-
 .../core/relations/EmptyRelationSupport.java    | 60 +++++++++++++++
 .../mgmt/persist/XmlMementoSerializerTest.java  | 18 +++++
 .../rebind/RebindClassInitializationTest.java   | 78 ++++++++++++++++++++
 .../core/mgmt/rebind/RebindEntityTest.java      |  3 +-
 21 files changed, 254 insertions(+), 57 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/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 a15f4e1..3b333e0 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
@@ -216,15 +216,9 @@ public interface Entity extends BrooklynObject {
      * via code like {@code sensors().get(key)}.
      */
     <T> T getAttribute(AttributeSensor<T> sensor);
-
-    /**
-     * Convenience for calling {@link ConfigurationSupport#get(ConfigKey)},
-     * via code like {@code config().get(key)}.
-     */
-    <T> T getConfig(ConfigKey<T> key);
     
     /**
-     * @see #getConfig(ConfigKey)}
+     * @see {@link #getConfig(ConfigKey)}
      */
     <T> T getConfig(HasConfigKey<T> key);
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/api/src/main/java/org/apache/brooklyn/api/location/Location.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/location/Location.java b/api/src/main/java/org/apache/brooklyn/api/location/Location.java
index 392af13..84e371b 100644
--- a/api/src/main/java/org/apache/brooklyn/api/location/Location.java
+++ b/api/src/main/java/org/apache/brooklyn/api/location/Location.java
@@ -89,13 +89,6 @@ public interface Location extends Serializable, BrooklynObject {
      */
     boolean containsLocation(Location potentialDescendent);
 
-    /** 
-     * Returns configuration set at this location or inherited or default.
-     * 
-     * Convenience method for {@code config().get(key)}
-     */
-    <T> T getConfig(ConfigKey<T> key);
-
     /**
      * Convenience method for {@code config().get(key)}
      * 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindExceptionHandler.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindExceptionHandler.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindExceptionHandler.java
index 48bb07f..9660930 100644
--- a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindExceptionHandler.java
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/RebindExceptionHandler.java
@@ -80,6 +80,11 @@ public interface RebindExceptionHandler {
      */
     CatalogItem<?, ?> onDanglingCatalogItemRef(String id);
 
+    /**
+     * @return the item to use in place of the missing one
+     */
+    BrooklynObject onDanglingUntypedItemRef(String id);
+
     void onCreateFailed(BrooklynObjectType type, String id, String instanceType, Exception e);
 
     void onNotFound(BrooklynObjectType type, String id);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoPersister.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoPersister.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoPersister.java
index e554e08..03673fd 100644
--- a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoPersister.java
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoPersister.java
@@ -57,9 +57,10 @@ public interface BrooklynMementoPersister {
         Feed lookupFeed(String id);
         CatalogItem<?, ?> lookupCatalogItem(String id);
         
-        BrooklynObject lookup(BrooklynObjectType type, String objectId);
+        /** retrieve the item with the given ID, optionally ensuring it is of the indicated type; null if not found */
+        BrooklynObject lookup(@Nullable BrooklynObjectType type, String objectId);
         /** like {@link #lookup(BrooklynObjectType, String)} but doesn't record an exception if not found */
-        BrooklynObject peek(BrooklynObjectType type, String objectId);
+        BrooklynObject peek(@Nullable BrooklynObjectType type, String objectId);
     }
     
     /**

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java
index b57780d..5911f28 100644
--- a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java
@@ -25,7 +25,6 @@ import java.util.Set;
 
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
-import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.objs.EntityAdjunct;
 
 /**
@@ -79,7 +78,7 @@ public interface Memento extends Serializable {
 
     public Collection<Object> getTags();
     
-    Map<String, Set<BrooklynObject>> getRelations();
+    public Map<String,Set<String>> getRelations();
     
     /** Null for {@link Entity}, but important for adjuncts; see {@link EntityAdjunct#getUniqueTag()} */
     public String getUniqueTag();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/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 8648491..9e1640f 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
@@ -151,8 +151,8 @@ public interface BrooklynObject extends Identifiable, Configurable {
     }
     
     public interface RelationSupport<T extends BrooklynObject> {
-        public <U extends BrooklynObject> void add(Relationship<? super T,U> relationship, U target);
-        public <U extends BrooklynObject> void remove(Relationship<? super T,U> relationship, U target);
+        public <U extends BrooklynObject> void add(Relationship<? super T,? super U> relationship, U target);
+        public <U extends BrooklynObject> void remove(Relationship<? super T,? super U> relationship, U target);
         public Set<Relationship<? super T,? extends BrooklynObject>> getRelationships();
         public <U extends BrooklynObject> Set<U> getRelations(Relationship<? super T,U> relationship);
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java b/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java
index 5f1b294..84b1fcb 100644
--- a/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java
+++ b/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java
@@ -42,7 +42,8 @@ public interface Configurable {
     public <T> T setConfig(ConfigKey<T> key, T val);
 
     /**
-     * Convenience method for {@code config().get(key)}
+     * Convenience for calling {@link ConfigurationSupport#get(ConfigKey)},
+     * via code like {@code config().get(key)}.
      */
     <T> T getConfig(ConfigKey<T> key);
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/api/src/main/java/org/apache/brooklyn/api/policy/Policy.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/policy/Policy.java b/api/src/main/java/org/apache/brooklyn/api/policy/Policy.java
index 957da0a..0235bac 100644
--- a/api/src/main/java/org/apache/brooklyn/api/policy/Policy.java
+++ b/api/src/main/java/org/apache/brooklyn/api/policy/Policy.java
@@ -60,11 +60,6 @@ public interface Policy extends EntityAdjunct, Rebindable, Configurable {
     boolean isSuspended();
     
     /**
-     * Convenience method for {@code config().get(key)}
-     */
-    <T> T getConfig(ConfigKey<T> key);
-    
-    /**
      * @deprecated since 0.7.0; use {@link #config()}, such as {@code policy.config().set(key, val)}
      */
     @Deprecated

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/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 7f3a54a..a3ae36e 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
@@ -29,6 +29,7 @@ import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.CatalogItemMemento;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
+import org.apache.brooklyn.core.relations.EmptyRelationSupport;
 
 import com.google.common.base.Preconditions;
 
@@ -65,11 +66,12 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT>, BrooklynObj
     }
     
     /**
-     * @throws UnsupportedOperationException; relations are not supported for catalog items
+     * @return an immutable empty relation support object; relations are not supported,
+     * but we do not throw on access to enable reads in a consistent manner
      */
     @Override
     public RelationSupportInternal<CatalogItem<T,SpecT>> relations() {
-        throw new UnsupportedOperationException();
+        return new EmptyRelationSupport<CatalogItem<T,SpecT>>(this);
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java b/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java
index 7b20845..7dfa93e 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java
@@ -136,23 +136,23 @@ public class EntityRelations<T extends BrooklynObject> {
     }
     
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    public static <T extends BrooklynObject> Set<Relationship<? super T,? extends BrooklynObject>> getRelations(T source) {
+    public static <T extends BrooklynObject> Set<Relationship<? super T,? extends BrooklynObject>> getRelationships(T source) {
         return ((BrooklynObjectInternal)source).relations().getLocalBackingStore().getRelationships();
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    public static <T extends BrooklynObject,U extends BrooklynObject> Set<U> getRelationships(Relationship<? super T,U> relationship, T source) {
+    public static <T extends BrooklynObject,U extends BrooklynObject> Set<U> getRelations(Relationship<? super T,U> relationship, T source) {
         return ((BrooklynObjectInternal)source).relations().getLocalBackingStore().getRelations(relationship);
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    public static <T extends BrooklynObject,U extends BrooklynObject> void add(T source, Relationship<? super T,U> relationship, U target) {
+    public static <T extends BrooklynObject,U extends BrooklynObject> void add(T source, Relationship<? super T,? super U> relationship, U target) {
         ((BrooklynObjectInternal)source).relations().getLocalBackingStore().add(relationship, target);
         ((BrooklynObjectInternal)target).relations().getLocalBackingStore().add(relationship.getInverseRelationship(), source);
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    public static <T extends BrooklynObject,U extends BrooklynObject> void remove(T source, Relationship<? super T,U> relationship, U target) {
+    public static <T extends BrooklynObject,U extends BrooklynObject> void remove(T source, Relationship<? super T,? super U> relationship, U target) {
         ((BrooklynObjectInternal)source).relations().getLocalBackingStore().remove(relationship, target);
         ((BrooklynObjectInternal)target).relations().getLocalBackingStore().remove(relationship.getInverseRelationship(), source);
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java
index 74a7dca..414cdbe 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java
@@ -86,11 +86,19 @@ public abstract class AbstractBrooklynObjectRebindSupport<T extends Memento> imp
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
     protected void addRelations(RebindContext rebindContext, T memento) {
-        for (Map.Entry<String,Set<BrooklynObject>> rEntry : memento.getRelations().entrySet()) {
+        for (Map.Entry<String,Set<String>> rEntry : memento.getRelations().entrySet()) {
             Relationship<? extends BrooklynObject, ? extends BrooklynObject> r = EntityRelations.lookup(instance.getManagementContext(), rEntry.getKey());
             if (r==null) throw new IllegalStateException("Unsupported relationship -- "+rEntry.getKey() + " -- in "+memento);
-            for (BrooklynObject item: rEntry.getValue())
-                instance.relations().add((Relationship)r, item);
+            for (String itemId: rEntry.getValue()) {
+                BrooklynObject item = rebindContext.lookup().lookup(null, itemId);
+                if (item != null) {
+                    instance.relations().add((Relationship)r, item);
+                } else {
+                    LOG.warn("Item not found; discarding item {} relation {} of entity {}({})",
+                            new Object[] {itemId, r, memento.getType(), memento.getId()});
+                    rebindContext.getExceptionHandler().onDanglingUntypedItemRef(itemId);
+                }
+            }
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextLookupContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextLookupContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextLookupContext.java
index 550f376..1faaa1c 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextLookupContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextLookupContext.java
@@ -18,6 +18,8 @@
  */
 package org.apache.brooklyn.core.mgmt.rebind;
 
+import java.util.NoSuchElementException;
+
 import javax.annotation.Nullable;
 
 import org.slf4j.Logger;
@@ -127,6 +129,14 @@ public class RebindContextLookupContext implements LookupContext {
     
     @Override
     public BrooklynObject lookup(BrooklynObjectType type, String id) {
+        if (type==null) {
+            BrooklynObject result = peek(null, id);
+            if (result==null) {
+                exceptionHandler.onDanglingUntypedItemRef(id);
+            }
+            type = BrooklynObjectType.of(result);
+        }
+        
         switch (type) {
         case CATALOG_ITEM: return lookupCatalogItem(id);
         case ENRICHER: return lookupEnricher(id);
@@ -141,6 +151,14 @@ public class RebindContextLookupContext implements LookupContext {
     
     @Override
     public BrooklynObject peek(BrooklynObjectType type, String id) {
+        if (type==null) {
+            for (BrooklynObjectType typeX: BrooklynObjectType.values()) {
+                BrooklynObject result = peek(typeX, id);
+                if (result!=null) return result;
+            }
+            return null;
+        }
+        
         switch (type) {
         case CATALOG_ITEM: return rebindContext.getCatalogItem(id);
         case ENRICHER: return rebindContext.getEnricher(id);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindExceptionHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindExceptionHandlerImpl.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindExceptionHandlerImpl.java
index b6b7fc4..7b4cd00 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindExceptionHandlerImpl.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindExceptionHandlerImpl.java
@@ -65,6 +65,7 @@ public class RebindExceptionHandlerImpl implements RebindExceptionHandler {
     protected final Set<String> missingEnrichers = Sets.newConcurrentHashSet();
     protected final Set<String> missingFeeds = Sets.newConcurrentHashSet();
     protected final Set<String> missingCatalogItems = Sets.newConcurrentHashSet();
+    protected final Set<String> missingUntypedItems = Sets.newConcurrentHashSet();
     protected final Set<String> creationFailedIds = Sets.newConcurrentHashSet();
     
     protected final Set<Exception> addPolicyFailures = Sets.newConcurrentHashSet();
@@ -237,6 +238,17 @@ public class RebindExceptionHandlerImpl implements RebindExceptionHandler {
     }
 
     @Override
+    public CatalogItem<?, ?> onDanglingUntypedItemRef(String id) {
+        missingUntypedItems.add(id);
+        if (danglingRefFailureMode == RebindManager.RebindFailureMode.FAIL_FAST) {
+            throw new IllegalStateException("No item found with id "+id);
+        } else {
+            warn("No item found with id "+id+"; dangling reference on rebind");
+            return null;
+        }
+    }
+
+    @Override
     public void onCreateFailed(BrooklynObjectType type, String id, String instanceType, Exception e) {
         Exceptions.propagateIfFatal(e);
         String errmsg = "problem creating "+type+" "+id+" of type "+instanceType;
@@ -395,7 +407,7 @@ public class RebindExceptionHandlerImpl implements RebindExceptionHandler {
         }
         done = true;
         
-        List<String> danglingIds = MutableList.copyOf(missingEntities).appendAll(missingLocations).appendAll(missingPolicies).appendAll(missingEnrichers).appendAll(missingFeeds).appendAll(missingCatalogItems);
+        List<String> danglingIds = MutableList.copyOf(missingEntities).appendAll(missingLocations).appendAll(missingPolicies).appendAll(missingEnrichers).appendAll(missingFeeds).appendAll(missingCatalogItems).appendAll(missingUntypedItems);
         int totalDangling = danglingIds.size();
         if (totalDangling>0) {
             int totalFound = context.getAllBrooklynObjects().size();
@@ -441,6 +453,9 @@ public class RebindExceptionHandlerImpl implements RebindExceptionHandler {
             if (!missingCatalogItems.isEmpty()) {
                 allExceptions.add(new IllegalStateException("Missing referenced catalog item" + Strings.s(missingCatalogItems) + ": " + missingCatalogItems));
             }
+            if (!missingUntypedItems.isEmpty()) {
+                allExceptions.add(new IllegalStateException("Missing referenced untyped items" + Strings.s(missingUntypedItems) + ": " + missingUntypedItems));
+            }
         }
         if (rebindFailureMode != RebindManager.RebindFailureMode.CONTINUE) {
             allExceptions.addAll(exceptions);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java
index 1fae585..6fae7f5 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java
@@ -25,14 +25,15 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.brooklyn.api.mgmt.rebind.mementos.Memento;
-import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.core.BrooklynVersion;
 import org.apache.brooklyn.core.config.Sanitizer;
 
 import com.google.common.base.Objects;
 import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
 
 public abstract class AbstractMemento implements Memento, Serializable {
 
@@ -47,8 +48,8 @@ public abstract class AbstractMemento implements Memento, Serializable {
         protected String catalogItemId;
         protected Map<String, Object> customFields = Maps.newLinkedHashMap();
         protected List<Object> tags = Lists.newArrayList();
-        protected Map<String,Set<BrooklynObject>> relations = Maps.newLinkedHashMap();
-        
+        protected Map<String,Set<String>> relations = Maps.newLinkedHashMap();
+
         // only supported for EntityAdjuncts
         protected String uniqueTag;
 
@@ -86,7 +87,7 @@ public abstract class AbstractMemento implements Memento, Serializable {
     private String displayName;
     private String catalogItemId;
     private List<Object> tags;
-    private Map<String, Set<BrooklynObject>> relations;
+    private Map<String,Set<String>> relations;
     
     // for EntityAdjuncts; not used for entity
     private String uniqueTag;
@@ -156,7 +157,7 @@ public abstract class AbstractMemento implements Memento, Serializable {
     }
 
     @Override
-    public Map<String, Set<BrooklynObject>> getRelations() {
+    public Map<String,Set<String>> getRelations() {
         return fromPersistedMap(relations);
     }
     
@@ -218,4 +219,12 @@ public abstract class AbstractMemento implements Memento, Serializable {
         if (m==null || m.isEmpty()) return null;
         return m;
     }
+    protected <K,V> Multimap<K,V> fromPersistedMultimap(Multimap<K,V> m) {
+        if (m==null) return ImmutableMultimap.of();
+        return ImmutableMultimap.copyOf(m);
+    }
+    protected <K,V> Multimap<K,V> toPersistedMultimap(Multimap<K,V> m) {
+        if (m==null || m.isEmpty()) return null;
+        return m;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java
index 6cfda79..918278c 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java
@@ -66,6 +66,7 @@ import org.apache.brooklyn.util.core.flags.FlagUtils;
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
 import com.google.common.base.Predicates;
+import com.google.common.collect.Sets;
 
 import brooklyn.basic.relations.Relationship;
 
@@ -431,7 +432,6 @@ public class MementosGenerators {
         return builder.build();
     }
     
-    @SuppressWarnings({ "unchecked", "rawtypes" })
     private static void populateBrooklynObjectMementoBuilder(BrooklynObject instance, AbstractMemento.Builder<?> builder) {
         if (Proxy.isProxyClass(instance.getClass())) {
             throw new IllegalStateException("Attempt to create memento from proxy "+instance+" (would fail with wrong type)");
@@ -448,12 +448,13 @@ public class MementosGenerators {
         for (Object tag : instance.tags().getTags()) {
             builder.tags.add(tag); 
         }
-        if (!(instance instanceof CatalogItem)) {
-            // CatalogItem is a BrooklynObject so it can be persisted
-            // but it does not support relations
-            for (Relationship<?,? extends BrooklynObject> relationship: instance.relations().getRelationships()) {
-                builder.relations.put(relationship.getRelationshipTypeName(), instance.relations().getRelations((Relationship)relationship));
-            }
+        // CatalogItems return empty support, so this is safe even through they don't support relations
+        for (Relationship<?,? extends BrooklynObject> relationship: instance.relations().getRelationships()) {
+            @SuppressWarnings({ "unchecked", "rawtypes" })
+            Set relations = instance.relations().getRelations((Relationship)relationship);
+            Set<String> relationIds = Sets.newLinkedHashSet();
+            for (Object r: relations) relationIds.add( ((BrooklynObject)r).getId() );
+            builder.relations.put(relationship.getRelationshipTypeName(), relationIds);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java b/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java
index e87d0ea..3694fa8 100644
--- a/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java
+++ b/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java
@@ -34,21 +34,21 @@ public abstract class AbstractBasicRelationSupport<SourceType extends BrooklynOb
         
     @Override
     public Set<Relationship<? super SourceType, ? extends BrooklynObject>> getRelationships() {
-        return EntityRelations.getRelations(source);
+        return EntityRelations.getRelationships(source);
     }
     
     @Override
     public <U extends BrooklynObject> Set<U> getRelations(Relationship<? super SourceType, U> relationship) {
-        return EntityRelations.getRelationships(relationship, source);
+        return EntityRelations.getRelations(relationship, source);
     }
 
     @Override
-    public <U extends BrooklynObject> void add(Relationship<? super SourceType, U> relationship, U target) {
+    public <U extends BrooklynObject> void add(Relationship<? super SourceType, ? super U> relationship, U target) {
         EntityRelations.add(source, relationship, target);
     }
 
     @Override
-    public <U extends BrooklynObject> void remove(Relationship<? super SourceType, U> relationship, U target) {
+    public <U extends BrooklynObject> void remove(Relationship<? super SourceType, ? super U> relationship, U target) {
         EntityRelations.remove(source, relationship, target);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java b/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java
index 1152e85..3600640 100644
--- a/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java
+++ b/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java
@@ -78,17 +78,18 @@ public class ByObjectBasicRelationSupport<SourceType extends BrooklynObject> ext
             }
         }
 
+        @SuppressWarnings({ "unchecked", "rawtypes" })
         @Override
-        public <U extends BrooklynObject> void add(Relationship<? super T,U> relationship, U target) {
+        public <U extends BrooklynObject> void add(Relationship<? super T,? super U> relationship, U target) {
             synchronized (relations) {
-                relationships.put(relationship.getRelationshipTypeName(), relationship);
+                relationships.put(relationship.getRelationshipTypeName(), (Relationship)relationship);
                 relations.put(relationship.getRelationshipTypeName(), target);
             }
             onRelationsChanged();
         }
 
         @Override
-        public <U extends BrooklynObject> void remove(Relationship<? super T,U> relationship, U target) {
+        public <U extends BrooklynObject> void remove(Relationship<? super T,? super U> relationship, U target) {
             synchronized (relations) {
                 relations.remove(relationship.getRelationshipTypeName(), target);
             }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/main/java/org/apache/brooklyn/core/relations/EmptyRelationSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/relations/EmptyRelationSupport.java b/core/src/main/java/org/apache/brooklyn/core/relations/EmptyRelationSupport.java
new file mode 100644
index 0000000..40b001a
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/relations/EmptyRelationSupport.java
@@ -0,0 +1,60 @@
+/*
+ * 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.relations;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.api.objs.BrooklynObject.RelationSupport;
+import org.apache.brooklyn.core.objs.BrooklynObjectInternal.RelationSupportInternal;
+
+import brooklyn.basic.relations.Relationship;
+
+public final class EmptyRelationSupport<SourceType extends BrooklynObject> implements RelationSupportInternal<SourceType> {
+
+    final SourceType source;
+    
+    public EmptyRelationSupport(SourceType source) { this.source = source; }
+        
+    @Override
+    public Set<Relationship<? super SourceType, ? extends BrooklynObject>> getRelationships() {
+        return Collections.emptySet();
+    }
+    
+    @Override
+    public <U extends BrooklynObject> Set<U> getRelations(Relationship<? super SourceType, U> relationship) {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public <U extends BrooklynObject> void add(Relationship<? super SourceType, ? super U> relationship, U target) {
+        throw new UnsupportedOperationException("Relations not available on "+source);
+    }
+
+    @Override
+    public <U extends BrooklynObject> void remove(Relationship<? super SourceType, ? super U> relationship, U target) {
+    }
+
+    @Override
+    public RelationSupport<SourceType> getLocalBackingStore() {
+        throw new UnsupportedOperationException("Relations not available on "+source);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
index 246e214..3ed5486 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
@@ -516,6 +516,16 @@ System.out.println("XXX: "+x);
         
         @Override
         public BrooklynObject lookup(BrooklynObjectType type, String id) {
+            if (type==null) {
+                BrooklynObject result = peek(null, id);
+                if (result==null) {
+                    if (failOnDangling) {
+                        throw new NoSuchElementException("no brooklyn object with id "+id+"; type not specified");
+                    }                    
+                }
+                type = BrooklynObjectType.of(result);
+            }
+            
             switch (type) {
             case CATALOG_ITEM: return lookupCatalogItem(id);
             case ENRICHER: return lookupEnricher(id);
@@ -529,6 +539,14 @@ System.out.println("XXX: "+x);
         }
         @Override
         public BrooklynObject peek(BrooklynObjectType type, String id) {
+            if (type==null) {
+                for (BrooklynObjectType typeX: BrooklynObjectType.values()) {
+                    BrooklynObject result = peek(typeX, id);
+                    if (result!=null) return result;
+                }
+                return null;
+            }
+            
             switch (type) {
             case CATALOG_ITEM: return catalogItems.get(id);
             case ENRICHER: return enrichers.get(id);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindClassInitializationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindClassInitializationTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindClassInitializationTest.java
new file mode 100644
index 0000000..a5105cc
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindClassInitializationTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.mgmt.rebind;
+
+import java.util.List;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.core.entity.AbstractEntity;
+import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.text.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class RebindClassInitializationTest extends RebindTestFixtureWithApp {
+
+    private static final Logger log = LoggerFactory.getLogger(RebindClassInitializationTest.class);
+    static List<String> messages = MutableList.of();
+    
+    @Test
+    public void testRestoresSimpleApp() throws Exception {
+        messages.clear();
+        messages.add("creating");
+        origApp.createAndManageChild(EntitySpec.create(Entity.class, MyEntityForClassInitializationTesting.class));
+        messages.add("created");
+        messages.add("rebinding");
+        newApp = rebind();
+        messages.add("rebinded");
+        
+        log.debug("Create and rebind message sequence is:\n- "+Strings.join(messages, "\n- "));
+        Assert.assertEquals(messages, MutableList.of(
+            "creating", "ME.static_initializer", "ME.initializer", 
+            "WIM.static_initializer", "WIM.initializer", "WIM.constructor", 
+            "ME.constructor", "created", 
+            "rebinding", "ME.initializer", "WIM.initializer", "WIM.constructor", 
+            "ME.constructor", "rebinded"));
+    }
+    
+    public static class MyEntityForClassInitializationTesting extends AbstractEntity {
+        
+        { messages.add("ME.initializer"); }
+        
+        static { messages.add("ME.static_initializer"); }
+        
+        @SuppressWarnings("unused")
+        private final Object dummy = new WriteInitMessage();
+
+        public MyEntityForClassInitializationTesting() {
+            messages.add("ME.constructor");
+        }
+    }
+
+    private static class WriteInitMessage {
+        public WriteInitMessage() { messages.add("WIM.constructor"); }
+        
+        { messages.add("WIM.initializer"); }
+        
+        static { messages.add("WIM.static_initializer"); }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ed113a34/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityTest.java
index 900b492..7c726e4 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindEntityTest.java
@@ -49,9 +49,9 @@ import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoManifest;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.EntityMemento;
 import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.api.sensor.AttributeSensor.SensorPersistenceMode;
 import org.apache.brooklyn.api.sensor.SensorEvent;
 import org.apache.brooklyn.api.sensor.SensorEventListener;
-import org.apache.brooklyn.api.sensor.AttributeSensor.SensorPersistenceMode;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.BasicConfigKey;
 import org.apache.brooklyn.core.entity.AbstractEntity;
@@ -61,7 +61,6 @@ import org.apache.brooklyn.core.entity.trait.Resizable;
 import org.apache.brooklyn.core.entity.trait.Startable;
 import org.apache.brooklyn.core.location.LocationConfigTest.MyLocation;
 import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
-import org.apache.brooklyn.core.mgmt.rebind.BasicEntityRebindSupport;
 import org.apache.brooklyn.core.sensor.BasicAttributeSensor;
 import org.apache.brooklyn.core.sensor.BasicSensorEvent;
 import org.apache.brooklyn.core.sensor.DependentConfiguration;



[6/8] incubator-brooklyn git commit: refer to RelationshipType rather than Relationship

Posted by sv...@apache.org.
refer to RelationshipType rather than Relationship

this allows us to reserve Relationships for instances of links which might be BrooklynObjects with config, etc.


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

Branch: refs/heads/master
Commit: 09aab586a1cb76dd587b947e3285afa96facce1b
Parents: 890c5c0
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Oct 27 12:44:17 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Oct 27 12:44:17 2015 +0000

----------------------------------------------------------------------
 .../brooklyn/basic/relations/Relationship.java  |  38 ----
 .../basic/relations/RelationshipType.java       |  38 ++++
 .../brooklyn/api/objs/BrooklynObject.java       |  21 ++-
 .../brooklyn/core/entity/EntityRelations.java   |  80 +++++---
 .../AbstractBrooklynObjectRebindSupport.java    |   6 +-
 .../mgmt/rebind/dto/MementosGenerators.java     |   6 +-
 .../relations/AbstractBasicRelationSupport.java |  14 +-
 .../relations/ByObjectBasicRelationSupport.java |  16 +-
 .../core/relations/EmptyRelationSupport.java    |  10 +-
 .../core/relations/RelationshipTypes.java       | 188 +++++++++++++++++++
 .../brooklyn/core/relations/Relationships.java  | 188 -------------------
 .../core/relations/RelationshipTest.java        |  10 +-
 12 files changed, 322 insertions(+), 293 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/09aab586/api/src/main/java/brooklyn/basic/relations/Relationship.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/basic/relations/Relationship.java b/api/src/main/java/brooklyn/basic/relations/Relationship.java
deleted file mode 100644
index bc17e6a..0000000
--- a/api/src/main/java/brooklyn/basic/relations/Relationship.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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 brooklyn.basic.relations;
-
-import brooklyn.basic.relations.Relationship;
-
-
-public interface Relationship<SourceType,TargetType> {
-
-    public String getRelationshipTypeName();
-    public Class<SourceType> getSourceType();
-    public Class<TargetType> getTargetType();
-    
-    public String getSourceName();
-    public String getSourceNamePlural();
-
-    public String getTargetName();
-    public String getTargetNamePlural();
-
-    public Relationship<TargetType,SourceType> getInverseRelationship();
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/09aab586/api/src/main/java/brooklyn/basic/relations/RelationshipType.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/basic/relations/RelationshipType.java b/api/src/main/java/brooklyn/basic/relations/RelationshipType.java
new file mode 100644
index 0000000..f7d6abb
--- /dev/null
+++ b/api/src/main/java/brooklyn/basic/relations/RelationshipType.java
@@ -0,0 +1,38 @@
+/*
+ * 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 brooklyn.basic.relations;
+
+import brooklyn.basic.relations.RelationshipType;
+
+
+public interface RelationshipType<SourceType,TargetType> {
+
+    public String getRelationshipTypeName();
+    public Class<SourceType> getSourceType();
+    public Class<TargetType> getTargetType();
+    
+    public String getSourceName();
+    public String getSourceNamePlural();
+
+    public String getTargetName();
+    public String getTargetNamePlural();
+
+    public RelationshipType<TargetType,SourceType> getInverseRelationshipType();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/09aab586/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 9e1640f..f388bd6 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
@@ -34,7 +34,7 @@ import org.apache.brooklyn.api.sensor.SensorEventListener;
 import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableMap;
 
-import brooklyn.basic.relations.Relationship;
+import brooklyn.basic.relations.RelationshipType;
 
 /**
  * Super-type of entity, location, policy and enricher.
@@ -151,9 +151,20 @@ public interface BrooklynObject extends Identifiable, Configurable {
     }
     
     public interface RelationSupport<T extends BrooklynObject> {
-        public <U extends BrooklynObject> void add(Relationship<? super T,? super U> relationship, U target);
-        public <U extends BrooklynObject> void remove(Relationship<? super T,? super U> relationship, U target);
-        public Set<Relationship<? super T,? extends BrooklynObject>> getRelationships();
-        public <U extends BrooklynObject> Set<U> getRelations(Relationship<? super T,U> relationship);
+        /** Adds a relationship of the given type from this object pointing at the given target, 
+         * and ensures that the inverse relationship (if there is one) is present at the target pointing back at this object. 
+         */
+        public <U extends BrooklynObject> void add(RelationshipType<? super T,? super U> relationship, U target);
+        
+        /** Removes any and all relationships of the given type from this object pointing at the given target,
+         * and ensures that the inverse relationships (if there are one) are also removed. 
+         */
+        public <U extends BrooklynObject> void remove(RelationshipType<? super T,? super U> relationship, U target);
+        
+        /** @return the {@link RelationshipType}s originating from this object */
+        public Set<RelationshipType<? super T,? extends BrooklynObject>> getRelationshipTypes();
+        
+        /** @return the {@link BrooklynObject}s which are targets of the given {@link RelationshipType} */
+        public <U extends BrooklynObject> Set<U> getRelations(RelationshipType<? super T,U> relationshipType);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/09aab586/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java b/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java
index 4621a76..6203f22 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/EntityRelations.java
@@ -26,14 +26,16 @@ import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.Group;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.api.objs.BrooklynObject.RelationSupport;
 import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
-import org.apache.brooklyn.core.relations.Relationships;
+import org.apache.brooklyn.core.relations.AbstractBasicRelationSupport;
+import org.apache.brooklyn.core.relations.RelationshipTypes;
 import org.apache.brooklyn.util.collections.MutableMap;
 
 import com.google.common.annotations.Beta;
 
-import brooklyn.basic.relations.Relationship;
+import brooklyn.basic.relations.RelationshipType;
 
 /** TODO these relations are not used yet; see issue where this is introduced and email thread */
 @Beta
@@ -43,31 +45,31 @@ public class EntityRelations<T extends BrooklynObject> {
      * in the internal Brooklyn management hierarchy model.
      * Apart from root {@link Application} entities, every deployed entity must have exactly one manager.  
      * The inverse relationship is {@link #MANAGED_BY}. */ 
-    public static final Relationship<Entity,Entity> MANAGER_OF = Relationships.newRelationshipPair(
+    public static final RelationshipType<Entity,Entity> MANAGER_OF = RelationshipTypes.newRelationshipPair(
         "manager", "managers", Entity.class, "manager_of", 
         "managed child", "managed children", Entity.class, "managed_by");
     /** Inverse of {@link #MANAGER_OF}. */
-    public static final Relationship<Entity,Entity> MANAGED_BY = MANAGER_OF.getInverseRelationship();
+    public static final RelationshipType<Entity,Entity> MANAGED_BY = MANAGER_OF.getInverseRelationshipType();
     
     /** {@link #GROUP_CONTAINS} indicates that one entity, typically a {@link Group},
      * has zero or more entities which are labelled as "members" of that group entity.
      * What membership means will depend on the group entity.
      * An entity may be a member of any number of other entities.  
      * The inverse relationship is {@link #IN_GROUP}. */ 
-    public static final Relationship<Entity,Entity> GROUP_CONTAINS = Relationships.newRelationshipPair(
+    public static final RelationshipType<Entity,Entity> GROUP_CONTAINS = RelationshipTypes.newRelationshipPair(
         "group", "groups", Entity.class, "group_contains",
         "member", "members", Entity.class, "in_group");
     /** Inverse of {@link #GROUP_CONTAINS}. */
-    public static final Relationship<Entity,Entity> IN_GROUP = GROUP_CONTAINS.getInverseRelationship();
+    public static final RelationshipType<Entity,Entity> IN_GROUP = GROUP_CONTAINS.getInverseRelationshipType();
 
     /** {@link #HAS_TARGET} indicates that one entity directs to one or more other entities.
      * What this targeting relationship means depends on the targetter.
      * The inverse relationship is {@link #TARGETTED_BY}. */
-    public static final Relationship<Entity,Entity> HAS_TARGET = Relationships.newRelationshipPair(
+    public static final RelationshipType<Entity,Entity> HAS_TARGET = RelationshipTypes.newRelationshipPair(
         "targetter", "targetters", Entity.class, "has_target", 
         "target", "targets", Entity.class, "targetted_by");
     /** Inverse of {@link #HAS_TARGET}. */
-    public static final Relationship<Entity,Entity> TARGETTED_BY = HAS_TARGET.getInverseRelationship();
+    public static final RelationshipType<Entity,Entity> TARGETTED_BY = HAS_TARGET.getInverseRelationshipType();
 
     /** {@link #ACTIVE_PARENT_OF} indicates that one entity is should be considered as the logical parent of another,
      * e.g. for presentation purposes to the end user.
@@ -86,28 +88,28 @@ public class EntityRelations<T extends BrooklynObject> {
      * <p> 
      * The inverse relationship is {@link #ACTIVE_CHILD_OF},
      * and an entity should normally be an {@link #ACTIVE_CHILD_OF} zero or one entities. */
-    public static final Relationship<Entity,Entity> ACTIVE_PARENT_OF = Relationships.newRelationshipPair(
+    public static final RelationshipType<Entity,Entity> ACTIVE_PARENT_OF = RelationshipTypes.newRelationshipPair(
         "parent", "parents", Entity.class, "parent_of_active", 
         "active child", "active children", Entity.class, "active_child_of");
     /** Inverse of {@link #ACTIVE_PARENT_OF}. */
-    public static final Relationship<Entity,Entity> ACTIVE_CHILD_OF = ACTIVE_PARENT_OF.getInverseRelationship();
+    public static final RelationshipType<Entity,Entity> ACTIVE_CHILD_OF = ACTIVE_PARENT_OF.getInverseRelationshipType();
     
     /** {@link #HAS_POLICY} indicates that an entity has a policy associated to it.
      * The inverse relationship is {@link #POLICY_FOR}. */
-    public static final Relationship<Entity,Policy> HAS_POLICY = Relationships.newRelationshipPair(
+    public static final RelationshipType<Entity,Policy> HAS_POLICY = RelationshipTypes.newRelationshipPair(
         "entity", "entities", Entity.class, "has_policy", 
         "policy", "policies", Policy.class, "policy_for");
     /** Inverse of {@link #HAS_POLICY}. */
-    public static final Relationship<Policy,Entity> POLICY_FOR = HAS_POLICY.getInverseRelationship();
+    public static final RelationshipType<Policy,Entity> POLICY_FOR = HAS_POLICY.getInverseRelationshipType();
 
     // ----
     
     // TODO replace by relations stored in catalog when catalog supports arbitrary types
-    private static Map<String,Relationship<? extends BrooklynObject, ? extends BrooklynObject>> KNOWN_RELATIONSHIPS = MutableMap.of();
-    private static void addRelationship(Relationship<? extends BrooklynObject, ? extends BrooklynObject> r) {
+    private static Map<String,RelationshipType<? extends BrooklynObject, ? extends BrooklynObject>> KNOWN_RELATIONSHIPS = MutableMap.of();
+    private static void addRelationship(RelationshipType<? extends BrooklynObject, ? extends BrooklynObject> r) {
         KNOWN_RELATIONSHIPS.put(r.getRelationshipTypeName(), r);
-        if (r.getInverseRelationship()!=null) {
-            KNOWN_RELATIONSHIPS.put(r.getInverseRelationship().getRelationshipTypeName(), r.getInverseRelationship());
+        if (r.getInverseRelationshipType()!=null) {
+            KNOWN_RELATIONSHIPS.put(r.getInverseRelationshipType().getRelationshipTypeName(), r.getInverseRelationshipType());
         }
     }
     static {
@@ -122,9 +124,9 @@ public class EntityRelations<T extends BrooklynObject> {
      * it may fail fast or return null or create a poor-man's relationship instance. 
      */
     @Beta
-    public static Relationship<? extends BrooklynObject, ? extends BrooklynObject> lookup(ManagementContext mgmt, String relationshipTypeName) {
+    public static RelationshipType<? extends BrooklynObject, ? extends BrooklynObject> lookup(ManagementContext mgmt, String relationshipTypeName) {
         if (relationshipTypeName==null) return null;
-        Relationship<? extends BrooklynObject, ? extends BrooklynObject> result = KNOWN_RELATIONSHIPS.get(relationshipTypeName);
+        RelationshipType<? extends BrooklynObject, ? extends BrooklynObject> result = KNOWN_RELATIONSHIPS.get(relationshipTypeName);
         if (result!=null) return result;
         
         /* TODO ultimately we'd like to support arbitrary relationships via persistence and lookup against the catalog;
@@ -132,31 +134,47 @@ public class EntityRelations<T extends BrooklynObject> {
          * we are smart about the relationships defined here, and we return a poor-man's version for items elsewhere.
          * 
          * for now, a poor-man's relationship; if not in catalog ultimately we should fail. */
-        return Relationships.newRelationshipOneway("source", "sources", BrooklynObject.class, relationshipTypeName, "target", "targets", BrooklynObject.class);
+        return RelationshipTypes.newRelationshipOneway("source", "sources", BrooklynObject.class, relationshipTypeName, "target", "targets", BrooklynObject.class);
     }
     
+    /** 
+     * As {@link RelationSupport#getRelationshipTypes()} for the given object.  Callers can use either method.
+     * See {@link AbstractBasicRelationSupport} for a discussion of why double dispatch is used and both methods are present.
+     */
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    public static <T extends BrooklynObject> Set<Relationship<? super T,? extends BrooklynObject>> getRelationships(T source) {
-        return (Set) ((BrooklynObjectInternal)source).relations().getLocalBackingStore().getRelationships();
+    public static <T extends BrooklynObject> Set<RelationshipType<? super T,? extends BrooklynObject>> getRelationshipTypes(T source) {
+        return (Set) ((BrooklynObjectInternal)source).relations().getLocalBackingStore().getRelationshipTypes();
     }
 
+    /** 
+     * As {@link RelationSupport#getRelations(RelationshipType)} for the given object.  Callers can use either method.
+     * See {@link AbstractBasicRelationSupport} for a discussion of why double dispatch is used and both methods are present.
+     */
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    public static <T extends BrooklynObject,U extends BrooklynObject> Set<U> getRelations(Relationship<? super T,U> relationship, T source) {
-        return (Set) ((BrooklynObjectInternal)source).relations().getLocalBackingStore().getRelations((Relationship)relationship);
+    public static <T extends BrooklynObject,U extends BrooklynObject> Set<U> getRelations(RelationshipType<? super T,U> relationship, T source) {
+        return (Set) ((BrooklynObjectInternal)source).relations().getLocalBackingStore().getRelations((RelationshipType)relationship);
     }
 
+    /** 
+     * As {@link RelationSupport#add(RelationshipType, BrooklynObject)} for the given object.  Callers can use either method.
+     * See {@link AbstractBasicRelationSupport} for a discussion of why double dispatch is used and both methods are present.
+     */
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    public static <T extends BrooklynObject,U extends BrooklynObject> void add(T source, Relationship<? super T,? super U> relationship, U target) {
-        ((BrooklynObjectInternal)source).relations().getLocalBackingStore().add((Relationship)relationship, target);
-        if (relationship.getInverseRelationship()!=null)
-            ((BrooklynObjectInternal)target).relations().getLocalBackingStore().add((Relationship)relationship.getInverseRelationship(), source);
+    public static <T extends BrooklynObject,U extends BrooklynObject> void add(T source, RelationshipType<? super T,? super U> relationship, U target) {
+        ((BrooklynObjectInternal)source).relations().getLocalBackingStore().add((RelationshipType)relationship, target);
+        if (relationship.getInverseRelationshipType()!=null)
+            ((BrooklynObjectInternal)target).relations().getLocalBackingStore().add((RelationshipType)relationship.getInverseRelationshipType(), source);
     }
 
+    /** 
+     * As {@link RelationSupport#remove(RelationshipType, BrooklynObject)} for the given object.  Callers can use either method.
+     * See {@link AbstractBasicRelationSupport} for a discussion of why double dispatch is used and both methods are present.
+     */
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    public static <T extends BrooklynObject,U extends BrooklynObject> void remove(T source, Relationship<? super T,? super U> relationship, U target) {
-        ((BrooklynObjectInternal)source).relations().getLocalBackingStore().remove((Relationship)relationship, target);
-        if (relationship.getInverseRelationship()!=null)
-            ((BrooklynObjectInternal)target).relations().getLocalBackingStore().remove((Relationship)relationship.getInverseRelationship(), source);
+    public static <T extends BrooklynObject,U extends BrooklynObject> void remove(T source, RelationshipType<? super T,? super U> relationship, U target) {
+        ((BrooklynObjectInternal)source).relations().getLocalBackingStore().remove((RelationshipType)relationship, target);
+        if (relationship.getInverseRelationshipType()!=null)
+            ((BrooklynObjectInternal)target).relations().getLocalBackingStore().remove((RelationshipType)relationship.getInverseRelationshipType(), source);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/09aab586/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java
index b56d8c6..8c5abdf 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/AbstractBrooklynObjectRebindSupport.java
@@ -34,7 +34,7 @@ import org.apache.brooklyn.util.text.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import brooklyn.basic.relations.Relationship;
+import brooklyn.basic.relations.RelationshipType;
 
 public abstract class AbstractBrooklynObjectRebindSupport<T extends Memento> implements RebindSupport<T> {
 
@@ -87,12 +87,12 @@ public abstract class AbstractBrooklynObjectRebindSupport<T extends Memento> imp
     @SuppressWarnings({ "unchecked", "rawtypes" })
     protected void addRelations(RebindContext rebindContext, T memento) {
         for (Map.Entry<String,Set<String>> rEntry : memento.getRelations().entrySet()) {
-            Relationship<? extends BrooklynObject, ? extends BrooklynObject> r = EntityRelations.lookup(instance.getManagementContext(), rEntry.getKey());
+            RelationshipType<? extends BrooklynObject, ? extends BrooklynObject> r = EntityRelations.lookup(instance.getManagementContext(), rEntry.getKey());
             if (r==null) throw new IllegalStateException("Unsupported relationship -- "+rEntry.getKey() + " -- in "+memento);
             for (String itemId: rEntry.getValue()) {
                 BrooklynObject item = rebindContext.lookup().lookup(null, itemId);
                 if (item != null) {
-                    instance.relations().add((Relationship)r, item);
+                    instance.relations().add((RelationshipType)r, item);
                 } else {
                     LOG.warn("Item not found; discarding item {} relation {} of entity {}({})",
                             new Object[] {itemId, r, memento.getType(), memento.getId()});

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/09aab586/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java
index 918278c..f0c08a6 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java
@@ -68,7 +68,7 @@ import com.google.common.base.Function;
 import com.google.common.base.Predicates;
 import com.google.common.collect.Sets;
 
-import brooklyn.basic.relations.Relationship;
+import brooklyn.basic.relations.RelationshipType;
 
 public class MementosGenerators {
 
@@ -449,9 +449,9 @@ public class MementosGenerators {
             builder.tags.add(tag); 
         }
         // CatalogItems return empty support, so this is safe even through they don't support relations
-        for (Relationship<?,? extends BrooklynObject> relationship: instance.relations().getRelationships()) {
+        for (RelationshipType<?,? extends BrooklynObject> relationship: instance.relations().getRelationshipTypes()) {
             @SuppressWarnings({ "unchecked", "rawtypes" })
-            Set relations = instance.relations().getRelations((Relationship)relationship);
+            Set relations = instance.relations().getRelations((RelationshipType)relationship);
             Set<String> relationIds = Sets.newLinkedHashSet();
             for (Object r: relations) relationIds.add( ((BrooklynObject)r).getId() );
             builder.relations.put(relationship.getRelationshipTypeName(), relationIds);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/09aab586/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java b/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java
index 6483e97..a76d349 100644
--- a/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java
+++ b/core/src/main/java/org/apache/brooklyn/core/relations/AbstractBasicRelationSupport.java
@@ -24,14 +24,14 @@ import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.core.entity.EntityRelations;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal.RelationSupportInternal;
 
-import brooklyn.basic.relations.Relationship;
+import brooklyn.basic.relations.RelationshipType;
 
 /** This abstract impl delegates to {@link EntityRelations} for all changes, routing through a local backing store.
  * This allows us to make the changes in both directions simultaneously when a relationship is bi-directional,
  * and should facilitate changing a backing datastore or remote instances when that is supported.
  * <p>
  * Currently it can be implemented without it, simplifying things a bit (avoiding the double dispatch)
- * apart from the {@link #add(Relationship, BrooklynObject)} method triggering the reverse addition
+ * apart from the {@link #add(RelationshipType, BrooklynObject)} method triggering the reverse addition
  * if it isn't already present. TBD which is better (and the internal call to get the backing store is 
  * marked as Beta). */
 public abstract class AbstractBasicRelationSupport<SourceType extends BrooklynObject> implements RelationSupportInternal<SourceType> {
@@ -41,22 +41,22 @@ public abstract class AbstractBasicRelationSupport<SourceType extends BrooklynOb
     public AbstractBasicRelationSupport(SourceType source) { this.source = source; }
         
     @Override
-    public Set<Relationship<? super SourceType, ? extends BrooklynObject>> getRelationships() {
-        return EntityRelations.getRelationships(source);
+    public Set<RelationshipType<? super SourceType, ? extends BrooklynObject>> getRelationshipTypes() {
+        return EntityRelations.getRelationshipTypes(source);
     }
     
     @Override
-    public <U extends BrooklynObject> Set<U> getRelations(Relationship<? super SourceType, U> relationship) {
+    public <U extends BrooklynObject> Set<U> getRelations(RelationshipType<? super SourceType, U> relationship) {
         return EntityRelations.getRelations(relationship, source);
     }
 
     @Override
-    public <U extends BrooklynObject> void add(Relationship<? super SourceType, ? super U> relationship, U target) {
+    public <U extends BrooklynObject> void add(RelationshipType<? super SourceType, ? super U> relationship, U target) {
         EntityRelations.add(source, relationship, target);
     }
 
     @Override
-    public <U extends BrooklynObject> void remove(Relationship<? super SourceType, ? super U> relationship, U target) {
+    public <U extends BrooklynObject> void remove(RelationshipType<? super SourceType, ? super U> relationship, U target) {
         EntityRelations.remove(source, relationship, target);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/09aab586/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java b/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java
index 3600640..5e065c0 100644
--- a/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java
+++ b/core/src/main/java/org/apache/brooklyn/core/relations/ByObjectBasicRelationSupport.java
@@ -31,7 +31,7 @@ import com.google.common.base.Supplier;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Multimaps;
 
-import brooklyn.basic.relations.Relationship;
+import brooklyn.basic.relations.RelationshipType;
 
 public class ByObjectBasicRelationSupport<SourceType extends BrooklynObject> extends AbstractBasicRelationSupport<SourceType> {
 
@@ -56,7 +56,7 @@ public class ByObjectBasicRelationSupport<SourceType extends BrooklynObject> ext
         }
         
         // TODO for now, relationships are stored here (and persisted); ideally we'd look them up in catalog
-        private Map<String,Relationship<? super T,? extends BrooklynObject>> relationships = MutableMap.of();
+        private Map<String,RelationshipType<? super T,? extends BrooklynObject>> relationshipTypes = MutableMap.of();
         
         private Multimap<String,BrooklynObject> relations = Multimaps.newMultimap(MutableMap.<String,Collection<BrooklynObject>>of(), 
             new Supplier<Collection<BrooklynObject>>() {
@@ -65,14 +65,14 @@ public class ByObjectBasicRelationSupport<SourceType extends BrooklynObject> ext
                 }
             });
 
-        public Set<Relationship<? super T,? extends BrooklynObject>> getRelationships() {
+        public Set<RelationshipType<? super T,? extends BrooklynObject>> getRelationshipTypes() {
             synchronized (relations) {
-                return MutableSet.copyOf(relationships.values());
+                return MutableSet.copyOf(relationshipTypes.values());
             }
         }
         
         @SuppressWarnings("unchecked") @Override 
-        public <U extends BrooklynObject> Set<U> getRelations(Relationship<? super T, U> relationship) {
+        public <U extends BrooklynObject> Set<U> getRelations(RelationshipType<? super T, U> relationship) {
             synchronized (relations) {
                 return (Set<U>)MutableSet.copyOf(relations.get(relationship.getRelationshipTypeName()));
             }
@@ -80,16 +80,16 @@ public class ByObjectBasicRelationSupport<SourceType extends BrooklynObject> ext
 
         @SuppressWarnings({ "unchecked", "rawtypes" })
         @Override
-        public <U extends BrooklynObject> void add(Relationship<? super T,? super U> relationship, U target) {
+        public <U extends BrooklynObject> void add(RelationshipType<? super T,? super U> relationship, U target) {
             synchronized (relations) {
-                relationships.put(relationship.getRelationshipTypeName(), (Relationship)relationship);
+                relationshipTypes.put(relationship.getRelationshipTypeName(), (RelationshipType)relationship);
                 relations.put(relationship.getRelationshipTypeName(), target);
             }
             onRelationsChanged();
         }
 
         @Override
-        public <U extends BrooklynObject> void remove(Relationship<? super T,? super U> relationship, U target) {
+        public <U extends BrooklynObject> void remove(RelationshipType<? super T,? super U> relationship, U target) {
             synchronized (relations) {
                 relations.remove(relationship.getRelationshipTypeName(), target);
             }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/09aab586/core/src/main/java/org/apache/brooklyn/core/relations/EmptyRelationSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/relations/EmptyRelationSupport.java b/core/src/main/java/org/apache/brooklyn/core/relations/EmptyRelationSupport.java
index 40b001a..e1e721d 100644
--- a/core/src/main/java/org/apache/brooklyn/core/relations/EmptyRelationSupport.java
+++ b/core/src/main/java/org/apache/brooklyn/core/relations/EmptyRelationSupport.java
@@ -25,7 +25,7 @@ import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.objs.BrooklynObject.RelationSupport;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal.RelationSupportInternal;
 
-import brooklyn.basic.relations.Relationship;
+import brooklyn.basic.relations.RelationshipType;
 
 public final class EmptyRelationSupport<SourceType extends BrooklynObject> implements RelationSupportInternal<SourceType> {
 
@@ -34,22 +34,22 @@ public final class EmptyRelationSupport<SourceType extends BrooklynObject> imple
     public EmptyRelationSupport(SourceType source) { this.source = source; }
         
     @Override
-    public Set<Relationship<? super SourceType, ? extends BrooklynObject>> getRelationships() {
+    public Set<RelationshipType<? super SourceType, ? extends BrooklynObject>> getRelationshipTypes() {
         return Collections.emptySet();
     }
     
     @Override
-    public <U extends BrooklynObject> Set<U> getRelations(Relationship<? super SourceType, U> relationship) {
+    public <U extends BrooklynObject> Set<U> getRelations(RelationshipType<? super SourceType, U> relationship) {
         return Collections.emptySet();
     }
 
     @Override
-    public <U extends BrooklynObject> void add(Relationship<? super SourceType, ? super U> relationship, U target) {
+    public <U extends BrooklynObject> void add(RelationshipType<? super SourceType, ? super U> relationship, U target) {
         throw new UnsupportedOperationException("Relations not available on "+source);
     }
 
     @Override
-    public <U extends BrooklynObject> void remove(Relationship<? super SourceType, ? super U> relationship, U target) {
+    public <U extends BrooklynObject> void remove(RelationshipType<? super SourceType, ? super U> relationship, U target) {
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/09aab586/core/src/main/java/org/apache/brooklyn/core/relations/RelationshipTypes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/relations/RelationshipTypes.java b/core/src/main/java/org/apache/brooklyn/core/relations/RelationshipTypes.java
new file mode 100644
index 0000000..b358039
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/relations/RelationshipTypes.java
@@ -0,0 +1,188 @@
+/*
+ * 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.relations;
+
+import com.google.common.base.Objects;
+
+import brooklyn.basic.relations.RelationshipType;
+
+public class RelationshipTypes {
+
+    private static abstract class AbstractBasicRelationship<SourceType,TargetType> implements RelationshipType<SourceType,TargetType> {
+        private final String relationshipTypeName;
+        private final String sourceName;
+        private final String sourceNamePlural;
+        private final Class<TargetType> targetType;
+        
+        private AbstractBasicRelationship(String relationshipTypeName, String sourceName, String sourceNamePlural, Class<TargetType> targetType) {
+            this.relationshipTypeName = relationshipTypeName;
+            this.sourceName = sourceName;
+            this.sourceNamePlural = sourceNamePlural;
+            this.targetType = targetType;
+        }
+
+        @Override
+        public String getRelationshipTypeName() {
+            return relationshipTypeName;
+        }
+
+        @Override
+        public String getSourceName() {
+            return sourceName;
+        }
+        
+        @Override
+        public String getSourceNamePlural() {
+            return sourceNamePlural;
+        }
+        
+        @Override
+        public Class<TargetType> getTargetType() {
+            return targetType;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) return true;
+            if (obj == null) return false;
+            if (!(obj instanceof AbstractBasicRelationship)) return false;
+            
+            @SuppressWarnings("rawtypes")
+            AbstractBasicRelationship other = (AbstractBasicRelationship) obj;
+
+            // only look at type name and class; name of source and target is informational
+            if (!Objects.equal(relationshipTypeName, other.relationshipTypeName)) return false;
+            if (!Objects.equal(getSourceType(), other.getSourceType())) return false;
+            if (!Objects.equal(targetType, other.targetType)) return false;
+
+            if (getInverseRelationshipType() == null) {
+                // require both null or...
+                if (other.getInverseRelationshipType() != null)
+                    return false;
+            } else {
+                // ... they have same type name
+                // (don't recurse as that sets up infinite loop)
+                if (other.getInverseRelationshipType() == null)
+                    return false;
+                if (!Objects.equal(getInverseRelationshipType().getRelationshipTypeName(), other.getInverseRelationshipType().getRelationshipTypeName())) return false;
+            }
+
+            return true;
+        }
+        
+        @Override
+        public int hashCode() {
+            // comments as per equals
+            return Objects.hashCode(relationshipTypeName, getSourceType(), targetType,
+                getInverseRelationshipType()!=null ? getInverseRelationshipType().getRelationshipTypeName() : null);
+        }
+        
+        @Override
+        public String toString() {
+            return relationshipTypeName;
+        }
+    }
+
+    private static class BasicRelationshipWithInverse<SourceType,TargetType> extends AbstractBasicRelationship<SourceType,TargetType> {
+        private BasicRelationshipWithInverse<TargetType,SourceType> inverseRelationshipType;
+        
+        private BasicRelationshipWithInverse(String relationshipTypeName, String sourceName, String sourceNamePlural, Class<TargetType> targetType) {
+            super(relationshipTypeName, sourceName, sourceNamePlural, targetType);
+        }
+
+        @Override
+        public RelationshipType<TargetType,SourceType> getInverseRelationshipType() {
+            return inverseRelationshipType;
+        }
+
+        @Override
+        public Class<SourceType> getSourceType() {
+            if (getInverseRelationshipType()==null) return null;
+            return getInverseRelationshipType().getTargetType();
+        }
+
+        @Override
+        public String getTargetName() {
+            if (getInverseRelationshipType()==null) return null;
+            return getInverseRelationshipType().getSourceName();
+        }
+
+        @Override
+        public String getTargetNamePlural() {
+            if (getInverseRelationshipType()==null) return null;
+            return getInverseRelationshipType().getSourceNamePlural();
+        }
+    }
+
+    private static class BasicRelationshipOneWay<SourceType,TargetType> extends AbstractBasicRelationship<SourceType,TargetType> {
+        
+        private final String targetName;
+        private final String targetNamePlural;
+        private final Class<SourceType> sourceType;
+
+        private BasicRelationshipOneWay(String sourceName, String sourceNamePlural, Class<SourceType> sourceType, String toTargetRelationshipTypeName, 
+                String targetName, String targetNamePlural, Class<TargetType> targetType) {
+            super(toTargetRelationshipTypeName, sourceName, sourceNamePlural, targetType);
+            this.targetName = targetName;
+            this.targetNamePlural = targetNamePlural;
+            this.sourceType = sourceType;
+        }
+
+        @Override
+        public Class<SourceType> getSourceType() {
+            return sourceType;
+        }
+
+        @Override
+        public String getTargetName() {
+            return targetName;
+        }
+
+        @Override
+        public String getTargetNamePlural() {
+            return targetNamePlural;
+        }
+
+        @Override
+        public RelationshipType<TargetType, SourceType> getInverseRelationshipType() {
+            return null;
+        }
+    }
+
+    public static <SourceType,TargetType> RelationshipType<SourceType,TargetType> newRelationshipPair(
+            String sourceName, String sourceNamePlural, Class<SourceType> sourceType, String toTargetRelationshipTypeName,   
+            String targetName, String targetNamePlural, Class<TargetType> targetType, String toSourceRelationshipTypeName) {
+        BasicRelationshipWithInverse<SourceType, TargetType> r1 = new BasicRelationshipWithInverse<SourceType, TargetType>(
+            toTargetRelationshipTypeName, sourceName, sourceNamePlural, targetType);
+        BasicRelationshipWithInverse<TargetType, SourceType> r2 = new BasicRelationshipWithInverse<TargetType, SourceType>(
+            toSourceRelationshipTypeName, targetName, targetNamePlural, sourceType);
+        r1.inverseRelationshipType = r2;
+        r2.inverseRelationshipType = r1;
+        return r1;
+    }
+
+    public static <SourceType,TargetType> RelationshipType<SourceType,TargetType> newRelationshipOneway(
+            String sourceName, String sourceNamePlural, Class<SourceType> sourceType, String toTargetRelationshipTypeName,   
+            String targetName, String targetNamePlural, Class<TargetType> targetType) {
+        return new BasicRelationshipOneWay<SourceType,TargetType>(
+            sourceName, sourceNamePlural, sourceType, toTargetRelationshipTypeName,
+            targetName, targetNamePlural, targetType);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/09aab586/core/src/main/java/org/apache/brooklyn/core/relations/Relationships.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/relations/Relationships.java b/core/src/main/java/org/apache/brooklyn/core/relations/Relationships.java
deleted file mode 100644
index 8f7ad54..0000000
--- a/core/src/main/java/org/apache/brooklyn/core/relations/Relationships.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * 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.relations;
-
-import com.google.common.base.Objects;
-
-import brooklyn.basic.relations.Relationship;
-
-public class Relationships {
-
-    private static abstract class AbstractBasicRelationship<SourceType,TargetType> implements Relationship<SourceType,TargetType> {
-        private final String relationshipTypeName;
-        private final String sourceName;
-        private final String sourceNamePlural;
-        private final Class<TargetType> targetType;
-        
-        private AbstractBasicRelationship(String relationshipTypeName, String sourceName, String sourceNamePlural, Class<TargetType> targetType) {
-            this.relationshipTypeName = relationshipTypeName;
-            this.sourceName = sourceName;
-            this.sourceNamePlural = sourceNamePlural;
-            this.targetType = targetType;
-        }
-
-        @Override
-        public String getRelationshipTypeName() {
-            return relationshipTypeName;
-        }
-
-        @Override
-        public String getSourceName() {
-            return sourceName;
-        }
-        
-        @Override
-        public String getSourceNamePlural() {
-            return sourceNamePlural;
-        }
-        
-        @Override
-        public Class<TargetType> getTargetType() {
-            return targetType;
-        }
-        
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) return true;
-            if (obj == null) return false;
-            if (!(obj instanceof AbstractBasicRelationship)) return false;
-            
-            @SuppressWarnings("rawtypes")
-            AbstractBasicRelationship other = (AbstractBasicRelationship) obj;
-
-            // only look at type name and class; name of source and target is informational
-            if (!Objects.equal(relationshipTypeName, other.relationshipTypeName)) return false;
-            if (!Objects.equal(getSourceType(), other.getSourceType())) return false;
-            if (!Objects.equal(targetType, other.targetType)) return false;
-
-            if (getInverseRelationship() == null) {
-                // require both null or...
-                if (other.getInverseRelationship() != null)
-                    return false;
-            } else {
-                // ... they have same type name
-                // (don't recurse as that sets up infinite loop)
-                if (other.getInverseRelationship() == null)
-                    return false;
-                if (!Objects.equal(getInverseRelationship().getRelationshipTypeName(), other.getInverseRelationship().getRelationshipTypeName())) return false;
-            }
-
-            return true;
-        }
-        
-        @Override
-        public int hashCode() {
-            // comments as per equals
-            return Objects.hashCode(relationshipTypeName, getSourceType(), targetType,
-                getInverseRelationship()!=null ? getInverseRelationship().getRelationshipTypeName() : null);
-        }
-        
-        @Override
-        public String toString() {
-            return relationshipTypeName;
-        }
-    }
-
-    private static class BasicRelationshipWithInverse<SourceType,TargetType> extends AbstractBasicRelationship<SourceType,TargetType> {
-        private BasicRelationshipWithInverse<TargetType,SourceType> inverseRelationship;
-        
-        private BasicRelationshipWithInverse(String relationshipTypeName, String sourceName, String sourceNamePlural, Class<TargetType> targetType) {
-            super(relationshipTypeName, sourceName, sourceNamePlural, targetType);
-        }
-
-        @Override
-        public Relationship<TargetType,SourceType> getInverseRelationship() {
-            return inverseRelationship;
-        }
-
-        @Override
-        public Class<SourceType> getSourceType() {
-            if (getInverseRelationship()==null) return null;
-            return getInverseRelationship().getTargetType();
-        }
-
-        @Override
-        public String getTargetName() {
-            if (getInverseRelationship()==null) return null;
-            return getInverseRelationship().getSourceName();
-        }
-
-        @Override
-        public String getTargetNamePlural() {
-            if (getInverseRelationship()==null) return null;
-            return getInverseRelationship().getSourceNamePlural();
-        }
-    }
-
-    private static class BasicRelationshipOneWay<SourceType,TargetType> extends AbstractBasicRelationship<SourceType,TargetType> {
-        
-        private final String targetName;
-        private final String targetNamePlural;
-        private final Class<SourceType> sourceType;
-
-        private BasicRelationshipOneWay(String sourceName, String sourceNamePlural, Class<SourceType> sourceType, String toTargetRelationshipTypeName, 
-                String targetName, String targetNamePlural, Class<TargetType> targetType) {
-            super(toTargetRelationshipTypeName, sourceName, sourceNamePlural, targetType);
-            this.targetName = targetName;
-            this.targetNamePlural = targetNamePlural;
-            this.sourceType = sourceType;
-        }
-
-        @Override
-        public Class<SourceType> getSourceType() {
-            return sourceType;
-        }
-
-        @Override
-        public String getTargetName() {
-            return targetName;
-        }
-
-        @Override
-        public String getTargetNamePlural() {
-            return targetNamePlural;
-        }
-
-        @Override
-        public Relationship<TargetType, SourceType> getInverseRelationship() {
-            return null;
-        }
-    }
-
-    public static <SourceType,TargetType> Relationship<SourceType,TargetType> newRelationshipPair(
-            String sourceName, String sourceNamePlural, Class<SourceType> sourceType, String toTargetRelationshipTypeName,   
-            String targetName, String targetNamePlural, Class<TargetType> targetType, String toSourceRelationshipTypeName) {
-        BasicRelationshipWithInverse<SourceType, TargetType> r1 = new BasicRelationshipWithInverse<SourceType, TargetType>(
-            toTargetRelationshipTypeName, sourceName, sourceNamePlural, targetType);
-        BasicRelationshipWithInverse<TargetType, SourceType> r2 = new BasicRelationshipWithInverse<TargetType, SourceType>(
-            toSourceRelationshipTypeName, targetName, targetNamePlural, sourceType);
-        r1.inverseRelationship = r2;
-        r2.inverseRelationship = r1;
-        return r1;
-    }
-
-    public static <SourceType,TargetType> Relationship<SourceType,TargetType> newRelationshipOneway(
-            String sourceName, String sourceNamePlural, Class<SourceType> sourceType, String toTargetRelationshipTypeName,   
-            String targetName, String targetNamePlural, Class<TargetType> targetType) {
-        return new BasicRelationshipOneWay<SourceType,TargetType>(
-            sourceName, sourceNamePlural, sourceType, toTargetRelationshipTypeName,
-            targetName, targetNamePlural, targetType);
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/09aab586/core/src/test/java/org/apache/brooklyn/core/relations/RelationshipTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/relations/RelationshipTest.java b/core/src/test/java/org/apache/brooklyn/core/relations/RelationshipTest.java
index ba114dd..5d73652 100644
--- a/core/src/test/java/org/apache/brooklyn/core/relations/RelationshipTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/relations/RelationshipTest.java
@@ -23,16 +23,16 @@ import org.apache.brooklyn.core.test.entity.TestEntity;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
-import brooklyn.basic.relations.Relationship;
+import brooklyn.basic.relations.RelationshipType;
 
 @Test
 public class RelationshipTest {
 
-    static Relationship<Entity, TestEntity> AUNTIE_OF = Relationships.newRelationshipPair(
+    static RelationshipType<Entity, TestEntity> AUNTIE_OF = RelationshipTypes.newRelationshipPair(
         "auntie", "aunties", Entity.class, "auntie_of_nephew",
         "nephew", "nephews", TestEntity.class, "nephew_of_auntie");
     
-    static Relationship<TestEntity, Entity> NEPHEW_OF = AUNTIE_OF.getInverseRelationship();
+    static RelationshipType<TestEntity, Entity> NEPHEW_OF = AUNTIE_OF.getInverseRelationshipType();
     
     public void testFields() {
         Assert.assertEquals(AUNTIE_OF.getRelationshipTypeName(), "auntie_of_nephew");
@@ -51,8 +51,8 @@ public class RelationshipTest {
         Assert.assertEquals(NEPHEW_OF.getSourceNamePlural(), "nephews");
         Assert.assertEquals(NEPHEW_OF.getTargetNamePlural(), "aunties");
         
-        Assert.assertEquals(NEPHEW_OF.getInverseRelationship(), AUNTIE_OF);
-        Assert.assertEquals(AUNTIE_OF.getInverseRelationship(), NEPHEW_OF);
+        Assert.assertEquals(NEPHEW_OF.getInverseRelationshipType(), AUNTIE_OF);
+        Assert.assertEquals(AUNTIE_OF.getInverseRelationshipType(), NEPHEW_OF);
     }
     
 }