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

[01/14] incubator-brooklyn git commit: Start to flesh out how types get created.

Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master 7c649d73d -> 3e40b2bfd


Start to flesh out how types get created.

also move inner classes to top level


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

Branch: refs/heads/master
Commit: 817e9bd278a2bf9e13341c67e9bc130dc897f889
Parents: 2aa01c0
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Nov 2 16:06:44 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Nov 10 17:13:01 2015 +0000

----------------------------------------------------------------------
 .../api/typereg/BrooklynTypeRegistry.java       |   8 +-
 .../brooklyn/api/typereg/RegisteredType.java    |  31 ++-
 .../api/typereg/RegisteredTypeConstraint.java   |   2 +-
 .../core/plan/PlanNotRecognizedException.java   |   6 +
 .../brooklyn/core/plan/PlanToSpecFactory.java   |   4 +
 .../core/plan/PlanToSpecTransformer.java        |   3 +-
 .../AbstractCustomImplementationPlan.java       |  52 +++++
 .../typereg/AbstractTypePlanTransformer.java    | 130 +++++++++++++
 .../core/typereg/BasicBrooklynTypeRegistry.java |  31 ++-
 .../core/typereg/BasicRegisteredType.java       | 122 ++++++++++++
 .../typereg/BasicTypeImplementationPlan.java    |  41 ++++
 .../typereg/BrooklynTypePlanTransformer.java    |  68 +++++++
 .../core/typereg/JavaTypePlanTransformer.java   | 112 +++++++++++
 .../core/typereg/RegisteredTypeConstraints.java |   9 +-
 .../core/typereg/RegisteredTypeKindVisitor.java |  42 ++++
 .../brooklyn/core/typereg/RegisteredTypes.java  | 192 ++-----------------
 .../core/typereg/TypePlanTransformers.java      | 160 ++++++++++++++++
 .../typereg/UnsupportedTypePlanException.java   |  37 ++++
 .../core/test/BrooklynAppLiveTestSupport.java   |  26 +--
 .../core/test/BrooklynAppUnitTestSupport.java   |  38 +---
 .../core/test/BrooklynMgmtUnitTestSupport.java  |  58 ++++++
 .../typereg/JavaTypePlanTransformerTest.java    |  90 +++++++++
 .../apache/brooklyn/util/text/Identifiers.java  |   3 +
 .../brooklyn/util/text/IdentifiersTest.java     |   6 +
 24 files changed, 1024 insertions(+), 247 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java b/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
index 3ade1db..f98f12f 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
@@ -33,10 +33,10 @@ public interface BrooklynTypeRegistry {
         /** a registered type which will create an {@link AbstractBrooklynObjectSpec} (e.g. {@link EntitySpec}) 
          * for the type registered (e.g. the {@link Entity} instance) */
         SPEC,
-        // TODO
-//        BEAN 
-        
-        // NB: additional kinds should have the Visitor in RegisteredTypes updated
+        /** a registered type which will create the java type described */
+        BEAN 
+        // note: additional kinds should have the visitor in core/RegisteredTypeKindVisitor updated
+        // to flush out all places which want to implement support for all kinds 
     }
     
     Iterable<RegisteredType> getAll();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
index 6ffa09c..a1fc5cf 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
@@ -20,14 +20,20 @@ package org.apache.brooklyn.api.typereg;
 
 import java.util.Collection;
 
+import javax.annotation.Nullable;
+
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.objs.Identifiable;
+import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
+
+import com.google.common.annotations.Beta;
 
 public interface RegisteredType extends Identifiable {
     
-    @Override
-    String getId();
+    @Override String getId();
+    
+    RegisteredTypeKind getKind();
     
     String getSymbolicName();
     String getVersion();
@@ -48,9 +54,12 @@ public interface RegisteredType extends Identifiable {
      * such as if the concrete type is private and callers should know only about a particular public interface,
      * or if precise type details are unavailable and all that is known at creation is some higher level interface/supertype
      * (e.g. this may return {@link Entity} even though the spec points at a specific subclass,
-     * for instance because the YAML has not yet been parsed or OSGi bundles downloaded). 
+     * for instance because the YAML has not yet been parsed or OSGi bundles downloaded).
+     * <p>
+     * If nothing is known, this will return null, and the item will not participate in type filtering.
      */
-    Class<?> getJavaType();
+    @Beta
+    @Nullable Class<?> getJavaType();
 
     /**
      * @return True if the item has been deprecated (i.e. its use is discouraged)
@@ -61,5 +70,19 @@ public interface RegisteredType extends Identifiable {
      * @return True if the item has been disabled (i.e. its use is forbidden, except for pre-existing apps)
      */
     boolean isDisabled();
+
+    /** @return implementation details, so that the framework can find a suitable {@link BrooklynTypePlanTransformer} 
+     * which can then use this object to instantiate this type */
+    TypeImplementationPlan getPlan();
+    
+    public interface TypeImplementationPlan {
+        /** hint which {@link BrooklynTypePlanTransformer} instance(s) can be used, if known;
+         * this may be null if the relevant transformer was not declared when created,
+         * but in general we should look to determine the kind as early as possible 
+         * and use that to retrieve the appropriate such transformer */
+        String getPlanFormat();
+        /** data for the implementation; may be more specific */
+        Object getPlanData();
+    }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java
index b55d546..851d88a 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java
@@ -41,5 +41,5 @@ public interface RegisteredTypeConstraint {
     /** encountered types, so that during resolution, 
      * if we have already attempted to resolve a given type,
      * the instantiator can avoid recursive cycles */
-    public Set<String> getEncounteredTypes();
+    @Nonnull public Set<String> getEncounteredTypes();
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/main/java/org/apache/brooklyn/core/plan/PlanNotRecognizedException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/plan/PlanNotRecognizedException.java b/core/src/main/java/org/apache/brooklyn/core/plan/PlanNotRecognizedException.java
index 4d62d4a..dd5c93d 100644
--- a/core/src/main/java/org/apache/brooklyn/core/plan/PlanNotRecognizedException.java
+++ b/core/src/main/java/org/apache/brooklyn/core/plan/PlanNotRecognizedException.java
@@ -18,8 +18,14 @@
  */
 package org.apache.brooklyn.core.plan;
 
+import org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer;
+import org.apache.brooklyn.core.typereg.UnsupportedTypePlanException;
+
+/** @deprecated since 0.9.0 use {@link UnsupportedTypePlanException} as part of switch to {@link BrooklynTypePlanTransformer} */
+@Deprecated 
 public class PlanNotRecognizedException extends RuntimeException {
 
+    /** {@link UnsupportedTypePlanException} */
     private static final long serialVersionUID = -5590108442839125317L;
 
     public PlanNotRecognizedException(String message, Throwable cause) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java b/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
index 1b49170..5614b97 100644
--- a/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
+++ b/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
@@ -24,6 +24,8 @@ import java.util.Collection;
 import java.util.ServiceLoader;
 
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer;
+import org.apache.brooklyn.core.typereg.TypePlanTransformers;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.exceptions.PropagatedRuntimeException;
 import org.apache.brooklyn.util.guava.Maybe;
@@ -36,6 +38,8 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.collect.ImmutableList;
 
+/** @deprecated since 0.9.0 use {@link TypePlanTransformers} as part of switch to {@link BrooklynTypePlanTransformer} */
+@Deprecated 
 public class PlanToSpecFactory {
     
     private static final Logger log = LoggerFactory.getLogger(PlanToSpecFactory.class);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecTransformer.java b/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecTransformer.java
index 24753aa..e88406c 100644
--- a/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecTransformer.java
+++ b/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecTransformer.java
@@ -26,13 +26,14 @@ import org.apache.brooklyn.api.entity.Application;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.core.mgmt.ManagementContextInjectable;
+import org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer;
 
 import com.google.common.annotations.Beta;
 
 /** Pluggable {@link ServiceLoader} interface for different plan-interpreters,
  * that is, different ways of taking an application plan and returning an {@link EntitySpec},
  * and a {@link CatalogItem} and returning an {@link AbstractBrooklynObjectSpec}.
- */
+ * @deprecated since 0.9.0 use {@link BrooklynTypePlanTransformer} */
 @Beta
 public interface PlanToSpecTransformer extends ManagementContextInjectable {
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractCustomImplementationPlan.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractCustomImplementationPlan.java b/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractCustomImplementationPlan.java
new file mode 100644
index 0000000..d9dde39
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractCustomImplementationPlan.java
@@ -0,0 +1,52 @@
+/*
+ * 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.typereg;
+
+import org.apache.brooklyn.api.typereg.RegisteredType.TypeImplementationPlan;
+
+/** Abstract superclass for plans to create {@link TypeImplementationPlan} with strong types on 
+ * {@link #getPlanData()} and ensuring the correct format (or null for no format) */
+public abstract class AbstractCustomImplementationPlan<T> extends BasicTypeImplementationPlan {
+    
+    public AbstractCustomImplementationPlan(String format, T data) {
+        super(format, data);
+    }
+    public AbstractCustomImplementationPlan(String expectedFormat, Class<T> expectedDataType, TypeImplementationPlan otherPlan) {
+        super(expectedFormat!=null ? expectedFormat : otherPlan.getPlanFormat(), otherPlan.getPlanData());
+        if (!expectedDataType.isInstance(otherPlan.getPlanData())) {
+            throw new IllegalArgumentException("Plan "+otherPlan+" does not have "+expectedDataType+" data so cannot cast to "+this);
+        }
+        if (expectedFormat!=null && otherPlan.getPlanFormat()!=null) {
+            if (!otherPlan.getPlanFormat().equals(expectedFormat)) {
+                throw new IllegalArgumentException("Plan "+otherPlan+" in wrong format "+otherPlan.getPlanFormat()+", when expecting "+expectedFormat);
+            }
+        }
+    }
+    
+    @Override
+    public String getPlanFormat() {
+        return format;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public T getPlanData() {
+        return (T)super.getPlanData();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java b/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java
new file mode 100644
index 0000000..ae2c610
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java
@@ -0,0 +1,130 @@
+/*
+ * 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.typereg;
+
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.javalang.JavaClassNames;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Convenience supertype for {@link BrooklynTypePlanTransformer} instances.
+ */
+public abstract class AbstractTypePlanTransformer implements BrooklynTypePlanTransformer {
+
+    private static final Logger log = LoggerFactory.getLogger(AbstractTypePlanTransformer.class);
+    
+    protected ManagementContext mgmt;
+
+    @Override
+    public void injectManagementContext(ManagementContext mgmt) {
+        this.mgmt = mgmt;
+    }
+
+    private final String format;
+    private final String formatName;
+    private final String formatDescription;
+    
+    protected AbstractTypePlanTransformer(String format, String formatName, String formatDescription) {
+        this.format = format;
+        this.formatName = formatName;
+        this.formatDescription = formatDescription;
+    }
+    
+    @Override
+    public String getFormatCode() {
+        return format;
+    }
+
+    @Override
+    public String getFormatName() {
+        return formatName;
+    }
+
+    @Override
+    public String getFormatDescription() {
+        return formatDescription;
+    }
+
+    @Override
+    public String toString() {
+        return getFormatCode()+":"+JavaClassNames.simpleClassName(this);
+    }
+    
+    @Override
+    public double scoreForType(RegisteredType type, RegisteredTypeConstraint context) {
+        if (getFormatCode().equals(type.getPlan().getPlanFormat())) return 1;
+        if (type.getPlan().getPlanFormat()==null)
+            return scoreForNullFormat(type.getPlan().getPlanData(), type, context);
+        else
+            return scoreForNonmatchingNonnullFormat(type.getPlan().getPlanFormat(), type.getPlan().getPlanData(), type, context);
+    }
+
+    protected abstract double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeConstraint context);
+    protected abstract double scoreForNonmatchingNonnullFormat(String planFormat, Object planData, RegisteredType type, RegisteredTypeConstraint context);
+
+    /** delegates to more specific abstract create methods,
+     * and performs common validation and customisation of the items created.
+     * <p>
+     * this includes:
+     * <li> setting the {@link AbstractBrooklynObjectSpec#catalogItemId(String)}
+     */
+    @Override
+    public Object create(final RegisteredType type, final RegisteredTypeConstraint context) {
+        try {
+            return validate(new RegisteredTypeKindVisitor<Object>() {
+                @Override protected Object visitSpec(RegisteredType type) {
+                    try { 
+                        AbstractBrooklynObjectSpec<?, ?> result = createSpec(type, context);
+                        result.catalogItemId(type.getId());
+                        return result;
+                    } catch (Exception e) { throw Exceptions.propagate(e); }
+                }
+                @Override protected Object visitBean(RegisteredType type) {
+                    try { 
+                        return createBean(type, context);
+                    } catch (Exception e) { throw Exceptions.propagate(e); }
+                }
+                
+            }.visit(type), type, context);
+        } catch (UnsupportedTypePlanException e) {
+            // no logging
+            throw Exceptions.propagate(e);
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            log.debug("Could not instantiate "+type+" (rethrowing): "+Exceptions.collapseText(e));
+            throw Exceptions.propagate(e);
+        }
+    }
+    
+    protected <T> T validate(T createdObject, RegisteredType type, RegisteredTypeConstraint context) {
+        if (createdObject==null) return null;
+        // TODO validation based on the constraint, throw UnsupportedTypePlanException with details if not matched
+        return createdObject;
+    }
+
+    protected abstract AbstractBrooklynObjectSpec<?,?> createSpec(RegisteredType type, RegisteredTypeConstraint context) throws Exception;
+
+    protected abstract Object createBean(RegisteredType type, RegisteredTypeConstraint context) throws Exception;
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
index 0a9a229..08b6103 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
@@ -29,10 +29,13 @@ import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
 import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
-import org.apache.brooklyn.core.typereg.RegisteredTypes.RegisteredSpecType;
+import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.api.client.util.Preconditions;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.Iterables;
@@ -96,8 +99,9 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
     @SuppressWarnings({ "deprecation", "unchecked", "rawtypes" })
     @Override
     public <SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpec(RegisteredType type, @Nullable RegisteredTypeConstraint constraint, Class<SpecT> specSuperType) {
-        if (!(type instanceof RegisteredSpecType)) { 
-            throw new IllegalStateException("Cannot create spec from type "+type);
+        Preconditions.checkNotNull(type, "type");
+        if (type.getKind()!=RegisteredTypeKind.SPEC) { 
+            throw new IllegalStateException("Cannot create spec from type "+type+" (kind "+type.getKind()+")");
         }
         if (constraint!=null) {
             if (constraint.getKind()!=null && constraint.getKind()!=RegisteredTypeKind.SPEC) {
@@ -110,11 +114,28 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
         }
         constraint = RegisteredTypeConstraints.extendedWithSpecSuperType(constraint, specSuperType);
 
-        // TODO look up in the actual registry
+        Maybe<Object> result = TypePlanTransformers.transform(mgmt, type, constraint);
+        if (result.isPresent()) return (SpecT) result.get();
         
         // fallback: look up in (legacy) catalog
+        // TODO remove once all transformers are available in the new style
         CatalogItem item = (CatalogItem) mgmt.getCatalog().getCatalogItem(type.getSymbolicName(), type.getVersion());
-        return (SpecT) BasicBrooklynCatalog.internalCreateSpecWithTransformers(mgmt, item, constraint.getEncounteredTypes());
+        try {
+            return (SpecT) BasicBrooklynCatalog.internalCreateSpecWithTransformers(mgmt, item, constraint.getEncounteredTypes());
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            // for now, combine this failure with the original
+            try {
+                result.get();
+                // won't come here
+                throw new IllegalStateException("should have failed getting type resolution for "+type);
+            } catch (Exception e0) {
+                // prefer older exception, until the new transformer is the primary pathway
+                throw Exceptions.create("Unable to instantiate "+type, MutableList.of(e, e0));
+            }
+            // ultimately swallow the legacy failure, return the original failure (the call below will throw because result is absent)
+//            return (SpecT) result.get();
+        }
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
new file mode 100644
index 0000000..ac0b266
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
@@ -0,0 +1,122 @@
+/*
+ * 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.typereg;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
+import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl;
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.util.javalang.JavaClassNames;
+
+public class BasicRegisteredType implements RegisteredType {
+
+    final String symbolicName;
+    final String version;
+    final RegisteredTypeKind kind;
+    
+    List<OsgiBundleWithUrl> bundles;
+    String displayName;
+    String description;
+    String iconUrl;
+    boolean deprecated;
+    boolean disabled;
+    
+    TypeImplementationPlan implementationPlan;
+
+    // TODO ensure this is re-populated on rebind?  or remove?
+    transient Class<?> javaType;
+    
+    public BasicRegisteredType(RegisteredTypeKind kind, String symbolicName, String version, Class<?> javaType, TypeImplementationPlan implementationPlan) {
+        this.kind = kind;
+        this.symbolicName = symbolicName;
+        this.version = version;
+        this.javaType = javaType;
+        this.implementationPlan = implementationPlan;
+    }
+
+    @Override
+    public String getId() {
+        return symbolicName + (version!=null ? ":"+version : "");
+    }
+
+    @Override
+    public String getSymbolicName() {
+        return symbolicName;
+    }
+
+    @Override
+    public String getVersion() {
+        return version;
+    }
+
+    @Override
+    public RegisteredTypeKind getKind() {
+        return kind;
+    }
+    
+    @Override
+    public Collection<OsgiBundleWithUrl> getLibraries() {
+        return bundles;
+    }
+
+    @Override
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public String getIconUrl() {
+        return iconUrl;
+    }
+    
+    @Override
+    public boolean isDisabled() {
+        return disabled;
+    }
+    
+    @Override
+    public boolean isDeprecated() {
+        return deprecated;
+    }
+    
+    @Override
+    public Class<?> getJavaType() {
+        return javaType;
+    }
+    
+    @Override
+    public TypeImplementationPlan getPlan() {
+        return implementationPlan;
+    }
+    
+    @Override
+    public String toString() {
+        return JavaClassNames.simpleClassName(this)+"["+getId()+
+            (isDisabled() ? ";DISABLED" : "")+
+            (isDeprecated() ? ";deprecated" : "")+
+            "]";
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/main/java/org/apache/brooklyn/core/typereg/BasicTypeImplementationPlan.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicTypeImplementationPlan.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicTypeImplementationPlan.java
new file mode 100644
index 0000000..7647323
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicTypeImplementationPlan.java
@@ -0,0 +1,41 @@
+/*
+ * 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.typereg;
+
+import org.apache.brooklyn.api.typereg.RegisteredType.TypeImplementationPlan;
+
+public class BasicTypeImplementationPlan implements TypeImplementationPlan {
+    final String format;
+    final Object data;
+    
+    public BasicTypeImplementationPlan(String format, Object data) {
+        this.format = format;
+        this.data = data;
+    }
+    
+    @Override
+    public String getPlanFormat() {
+        return format;
+    }
+
+    @Override
+    public Object getPlanData() {
+        return data;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
new file mode 100644
index 0000000..96c9cb7
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
@@ -0,0 +1,68 @@
+/*
+ * 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.typereg;
+
+import java.util.List;
+import java.util.ServiceLoader;
+
+import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry;
+import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.core.mgmt.ManagementContextInjectable;
+
+/**
+ * Interface for use by schemes which with to be able to transform plans.
+ * <p>
+ * To add a new plan transformation scheme, simply create an implementation and declare it
+ * as a java service (cf {@link ServiceLoader}).
+ * <p>
+ * Implementations may wish to extend {@link AbstractTypePlanTransformer} which simplifies the process.
+ */
+public interface BrooklynTypePlanTransformer extends ManagementContextInjectable {
+
+    /** @return a code to identify type implementations created specifying the use of this plan transformer. */
+    String getFormatCode();
+    /** @return a display name for this transformer. */
+    String getFormatName();
+    /** @return a description for this transformer */
+    String getFormatDescription();
+
+    /** @return how appropriate is this transformer for the {@link RegisteredType#getPlan()} of the type;
+     * 0 (or less) if not, 1 for absolutely, and in some autodetect cases a value between 0 and 1 indicate a ranking.
+     * <p>
+     * The framework guarantees arguments are nonnull, and that the {@link RegisteredType#getPlan()} is also not-null.
+     * However the format in that plan may be null. */
+    double scoreForType(RegisteredType type, RegisteredTypeConstraint context);
+    /** Creates a new instance of the indicated type, or throws if not supported;
+     * this method is used by the {@link BrooklynTypeRegistry} when it creates instances,
+     * so implementations must respect the {@link RegisteredTypeKind} semantics and the {@link RegisteredTypeConstraint}
+     * if they return an instance.
+     * <p>
+     * The framework guarantees this will only be invoked when {@link #scoreForType(RegisteredType, RegisteredTypeConstraint)} 
+     * has returned a positive value.
+     * <p>
+     * Implementations should either return null or throw {@link UnsupportedTypePlanException} 
+     * if the {@link RegisteredType#getPlan()} is not supported. */
+    Object create(RegisteredType type, RegisteredTypeConstraint context);
+    
+    double scoreForTypeDefinition(String formatCode, Object catalogData);
+    List<RegisteredType> createFromTypeDefinition(String formatCode, Object catalogData);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/main/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformer.java b/core/src/main/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformer.java
new file mode 100644
index 0000000..febf52a
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformer.java
@@ -0,0 +1,112 @@
+/*
+ * 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.typereg;
+
+import java.util.List;
+
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.util.text.Identifiers;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Instantiates classes from a registered type which simply
+ * defines the java class name and OSGi bundles to use.
+ * <p>
+ * This is used where a {@link RegisteredType} is defined simply with the name of a java class
+ * e.g. with a no-arg constructor -- no YAML etc just the name of the class.
+ */
+public class JavaTypePlanTransformer extends AbstractTypePlanTransformer {
+    
+    private static final Logger log = LoggerFactory.getLogger(JavaTypePlanTransformer.class);
+    public static final String FORMAT = "java-type-name";
+
+    public static class JavaTypeNameImplementation extends AbstractCustomImplementationPlan<String> {
+        private transient Class<?> cachedType;
+        public JavaTypeNameImplementation(String javaType) {
+            super(FORMAT, javaType);
+        }
+        public Class<?> getCachedType() {
+            return cachedType;
+        }
+    }
+
+    public JavaTypePlanTransformer() {
+        super(FORMAT, "Java type name", "Expects a java type name in a format suitable for use with ClassLoader.loadClass");
+    }
+
+    @Override
+    protected double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeConstraint context) {
+        if (type.getPlan().getPlanData() instanceof String && 
+                ((String)type.getPlan().getPlanData()).matches(Identifiers.JAVA_BINARY_REGEX)) {
+            return 0.1;
+        }
+        return 0;
+    }
+    
+    @Override
+    protected double scoreForNonmatchingNonnullFormat(String planFormat, Object planData, RegisteredType type, RegisteredTypeConstraint context) {
+        return 0;
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Override
+    protected AbstractBrooklynObjectSpec<?,?> createSpec(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
+        Class targetType = getType(type, context);
+        Class specType = RegisteredTypeConstraints.spec((Class)targetType).getJavaSuperType();
+        AbstractBrooklynObjectSpec result = (AbstractBrooklynObjectSpec) specType.getConstructor(Class.class).newInstance(targetType);
+        return result;
+    }
+
+    @Override
+    protected Object createBean(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
+        return getType(type, context).newInstance();
+    }
+
+    private Class<?> getType(RegisteredType type, RegisteredTypeConstraint context) {
+        if (type.getPlan() instanceof JavaTypeNameImplementation) {
+            Class<?> cachedType = ((JavaTypeNameImplementation)type.getPlan()).getCachedType();
+            if (cachedType==null) {
+                log.debug("Storing cached type "+cachedType+" for "+type);
+                cachedType = loadType(type, context);
+            }
+            return cachedType;
+        }
+        return loadType(type, context);
+    }
+    private Class<?> loadType(RegisteredType type, RegisteredTypeConstraint context) {
+        return CatalogUtils.newClassLoadingContext(mgmt, type).loadClass( ((String)type.getPlan().getPlanData()) );
+    }
+
+    
+    // TODO not supported as a catalog format (yet)
+    @Override
+    public double scoreForTypeDefinition(String formatCode, Object catalogData) {
+        return 0;
+    }
+
+    @Override
+    public List<RegisteredType> createFromTypeDefinition(String formatCode, Object catalogData) {
+        throw new UnsupportedTypePlanException("this transformer does not support YAML catalog additions");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java
index 9d59343..c880b7e 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java
@@ -22,6 +22,7 @@ import groovy.xml.Entity;
 
 import java.util.Set;
 
+import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import org.apache.brooklyn.api.entity.EntitySpec;
@@ -42,9 +43,9 @@ public class RegisteredTypeConstraints {
     
     /** Immutable (from caller's perspective) record of a constraint */
     public final static class BasicRegisteredTypeConstraint implements RegisteredTypeConstraint {
-        private RegisteredTypeKind kind;
-        private Class<?> javaSuperType;
-        private Set<String> encounteredTypes;
+        @Nullable private RegisteredTypeKind kind;
+        @Nullable private Class<?> javaSuperType;
+        @Nonnull private Set<String> encounteredTypes = ImmutableSet.of();
         
         private BasicRegisteredTypeConstraint() {}
         
@@ -108,7 +109,7 @@ public class RegisteredTypeConstraints {
         return of(RegisteredTypeKind.SPEC, javaSuperType);
     }
 
-    public static <T extends AbstractBrooklynObjectSpec<?,?>> RegisteredTypeConstraint extendedWithSpecSuperType(RegisteredTypeConstraint source, Class<T> specSuperType) {
+    public static <T extends AbstractBrooklynObjectSpec<?,?>> RegisteredTypeConstraint extendedWithSpecSuperType(@Nullable RegisteredTypeConstraint source, @Nullable Class<T> specSuperType) {
         Class<?> superType = lookupTargetTypeForSpec(specSuperType);
         BasicRegisteredTypeConstraint constraint = new BasicRegisteredTypeConstraint(source);
         if (source==null) source = constraint;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeKindVisitor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeKindVisitor.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeKindVisitor.java
new file mode 100644
index 0000000..530828e
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeKindVisitor.java
@@ -0,0 +1,42 @@
+/*
+ * 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.typereg;
+
+import org.apache.brooklyn.api.typereg.RegisteredType;
+
+/** Visitor adapter which can be used to ensure all kinds are supported
+ * <p>
+ * By design this class may have abstract methods added without notification,
+ * and subclasses will be responsible for providing the implementation in order to ensure compatibility. */
+public abstract class RegisteredTypeKindVisitor<T> {
+    
+    public T visit(RegisteredType type) {
+        if (type==null) throw new NullPointerException("Registered type must not be null");
+        switch (type.getKind()) {
+        case SPEC: return visitSpec(type);
+        case BEAN: return visitBean(type);
+        // others go here
+        default:
+            throw new IllegalStateException("Unexpected registered type: "+type.getClass());
+        }
+    }
+
+    protected abstract T visitSpec(RegisteredType type);
+    protected abstract T visitBean(RegisteredType type);
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
index 8cddde2..7e35084 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
@@ -18,15 +18,12 @@
  */
 package org.apache.brooklyn.core.typereg;
 
-import java.util.Collection;
-import java.util.List;
-
 import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
 import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl;
 import org.apache.brooklyn.api.typereg.RegisteredType;
-import org.apache.brooklyn.core.plan.PlanToSpecTransformer;
-import org.apache.brooklyn.util.javalang.JavaClassNames;
+import org.apache.brooklyn.api.typereg.RegisteredType.TypeImplementationPlan;
+import org.apache.brooklyn.core.typereg.JavaTypePlanTransformer.JavaTypeNameImplementation;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
@@ -47,17 +44,16 @@ public class RegisteredTypes {
     @Deprecated
     public static RegisteredType of(CatalogItem<?, ?> item) {
         if (item==null) return null;
-        TypeImplementation impl = null;
+        TypeImplementationPlan impl = null;
         if (item.getPlanYaml()!=null) {
-            impl = new TypeImplementation(null, item.getPlanYaml());
+            impl = new BasicTypeImplementationPlan(null, item.getPlanYaml());
         } else if (item.getJavaType()!=null) {
-            impl = new JavaTypeImplementation(item.getJavaType());
+            impl = new JavaTypeNameImplementation(item.getJavaType());
         } else {
             throw new IllegalStateException("Unsupported catalog item "+item+" when trying to create RegisteredType");
         }
         
-        RegisteredSpecType type = new RegisteredSpecType(item.getSymbolicName(), item.getVersion(),
-            item.getCatalogItemJavaType(), impl);
+        BasicRegisteredType type = (BasicRegisteredType) spec(item.getSymbolicName(), item.getVersion(), item.getCatalogItemJavaType(), impl);
         type.bundles = item.getLibraries()==null ? ImmutableList.<OsgiBundleWithUrl>of() : ImmutableList.<OsgiBundleWithUrl>copyOf(item.getLibraries());
         type.displayName = item.getDisplayName();
         type.description = item.getDescription();
@@ -66,180 +62,26 @@ public class RegisteredTypes {
         type.deprecated = item.isDeprecated();
 
         // TODO
-        // javaType, specType, registeredTypeName ...
-        // tags ?
+        // probably not: javaType, specType, registeredTypeName ...
+        // maybe: tags ?
         return type;
     }
-
-    /** Visitor adapter which can be used to ensure all kinds are supported */
-    public static abstract class RegisteredTypeKindVisitor<T> {
-        public T visit(RegisteredType type) {
-            if (type==null) throw new NullPointerException("Registered type must not be null");
-            if (type instanceof RegisteredSpecType) {
-                return visitSpec((RegisteredSpecType)type);
-            }
-            // others go here
-            throw new IllegalStateException("Unexpected registered type: "+type.getClass());
-        }
-
-        protected abstract T visitSpec(RegisteredSpecType type);
-        
-        // TODO beans, others
-    }
-    
-    public static RegisteredTypeKind getKindOf(RegisteredType type) {
-        return new RegisteredTypeKindVisitor<RegisteredTypeKind>() {
-            @Override protected RegisteredTypeKind visitSpec(RegisteredSpecType type) { return RegisteredTypeKind.SPEC; }
-        }.visit(type);
-    }
-    
-    public abstract static class AbstractRegisteredType implements RegisteredType {
-
-        final String symbolicName;
-        final String version;
-        
-        List<OsgiBundleWithUrl> bundles;
-        String displayName;
-        String description;
-        String iconUrl;
-        boolean deprecated;
-        boolean disabled;
-
-        // TODO ensure this is re-populated on rebind
-        transient Class<?> javaType;
-        
-        public AbstractRegisteredType(String symbolicName, String version, Class<?> javaType) {
-            this.symbolicName = symbolicName;
-            this.version = version;
-            this.javaType = javaType;
-        }
-
-        @Override
-        public String getId() {
-            return symbolicName + (version!=null ? ":"+version : "");
-        }
-
-        @Override
-        public String getSymbolicName() {
-            return symbolicName;
-        }
-
-        @Override
-        public String getVersion() {
-            return version;
-        }
-        
-        @Override
-        public Collection<OsgiBundleWithUrl> getLibraries() {
-            return bundles;
-        }
-
-        @Override
-        public String getDisplayName() {
-            return displayName;
-        }
-
-        @Override
-        public String getDescription() {
-            return description;
-        }
-
-        @Override
-        public String getIconUrl() {
-            return iconUrl;
-        }
-        
-        @Override
-        public boolean isDisabled() {
-            return disabled;
-        }
-        
-        @Override
-        public boolean isDeprecated() {
-            return deprecated;
-        }
-        
-        @Override
-        public Class<?> getJavaType() {
-            return javaType;
-        }
-        
-        @Override
-        public String toString() {
-            return JavaClassNames.simpleClassName(this)+"["+getId()+
-                (isDisabled() ? ";DISABLED" : "")+
-                (isDeprecated() ? ";deprecated" : "")+
-                "]";
-        }
-    }
-
-    // TODO
-//    public static class RegisteredBeanType extends AbstractRegisteredType {
-//        
-//    }
     
-    public static class RegisteredSpecType extends AbstractRegisteredType {
-
-        private TypeImplementation impl;
-        
-        public RegisteredSpecType(String symbolicName, String version, Class<?> javaType, TypeImplementation impl) {
-            super(symbolicName, version, javaType);
-            this.impl = impl;
-        }
-
-        public TypeImplementation getImplementation() {
-            return impl;
-        }
-    }
-
-    public static class TypeImplementation {
-        final String format;
-        final Object data;
-        
-        public TypeImplementation(String kind, Object data) {
-            super();
-            this.format = kind;
-            this.data = data;
-        }
-
-        /** details of the implementation, if known;
-         * this may be null if the relevant {@link PlanToSpecTransformer} was not declared when created,
-         * but in general we should look to determine the kind as early as possible and use that
-         * to retrieve the appropriate such transformer.
-         */
-        public String getFormat() {
-            return format;
-        }
-        
-        public Object getData() {
-            return data;
-        }
+    public static RegisteredType bean(String symbolicName, String version, Class<?> javaType, TypeImplementationPlan plan) {
+        return new BasicRegisteredType(RegisteredTypeKind.BEAN, symbolicName, version, javaType, plan);
     }
     
-    public static class JavaTypeImplementation extends TypeImplementation {
-        public static final String FORMAT = "java";
-        public JavaTypeImplementation(String javaType) {
-            super(FORMAT, javaType);
-        }
-        public String getJavaType() { return (String)getData(); }
+    public static RegisteredType spec(String symbolicName, String version, Class<?> javaType, TypeImplementationPlan plan) {
+        return new BasicRegisteredType(RegisteredTypeKind.SPEC, symbolicName, version, javaType, plan);
     }
-    
-//    // TODO remove, unless we want it
-//    public static class CampYamlTypeImplementation extends TypeImplementation {
-//        public static final String FORMAT = "camp";
-//        public CampYamlTypeImplementation(String javaType) {
-//            super(FORMAT, javaType);
-//        }
-//        public String getCampYaml() { return (String)getData(); }
-//    }
 
     /** returns the implementation data for a spec if it is a string (e.g. plan yaml or java class name); else false */
     @Beta
     public static String getImplementationDataStringForSpec(RegisteredType item) {
-        if (!(item instanceof RegisteredSpecType)) return null;
-        Object data = ((RegisteredSpecType)item).getImplementation().getData();
-        if (data instanceof String) return (String) data;
-        return null;
+        if (item==null || item.getPlan()==null) return null;
+        Object data = item.getPlan().getPlanData();
+        if (!(data instanceof String)) return null;
+        return (String)data;
     }
-    
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java b/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java
new file mode 100644
index 0000000..b2b496e
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.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.typereg;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.TreeMap;
+
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry;
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.exceptions.PropagatedRuntimeException;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.text.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+
+public class TypePlanTransformers {
+
+    private static final Logger log = LoggerFactory.getLogger(TypePlanTransformers.class);
+
+    private static Collection<BrooklynTypePlanTransformer> getAll() {
+        return ImmutableList.copyOf(ServiceLoader.load(BrooklynTypePlanTransformer.class));
+    }
+
+    private static Collection<Class<? extends BrooklynTypePlanTransformer>> OVERRIDE;
+    @SafeVarargs
+    @VisibleForTesting
+    public synchronized static void forceAvailable(Class<? extends BrooklynTypePlanTransformer> ...classes) {
+        OVERRIDE = Arrays.asList(classes);
+    }
+    public synchronized static void clearForced() {
+        OVERRIDE = null;
+    }
+
+    public static Collection<BrooklynTypePlanTransformer> all(ManagementContext mgmt) {
+        // TODO cache these in the TypeRegistry, looking for new ones periodically or supplying a way to register them
+        Collection<Class<? extends BrooklynTypePlanTransformer>> override = OVERRIDE;
+        Collection<BrooklynTypePlanTransformer> result = new ArrayList<BrooklynTypePlanTransformer>();
+        if (override!=null) {
+            for (Class<? extends BrooklynTypePlanTransformer> o1: override) {
+                try {
+                    result.add(o1.newInstance());
+                } catch (Exception e) {
+                    Exceptions.propagate(e);
+                }
+            }
+        } else {
+            result.addAll(getAll());
+        }
+        for(BrooklynTypePlanTransformer t : result) {
+            t.injectManagementContext(mgmt);
+        }
+        return result;
+    }
+
+    /** returns a list of {@link BrooklynTypePlanTransformer} instances for this {@link ManagementContext}
+     * which may be able to handle the given plan; the list is sorted with highest-score transformer first */
+    @Beta
+    public static List<BrooklynTypePlanTransformer> forType(ManagementContext mgmt, RegisteredType type, RegisteredTypeConstraint constraint) {
+        Multimap<Double,BrooklynTypePlanTransformer> byScoreMulti = ArrayListMultimap.create(); 
+        Collection<BrooklynTypePlanTransformer> transformers = all(mgmt);
+        for (BrooklynTypePlanTransformer transformer : transformers) {
+            double score = transformer.scoreForType(type, constraint);
+            if (score>0) byScoreMulti.put(score, transformer);
+        }
+        Map<Double, Collection<BrooklynTypePlanTransformer>> tree = new TreeMap<Double, Collection<BrooklynTypePlanTransformer>>(byScoreMulti.asMap());
+        List<Collection<BrooklynTypePlanTransformer>> highestFirst = new ArrayList<Collection<BrooklynTypePlanTransformer>>(tree.values());
+        Collections.reverse(highestFirst);
+        return MutableList.copyOf(Iterables.concat(highestFirst)).asUnmodifiable();
+    }
+
+    /** transforms the given type to an instance, if possible
+     * <p>
+     * callers should generally use one of the create methods on {@link BrooklynTypeRegistry} rather than using this method directly. */
+    @Beta
+    public static Maybe<Object> transform(ManagementContext mgmt, RegisteredType type, RegisteredTypeConstraint constraint) {
+        if (type==null) return Maybe.absent("type cannot be null");
+        if (type.getPlan()==null) return Maybe.absent("type plan cannot be null, when instantiating "+type);
+        
+        List<BrooklynTypePlanTransformer> transformers = forType(mgmt, type, constraint);
+        Collection<String> transformersWhoDontSupport = new ArrayList<String>();
+        Collection<Exception> failuresFromTransformers = new ArrayList<Exception>();
+        for (BrooklynTypePlanTransformer t: transformers) {
+            try {
+                Object result = t.create(type, constraint);
+                if (result==null) {
+                    transformersWhoDontSupport.add(t.getFormatCode() + " (returned null)");
+                    continue;
+                }
+                return Maybe.of(result);
+            } catch (UnsupportedTypePlanException e) {
+                transformersWhoDontSupport.add(t.getFormatCode() +
+                    (Strings.isNonBlank(e.getMessage()) ? " ("+e.getMessage()+")" : ""));
+            } catch (@SuppressWarnings("deprecation") org.apache.brooklyn.core.plan.PlanNotRecognizedException e) {
+                // just in case (shouldn't happen)
+                transformersWhoDontSupport.add(t.getFormatCode() +
+                    (Strings.isNonBlank(e.getMessage()) ? " ("+e.getMessage()+")" : ""));
+            } catch (Throwable e) {
+                Exceptions.propagateIfFatal(e);
+                failuresFromTransformers.add(new PropagatedRuntimeException("Transformer for "+t.getFormatCode()+" gave an error creating this plan: "+
+                    Exceptions.collapseText(e), e));
+            }
+        }
+        
+        // failed
+        Exception result;
+        if (!failuresFromTransformers.isEmpty()) {
+            // at least one thought he could do it
+            if (log.isDebugEnabled()) {
+                log.debug("Failure transforming plan; returning summary failure, but for reference "
+                    + "potentially application transformers were "+transformers+", "
+                    + "others available are "+MutableList.builder().addAll(all(mgmt)).removeAll(transformers).build()+"; "
+                    + "failures: "+failuresFromTransformers);
+            }
+            result = failuresFromTransformers.size()==1 ? Exceptions.create(null, failuresFromTransformers) :
+                Exceptions.create("All plan transformers failed", failuresFromTransformers);
+        } else {
+            if (transformers.isEmpty()) {
+                result = new UnsupportedTypePlanException("Invalid plan; format could not be recognized, none of the available transformers "+all(mgmt)+" support "+type);
+            } else {
+                result = new UnsupportedTypePlanException("Invalid plan; potentially applicable transformers "+transformers+" do not support it, and other available transformers "+
+                    MutableList.builder().addAll(all(mgmt)).removeAll(transformers).build()+" do not accept it");
+            }
+        }
+        return Maybe.absent(result);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/main/java/org/apache/brooklyn/core/typereg/UnsupportedTypePlanException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/UnsupportedTypePlanException.java b/core/src/main/java/org/apache/brooklyn/core/typereg/UnsupportedTypePlanException.java
new file mode 100644
index 0000000..98cbd7a
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/UnsupportedTypePlanException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.typereg;
+
+public class UnsupportedTypePlanException extends RuntimeException {
+
+    private static final long serialVersionUID = -5590108442839125317L;
+
+    public UnsupportedTypePlanException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public UnsupportedTypePlanException(String message) {
+        super(message);
+    }
+
+    public UnsupportedTypePlanException(Throwable cause) {
+        super(cause);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/test/java/org/apache/brooklyn/core/test/BrooklynAppLiveTestSupport.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/BrooklynAppLiveTestSupport.java b/core/src/test/java/org/apache/brooklyn/core/test/BrooklynAppLiveTestSupport.java
index b986fed..977b7a5 100644
--- a/core/src/test/java/org/apache/brooklyn/core/test/BrooklynAppLiveTestSupport.java
+++ b/core/src/test/java/org/apache/brooklyn/core/test/BrooklynAppLiveTestSupport.java
@@ -19,15 +19,9 @@
 package org.apache.brooklyn.core.test;
 
 import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.core.entity.Entities;
-import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
 import org.apache.brooklyn.core.internal.BrooklynProperties;
-import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
 import org.apache.brooklyn.core.test.entity.TestApplication;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 
 /**
@@ -36,31 +30,17 @@ import org.testng.annotations.BeforeMethod;
  * Uses a management context that will not load {@code ~/.brooklyn/catalog.xml} but will
  * read from the default {@code ~/.brooklyn/brooklyn.properties}.
  */
-public class BrooklynAppLiveTestSupport {
-
-    private static final Logger LOG = LoggerFactory.getLogger(BrooklynAppLiveTestSupport.class);
+public class BrooklynAppLiveTestSupport extends BrooklynMgmtUnitTestSupport {
 
     protected TestApplication app;
-    protected ManagementContextInternal mgmt;
 
     @BeforeMethod(alwaysRun=true)
     public void setUp() throws Exception {
         if (mgmt!=null) {
-            app = ApplicationBuilder.newManagedApp(newAppSpec(), mgmt);
+            app = mgmt.getEntityManager().createEntity(newAppSpec());
         } else {
             mgmt = new LocalManagementContextForTests(BrooklynProperties.Factory.newDefault());
-            app = ApplicationBuilder.newManagedApp(newAppSpec(), mgmt);
-        }
-    }
-
-    @AfterMethod(alwaysRun=true)
-    public void tearDown() throws Exception {
-        try {
-            if (mgmt != null) Entities.destroyAll(mgmt);
-        } catch (Throwable t) {
-            LOG.error("Caught exception in tearDown method", t);
-        } finally {
-            mgmt = null;
+            app = mgmt.getEntityManager().createEntity(newAppSpec());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/test/java/org/apache/brooklyn/core/test/BrooklynAppUnitTestSupport.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/BrooklynAppUnitTestSupport.java b/core/src/test/java/org/apache/brooklyn/core/test/BrooklynAppUnitTestSupport.java
index fa96e0b..cbe39d0 100644
--- a/core/src/test/java/org/apache/brooklyn/core/test/BrooklynAppUnitTestSupport.java
+++ b/core/src/test/java/org/apache/brooklyn/core/test/BrooklynAppUnitTestSupport.java
@@ -20,14 +20,7 @@ package org.apache.brooklyn.core.test;
 
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
-import org.apache.brooklyn.core.entity.Entities;
-import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
-import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
-import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
 import org.apache.brooklyn.core.test.entity.TestApplication;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 
 /**
@@ -35,40 +28,25 @@ import org.testng.annotations.BeforeMethod;
  * <p>
  * Uses a light-weight management context that will not read {@code ~/.brooklyn/brooklyn.properties}.
  */
-public class BrooklynAppUnitTestSupport {
-
-    private static final Logger LOG = LoggerFactory.getLogger(BrooklynAppUnitTestSupport.class);
+public class BrooklynAppUnitTestSupport extends BrooklynMgmtUnitTestSupport {
 
     protected TestApplication app;
-    protected ManagementContextInternal mgmt;
-
-    protected boolean shouldSkipOnBoxBaseDirResolution() {
-        return true;
-    }
 
     @BeforeMethod(alwaysRun=true)
     public void setUp() throws Exception {
-        if (mgmt == null) {
-            mgmt = LocalManagementContextForTests.newInstance();
-        }
+        super.setUp();
         setUpApp();
     }
 
+    protected boolean shouldSkipOnBoxBaseDirResolution() {
+        return true;
+    }
+
     protected void setUpApp() {
         EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class)
                 .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, shouldSkipOnBoxBaseDirResolution());
-        app = ApplicationBuilder.newManagedApp(appSpec, mgmt);
-    }
-
-    @AfterMethod(alwaysRun=true)
-    public void tearDown() throws Exception {
-        try {
-            if (mgmt != null) Entities.destroyAll(mgmt);
-        } catch (Throwable t) {
-            LOG.error("Caught exception in tearDown method", t);
-        } finally {
-            mgmt = null;
-        }
+        
+        app = mgmt.getEntityManager().createEntity(appSpec);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/test/java/org/apache/brooklyn/core/test/BrooklynMgmtUnitTestSupport.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/BrooklynMgmtUnitTestSupport.java b/core/src/test/java/org/apache/brooklyn/core/test/BrooklynMgmtUnitTestSupport.java
new file mode 100644
index 0000000..956ad63
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/test/BrooklynMgmtUnitTestSupport.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.test;
+
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+
+/**
+ * To be extended by unit/integration tests.
+ * <p>
+ * Uses a light-weight management context that will not read {@code ~/.brooklyn/brooklyn.properties}.
+ */
+public class BrooklynMgmtUnitTestSupport {
+
+    private static final Logger LOG = LoggerFactory.getLogger(BrooklynMgmtUnitTestSupport.class);
+
+    protected ManagementContextInternal mgmt;
+
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        if (mgmt == null) {
+            mgmt = LocalManagementContextForTests.newInstance();
+        }
+    }
+
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        try {
+            if (mgmt != null) Entities.destroyAll(mgmt);
+        } catch (Throwable t) {
+            LOG.error("Caught exception in tearDown method", t);
+        } finally {
+            mgmt = null;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java b/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java
new file mode 100644
index 0000000..c4d8038
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.typereg;
+
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.core.test.BrooklynMgmtUnitTestSupport;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class JavaTypePlanTransformerTest extends BrooklynMgmtUnitTestSupport {
+
+    public static class NoArg {
+        public String name() { return "no-arg"; }
+    }
+
+    protected RegisteredType type;
+    protected BrooklynTypePlanTransformer transformer;
+    
+    @BeforeMethod(alwaysRun=true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        type = newNoArgRegisteredType(JavaTypePlanTransformer.FORMAT);
+        transformer = newTransformer();
+    }
+    
+    protected RegisteredType newNoArgRegisteredType(String format) {
+        return RegisteredTypes.bean("no-arg", "1.0", null, new BasicTypeImplementationPlan(format, NoArg.class.getName()));
+    }
+    
+    protected BrooklynTypePlanTransformer newTransformer() {
+        BrooklynTypePlanTransformer xf = new JavaTypePlanTransformer();
+        xf.injectManagementContext(mgmt);
+        return xf;
+    }
+    
+    @Test
+    public void testScoreJavaType() {
+        double score = transformer.scoreForType(type, null);
+        Assert.assertEquals(score, 1, 0.00001);
+    }
+
+    @Test
+    public void testCreateJavaType() {
+        Object obj = transformer.create(type, null);
+        Assert.assertTrue(obj instanceof NoArg, "obj is "+obj);
+        Assert.assertEquals(((NoArg)obj).name(), "no-arg");
+    }
+
+    @Test
+    public void testScoreJavaTypeWithNullFormat() {
+        type = newNoArgRegisteredType(null);
+        double score = transformer.scoreForType(type, null);
+        Assert.assertEquals(score, 0.1, 0.00001);
+    }
+
+    @Test
+    public void testCreateJavaTypeWithNullFormat() {
+        type = newNoArgRegisteredType(null);
+        Object obj = transformer.create(type, null);
+        Assert.assertTrue(obj instanceof NoArg, "obj is "+obj);
+        Assert.assertEquals(((NoArg)obj).name(), "no-arg");
+    }
+
+    @Test
+    public void testScoreJavaTypeWithOtherFormat() {
+        type = newNoArgRegisteredType("crazy-format");
+        double score = transformer.scoreForType(type, null);
+        Assert.assertEquals(score, 0, 0.00001);
+        // we don't test creation; it may or may not succeed, but with score 0 it shouldn't get invoked
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/utils/common/src/main/java/org/apache/brooklyn/util/text/Identifiers.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/text/Identifiers.java b/utils/common/src/main/java/org/apache/brooklyn/util/text/Identifiers.java
index 8d3e035..b389f9c 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/text/Identifiers.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/text/Identifiers.java
@@ -26,6 +26,9 @@ public class Identifiers {
     
     public static final String JAVA_GOOD_START_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_";
     public static final String JAVA_GOOD_NONSTART_CHARS = JAVA_GOOD_START_CHARS+"1234567890";
+    public static final String JAVA_SEGMENT_REGEX = "["+JAVA_GOOD_START_CHARS+"]"+"["+JAVA_GOOD_NONSTART_CHARS+"]*";
+    public static final String JAVA_PACKAGE_OR_CLASS_REGEX = "("+JAVA_SEGMENT_REGEX+"\\."+")*"+JAVA_SEGMENT_REGEX;
+    public static final String JAVA_BINARY_REGEX = JAVA_PACKAGE_OR_CLASS_REGEX+"(\\$["+JAVA_GOOD_NONSTART_CHARS+"]+)*";
     
     public static final String JAVA_GENERATED_IDENTIFIER_START_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
     public static final String JAVA_GENERATED_IDENTIFIERNONSTART_CHARS = JAVA_GENERATED_IDENTIFIER_START_CHARS+"1234567890";

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/817e9bd2/utils/common/src/test/java/org/apache/brooklyn/util/text/IdentifiersTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/text/IdentifiersTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/text/IdentifiersTest.java
index 1b2068f..8f4463f 100644
--- a/utils/common/src/test/java/org/apache/brooklyn/util/text/IdentifiersTest.java
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/text/IdentifiersTest.java
@@ -86,4 +86,10 @@ public class IdentifiersTest {
         log.info("ID's made from hash, of -1 is "+id1+" and of Long.MIN_VALUE is "+Identifiers.makeIdFromHash(Long.MIN_VALUE));
     }
 
+    @Test
+    public void testJavaClassRegex() {
+        Assert.assertTrue("foo".matches(Identifiers.JAVA_BINARY_REGEX));
+        Assert.assertTrue("foo.bar.Baz$1".matches(Identifiers.JAVA_BINARY_REGEX));
+    }
+    
 }


[09/14] incubator-brooklyn git commit: code review part one, simplify AbstractBOSpec, and more

Posted by he...@apache.org.
code review part one, simplify AbstractBOSpec, and more

minor tweaks based on @neykov's comments


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

Branch: refs/heads/master
Commit: 90e8911f64515d94ec52f21d9ebd06df4b404847
Parents: 42bf7c4
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Nov 17 10:24:34 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Nov 17 10:24:34 2015 +0000

----------------------------------------------------------------------
 .../apache/brooklyn/api/entity/EntitySpec.java  | 91 --------------------
 .../internal/AbstractBrooklynObjectSpec.java    | 84 +++++++++++++++++-
 .../brooklyn/api/location/LocationSpec.java     | 78 ++---------------
 .../apache/brooklyn/api/policy/PolicySpec.java  | 75 ----------------
 .../brooklyn/api/sensor/EnricherSpec.java       | 75 +---------------
 .../api/typereg/BrooklynTypeRegistry.java       | 15 ++--
 .../core/location/CatalogLocationResolver.java  |  3 +-
 .../core/plan/PlanNotRecognizedException.java   |  1 -
 .../typereg/AbstractTypePlanTransformer.java    | 13 ++-
 .../typereg/BrooklynTypePlanTransformer.java    | 34 +++++---
 .../spi/creation/CampTypePlanTransformer.java   |  4 +-
 11 files changed, 138 insertions(+), 335 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/90e8911f/api/src/main/java/org/apache/brooklyn/api/entity/EntitySpec.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/EntitySpec.java b/api/src/main/java/org/apache/brooklyn/api/entity/EntitySpec.java
index 500952d..a73298a 100644
--- a/api/src/main/java/org/apache/brooklyn/api/entity/EntitySpec.java
+++ b/api/src/main/java/org/apache/brooklyn/api/entity/EntitySpec.java
@@ -20,7 +20,6 @@ package org.apache.brooklyn.api.entity;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -29,22 +28,15 @@ import javax.annotation.Nullable;
 
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.api.policy.PolicySpec;
 import org.apache.brooklyn.api.sensor.Enricher;
 import org.apache.brooklyn.api.sensor.EnricherSpec;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
 import org.apache.brooklyn.util.collections.MutableList;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Supplier;
 import com.google.common.base.Throwables;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 
 /**
@@ -63,8 +55,6 @@ public class EntitySpec<T extends Entity> extends AbstractBrooklynObjectSpec<T,E
 
     private static final long serialVersionUID = -2247153452919128990L;
     
-    private static final Logger log = LoggerFactory.getLogger(EntitySpec.class);
-
     /**
      * Creates a new {@link EntitySpec} instance for an entity of the given type. The returned 
      * {@link EntitySpec} can then be customized.
@@ -112,8 +102,6 @@ public class EntitySpec<T extends Entity> extends AbstractBrooklynObjectSpec<T,E
 
     private Class<? extends T> impl;
     private Entity parent;
-    private final Map<String, Object> flags = Maps.newLinkedHashMap();
-    private final Map<ConfigKey<?>, Object> config = Maps.newLinkedHashMap();
     private final List<Policy> policies = Lists.newArrayList();
     private final List<PolicySpec<?>> policySpecs = Lists.newArrayList();
     private final List<Enricher> enrichers = Lists.newArrayList();
@@ -133,11 +121,7 @@ public class EntitySpec<T extends Entity> extends AbstractBrooklynObjectSpec<T,E
     @Override
     protected EntitySpec<T> copyFrom(EntitySpec<T> otherSpec) {
         super.copyFrom(otherSpec)
-                .displayName(otherSpec.getDisplayName())
-                .tags(otherSpec.getTags())
                 .additionalInterfaces(otherSpec.getAdditionalInterfaces())
-                .configure(otherSpec.getConfig())
-                .configure(otherSpec.getFlags())
                 .policySpecs(otherSpec.getPolicySpecs())
                 .policies(otherSpec.getPolicies())
                 .enricherSpecs(otherSpec.getEnricherSpecs())
@@ -146,7 +130,6 @@ public class EntitySpec<T extends Entity> extends AbstractBrooklynObjectSpec<T,E
                 .children(otherSpec.getChildren())
                 .members(otherSpec.getMembers())
                 .groups(otherSpec.getGroups())
-                .catalogItemId(otherSpec.getCatalogItemId())
                 .locations(otherSpec.getLocations());
         
         if (otherSpec.getParent() != null) parent(otherSpec.getParent());
@@ -208,27 +191,7 @@ public class EntitySpec<T extends Entity> extends AbstractBrooklynObjectSpec<T,E
     public Entity getParent() {
         return parent;
     }
-    
-    /**
-     * @return Read-only construction flags
-     * @see SetFromFlag declarations on the entity type
-     */
-    public Map<String, ?> getFlags() {
-        return Collections.unmodifiableMap(flags);
-    }
-    
-    /**
-     * @return Read-only configuration values
-     */
-    public Map<ConfigKey<?>, Object> getConfig() {
-        return Collections.unmodifiableMap(config);
-    }
 
-    /** Clears the config map, removing any config previously set. */
-    public void clearConfig() {
-        config.clear();
-    }
-        
     public List<PolicySpec<?>> getPolicySpecs() {
         return policySpecs;
     }
@@ -336,60 +299,6 @@ public class EntitySpec<T extends Entity> extends AbstractBrooklynObjectSpec<T,E
         parent = checkNotNull(val, "parent");
         return this;
     }
-    
-    public EntitySpec<T> configure(Map<?,?> val) {
-        checkMutable();
-        for (Map.Entry<?, ?> entry: val.entrySet()) {
-            if (entry.getKey()==null) throw new NullPointerException("Null key not permitted");
-            if (entry.getKey() instanceof CharSequence)
-                flags.put(entry.getKey().toString(), entry.getValue());
-            else if (entry.getKey() instanceof ConfigKey<?>)
-                config.put((ConfigKey<?>)entry.getKey(), entry.getValue());
-            else if (entry.getKey() instanceof HasConfigKey<?>)
-                config.put(((HasConfigKey<?>)entry.getKey()).getConfigKey(), entry.getValue());
-            else {
-                log.warn("Spec "+this+" ignoring unknown config key "+entry.getKey());
-            }
-        }
-        return this;
-    }
-    
-    public EntitySpec<T> configure(CharSequence key, Object val) {
-        checkMutable();
-        flags.put(checkNotNull(key, "key").toString(), val);
-        return this;
-    }
-    
-    public <V> EntitySpec<T> configure(ConfigKey<V> key, V val) {
-        checkMutable();
-        config.put(checkNotNull(key, "key"), val);
-        return this;
-    }
-
-    public <V> EntitySpec<T> configure(ConfigKey<V> key, Task<? extends V> val) {
-        checkMutable();
-        config.put(checkNotNull(key, "key"), val);
-        return this;
-    }
-
-    public <V> EntitySpec<T> configure(ConfigKey<V> key, Supplier<? extends V> val) {
-        checkMutable();
-        config.put(checkNotNull(key, "key"), val);
-        return this;
-    }
-
-    public <V> EntitySpec<T> configure(HasConfigKey<V> key, V val) {
-        checkMutable();
-        config.put(checkNotNull(key, "key").getConfigKey(), val);
-        return this;
-    }
-
-    public <V> EntitySpec<T> configure(HasConfigKey<V> key, Task<? extends V> val) {
-        checkMutable();
-        config.put(checkNotNull(key, "key").getConfigKey(), val);
-        return this;
-    }
-
 
     /** adds a policy to the spec */
     public <V> EntitySpec<T> policy(Policy val) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/90e8911f/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java b/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java
index de2954d..72fa96f 100644
--- a/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java
+++ b/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java
@@ -22,20 +22,27 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.io.Serializable;
 import java.lang.reflect.Modifier;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import org.apache.brooklyn.api.mgmt.EntityManager;
+import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.objs.SpecParameter;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
 import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Objects;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
 
 /** Defines a spec for creating a {@link BrooklynObject}.
  * <p>
@@ -49,6 +56,8 @@ import com.google.common.collect.Iterables;
 public abstract class AbstractBrooklynObjectSpec<T,SpecT extends AbstractBrooklynObjectSpec<T,SpecT>> implements Serializable {
 
     private static final long serialVersionUID = 3010955277740333030L;
+
+    private static final Logger log = LoggerFactory.getLogger(AbstractBrooklynObjectSpec.class);
     
     private final Class<? extends T> type;
     private String displayName;
@@ -56,6 +65,9 @@ public abstract class AbstractBrooklynObjectSpec<T,SpecT extends AbstractBrookly
     private Set<Object> tags = MutableSet.of();
     private List<SpecParameter<?>> parameters = ImmutableList.of();
 
+    protected final Map<String, Object> flags = Maps.newLinkedHashMap();
+    protected final Map<ConfigKey<?>, Object> config = Maps.newLinkedHashMap();
+
     protected AbstractBrooklynObjectSpec(Class<? extends T> type) {
         checkValidType(type);
         this.type = type;
@@ -150,6 +162,8 @@ public abstract class AbstractBrooklynObjectSpec<T,SpecT extends AbstractBrookly
     
     protected SpecT copyFrom(SpecT otherSpec) {
         return displayName(otherSpec.getDisplayName())
+            .configure(otherSpec.getConfig())
+            .configure(otherSpec.getFlags())
             .tags(otherSpec.getTags())
             .catalogItemId(otherSpec.getCatalogItemId())
             .parameters(otherSpec.getParameters());
@@ -175,6 +189,74 @@ public abstract class AbstractBrooklynObjectSpec<T,SpecT extends AbstractBrookly
 
     /** strings inserted as flags, config keys inserted as config keys; 
      * if you want to force one or the other, create a ConfigBag and convert to the appropriate map type */
-    public abstract SpecT configure(Map<?,?> val);
+    public SpecT configure(Map<?,?> val) {
+        for (Map.Entry<?, ?> entry: val.entrySet()) {
+            if (entry.getKey()==null) throw new NullPointerException("Null key not permitted");
+            if (entry.getKey() instanceof CharSequence)
+                flags.put(entry.getKey().toString(), entry.getValue());
+            else if (entry.getKey() instanceof ConfigKey<?>)
+                config.put((ConfigKey<?>)entry.getKey(), entry.getValue());
+            else if (entry.getKey() instanceof HasConfigKey<?>)
+                config.put(((HasConfigKey<?>)entry.getKey()).getConfigKey(), entry.getValue());
+            else {
+                log.warn("Spec "+this+" ignoring unknown config key "+entry.getKey());
+            }
+        }
+        return self();
+    }
+
+    public SpecT configure(CharSequence key, Object val) {
+        flags.put(checkNotNull(key, "key").toString(), val);
+        return self();
+    }
     
+    public <V> SpecT configure(ConfigKey<V> key, V val) {
+        config.put(checkNotNull(key, "key"), val);
+        return self();
+    }
+
+    public <V> SpecT configureIfNotNull(ConfigKey<V> key, V val) {
+        return (val != null) ? configure(key, val) : self();
+    }
+
+    public <V> SpecT configure(ConfigKey<V> key, Task<? extends V> val) {
+        config.put(checkNotNull(key, "key"), val);
+        return self();
+    }
+
+    public <V> SpecT configure(HasConfigKey<V> key, V val) {
+        config.put(checkNotNull(key, "key").getConfigKey(), val);
+        return self();
+    }
+
+    public <V> SpecT configure(HasConfigKey<V> key, Task<? extends V> val) {
+        config.put(checkNotNull(key, "key").getConfigKey(), val);
+        return self();
+    }
+
+    public <V> SpecT removeConfig(ConfigKey<V> key) {
+        config.remove( checkNotNull(key, "key") );
+        return self();
+    }
+
+    /** Clears the config map, removing any config previously set. */
+    public void clearConfig() {
+        config.clear();
+    }
+        
+    /**
+     * @return Read-only construction flags
+     * @see SetFromFlag declarations on the policy type
+     */
+    public Map<String, ?> getFlags() {
+        return Collections.unmodifiableMap(flags);
+    }
+    
+    /**
+     * @return Read-only configuration values
+     */
+    public Map<ConfigKey<?>, Object> getConfig() {
+        return Collections.unmodifiableMap(config);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/90e8911f/api/src/main/java/org/apache/brooklyn/api/location/LocationSpec.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/location/LocationSpec.java b/api/src/main/java/org/apache/brooklyn/api/location/LocationSpec.java
index eca8964..b66ebea 100644
--- a/api/src/main/java/org/apache/brooklyn/api/location/LocationSpec.java
+++ b/api/src/main/java/org/apache/brooklyn/api/location/LocationSpec.java
@@ -24,11 +24,7 @@ import java.util.Collections;
 import java.util.Map;
 
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
-import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.Maps;
 
@@ -46,8 +42,6 @@ public class LocationSpec<T extends Location> extends AbstractBrooklynObjectSpec
 
     // TODO Would like to add `configure(ConfigBag)`, but `ConfigBag` is in core rather than api
     
-    private static final Logger log = LoggerFactory.getLogger(LocationSpec.class);
-
     private final static long serialVersionUID = 1L;
 
     /**
@@ -81,29 +75,25 @@ public class LocationSpec<T extends Location> extends AbstractBrooklynObjectSpec
         @SuppressWarnings("unchecked")
         Class<T> exactType = (Class<T>)spec.getType();
         
-        LocationSpec<T> result = create(exactType)
-                .displayName(spec.getDisplayName())
-                .tags(spec.getTags())
-                .configure(spec.getConfig())
-                .configure(spec.getFlags())
-                .catalogItemId(spec.getCatalogItemId())
-                .extensions(spec.getExtensions());
-        
-        if (spec.getParent() != null) result.parent(spec.getParent());
-        
-        return (LocationSpec<T>) result;
+        return create(exactType).copyFrom(spec);
     }
 
     private String id;
     private Location parent;
-    private final Map<String, Object> flags = Maps.newLinkedHashMap();
-    private final Map<ConfigKey<?>, Object> config = Maps.newLinkedHashMap();
     private final Map<Class<?>, Object> extensions = Maps.newLinkedHashMap();
 
     protected LocationSpec(Class<T> type) {
         super(type);
     }
      
+    @Override
+    protected LocationSpec<T> copyFrom(LocationSpec<T> otherSpec) {
+        LocationSpec<T> result = super.copyFrom(otherSpec).extensions(otherSpec.getExtensions());
+        if (otherSpec.getParent() != null) result.parent(otherSpec.getParent());
+        if (otherSpec.getId() != null) result.id(otherSpec.getId());
+        return result;
+    }
+    
     protected void checkValidType(Class<? extends T> type) {
         checkIsImplementation(type, Location.class);
         checkIsNewStyleImplementation(type);
@@ -123,56 +113,6 @@ public class LocationSpec<T extends Location> extends AbstractBrooklynObjectSpec
         return this;
     }
 
-    public LocationSpec<T> configure(Map<?,?> val) {
-        for (Map.Entry<?, ?> entry: val.entrySet()) {
-            if (entry.getKey()==null) throw new NullPointerException("Null key not permitted");
-            if (entry.getKey() instanceof CharSequence)
-                flags.put(entry.getKey().toString(), entry.getValue());
-            else if (entry.getKey() instanceof ConfigKey<?>)
-                config.put((ConfigKey<?>)entry.getKey(), entry.getValue());
-            else if (entry.getKey() instanceof HasConfigKey<?>)
-                config.put(((HasConfigKey<?>)entry.getKey()).getConfigKey(), entry.getValue());
-            else {
-                log.warn("Spec "+this+" ignoring unknown config key "+entry.getKey());
-            }
-        }
-        return this;
-    }
-    
-    public LocationSpec<T> configure(CharSequence key, Object val) {
-        flags.put(checkNotNull(key, "key").toString(), val);
-        return this;
-    }
-    
-    public <V> LocationSpec<T> configure(ConfigKey<V> key, V val) {
-        config.put(checkNotNull(key, "key"), val);
-        return this;
-    }
-
-    public <V> LocationSpec<T> configureIfNotNull(ConfigKey<V> key, V val) {
-        return (val != null) ? configure(key, val) : this;
-    }
-
-    public <V> LocationSpec<T> configure(ConfigKey<V> key, Task<? extends V> val) {
-        config.put(checkNotNull(key, "key"), val);
-        return this;
-    }
-
-    public <V> LocationSpec<T> configure(HasConfigKey<V> key, V val) {
-        config.put(checkNotNull(key, "key").getConfigKey(), val);
-        return this;
-    }
-
-    public <V> LocationSpec<T> configure(HasConfigKey<V> key, Task<? extends V> val) {
-        config.put(checkNotNull(key, "key").getConfigKey(), val);
-        return this;
-    }
-
-    public <V> LocationSpec<T> removeConfig(ConfigKey<V> key) {
-        config.remove( checkNotNull(key, "key") );
-        return this;
-    }
-
     public <E> LocationSpec<T> extension(Class<E> extensionType, E extension) {
         extensions.put(checkNotNull(extensionType, "extensionType"), checkNotNull(extension, "extension"));
         return this;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/90e8911f/api/src/main/java/org/apache/brooklyn/api/policy/PolicySpec.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/policy/PolicySpec.java b/api/src/main/java/org/apache/brooklyn/api/policy/PolicySpec.java
index 92caba9..a139d5d 100644
--- a/api/src/main/java/org/apache/brooklyn/api/policy/PolicySpec.java
+++ b/api/src/main/java/org/apache/brooklyn/api/policy/PolicySpec.java
@@ -18,19 +18,9 @@
  */
 package org.apache.brooklyn.api.policy;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Collections;
 import java.util.Map;
 
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
-import org.apache.brooklyn.api.mgmt.Task;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Maps;
 
 /**
  * Gives details of a policy to be created. It describes the policy's configuration, and is
@@ -44,8 +34,6 @@ import com.google.common.collect.Maps;
  */
 public class PolicySpec<T extends Policy> extends AbstractBrooklynObjectSpec<T,PolicySpec<T>> {
 
-    private static final Logger log = LoggerFactory.getLogger(PolicySpec.class);
-
     private final static long serialVersionUID = 1L;
 
 
@@ -71,9 +59,6 @@ public class PolicySpec<T extends Policy> extends AbstractBrooklynObjectSpec<T,P
         return PolicySpec.create(type).configure(config);
     }
     
-    private final Map<String, Object> flags = Maps.newLinkedHashMap();
-    private final Map<ConfigKey<?>, Object> config = Maps.newLinkedHashMap();
-
     protected PolicySpec(Class<T> type) {
         super(type);
     }
@@ -87,65 +72,5 @@ public class PolicySpec<T extends Policy> extends AbstractBrooklynObjectSpec<T,P
         flags.put("uniqueTag", uniqueTag);
         return this;
     }
-
-    public PolicySpec<T> configure(Map<?,?> val) {
-        for (Map.Entry<?, ?> entry: val.entrySet()) {
-            if (entry.getKey()==null) throw new NullPointerException("Null key not permitted");
-            if (entry.getKey() instanceof CharSequence)
-                flags.put(entry.getKey().toString(), entry.getValue());
-            else if (entry.getKey() instanceof ConfigKey<?>)
-                config.put((ConfigKey<?>)entry.getKey(), entry.getValue());
-            else if (entry.getKey() instanceof HasConfigKey<?>)
-                config.put(((HasConfigKey<?>)entry.getKey()).getConfigKey(), entry.getValue());
-            else {
-                log.warn("Spec "+this+" ignoring unknown config key "+entry.getKey());
-            }
-        }
-        return this;
-    }
-    
-    public PolicySpec<T> configure(CharSequence key, Object val) {
-        flags.put(checkNotNull(key, "key").toString(), val);
-        return this;
-    }
-    
-    public <V> PolicySpec<T> configure(ConfigKey<V> key, V val) {
-        config.put(checkNotNull(key, "key"), val);
-        return this;
-    }
-
-    public <V> PolicySpec<T> configureIfNotNull(ConfigKey<V> key, V val) {
-        return (val != null) ? configure(key, val) : this;
-    }
-
-    public <V> PolicySpec<T> configure(ConfigKey<V> key, Task<? extends V> val) {
-        config.put(checkNotNull(key, "key"), val);
-        return this;
-    }
-
-    public <V> PolicySpec<T> configure(HasConfigKey<V> key, V val) {
-        config.put(checkNotNull(key, "key").getConfigKey(), val);
-        return this;
-    }
-
-    public <V> PolicySpec<T> configure(HasConfigKey<V> key, Task<? extends V> val) {
-        config.put(checkNotNull(key, "key").getConfigKey(), val);
-        return this;
-    }
-
-    /**
-     * @return Read-only construction flags
-     * @see SetFromFlag declarations on the policy type
-     */
-    public Map<String, ?> getFlags() {
-        return Collections.unmodifiableMap(flags);
-    }
-    
-    /**
-     * @return Read-only configuration values
-     */
-    public Map<ConfigKey<?>, Object> getConfig() {
-        return Collections.unmodifiableMap(config);
-    }
         
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/90e8911f/api/src/main/java/org/apache/brooklyn/api/sensor/EnricherSpec.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/sensor/EnricherSpec.java b/api/src/main/java/org/apache/brooklyn/api/sensor/EnricherSpec.java
index 87dc2ef..ae50e2d 100644
--- a/api/src/main/java/org/apache/brooklyn/api/sensor/EnricherSpec.java
+++ b/api/src/main/java/org/apache/brooklyn/api/sensor/EnricherSpec.java
@@ -18,19 +18,12 @@
  */
 package org.apache.brooklyn.api.sensor;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Collections;
 import java.util.Map;
 
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Maps;
 
 /**
  * Gives details of an enricher to be created. It describes the enricher's configuration, and is
@@ -44,10 +37,7 @@ import com.google.common.collect.Maps;
  */
 public class EnricherSpec<T extends Enricher> extends AbstractBrooklynObjectSpec<T,EnricherSpec<T>> {
 
-    private static final Logger log = LoggerFactory.getLogger(EnricherSpec.class);
-
-    private final static long serialVersionUID = 1L;
-
+    private static final long serialVersionUID = -6012873926010992062L;
 
     /**
      * Creates a new {@link EnricherSpec} instance for an enricher of the given type. The returned 
@@ -71,9 +61,6 @@ public class EnricherSpec<T extends Enricher> extends AbstractBrooklynObjectSpec
         return EnricherSpec.create(type).configure(config);
     }
     
-    private final Map<String, Object> flags = Maps.newLinkedHashMap();
-    private final Map<ConfigKey<?>, Object> config = Maps.newLinkedHashMap();
-
     protected EnricherSpec(Class<? extends T> type) {
         super(type);
     }
@@ -88,66 +75,6 @@ public class EnricherSpec<T extends Enricher> extends AbstractBrooklynObjectSpec
         return this;
     }
     
-    public EnricherSpec<T> configure(Map<?,?> val) {
-        for (Map.Entry<?, ?> entry: val.entrySet()) {
-            if (entry.getKey()==null) throw new NullPointerException("Null key not permitted");
-            if (entry.getKey() instanceof CharSequence)
-                flags.put(entry.getKey().toString(), entry.getValue());
-            else if (entry.getKey() instanceof ConfigKey<?>)
-                config.put((ConfigKey<?>)entry.getKey(), entry.getValue());
-            else if (entry.getKey() instanceof HasConfigKey<?>)
-                config.put(((HasConfigKey<?>)entry.getKey()).getConfigKey(), entry.getValue());
-            else {
-                log.warn("Spec "+this+" ignoring unknown config key "+entry.getKey());
-            }
-        }
-        return this;
-    }
-    
-    public EnricherSpec<T> configure(CharSequence key, Object val) {
-        flags.put(checkNotNull(key, "key").toString(), val);
-        return this;
-    }
-    
-    public <V> EnricherSpec<T> configure(ConfigKey<V> key, V val) {
-        config.put(checkNotNull(key, "key"), val);
-        return this;
-    }
-
-    public <V> EnricherSpec<T> configureIfNotNull(ConfigKey<V> key, V val) {
-        return (val != null) ? configure(key, val) : this;
-    }
-
-    public <V> EnricherSpec<T> configure(ConfigKey<V> key, Task<? extends V> val) {
-        config.put(checkNotNull(key, "key"), val);
-        return this;
-    }
-
-    public <V> EnricherSpec<T> configure(HasConfigKey<V> key, V val) {
-        config.put(checkNotNull(key, "key").getConfigKey(), val);
-        return this;
-    }
-
-    public <V> EnricherSpec<T> configure(HasConfigKey<V> key, Task<? extends V> val) {
-        config.put(checkNotNull(key, "key").getConfigKey(), val);
-        return this;
-    }
-
-    /**
-     * @return Read-only construction flags
-     * @see SetFromFlag declarations on the enricher type
-     */
-    public Map<String, ?> getFlags() {
-        return Collections.unmodifiableMap(flags);
-    }
-    
-    /**
-     * @return Read-only configuration values
-     */
-    public Map<ConfigKey<?>, Object> getConfig() {
-        return Collections.unmodifiableMap(config);
-    }
-
     public abstract static class ExtensibleEnricherSpec<T extends Enricher,K extends ExtensibleEnricherSpec<T,K>> extends EnricherSpec<T> {
         private static final long serialVersionUID = -3649347642882809739L;
         

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/90e8911f/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java b/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
index 476034f..ec5db91 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
@@ -41,29 +41,30 @@ public interface BrooklynTypeRegistry {
     
     Iterable<RegisteredType> getAll();
     Iterable<RegisteredType> getAll(Predicate<? super RegisteredType> filter);
-    
+
+    // XXX remove `context` parameter?
     /** @return The item matching the given given 
      * {@link RegisteredType#getSymbolicName() symbolicName} 
      * and optionally {@link RegisteredType#getVersion()},
      * filtered for the optionally supplied {@link RegisteredTypeLoadingContext}, 
      * taking the best version if the version is null or a default marker,
      * returning null if no matches are found. */
-    RegisteredType get(String symbolicName, String version, @Nullable RegisteredTypeLoadingContext constraint);
+    RegisteredType get(String symbolicName, String version, @Nullable RegisteredTypeLoadingContext context);
     /** as {@link #get(String, String, RegisteredTypeLoadingContext)} with no constraints */
     RegisteredType get(String symbolicName, String version);
     /** as {@link #get(String, String, RegisteredTypeLoadingContext)} but allows <code>"name:version"</code> 
      * (the {@link RegisteredType#getId()}) in addition to the unversioned name,
      * using a default marker if no version can be inferred */
-    RegisteredType get(String symbolicNameWithOptionalVersion, @Nullable RegisteredTypeLoadingContext constraint);
+    RegisteredType get(String symbolicNameWithOptionalVersion, @Nullable RegisteredTypeLoadingContext context);
     /** as {@link #get(String, RegisteredTypeLoadingContext)} but with no constraints */
     RegisteredType get(String symbolicNameWithOptionalVersion);
 
     // NB the seemingly more correct generics <T,SpecT extends AbstractBrooklynObjectSpec<T,SpecT>> 
     // cause compile errors, not in Eclipse, but in maven (?) 
-    <SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpec(RegisteredType type, @Nullable RegisteredTypeLoadingContext optionalConstraint, Class<SpecT> optionalSpecSuperType);
-    <SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpecFromPlan(String planFormat, Object planData, @Nullable RegisteredTypeLoadingContext optionalConstraint, Class<SpecT> optionalSpecSuperType);
-    
-    <T> T createBean(RegisteredType type, @Nullable RegisteredTypeLoadingContext optionalConstraint, Class<T> optionalResultSuperType);
+    // TODO do these belong here, or in a separate master TypePlanTransformer ?
+    <SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpec(RegisteredType type, @Nullable RegisteredTypeLoadingContext optionalContext, Class<SpecT> optionalSpecSuperType);
+    <SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpecFromPlan(String planFormat, Object planData, @Nullable RegisteredTypeLoadingContext optionalContext, Class<SpecT> optionalSpecSuperType);
+    <T> T createBean(RegisteredType type, @Nullable RegisteredTypeLoadingContext optionalContext, Class<T> optionalResultSuperType);
     <T> T createBeanFromPlan(String planFormat, Object planData, @Nullable RegisteredTypeLoadingContext optionalConstraint, Class<T> optionalBeanSuperType);
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/90e8911f/core/src/main/java/org/apache/brooklyn/core/location/CatalogLocationResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/location/CatalogLocationResolver.java b/core/src/main/java/org/apache/brooklyn/core/location/CatalogLocationResolver.java
index 5db14b7..194e946 100644
--- a/core/src/main/java/org/apache/brooklyn/core/location/CatalogLocationResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/core/location/CatalogLocationResolver.java
@@ -22,7 +22,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import java.util.Map;
 
-import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.location.LocationRegistry;
 import org.apache.brooklyn.api.location.LocationResolver;
@@ -60,7 +59,7 @@ public class CatalogLocationResolver implements LocationResolver {
             log.warn("Use of deprecated catalog item "+item.getSymbolicName()+":"+item.getVersion());
         }
         
-        LocationSpec origLocSpec = (LocationSpec) managementContext.getTypeRegistry().createSpec(item, null, LocationSpec.class);
+        LocationSpec<?> origLocSpec = (LocationSpec) managementContext.getTypeRegistry().createSpec(item, null, LocationSpec.class);
         LocationSpec locSpec = LocationSpec.create(origLocSpec)
                 .configure(locationFlags);
         return managementContext.getLocationManager().createLocation(locSpec);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/90e8911f/core/src/main/java/org/apache/brooklyn/core/plan/PlanNotRecognizedException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/plan/PlanNotRecognizedException.java b/core/src/main/java/org/apache/brooklyn/core/plan/PlanNotRecognizedException.java
index dd5c93d..4010cff 100644
--- a/core/src/main/java/org/apache/brooklyn/core/plan/PlanNotRecognizedException.java
+++ b/core/src/main/java/org/apache/brooklyn/core/plan/PlanNotRecognizedException.java
@@ -25,7 +25,6 @@ import org.apache.brooklyn.core.typereg.UnsupportedTypePlanException;
 @Deprecated 
 public class PlanNotRecognizedException extends RuntimeException {
 
-    /** {@link UnsupportedTypePlanException} */
     private static final long serialVersionUID = -5590108442839125317L;
 
     public PlanNotRecognizedException(String message, Throwable cause) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/90e8911f/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java b/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java
index b4d79c2..2900e20 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java
@@ -29,6 +29,12 @@ import org.slf4j.LoggerFactory;
 
 /**
  * Convenience supertype for {@link BrooklynTypePlanTransformer} instances.
+ * <p>
+ * This supplies a default {@link #scoreForType(RegisteredType, RegisteredTypeLoadingContext)}
+ * method which returns 1 if the format code matches,
+ * and otherwise branches to two methods {@link #scoreForNullFormat(Object, RegisteredType, RegisteredTypeLoadingContext)}
+ * and {@link #scoreForNonmatchingNonnullFormat(String, Object, RegisteredType, RegisteredTypeLoadingContext)}
+ * which subclasses can implement.  (Often the implementation of the latter is 0.)
  */
 public abstract class AbstractTypePlanTransformer implements BrooklynTypePlanTransformer {
 
@@ -107,12 +113,11 @@ public abstract class AbstractTypePlanTransformer implements BrooklynTypePlanTra
                 }
                 
             }.visit(type), type, context);
-        } catch (UnsupportedTypePlanException e) {
-            // no logging
-            throw Exceptions.propagate(e);
         } catch (Exception e) {
             Exceptions.propagateIfFatal(e);
-            log.debug("Could not instantiate "+type+" (rethrowing): "+Exceptions.collapseText(e));
+            if (!(e instanceof UnsupportedTypePlanException)) {
+                log.debug("Could not instantiate "+type+" (rethrowing): "+Exceptions.collapseText(e));
+            }
             throw Exceptions.propagate(e);
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/90e8911f/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
index 224aca2..e185d3f 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
@@ -21,6 +21,9 @@ package org.apache.brooklyn.core.typereg;
 import java.util.List;
 import java.util.ServiceLoader;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry;
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
 import org.apache.brooklyn.api.typereg.RegisteredType;
@@ -28,7 +31,8 @@ import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
 import org.apache.brooklyn.core.mgmt.ManagementContextInjectable;
 
 /**
- * Interface for use by schemes which with to be able to transform plans.
+ * Interface for use by schemes which provide the capability to transform plans
+ * (serialized descriptions) to brooklyn objecs and specs.
  * <p>
  * To add a new plan transformation scheme, simply create an implementation and declare it
  * as a java service (cf {@link ServiceLoader}).
@@ -37,19 +41,29 @@ import org.apache.brooklyn.core.mgmt.ManagementContextInjectable;
  */
 public interface BrooklynTypePlanTransformer extends ManagementContextInjectable {
 
-    /** @return a code to identify type implementations created specifying the use of this plan transformer. */
+    /** @return An identifier for the transformer. 
+     * This may be used by RegisteredType instances to target a specific transformer. */
     String getFormatCode();
-    /** @return a display name for this transformer. */
+    /** @return A display name for this transformer. 
+     * This may be used to prompt a user what type of plan they are supplying. */
     String getFormatName();
-    /** @return a description for this transformer */
+    /** @return A description for this transformer */
     String getFormatDescription();
 
-    /** @return how appropriate is this transformer for the {@link RegisteredType#getPlan()} of the type;
-     * 0 (or less) if not, 1 for absolutely, and in some autodetect cases a value between 0 and 1 indicate a ranking.
-     * <p>
+    /** 
+     * Determines how appropriate is this transformer for the {@link RegisteredType#getPlan()} of the type.
      * The framework guarantees arguments are nonnull, and that the {@link RegisteredType#getPlan()} is also not-null.
-     * However the format in that plan may be null. */
-    double scoreForType(RegisteredType type, RegisteredTypeLoadingContext context);
+     * However the format in that plan may be null. 
+     * @return A co-ordinated score / confidence value in the range 0 to 1. 
+     * 0 means not compatible, 
+     * 1 means this is clearly the intended transformer and no others need be tried 
+     * (for instance because the format is explicitly specified),
+     * and values between 0 and 1 indicate how likely a transformer believes it should be used.
+     * Values greater than 0.5 are generally reserved for the presence of marker tags or files
+     * which strongly indicate that the format is compatible.
+     * <p>
+     * */
+    double scoreForType(@Nonnull RegisteredType type, @Nonnull RegisteredTypeLoadingContext context);
     /** Creates a new instance of the indicated type, or throws if not supported;
      * this method is used by the {@link BrooklynTypeRegistry} when it creates instances,
      * so implementations must respect the {@link RegisteredTypeKind} semantics and the {@link RegisteredTypeLoadingContext}
@@ -60,7 +74,7 @@ public interface BrooklynTypePlanTransformer extends ManagementContextInjectable
      * <p>
      * Implementations should either return null or throw {@link UnsupportedTypePlanException} 
      * if the {@link RegisteredType#getPlan()} is not supported. */
-    Object create(RegisteredType type, RegisteredTypeLoadingContext context);
+    @Nullable Object create(@Nonnull RegisteredType type, @Nonnull RegisteredTypeLoadingContext context);
     
     double scoreForTypeDefinition(String formatCode, Object catalogData);
     List<RegisteredType> createFromTypeDefinition(String formatCode, Object catalogData);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/90e8911f/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
index 56eeb99..f287fec 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
@@ -35,7 +35,9 @@ import com.google.common.collect.ImmutableList;
 
 public class CampTypePlanTransformer extends AbstractTypePlanTransformer {
 
-    private static final List<String> FORMATS = ImmutableList.of("brooklyn-camp", "camp", "brooklyn");
+    private static final List<String> FORMATS = ImmutableList.of("brooklyn-camp");
+    // TODO any use in having these formats? if not, remove. Nov 2015.
+    // , "camp", "brooklyn");
     
     public static final String FORMAT = FORMATS.get(0);
     



[14/14] incubator-brooklyn git commit: This closes #1017

Posted by he...@apache.org.
This closes #1017


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

Branch: refs/heads/master
Commit: 3e40b2bfd609e6313c9f48d42be722f708043da1
Parents: 7c649d7 c575708
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Nov 17 22:50:49 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Nov 17 22:50:49 2015 +0000

----------------------------------------------------------------------
 .../brooklyn/api/catalog/CatalogItem.java       |  24 ++
 .../apache/brooklyn/api/entity/EntitySpec.java  |  93 -----
 .../internal/AbstractBrooklynObjectSpec.java    | 100 ++++-
 .../brooklyn/api/location/LocationSpec.java     |  78 +---
 .../BrooklynClassLoadingContext.java            |  50 +++
 .../apache/brooklyn/api/policy/PolicySpec.java  |  75 ----
 .../brooklyn/api/sensor/EnricherSpec.java       |  75 +---
 .../api/typereg/BrooklynTypeRegistry.java       |  32 +-
 .../brooklyn/api/typereg/RegisteredType.java    |  45 ++-
 .../api/typereg/RegisteredTypeConstraint.java   |  45 ---
 .../typereg/RegisteredTypeLoadingContext.java   |  50 +++
 .../catalog/internal/BasicBrooklynCatalog.java  |  41 +-
 .../catalog/internal/CatalogItemBuilder.java    |  44 ++-
 .../core/catalog/internal/CatalogUtils.java     |  33 +-
 .../core/location/CatalogLocationResolver.java  |   3 +-
 .../core/mgmt/EntityManagementUtils.java        |  17 +-
 .../AbstractBrooklynClassLoadingContext.java    |   5 +-
 .../BrooklynClassLoadingContext.java            |  30 +-
 .../BrooklynClassLoadingContextSequential.java  |   1 +
 ...ssLoaderFromBrooklynClassLoadingContext.java |   2 +
 .../internal/AbstractManagementContext.java     |   2 +-
 .../core/mgmt/persist/XmlMementoSerializer.java |   2 +-
 .../core/mgmt/rebind/RebindIteration.java       |   2 +-
 .../brooklyn/core/objs/BasicSpecParameter.java  |   2 +-
 .../core/plan/PlanNotRecognizedException.java   |   5 +
 .../brooklyn/core/plan/PlanToSpecFactory.java   |  40 +-
 .../core/plan/PlanToSpecTransformer.java        |   3 +-
 .../entity/AbstractEntitySpecResolver.java      |   2 +-
 .../entity/CatalogEntitySpecResolver.java       |   6 +-
 .../entity/DelegatingEntitySpecResolver.java    |   4 +-
 .../core/resolve/entity/EntitySpecResolver.java |   2 +-
 .../resolve/entity/JavaEntitySpecResolver.java  |   2 +-
 ...actFormatSpecificTypeImplementationPlan.java |  52 +++
 .../typereg/AbstractTypePlanTransformer.java    | 142 +++++++
 .../core/typereg/BasicBrooklynTypeRegistry.java | 126 +++++-
 .../core/typereg/BasicRegisteredType.java       | 135 +++++++
 .../typereg/BasicTypeImplementationPlan.java    |  41 ++
 .../typereg/BrooklynTypePlanTransformer.java    |  88 +++++
 .../JavaClassNameTypePlanTransformer.java       |  91 +++++
 .../core/typereg/RegisteredTypeConstraints.java | 156 --------
 .../core/typereg/RegisteredTypeKindVisitor.java |  45 +++
 .../typereg/RegisteredTypeLoadingContexts.java  | 236 +++++++++++
 .../core/typereg/RegisteredTypePredicates.java  |  28 +-
 .../brooklyn/core/typereg/RegisteredTypes.java  | 389 ++++++++++++-------
 .../core/typereg/TypePlanTransformers.java      | 165 ++++++++
 .../typereg/UnsupportedTypePlanException.java   |  37 ++
 .../brooklyn/util/core/ResourceUtils.java       |   3 +-
 ...lyn.core.typereg.BrooklynTypePlanTransformer |  19 +
 .../policy/basic/AbstractEntityAdjunctTest.java |  52 ---
 .../internal/StaticTypePlanTransformer.java     | 124 ++++++
 .../internal/StaticTypePlanTransformerTest.java |  63 +++
 .../core/objs/AbstractEntityAdjunctTest.java    |  52 +++
 .../objs/BasicSpecParameterFromListTest.java    |   2 +-
 .../core/plan/XmlPlanToSpecTransformer.java     |   5 +-
 .../core/plan/XmlPlanToSpecTransformerTest.java |   2 +
 .../brooklyn/core/sensor/StaticSensorTest.java  |   8 +-
 .../core/test/BrooklynAppLiveTestSupport.java   |  26 +-
 .../core/test/BrooklynAppUnitTestSupport.java   |  38 +-
 .../core/test/BrooklynMgmtUnitTestSupport.java  |  61 +++
 .../core/test/entity/TestEntityImpl.java        |   1 -
 .../typereg/ExampleXmlTypePlanTransformer.java  | 140 +++++++
 .../ExampleXmlTypePlanTransformerTest.java      |  67 ++++
 .../JavaClassNameTypePlanTransformerTest.java   |  90 +++++
 .../entity/resolve/ChefEntitySpecResolver.java  |   2 +-
 .../HardcodedCatalogEntitySpecResolver.java     |   2 +-
 .../api/AssemblyTemplateSpecInstantiator.java   |   7 +-
 .../BrooklynAssemblyTemplateInstantiator.java   |  13 +-
 .../BrooklynComponentTemplateResolver.java      |   2 +-
 .../BrooklynEntityDecorationResolver.java       |   5 +-
 .../spi/creation/BrooklynEntityMatcher.java     |   2 +-
 .../creation/BrooklynYamlTypeInstantiator.java  |   2 +-
 .../brooklyn/spi/creation/CampCatalogUtils.java |  54 +--
 .../spi/creation/CampInternalUtils.java         | 247 ++++++++++++
 .../brooklyn/spi/creation/CampResolver.java     | 147 +++++++
 .../spi/creation/CampToSpecTransformer.java     |  17 +-
 .../spi/creation/CampTypePlanTransformer.java   |  98 +++++
 .../camp/brooklyn/spi/creation/CampUtils.java   | 267 -------------
 .../service/ServiceTypeResolverAdaptor.java     |   2 +-
 .../service/UrlServiceSpecResolver.java         |  20 +-
 ...lyn.core.typereg.BrooklynTypePlanTransformer |  19 +
 .../camp/brooklyn/AbstractYamlTest.java         |  39 +-
 .../BrooklynYamlTypeInstantiatorTest.java       |   2 +-
 .../camp/brooklyn/EntitiesYamlTest.java         |   2 +
 .../camp/brooklyn/LocationsYamlTest.java        |   4 +-
 .../camp/brooklyn/ReferencedYamlTest.java       |   1 +
 .../CatalogOsgiVersionMoreEntityTest.java       |  18 +-
 .../catalog/CatalogYamlLocationTest.java        |   3 +-
 .../catalog/SpecParameterParsingTest.java       |  44 ++-
 .../brooklyn/test/lite/CampYamlLiteTest.java    |   6 +-
 .../test/lite/TestAppAssemblyInstantiator.java  |  10 +-
 .../rest/resources/ApplicationResource.java     |  14 +-
 .../rest/resources/CatalogResource.java         |   5 +-
 .../rest/util/BrooklynRestResourceUtils.java    |   2 +-
 .../exceptions/PropagatedRuntimeException.java  |   6 +
 .../apache/brooklyn/util/text/Identifiers.java  |  13 +-
 .../brooklyn/util/text/IdentifiersTest.java     |  13 +
 96 files changed, 3133 insertions(+), 1354 deletions(-)
----------------------------------------------------------------------



[05/14] incubator-brooklyn git commit: Big refactoring of new type registry code

Posted by he...@apache.org.
Big refactoring of new type registry code

* call the class RegisteredTypeLoadingContext instead of constraint, improve method names based on better understood semantics
* clean up how plans can be passed directly, without needing an anonymous RegisteredType
* move BrooklynClassLoadingContext to API project (keeping temporary sub-interface in core)


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

Branch: refs/heads/master
Commit: e932d5fcf0686440a295ed27d205454512153549
Parents: 904c45e
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Nov 9 16:09:56 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Nov 10 17:13:02 2015 +0000

----------------------------------------------------------------------
 .../BrooklynClassLoadingContext.java            |  50 ++++
 .../api/typereg/BrooklynTypeRegistry.java       |  19 +-
 .../api/typereg/RegisteredTypeConstraint.java   |  50 ----
 .../typereg/RegisteredTypeLoadingContext.java   |  50 ++++
 .../catalog/internal/BasicBrooklynCatalog.java  |  29 +--
 .../core/catalog/internal/CatalogUtils.java     |   6 +-
 .../core/mgmt/EntityManagementUtils.java        |  15 +-
 .../AbstractBrooklynClassLoadingContext.java    |   5 +-
 .../BrooklynClassLoadingContext.java            |  30 +--
 .../BrooklynClassLoadingContextSequential.java  |   1 +
 ...ssLoaderFromBrooklynClassLoadingContext.java |   2 +
 .../internal/AbstractManagementContext.java     |   2 +-
 .../core/mgmt/persist/XmlMementoSerializer.java |   2 +-
 .../core/mgmt/rebind/RebindIteration.java       |   2 +-
 .../brooklyn/core/objs/BasicSpecParameter.java  |   2 +-
 .../brooklyn/core/plan/PlanToSpecFactory.java   |  36 ++-
 .../entity/AbstractEntitySpecResolver.java      |   2 +-
 .../entity/CatalogEntitySpecResolver.java       |   6 +-
 .../entity/DelegatingEntitySpecResolver.java    |   2 +-
 .../core/resolve/entity/EntitySpecResolver.java |   2 +-
 .../resolve/entity/JavaEntitySpecResolver.java  |   2 +-
 .../typereg/AbstractTypePlanTransformer.java    |  16 +-
 .../core/typereg/BasicBrooklynTypeRegistry.java |  59 +++--
 .../typereg/BrooklynTypePlanTransformer.java    |  10 +-
 .../JavaClassNameTypePlanTransformer.java       |  12 +-
 .../core/typereg/RegisteredTypeConstraints.java | 206 ----------------
 .../typereg/RegisteredTypeLoadingContexts.java  | 234 +++++++++++++++++++
 .../brooklyn/core/typereg/RegisteredTypes.java  |   8 +-
 .../core/typereg/TypePlanTransformers.java      |   6 +-
 .../brooklyn/util/core/ResourceUtils.java       |   3 +-
 .../objs/BasicSpecParameterFromListTest.java    |   2 +-
 .../entity/resolve/ChefEntitySpecResolver.java  |   2 +-
 .../HardcodedCatalogEntitySpecResolver.java     |   2 +-
 .../api/AssemblyTemplateSpecInstantiator.java   |   2 +-
 .../BrooklynAssemblyTemplateInstantiator.java   |   2 +-
 .../BrooklynComponentTemplateResolver.java      |   2 +-
 .../BrooklynEntityDecorationResolver.java       |   4 +-
 .../spi/creation/BrooklynEntityMatcher.java     |   2 +-
 .../creation/BrooklynYamlTypeInstantiator.java  |   2 +-
 .../spi/creation/CampInternalUtils.java         |   2 +-
 .../brooklyn/spi/creation/CampResolver.java     |  13 +-
 .../spi/creation/CampToSpecTransformer.java     |   2 +-
 .../spi/creation/CampTypePlanTransformer.java   |  14 +-
 .../service/ServiceTypeResolverAdaptor.java     |   2 +-
 .../service/UrlServiceSpecResolver.java         |  13 +-
 .../camp/brooklyn/AbstractYamlTest.java         |   6 +-
 .../BrooklynYamlTypeInstantiatorTest.java       |   2 +-
 .../brooklyn/test/lite/CampYamlLiteTest.java    |   4 +-
 .../test/lite/TestAppAssemblyInstantiator.java  |   2 +-
 .../rest/resources/ApplicationResource.java     |   4 +-
 .../rest/resources/CatalogResource.java         |   4 +-
 51 files changed, 531 insertions(+), 426 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/api/src/main/java/org/apache/brooklyn/api/mgmt/classloading/BrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/classloading/BrooklynClassLoadingContext.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/classloading/BrooklynClassLoadingContext.java
new file mode 100644
index 0000000..f95c0d8
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/classloading/BrooklynClassLoadingContext.java
@@ -0,0 +1,50 @@
+/*
+ * 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.api.mgmt.classloading;
+
+import java.net.URL;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.util.guava.Maybe;
+
+/** 
+ * Provides functionality for loading classes based on the current context
+ * (e.g. the bundles of a registered type from which an entity is created)
+ */
+public interface BrooklynClassLoadingContext {
+
+    public ManagementContext getManagementContext();
+    public Class<?> loadClass(String className);
+    public <T> Class<? extends T> loadClass(String className, @Nullable Class<T> supertype);
+
+    public Maybe<Class<?>> tryLoadClass(String className);
+    public <T> Maybe<Class<? extends T>> tryLoadClass(String className, @Nullable Class<T> supertype);
+
+    /** As {@link ClassLoader#getResource(String)} */
+    public URL getResource(String name);
+
+    /**
+     * As {@link ClassLoader#getResources(String)} but returning an {@link Iterable} rather than
+     * an {@link java.util.Enumeration}.
+     */
+    public Iterable<URL> getResources(String name);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java b/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
index f98f12f..476034f 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
@@ -45,24 +45,25 @@ public interface BrooklynTypeRegistry {
     /** @return The item matching the given given 
      * {@link RegisteredType#getSymbolicName() symbolicName} 
      * and optionally {@link RegisteredType#getVersion()},
-     * filtered for the optionally supplied {@link RegisteredTypeConstraint}, 
+     * filtered for the optionally supplied {@link RegisteredTypeLoadingContext}, 
      * taking the best version if the version is null or a default marker,
      * returning null if no matches are found. */
-    RegisteredType get(String symbolicName, String version, @Nullable RegisteredTypeConstraint constraint);
-    /** as {@link #get(String, String, RegisteredTypeConstraint)} with no constraints */
+    RegisteredType get(String symbolicName, String version, @Nullable RegisteredTypeLoadingContext constraint);
+    /** as {@link #get(String, String, RegisteredTypeLoadingContext)} with no constraints */
     RegisteredType get(String symbolicName, String version);
-    /** as {@link #get(String, String, RegisteredTypeConstraint)} but allows <code>"name:version"</code> 
+    /** as {@link #get(String, String, RegisteredTypeLoadingContext)} but allows <code>"name:version"</code> 
      * (the {@link RegisteredType#getId()}) in addition to the unversioned name,
      * using a default marker if no version can be inferred */
-    RegisteredType get(String symbolicNameWithOptionalVersion, @Nullable RegisteredTypeConstraint constraint);
-    /** as {@link #get(String, RegisteredTypeConstraint)} but with no constraints */
+    RegisteredType get(String symbolicNameWithOptionalVersion, @Nullable RegisteredTypeLoadingContext constraint);
+    /** as {@link #get(String, RegisteredTypeLoadingContext)} but with no constraints */
     RegisteredType get(String symbolicNameWithOptionalVersion);
 
     // NB the seemingly more correct generics <T,SpecT extends AbstractBrooklynObjectSpec<T,SpecT>> 
     // cause compile errors, not in Eclipse, but in maven (?) 
-    <SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpec(RegisteredType type, @Nullable RegisteredTypeConstraint optionalConstraint, Class<SpecT> optionalSpecSuperType);
+    <SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpec(RegisteredType type, @Nullable RegisteredTypeLoadingContext optionalConstraint, Class<SpecT> optionalSpecSuperType);
+    <SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpecFromPlan(String planFormat, Object planData, @Nullable RegisteredTypeLoadingContext optionalConstraint, Class<SpecT> optionalSpecSuperType);
     
-    // TODO when we support beans
-//    <T> T createBean(RegisteredType type, @Nullable RegisteredTypeConstraint optionalConstraint, Class<T> optionalResultSuperType);
+    <T> T createBean(RegisteredType type, @Nullable RegisteredTypeLoadingContext optionalConstraint, Class<T> optionalResultSuperType);
+    <T> T createBeanFromPlan(String planFormat, Object planData, @Nullable RegisteredTypeLoadingContext optionalConstraint, Class<T> optionalBeanSuperType);
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java
deleted file mode 100644
index 8bcff38..0000000
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java
+++ /dev/null
@@ -1,50 +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.api.typereg;
-
-import java.util.Set;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
-
-public interface RegisteredTypeConstraint {
-    
-    /** The kind required, if specified. */
-    @Nullable public RegisteredTypeKind getKind();
-    
-    /** A java super-type or interface that should be filtered for; 
-     * for specs, this refers to the target type, not the spec 
-     * (eg {@link Entity} not {@link EntitySpec}). 
-     * If nothing is specified, this returns {@link Object}'s class. */
-    @Nonnull public Class<?> getJavaSuperType();
-    
-    /** encountered types, so that during resolution, 
-     * if we have already attempted to resolve a given type,
-     * the instantiator can avoid recursive cycles */
-    @Nonnull public Set<String> getEncounteredTypes();
-    
-    /** A special loader to use, if available.
-     * For internal use only; implementations should be a BrooklynClassLoadingContext */
-    @Nullable public Object getLoader();
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeLoadingContext.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeLoadingContext.java b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeLoadingContext.java
new file mode 100644
index 0000000..d37666e
--- /dev/null
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeLoadingContext.java
@@ -0,0 +1,50 @@
+/*
+ * 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.api.typereg;
+
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
+
+public interface RegisteredTypeLoadingContext {
+    
+    /** The kind required, if specified. */
+    @Nullable public RegisteredTypeKind getExpectedKind();
+    
+    /** A java super-type or interface that should be filtered for; 
+     * for specs, this refers to the target type, not the spec 
+     * (eg {@link Entity} not {@link EntitySpec}). 
+     * If nothing is specified, this returns {@link Object}'s class. */
+    @Nonnull public Class<?> getExpectedJavaSuperType();
+    
+    /** encountered types, so that during resolution, 
+     * if we have already attempted to resolve a given type,
+     * the instantiator can avoid recursive cycles */
+    @Nonnull public Set<String> getAlreadyEncounteredTypes();
+    
+    /** A loader to use, supplying additional search paths */
+    @Nullable public BrooklynClassLoadingContext getLoader();
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
index 262e3b4..0832b4f 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
@@ -37,15 +37,14 @@ import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.location.LocationSpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.api.objs.SpecParameter;
 import org.apache.brooklyn.core.catalog.CatalogPredicates;
 import org.apache.brooklyn.core.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
 import org.apache.brooklyn.core.location.BasicLocationRegistry;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.objs.BasicSpecParameter;
-import org.apache.brooklyn.core.plan.PlanToSpecFactory;
-import org.apache.brooklyn.core.plan.PlanToSpecTransformer;
+import org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.collections.MutableSet;
@@ -303,7 +302,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         if (loadedItem == null) throw new RuntimeException(item+" not in catalog; cannot create spec");
         if (loadedItem.getSpecType()==null) return null;
 
-        SpecT spec = internalCreateSpecWithTransformers(mgmt, loadedItem, MutableSet.<String>of());
+        SpecT spec = internalCreateSpecLegacy(mgmt, loadedItem, MutableSet.<String>of(), false);
         if (spec != null) {
             return spec;
         }
@@ -312,16 +311,18 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     }
     
     /** @deprecated since introduction in 0.9.0, only used for backwards compatibility, can be removed any time;
-     * uses the type-creation info on the item */
+     * uses the type-creation info on the item.
+     * deprecated transformers must be included by routines which don't use {@link BrooklynTypePlanTransformer} instances;
+     * otherwise deprecated transformers should be excluded. (deprecation is taken as equivalent to having a new-style transformer.) */
     @Deprecated 
-    public static <T,SpecT extends AbstractBrooklynObjectSpec<? extends T, SpecT>> SpecT internalCreateSpecWithTransformers(ManagementContext mgmt, final CatalogItem<T, SpecT> item, final Set<String> encounteredTypes) {
+    public static <T,SpecT extends AbstractBrooklynObjectSpec<? extends T, SpecT>> SpecT internalCreateSpecLegacy(ManagementContext mgmt, final CatalogItem<T, SpecT> item, final Set<String> encounteredTypes, boolean includeDeprecatedTransformers) {
         // deprecated lookup
         if (encounteredTypes.contains(item.getSymbolicName())) {
             throw new IllegalStateException("Type being resolved '"+item.getSymbolicName()+"' has already been encountered in " + encounteredTypes + "; recursive cycle detected");
         }
-        Maybe<SpecT> specMaybe = PlanToSpecFactory.attemptWithLoaders(mgmt, new Function<PlanToSpecTransformer, SpecT>() {
+        Maybe<SpecT> specMaybe = org.apache.brooklyn.core.plan.PlanToSpecFactory.attemptWithLoaders(mgmt, includeDeprecatedTransformers, new Function<org.apache.brooklyn.core.plan.PlanToSpecTransformer, SpecT>() {
             @Override
-            public SpecT apply(PlanToSpecTransformer input) {
+            public SpecT apply(org.apache.brooklyn.core.plan.PlanToSpecTransformer input) {
                 return input.createCatalogSpec(item, encounteredTypes);
             }
         });
@@ -331,14 +332,6 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         return specMaybe.get();
     }
 
-    /**
-     * as internalCreateSpecFromItemWithTransformers, but marking contexts where the creation is being attempted
-     * @deprecated since introduction in 0.9.0, only used for backwards compatibility, can be removed any time */
-    @Deprecated
-    public static <T,SpecT extends AbstractBrooklynObjectSpec<? extends T, SpecT>> SpecT internalCreateSpecAttempting(ManagementContext mgmt, final CatalogItem<T, SpecT> item, final Set<String> encounteredTypes) {
-        return internalCreateSpecWithTransformers(mgmt, item, encounteredTypes);
-    }
-
     @Deprecated /** @deprecated since 0.7.0 only used by other deprecated items */ 
     private <T,SpecT> CatalogItemDtoAbstract<T,SpecT> getAbstractCatalogItem(CatalogItem<T,SpecT> item) {
         while (item instanceof CatalogItemDo) item = ((CatalogItemDo<T,SpecT>)item).itemDto;
@@ -772,7 +765,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
                     .libraries(libraryBundles)
                     .build();
                 @SuppressWarnings("unchecked")
-                AbstractBrooklynObjectSpec<?, ?> spec = internalCreateSpecAttempting(mgmt, itemToAttempt, MutableSet.<String>of());
+                AbstractBrooklynObjectSpec<?, ?> spec = internalCreateSpecLegacy(mgmt, itemToAttempt, MutableSet.<String>of(), true);
                 if (spec!=null) {
                     catalogItemType = candidateCiType;
                     planYaml = candidateYaml;
@@ -814,7 +807,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
                             .libraries(libraryBundles)
                             .build();
                     @SuppressWarnings("unchecked")
-                    AbstractBrooklynObjectSpec<?, ?> cutdownSpec = internalCreateSpecAttempting(mgmt, itemToAttempt, MutableSet.<String>of());
+                    AbstractBrooklynObjectSpec<?, ?> cutdownSpec = internalCreateSpecLegacy(mgmt, itemToAttempt, MutableSet.<String>of(), true);
                     if (cutdownSpec!=null) {
                         catalogItemType = candidateCiType;
                         planYaml = candidateYaml;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
index 2955895..4a54800 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
@@ -27,6 +27,7 @@ import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry;
 import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl;
@@ -34,7 +35,6 @@ import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.core.BrooklynLogging;
 import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
 import org.apache.brooklyn.core.entity.EntityInternal;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContextSequential;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.OsgiBrooklynClassLoadingContext;
@@ -42,7 +42,7 @@ import org.apache.brooklyn.core.mgmt.ha.OsgiManager;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.mgmt.rebind.RebindManagerImpl.RebindTracker;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
-import org.apache.brooklyn.core.typereg.RegisteredTypeConstraints;
+import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.time.Time;
@@ -80,7 +80,7 @@ public class CatalogUtils {
         ManagementContext mgmt = ((EntityInternal)entity).getManagementContext();
         String catId = entity.getCatalogItemId();
         if (Strings.isBlank(catId)) return JavaBrooklynClassLoadingContext.create(mgmt);
-        RegisteredType cat = mgmt.getTypeRegistry().get(catId, RegisteredTypeConstraints.spec(Entity.class));
+        RegisteredType cat = mgmt.getTypeRegistry().get(catId, RegisteredTypeLoadingContexts.spec(Entity.class));
         if (cat==null) {
             log.warn("Cannot load "+catId+" to get classloader for "+entity+"; will try with standard loader, but might fail subsequently");
             return JavaBrooklynClassLoadingContext.create(mgmt);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
index e1a5593..0f8da61 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
@@ -39,8 +39,7 @@ import org.apache.brooklyn.core.effector.Effectors;
 import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.entity.EntityFunctions;
 import org.apache.brooklyn.core.entity.trait.Startable;
-import org.apache.brooklyn.core.plan.PlanToSpecFactory;
-import org.apache.brooklyn.core.plan.PlanToSpecTransformer;
+import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
 import org.apache.brooklyn.entity.stock.BasicApplication;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
@@ -52,7 +51,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.annotations.Beta;
-import com.google.common.base.Function;
 import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -89,14 +87,9 @@ public class EntityManagementUtils {
         return createUnstarted(mgmt, spec);
     }
     
+    @SuppressWarnings("unchecked")
     public static EntitySpec<? extends Application> createEntitySpecForApplication(ManagementContext mgmt, final String plan) {
-        // TODO-type-registry
-        return PlanToSpecFactory.attemptWithLoaders(mgmt, new Function<PlanToSpecTransformer, EntitySpec<? extends Application>>() {
-            @Override
-            public EntitySpec<? extends Application> apply(PlanToSpecTransformer input) {
-                return input.createApplicationSpec(plan);
-            }
-        }).get();
+        return mgmt.getTypeRegistry().createSpecFromPlan(null, plan, RegisteredTypeLoadingContexts.spec(Application.class), EntitySpec.class);
     }
 
     @Deprecated /** @deprecated since 0.9.0; use {@link BrooklynTypeRegistry#createSpec(RegisteredType, org.apache.brooklyn.api.typereg.RegisteredTypeConstraint, Class)} */
@@ -108,7 +101,7 @@ public class EntityManagementUtils {
     @Deprecated /** @deprecated since 0.9.0; use {@link BrooklynTypeRegistry#createSpec(RegisteredType, org.apache.brooklyn.api.typereg.RegisteredTypeConstraint, Class)} */
     // not used in Brooklyn
     public static <T,SpecT extends AbstractBrooklynObjectSpec<? extends T, SpecT>> SpecT createCatalogSpec(ManagementContext mgmt, final CatalogItem<T, SpecT> item, final Set<String> encounteredTypes) {
-        return BasicBrooklynCatalog.internalCreateSpecWithTransformers(mgmt, item, encounteredTypes);
+        return BasicBrooklynCatalog.internalCreateSpecLegacy(mgmt, item, encounteredTypes, true);
     }
 
     /** container for operation which creates something and which wants to return both

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/AbstractBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/AbstractBrooklynClassLoadingContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/AbstractBrooklynClassLoadingContext.java
index 10d3c99..8003948 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/AbstractBrooklynClassLoadingContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/AbstractBrooklynClassLoadingContext.java
@@ -3,6 +3,7 @@ package org.apache.brooklyn.core.mgmt.classloading;
 import javax.annotation.Nullable;
 
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.util.guava.Maybe;
 
 import com.google.common.base.Objects;
@@ -25,7 +26,9 @@ import com.google.common.base.Objects;
  * specific language governing permissions and limitations
  * under the License.
  */
-public abstract class AbstractBrooklynClassLoadingContext implements BrooklynClassLoadingContext {
+@SuppressWarnings("deprecation")
+public abstract class AbstractBrooklynClassLoadingContext implements BrooklynClassLoadingContext,
+    org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext {
 
     protected final ManagementContext mgmt;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/BrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/BrooklynClassLoadingContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/BrooklynClassLoadingContext.java
index 20e8719..b6a5e50 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/BrooklynClassLoadingContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/BrooklynClassLoadingContext.java
@@ -18,33 +18,11 @@
  */
 package org.apache.brooklyn.core.mgmt.classloading;
 
-import java.net.URL;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.mgmt.ManagementContext;
-import org.apache.brooklyn.util.guava.Maybe;
 
 /** 
- * Provides functionality for loading classes based on the current context
- * (e.g. catalog item, entity, etc). 
+ * @deprecated since 0.9.0; moved to API package; use the super-interface
+ * {@link org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext}
  */
-public interface BrooklynClassLoadingContext {
-
-    public ManagementContext getManagementContext();
-    public Class<?> loadClass(String className);
-    public <T> Class<? extends T> loadClass(String className, @Nullable Class<T> supertype);
-
-    public Maybe<Class<?>> tryLoadClass(String className);
-    public <T> Maybe<Class<? extends T>> tryLoadClass(String className, @Nullable Class<T> supertype);
-
-    /** As {@link ClassLoader#getResource(String)} */
-    public URL getResource(String name);
-
-    /**
-     * As {@link ClassLoader#getResources(String)} but returning an {@link Iterable} rather than
-     * an {@link java.util.Enumeration}.
-     */
-    public Iterable<URL> getResources(String name);
-
+@Deprecated
+public interface BrooklynClassLoadingContext extends org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext {
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/BrooklynClassLoadingContextSequential.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/BrooklynClassLoadingContextSequential.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/BrooklynClassLoadingContextSequential.java
index 9b49599..530039a 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/BrooklynClassLoadingContextSequential.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/BrooklynClassLoadingContextSequential.java
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.Set;
 
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.exceptions.Exceptions;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromBrooklynClassLoadingContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromBrooklynClassLoadingContext.java
index dbd6d2c..f36e2ac 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromBrooklynClassLoadingContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromBrooklynClassLoadingContext.java
@@ -20,6 +20,8 @@ package org.apache.brooklyn.core.mgmt.classloading;
 
 import java.net.URL;
 
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
+
 public class ClassLoaderFromBrooklynClassLoadingContext extends ClassLoader {
 
     /** Constructs a {@link ClassLoader} which delegates to the given {@link BrooklynClassLoadingContext} */

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java
index cba394c..67e3ab3 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java
@@ -43,6 +43,7 @@ import org.apache.brooklyn.api.mgmt.ExecutionContext;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.mgmt.SubscriptionContext;
 import org.apache.brooklyn.api.mgmt.Task;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.api.mgmt.entitlement.EntitlementManager;
 import org.apache.brooklyn.api.mgmt.ha.HighAvailabilityManager;
 import org.apache.brooklyn.api.mgmt.rebind.RebindManager;
@@ -65,7 +66,6 @@ import org.apache.brooklyn.core.internal.storage.impl.BrooklynStorageImpl;
 import org.apache.brooklyn.core.internal.storage.impl.inmemory.InMemoryDataGridFactory;
 import org.apache.brooklyn.core.location.BasicLocationRegistry;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
 import org.apache.brooklyn.core.mgmt.ha.HighAvailabilityManagerImpl;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java
index 98b5aa2..603f627 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java
@@ -35,6 +35,7 @@ import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.mgmt.Task;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoPersister.LookupContext;
 import org.apache.brooklyn.api.objs.Identifiable;
 import org.apache.brooklyn.api.policy.Policy;
@@ -48,7 +49,6 @@ import org.apache.brooklyn.core.effector.BasicParameterType;
 import org.apache.brooklyn.core.effector.EffectorAndBody;
 import org.apache.brooklyn.core.effector.EffectorTasks.EffectorBodyTaskFactory;
 import org.apache.brooklyn.core.effector.EffectorTasks.EffectorTaskFactory;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContextSequential;
 import org.apache.brooklyn.core.mgmt.classloading.ClassLoaderFromBrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java
index 3655886..5c77753 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java
@@ -35,6 +35,7 @@ import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.entity.Application;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.api.mgmt.ha.ManagementNodeState;
 import org.apache.brooklyn.api.mgmt.rebind.RebindContext;
 import org.apache.brooklyn.api.mgmt.rebind.RebindExceptionHandler;
@@ -71,7 +72,6 @@ import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.core.feed.AbstractFeed;
 import org.apache.brooklyn.core.location.AbstractLocation;
 import org.apache.brooklyn.core.location.internal.LocationInternal;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.internal.BrooklynObjectManagementMode;
 import org.apache.brooklyn.core.mgmt.internal.BrooklynObjectManagerInternal;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java b/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java
index e882d79..dfbe1c1 100644
--- a/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java
+++ b/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java
@@ -32,12 +32,12 @@ import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.location.PortRange;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.objs.BrooklynType;
 import org.apache.brooklyn.api.objs.SpecParameter;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.BasicConfigKey;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.text.StringPredicates;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java b/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
index 7aef313..002c6b5 100644
--- a/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
+++ b/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
@@ -21,11 +21,13 @@ package org.apache.brooklyn.core.plan;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.List;
 import java.util.ServiceLoader;
 
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer;
 import org.apache.brooklyn.core.typereg.TypePlanTransformers;
+import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.exceptions.PropagatedRuntimeException;
 import org.apache.brooklyn.util.guava.Maybe;
@@ -38,14 +40,30 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.collect.ImmutableList;
 
-/** @deprecated since 0.9.0 use {@link TypePlanTransformers} as part of switch to {@link BrooklynTypePlanTransformer} */
+/** @deprecated since 0.9.0 use {@link TypePlanTransformers} as part of switch to {@link BrooklynTypePlanTransformer};
+ * mark transformers as deprecated if there is a preferred corresponding {@link BrooklynTypePlanTransformer} */
 @Deprecated 
 public class PlanToSpecFactory {
     
     private static final Logger log = LoggerFactory.getLogger(PlanToSpecFactory.class);
 
-    private static Collection<PlanToSpecTransformer> getAll() {
-        return ImmutableList.copyOf(ServiceLoader.load(PlanToSpecTransformer.class));
+    private static Collection<PlanToSpecTransformer> getAll(boolean includeDeprecated) {
+        ServiceLoader<PlanToSpecTransformer> loader = ServiceLoader.load(PlanToSpecTransformer.class);
+        return ImmutableList.copyOf(includeDeprecated ? loader : filterDeprecated(loader));
+    }
+
+    private static Iterable<PlanToSpecTransformer> filterDeprecated(ServiceLoader<PlanToSpecTransformer> loader) {
+        List<PlanToSpecTransformer> result = MutableList.of();
+        for (PlanToSpecTransformer t: loader) {
+            if (!isDeprecated(t.getClass())) {
+                result.add(t);
+            }
+        }
+        return result;
+    }
+
+    private static boolean isDeprecated(Class<? extends PlanToSpecTransformer> c) {
+        return (c.getAnnotation(Deprecated.class)!=null);
     }
 
     private static Collection<Class<? extends PlanToSpecTransformer>> OVERRIDE;
@@ -59,18 +77,22 @@ public class PlanToSpecFactory {
     }
 
     public static Collection<PlanToSpecTransformer> all(ManagementContext mgmt) {
+        return all(mgmt, true);
+    }
+    public static Collection<PlanToSpecTransformer> all(ManagementContext mgmt, boolean includeSuperseded) {
         Collection<Class<? extends PlanToSpecTransformer>> override = OVERRIDE;
         Collection<PlanToSpecTransformer> result = new ArrayList<PlanToSpecTransformer>();
         if (override!=null) {
             for (Class<? extends PlanToSpecTransformer> o1: override) {
                 try {
-                    result.add(o1.newInstance());
+                    if (includeSuperseded || !isDeprecated(o1))
+                        result.add(o1.newInstance());
                 } catch (Exception e) {
                     Exceptions.propagate(e);
                 }
             }
         } else {
-            result.addAll(getAll());
+            result.addAll(getAll(includeSuperseded));
         }
         for(PlanToSpecTransformer t : result) {
             t.injectManagementContext(mgmt);
@@ -91,8 +113,8 @@ public class PlanToSpecFactory {
     
     // TODO primitive loading mechanism, just tries all in order; we'll want something better as we get more plan transformers 
     @Beta
-    public static <T> Maybe<T> attemptWithLoaders(ManagementContext mgmt, Function<PlanToSpecTransformer,T> f) {
-        return attemptWithLoaders(all(mgmt), f);
+    public static <T> Maybe<T> attemptWithLoaders(ManagementContext mgmt, boolean includeDeprecated, Function<PlanToSpecTransformer,T> f) {
+        return attemptWithLoaders(all(mgmt, includeDeprecated), f);
     }
     
     public static <T> Maybe<T> attemptWithLoaders(Iterable<PlanToSpecTransformer> transformers, Function<PlanToSpecTransformer,T> f) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/resolve/entity/AbstractEntitySpecResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/resolve/entity/AbstractEntitySpecResolver.java b/core/src/main/java/org/apache/brooklyn/core/resolve/entity/AbstractEntitySpecResolver.java
index ae3ddb2..f3ea9e4 100644
--- a/core/src/main/java/org/apache/brooklyn/core/resolve/entity/AbstractEntitySpecResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/core/resolve/entity/AbstractEntitySpecResolver.java
@@ -22,7 +22,7 @@ import java.util.Set;
 
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.util.text.Strings;
 
 public abstract class AbstractEntitySpecResolver implements EntitySpecResolver {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/resolve/entity/CatalogEntitySpecResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/resolve/entity/CatalogEntitySpecResolver.java b/core/src/main/java/org/apache/brooklyn/core/resolve/entity/CatalogEntitySpecResolver.java
index 70224aa..eba5201 100644
--- a/core/src/main/java/org/apache/brooklyn/core/resolve/entity/CatalogEntitySpecResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/core/resolve/entity/CatalogEntitySpecResolver.java
@@ -21,9 +21,9 @@ package org.apache.brooklyn.core.resolve.entity;
 import java.util.Set;
 
 import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.api.typereg.RegisteredType;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
-import org.apache.brooklyn.core.typereg.RegisteredTypeConstraints;
+import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -65,7 +65,7 @@ public class CatalogEntitySpecResolver extends AbstractEntitySpecResolver {
         boolean recursiveCall = parentEncounteredTypes.contains(item.getSymbolicName());
         if (recursiveCall) return null;
         return mgmt.getTypeRegistry().createSpec(item, 
-            RegisteredTypeConstraints.alreadyVisited(parentEncounteredTypes), 
+            RegisteredTypeLoadingContexts.alreadyEncountered(parentEncounteredTypes), 
             EntitySpec.class);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/resolve/entity/DelegatingEntitySpecResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/resolve/entity/DelegatingEntitySpecResolver.java b/core/src/main/java/org/apache/brooklyn/core/resolve/entity/DelegatingEntitySpecResolver.java
index 415f209..688c4dd 100644
--- a/core/src/main/java/org/apache/brooklyn/core/resolve/entity/DelegatingEntitySpecResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/core/resolve/entity/DelegatingEntitySpecResolver.java
@@ -27,7 +27,7 @@ import java.util.Set;
 import javax.annotation.Nonnull;
 
 import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.exceptions.PropagatedRuntimeException;
 import org.slf4j.Logger;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/resolve/entity/EntitySpecResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/resolve/entity/EntitySpecResolver.java b/core/src/main/java/org/apache/brooklyn/core/resolve/entity/EntitySpecResolver.java
index 83e0fab..9fa9fc2 100644
--- a/core/src/main/java/org/apache/brooklyn/core/resolve/entity/EntitySpecResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/core/resolve/entity/EntitySpecResolver.java
@@ -24,8 +24,8 @@ import java.util.Set;
 import javax.annotation.Nullable;
 
 import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.ManagementContextInjectable;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 
 /**
  * Resolves and decorates {@link EntitySpec entity specifications} based on the {@code serviceType} in a template.

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/resolve/entity/JavaEntitySpecResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/resolve/entity/JavaEntitySpecResolver.java b/core/src/main/java/org/apache/brooklyn/core/resolve/entity/JavaEntitySpecResolver.java
index 047e11d..55cda9f 100644
--- a/core/src/main/java/org/apache/brooklyn/core/resolve/entity/JavaEntitySpecResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/core/resolve/entity/JavaEntitySpecResolver.java
@@ -24,8 +24,8 @@ import java.util.Set;
 import org.apache.brooklyn.api.entity.Application;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.persist.DeserializingClassRenamesProvider;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.javalang.Reflections;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java b/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java
index ae2c610..b4d79c2 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java
@@ -21,7 +21,7 @@ package org.apache.brooklyn.core.typereg;
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.typereg.RegisteredType;
-import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.javalang.JavaClassNames;
 import org.slf4j.Logger;
@@ -72,7 +72,7 @@ public abstract class AbstractTypePlanTransformer implements BrooklynTypePlanTra
     }
     
     @Override
-    public double scoreForType(RegisteredType type, RegisteredTypeConstraint context) {
+    public double scoreForType(RegisteredType type, RegisteredTypeLoadingContext context) {
         if (getFormatCode().equals(type.getPlan().getPlanFormat())) return 1;
         if (type.getPlan().getPlanFormat()==null)
             return scoreForNullFormat(type.getPlan().getPlanData(), type, context);
@@ -80,8 +80,8 @@ public abstract class AbstractTypePlanTransformer implements BrooklynTypePlanTra
             return scoreForNonmatchingNonnullFormat(type.getPlan().getPlanFormat(), type.getPlan().getPlanData(), type, context);
     }
 
-    protected abstract double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeConstraint context);
-    protected abstract double scoreForNonmatchingNonnullFormat(String planFormat, Object planData, RegisteredType type, RegisteredTypeConstraint context);
+    protected abstract double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeLoadingContext context);
+    protected abstract double scoreForNonmatchingNonnullFormat(String planFormat, Object planData, RegisteredType type, RegisteredTypeLoadingContext context);
 
     /** delegates to more specific abstract create methods,
      * and performs common validation and customisation of the items created.
@@ -90,7 +90,7 @@ public abstract class AbstractTypePlanTransformer implements BrooklynTypePlanTra
      * <li> setting the {@link AbstractBrooklynObjectSpec#catalogItemId(String)}
      */
     @Override
-    public Object create(final RegisteredType type, final RegisteredTypeConstraint context) {
+    public Object create(final RegisteredType type, final RegisteredTypeLoadingContext context) {
         try {
             return validate(new RegisteredTypeKindVisitor<Object>() {
                 @Override protected Object visitSpec(RegisteredType type) {
@@ -117,14 +117,14 @@ public abstract class AbstractTypePlanTransformer implements BrooklynTypePlanTra
         }
     }
     
-    protected <T> T validate(T createdObject, RegisteredType type, RegisteredTypeConstraint context) {
+    protected <T> T validate(T createdObject, RegisteredType type, RegisteredTypeLoadingContext context) {
         if (createdObject==null) return null;
         // TODO validation based on the constraint, throw UnsupportedTypePlanException with details if not matched
         return createdObject;
     }
 
-    protected abstract AbstractBrooklynObjectSpec<?,?> createSpec(RegisteredType type, RegisteredTypeConstraint context) throws Exception;
+    protected abstract AbstractBrooklynObjectSpec<?,?> createSpec(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception;
 
-    protected abstract Object createBean(RegisteredType type, RegisteredTypeConstraint context) throws Exception;
+    protected abstract Object createBean(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception;
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
index 0ca8bc7..cfb9f9b 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
@@ -26,7 +26,7 @@ import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry;
 import org.apache.brooklyn.api.typereg.RegisteredType;
-import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
 import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.util.collections.MutableList;
@@ -63,8 +63,8 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
 
     @SuppressWarnings("deprecation")
     @Override
-    public RegisteredType get(String symbolicName, String version, RegisteredTypeConstraint constraint) {
-        if (constraint==null) constraint = RegisteredTypeConstraints.any();
+    public RegisteredType get(String symbolicName, String version, RegisteredTypeLoadingContext constraint) {
+        if (constraint==null) constraint = RegisteredTypeLoadingContexts.any();
         if (version==null) version = BrooklynCatalog.DEFAULT_VERSION;
         
         // TODO lookup here, using constraints
@@ -81,7 +81,7 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
     }
     
     @Override
-    public RegisteredType get(String symbolicNameWithOptionalVersion, RegisteredTypeConstraint constraint) {
+    public RegisteredType get(String symbolicNameWithOptionalVersion, RegisteredTypeLoadingContext constraint) {
         if (CatalogUtils.looksLikeVersionedId(symbolicNameWithOptionalVersion)) {
             String symbolicName = CatalogUtils.getSymbolicNameFromVersionedId(symbolicNameWithOptionalVersion);
             String version = CatalogUtils.getVersionFromVersionedId(symbolicNameWithOptionalVersion);
@@ -93,26 +93,26 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
 
     @Override
     public RegisteredType get(String symbolicNameWithOptionalVersion) {
-        return get(symbolicNameWithOptionalVersion, (RegisteredTypeConstraint)null);
+        return get(symbolicNameWithOptionalVersion, (RegisteredTypeLoadingContext)null);
     }
 
     @SuppressWarnings({ "deprecation", "unchecked", "rawtypes" })
     @Override
-    public <SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpec(RegisteredType type, @Nullable RegisteredTypeConstraint constraint, Class<SpecT> specSuperType) {
+    public <SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpec(RegisteredType type, @Nullable RegisteredTypeLoadingContext constraint, Class<SpecT> specSuperType) {
         Preconditions.checkNotNull(type, "type");
         if (type.getKind()!=RegisteredTypeKind.SPEC) { 
             throw new IllegalStateException("Cannot create spec from type "+type+" (kind "+type.getKind()+")");
         }
         if (constraint!=null) {
-            if (constraint.getKind()!=null && constraint.getKind()!=RegisteredTypeKind.SPEC) {
+            if (constraint.getExpectedKind()!=null && constraint.getExpectedKind()!=RegisteredTypeKind.SPEC) {
                 throw new IllegalStateException("Cannot create spec with constraint "+constraint);
             }
-            if (constraint.getEncounteredTypes().contains(type.getSymbolicName())) {
+            if (constraint.getAlreadyEncounteredTypes().contains(type.getSymbolicName())) {
                 // avoid recursive cycle
                 // TODO implement using java if permitted
             }
         }
-        constraint = RegisteredTypeConstraints.withSpecSuperType(constraint, specSuperType);
+        constraint = RegisteredTypeLoadingContexts.withSpecSuperType(constraint, specSuperType);
 
         Maybe<Object> result = TypePlanTransformers.transform(mgmt, type, constraint);
         if (result.isPresent()) return (SpecT) result.get();
@@ -121,11 +121,12 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
         // TODO remove once all transformers are available in the new style
         CatalogItem item = (CatalogItem) mgmt.getCatalog().getCatalogItem(type.getSymbolicName(), type.getVersion());
         if (item==null) {
-            // if not in catalog (because loading new one?) then throw original
+            // if not in catalog (because loading a new item?) then throw original
+            // (NB: to support any recursive legacy transformers we might have to create a CI; cross that bridge when we come to it)
             result.get();
         }
         try {
-            return (SpecT) BasicBrooklynCatalog.internalCreateSpecWithTransformers(mgmt, item, constraint.getEncounteredTypes());
+            return (SpecT) BasicBrooklynCatalog.internalCreateSpecLegacy(mgmt, item, constraint.getAlreadyEncounteredTypes(), false);
         } catch (Exception e) {
             Exceptions.propagateIfFatal(e);
             // for now, combine this failure with the original
@@ -137,9 +138,41 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
                 // prefer older exception, until the new transformer is the primary pathway
                 throw Exceptions.create("Unable to instantiate "+type, MutableList.of(e, e0));
             }
-            // ultimately swallow the legacy failure, return the original failure (the call below will throw because result is absent)
-//            return (SpecT) result.get();
         }
     }
 
+    @Override
+    public <SpecT extends AbstractBrooklynObjectSpec<?, ?>> SpecT createSpecFromPlan(String planFormat, Object planData, RegisteredTypeLoadingContext optionalConstraint, Class<SpecT> optionalSpecSuperType) {
+        return createSpec(RegisteredTypes.spec(null, null, new BasicTypeImplementationPlan(planFormat, planData), null),
+            optionalConstraint, optionalSpecSuperType);
+    }
+
+    @Override
+    public <T> T createBean(RegisteredType type, RegisteredTypeLoadingContext constraint, Class<T> optionalResultSuperType) {
+        Preconditions.checkNotNull(type, "type");
+        if (type.getKind()!=RegisteredTypeKind.SPEC) { 
+            throw new IllegalStateException("Cannot create spec from type "+type+" (kind "+type.getKind()+")");
+        }
+        if (constraint!=null) {
+            if (constraint.getExpectedKind()!=null && constraint.getExpectedKind()!=RegisteredTypeKind.SPEC) {
+                throw new IllegalStateException("Cannot create spec with constraint "+constraint);
+            }
+            if (constraint.getAlreadyEncounteredTypes().contains(type.getSymbolicName())) {
+                // avoid recursive cycle
+                // TODO implement using java if permitted
+            }
+        }
+        constraint = RegisteredTypeLoadingContexts.withBeanSuperType(constraint, optionalResultSuperType);
+
+        @SuppressWarnings("unchecked")
+        T result = (T) TypePlanTransformers.transform(mgmt, type, constraint).get();
+        return result;
+    }
+
+    @Override
+    public <T> T createBeanFromPlan(String planFormat, Object planData, RegisteredTypeLoadingContext optionalConstraint, Class<T> optionalBeanSuperType) {
+        return createBean(RegisteredTypes.bean(null, null, new BasicTypeImplementationPlan(planFormat, planData), null),
+            optionalConstraint, optionalBeanSuperType);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
index 96c9cb7..224aca2 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
@@ -24,7 +24,7 @@ import java.util.ServiceLoader;
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry;
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
 import org.apache.brooklyn.api.typereg.RegisteredType;
-import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
 import org.apache.brooklyn.core.mgmt.ManagementContextInjectable;
 
 /**
@@ -49,18 +49,18 @@ public interface BrooklynTypePlanTransformer extends ManagementContextInjectable
      * <p>
      * The framework guarantees arguments are nonnull, and that the {@link RegisteredType#getPlan()} is also not-null.
      * However the format in that plan may be null. */
-    double scoreForType(RegisteredType type, RegisteredTypeConstraint context);
+    double scoreForType(RegisteredType type, RegisteredTypeLoadingContext context);
     /** Creates a new instance of the indicated type, or throws if not supported;
      * this method is used by the {@link BrooklynTypeRegistry} when it creates instances,
-     * so implementations must respect the {@link RegisteredTypeKind} semantics and the {@link RegisteredTypeConstraint}
+     * so implementations must respect the {@link RegisteredTypeKind} semantics and the {@link RegisteredTypeLoadingContext}
      * if they return an instance.
      * <p>
-     * The framework guarantees this will only be invoked when {@link #scoreForType(RegisteredType, RegisteredTypeConstraint)} 
+     * The framework guarantees this will only be invoked when {@link #scoreForType(RegisteredType, RegisteredTypeLoadingContext)} 
      * has returned a positive value.
      * <p>
      * Implementations should either return null or throw {@link UnsupportedTypePlanException} 
      * if the {@link RegisteredType#getPlan()} is not supported. */
-    Object create(RegisteredType type, RegisteredTypeConstraint context);
+    Object create(RegisteredType type, RegisteredTypeLoadingContext context);
     
     double scoreForTypeDefinition(String formatCode, Object catalogData);
     List<RegisteredType> createFromTypeDefinition(String formatCode, Object catalogData);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java b/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java
index a84c9f5..5e6877b 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java
@@ -23,7 +23,7 @@ import java.util.List;
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.typereg.RegisteredType;
-import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
 import org.apache.brooklyn.util.text.Identifiers;
 
 /**
@@ -46,7 +46,7 @@ public class JavaClassNameTypePlanTransformer extends AbstractTypePlanTransforme
     }
 
     @Override
-    protected double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeConstraint context) {
+    protected double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeLoadingContext context) {
         if (type.getPlan().getPlanData() instanceof String && 
                 ((String)type.getPlan().getPlanData()).matches(Identifiers.JAVA_BINARY_REGEX)) {
             return 0.1;
@@ -55,22 +55,22 @@ public class JavaClassNameTypePlanTransformer extends AbstractTypePlanTransforme
     }
     
     @Override
-    protected double scoreForNonmatchingNonnullFormat(String planFormat, Object planData, RegisteredType type, RegisteredTypeConstraint context) {
+    protected double scoreForNonmatchingNonnullFormat(String planFormat, Object planData, RegisteredType type, RegisteredTypeLoadingContext context) {
         return 0;
     }
 
     @SuppressWarnings({ "unchecked" })
     @Override
-    protected AbstractBrooklynObjectSpec<?,?> createSpec(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
+    protected AbstractBrooklynObjectSpec<?,?> createSpec(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception {
         return RegisteredTypes.newSpecInstance(mgmt, (Class<? extends BrooklynObject>) getType(type, context));
     }
 
     @Override
-    protected Object createBean(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
+    protected Object createBean(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception {
         return getType(type, context).newInstance();
     }
 
-    private Class<?> getType(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
+    private Class<?> getType(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception {
         return RegisteredTypes.loadActualJavaType((String)type.getPlan().getPlanData(), mgmt, type, context);
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java
deleted file mode 100644
index 5b4c0cf..0000000
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java
+++ /dev/null
@@ -1,206 +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.typereg;
-
-import groovy.xml.Entity;
-
-import java.util.Set;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
-import org.apache.brooklyn.api.objs.BrooklynObject;
-import org.apache.brooklyn.api.objs.BrooklynObjectType;
-import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
-import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
-import org.apache.brooklyn.util.collections.MutableSet;
-import org.apache.brooklyn.util.javalang.JavaClassNames;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.ImmutableSet;
-
-public class RegisteredTypeConstraints {
-
-    private static final Logger log = LoggerFactory.getLogger(RegisteredTypeConstraints.BasicRegisteredTypeConstraint.class);
-    
-    /** Immutable (from caller's perspective) record of a constraint */
-    public final static class BasicRegisteredTypeConstraint implements RegisteredTypeConstraint {
-        @Nullable private RegisteredTypeKind kind;
-        @Nullable private Class<?> javaSuperType;
-        @Nonnull private Set<String> encounteredTypes = ImmutableSet.of();
-        @Nullable BrooklynClassLoadingContext loader;
-        
-        private BasicRegisteredTypeConstraint() {}
-        
-        public BasicRegisteredTypeConstraint(@Nullable RegisteredTypeConstraint source) {
-            if (source==null) return;
-            
-            this.kind = source.getKind();
-            this.javaSuperType = source.getJavaSuperType();
-            this.encounteredTypes = source.getEncounteredTypes();
-            this.loader = (BrooklynClassLoadingContext) source.getLoader();
-        }
-
-        @Override
-        public RegisteredTypeKind getKind() {
-            return kind;
-        }
-        
-        @Override
-        public Class<?> getJavaSuperType() {
-            if (javaSuperType==null) return Object.class;
-            return javaSuperType;
-        }
-
-        @Override
-        public Set<String> getEncounteredTypes() {
-            if (encounteredTypes==null) return ImmutableSet.of();
-            return ImmutableSet.<String>copyOf(encounteredTypes);
-        }
-        
-        @Override
-        public BrooklynClassLoadingContext getLoader() {
-            return loader;
-        }
-        
-        @Override
-        public String toString() {
-            return JavaClassNames.cleanSimpleClassName(this)+"["+kind+","+javaSuperType+","+encounteredTypes+"]";
-        }
-    }
-
-    /** returns a constraint which allows anything */
-    public static RegisteredTypeConstraint any() {
-        return new BasicRegisteredTypeConstraint();
-    }
-
-    public static RegisteredTypeConstraint alreadyVisited(Set<String> encounteredTypeSymbolicNames) {
-        BasicRegisteredTypeConstraint result = new BasicRegisteredTypeConstraint();
-        result.encounteredTypes = encounteredTypeSymbolicNames == null ? ImmutableSet.<String>of() : ImmutableSet.copyOf(encounteredTypeSymbolicNames);
-        return result;
-    }
-    public static RegisteredTypeConstraint alreadyVisited(Set<String> encounteredTypeSymbolicNames, String anotherEncounteredType) {
-        BasicRegisteredTypeConstraint result = new BasicRegisteredTypeConstraint();
-        MutableSet<String> encounteredTypes = MutableSet.copyOf(encounteredTypeSymbolicNames);
-        encounteredTypes.addIfNotNull(anotherEncounteredType);
-        result.encounteredTypes = encounteredTypes.asUnmodifiable();
-        return result;
-    }
-
-    public static RegisteredTypeConstraint alreadyVisited(Set<String> encounteredTypeSymbolicNames, BrooklynClassLoadingContext loader) {
-        return withLoader(alreadyVisited(encounteredTypeSymbolicNames), loader);
-    }
-
-    private static RegisteredTypeConstraint of(RegisteredTypeKind kind, Class<? extends BrooklynObject> javaSuperType) {
-        BasicRegisteredTypeConstraint result = new BasicRegisteredTypeConstraint();
-        result.kind = kind;
-        result.javaSuperType = javaSuperType;
-        return result;
-    }
-
-    public static RegisteredTypeConstraint spec(Class<? extends BrooklynObject> javaSuperType) {
-        return of(RegisteredTypeKind.SPEC, javaSuperType);
-    }
-
-    public static <T extends AbstractBrooklynObjectSpec<?,?>> RegisteredTypeConstraint withSpecSuperType(@Nullable RegisteredTypeConstraint source, @Nullable Class<T> specSuperType) {
-        Class<?> superType = lookupTargetTypeForSpec(specSuperType);
-        BasicRegisteredTypeConstraint constraint = new BasicRegisteredTypeConstraint(source);
-        if (source==null) source = constraint;
-        if (source.getJavaSuperType()==null || source.getJavaSuperType().isAssignableFrom( superType )) {
-            // the constraint was weaker than present; return the new constraint
-            return constraint;
-        }
-        if (superType.isAssignableFrom( source.getJavaSuperType() )) {
-            // the constraint was already for something more specific; ignore what we've inferred here
-            return source;
-        }
-        // trickier situation; the constraint had a type not compatible with the spec type; log a warning and leave alone
-        // (e.g. caller specified some java super type which is not a super or sub of the spec target type;
-        // this may be because the caller specified a Spec as the type supertype, which is wrong;
-        // or they may have specified an interface along a different hierarchy, which we discouraged
-        // as it will make filtering/indexing more complex)
-        log.warn("Ambiguous spec supertypes ("+specSuperType+" for target "+source.getJavaSuperType()+"); "
-            + "it is recommended that any registered type constraint for a spec be compatible with the spec type");
-        return source;
-    }
-    
-    /** given a spec, returns the class of the item it targets, for instance returns {@link Entity} given {@link EntitySpec};
-     * see also {@link #lookupSpecTypeForTarget(Class)} */
-    static <T extends AbstractBrooklynObjectSpec<?,?>> Class<? extends BrooklynObject> lookupTargetTypeForSpec(Class<T> specSuperType) {
-        if (specSuperType==null) return BrooklynObject.class;
-        BrooklynObjectType best = null;
-
-        for (BrooklynObjectType t: BrooklynObjectType.values()) {
-            if (t.getSpecType()==null) continue;
-            if (!t.getSpecType().isAssignableFrom(specSuperType)) continue;
-            // on equality, exit immediately
-            if (t.getSpecType().equals(specSuperType)) return t.getInterfaceType();
-            // else pick which is best
-            if (best==null) { best = t; continue; }
-            // if t is more specific, it is better (handles case when e.g. a Policy is a subclass of Entity)
-            if (best.getSpecType().isAssignableFrom(t.getSpecType())) { best = t; continue; }
-        }
-        if (best==null) {
-            log.warn("Unexpected spec supertype ("+specSuperType+"); treating as any "+BrooklynObject.class, new Throwable("Trace for unexpected spec supertype"));
-            return BrooklynObject.class;
-        }
-        // the spec is more specific, but we're not familiar with it here; return the best
-        return best.getInterfaceType();
-    }
-
-    /** given a {@link BrooklynObject}, returns the spec class which would generate it, for instance returns {@link EntitySpec} given {@link Entity},
-     * or null if not known */
-    static <BO extends BrooklynObject> Class<? extends AbstractBrooklynObjectSpec<?,?>> lookupSpecTypeForTarget(Class<BO> targetSuperType) {
-        if (targetSuperType==null) return null;
-        BrooklynObjectType best = null;
-
-        for (BrooklynObjectType t: BrooklynObjectType.values()) {
-            if (t.getSpecType()==null) continue;
-            if (!t.getInterfaceType().isAssignableFrom(targetSuperType)) continue;
-            // on equality, exit immediately
-            if (t.getInterfaceType().equals(targetSuperType)) return t.getSpecType();
-            // else pick which is best
-            if (best==null) { best = t; continue; }
-            // if t is more specific, it is better (handles case when e.g. a Policy is a subclass of Entity)
-            if (best.getSpecType().isAssignableFrom(t.getSpecType())) { best = t; continue; }
-        }
-        if (best==null) {
-            log.warn("Unexpected target supertype ("+targetSuperType+"); unable to infer spec type");
-            return null;
-        }
-        // the spec is more specific, but we're not familiar with it here; return the best
-        return best.getSpecType();
-    }
-
-    public static RegisteredTypeConstraint loader(BrooklynClassLoadingContext loader) {
-        BasicRegisteredTypeConstraint result = new BasicRegisteredTypeConstraint();
-        result.loader = loader;
-        return result;
-    }
-    
-    public static RegisteredTypeConstraint withLoader(RegisteredTypeConstraint constraint, BrooklynClassLoadingContext loader) {
-        ((BasicRegisteredTypeConstraint)constraint).loader = loader;
-        return constraint;
-    }
-
-}


[12/14] incubator-brooklyn git commit: Merge branch 'master' into type-registry

Posted by he...@apache.org.
Merge branch 'master' into type-registry

Conflicts - CI parameters removed, and TypeRegistry expanded; resolved, except we'll want to add a test for StaticTypePlanTransformer
	api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
	core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
	core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemBuilder.java
	core/src/main/resources/META-INF/services/org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer
	core/src/test/java/org/apache/brooklyn/core/catalog/internal/TestToSpecTransformer.java
	usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/SpecParameterParsingTest.java
	usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/SpecParameterUnwrappingTest.java


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

Branch: refs/heads/master
Commit: 03aacd3e4d64a4d0701e122e0ee6931408c7e07e
Parents: 5dd940b 462e5ea
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Nov 17 15:41:49 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Nov 17 22:50:17 2015 +0000

----------------------------------------------------------------------
 .../brooklyn/api/catalog/CatalogItem.java       |   4 -
 .../apache/brooklyn/api/location/Location.java  |   3 +-
 .../api/mgmt/rebind/RebindExceptionHandler.java |   4 +
 .../brooklyn/api/typereg/RegisteredType.java    |   2 +-
 .../catalog/internal/BasicBrooklynCatalog.java  |  32 --
 .../catalog/internal/CatalogClasspathDo.java    |   8 -
 .../catalog/internal/CatalogItemBuilder.java    |  10 -
 .../core/catalog/internal/CatalogItemDo.java    |   5 -
 .../internal/CatalogItemDtoAbstract.java        |  24 +-
 .../apache/brooklyn/core/config/ConfigKeys.java |   8 +
 .../vault/VaultExternalConfigSupplier.java      |  22 +-
 .../core/entity/BrooklynConfigKeys.java         |  12 +-
 .../core/location/AbstractLocation.java         |   2 -
 .../AggregatingMachineProvisioningLocation.java |   2 -
 .../access/PortForwardManagerClient.java        |   2 -
 .../mgmt/ha/HighAvailabilityManagerImpl.java    |  17 +-
 .../persist/FileBasedStoreObjectAccessor.java   |  10 +-
 .../mgmt/rebind/BasicEntityRebindSupport.java   |   9 +-
 .../mgmt/rebind/RebindExceptionHandlerImpl.java |  27 ++
 .../core/mgmt/rebind/RebindManagerImpl.java     |   8 +
 .../brooklyn/core/sensor/AttributeMap.java      |   5 +-
 .../entity/stock/EffectorStartableImpl.java     |   2 -
 .../byon/SingleMachineProvisioningLocation.java |   1 -
 .../LocalhostMachineProvisioningLocation.java   |   6 +-
 .../brooklyn/location/multi/MultiLocation.java  |   2 -
 .../location/ssh/SshMachineLocation.java        |  83 ++--
 .../util/core/internal/ssh/SshTool.java         |  14 +-
 .../internal/SpecParameterInMetaTest.java       | 200 ----------
 .../catalog/internal/TestToSpecTransformer.java | 120 ------
 .../brooklyn/core/config/ConfigKeysTest.java    |  21 +-
 .../core/location/AbstractLocationTest.java     |   1 -
 .../core/location/LocationExtensionsTest.java   |   2 -
 .../core/location/SimulatedLocation.java        |   2 -
 .../FileBasedStoreObjectAccessorWriterTest.java |  32 +-
 .../core/mgmt/rebind/RebindLocationTest.java    |   8 -
 .../qa/performance/AbstractPerformanceTest.java |  47 ++-
 .../qa/performance/EntityPerformanceTest.java   |  84 ++--
 .../FilePersistencePerformanceTest.java         | 146 ++++---
 .../GroovyYardStickPerformanceTest.groovy       |   7 +-
 .../JavaYardStickPerformanceTest.java           |  35 +-
 .../SubscriptionPerformanceTest.java            |  58 ++-
 .../qa/performance/TaskPerformanceTest.java     |  63 ++-
 .../SshMachineLocationReuseIntegrationTest.java |  11 +-
 .../ssh/SshMachineLocationSshToolTest.java      |  96 +++++
 .../location/ssh/SshMachineLocationTest.java    |  27 +-
 .../core/task/DynamicSequentialTaskTest.java    |  41 +-
 docs/guide/index.md                             |   1 +
 docs/guide/ops/catalog/index.md                 |  25 --
 docs/guide/ops/persistence/index.md             |   2 +
 docs/guide/test/entities.md                     | 143 +++++++
 docs/guide/test/index.md                        |   8 +
 docs/guide/yaml/yaml-reference.md               |  35 +-
 docs/website/documentation/faq.md               |  28 ++
 .../jclouds/JcloudsSshMachineLocation.java      |   1 -
 .../BlobStorePersistencePerformanceTest.java    |  39 +-
 .../jclouds/BailOutJcloudsLocation.java         |   3 -
 .../policy/jclouds/os/CreateUserPolicyTest.java |   2 -
 .../entity/machine/pool/ServerPoolLocation.java |   2 -
 .../brooklyn/entity/java/JavaOptsTest.java      |  17 +-
 .../entity/software/base/EntitySshToolTest.java | 103 +++++
 .../base/SoftwareProcessEntityRebindTest.java   |   2 -
 .../base/SoftwareProcessEntityTest.java         |   2 -
 .../base/lifecycle/StartStopSshDriverTest.java  |   4 +-
 .../mgmt/usage/LocationUsageTrackingTest.java   |   2 -
 .../nginx/NginxRebindWithHaIntegrationTest.java |   9 +-
 usage/all/pom.xml                               |   6 +
 .../brooklyn/catalog/CatalogParametersTest.java | 365 ------------------
 .../catalog/SpecParameterParsingTest.java       | 156 ++++++++
 .../catalog/SpecParameterUnwrappingTest.java    | 379 +++++++++++++++++++
 usage/dist/licensing/overrides.yaml             |  44 ++-
 usage/dist/src/main/license/files/LICENSE       |  92 +++--
 .../assets/js/view/application-add-wizard.js    |  11 +-
 .../org/apache/brooklyn/rest/api/ServerApi.java |   4 +-
 .../rest/transform/CatalogTransformer.java      |   5 +-
 .../rest/resources/UsageResourceTest.java       |   2 -
 usage/test-framework/README.md                  | 109 ------
 usage/test-framework/pom.xml                    |  27 +-
 .../brooklyn/test/framework/AbstractTest.java   |  19 +-
 .../brooklyn/test/framework/BaseTest.java       |  18 +
 .../test/framework/ParallelTestCase.java        |  18 +
 .../test/framework/ParallelTestCaseImpl.java    |  59 ++-
 .../brooklyn/test/framework/TestCase.java       |  18 +
 .../brooklyn/test/framework/TestCaseImpl.java   |  18 +
 .../brooklyn/test/framework/TestEffector.java   |  20 +-
 .../test/framework/TestEffectorImpl.java        |  18 +
 .../brooklyn/test/framework/TestHttpCall.java   |  18 +
 .../test/framework/TestHttpCallImpl.java        |  18 +
 .../brooklyn/test/framework/TestSensor.java     |  23 +-
 .../brooklyn/test/framework/TestSensorImpl.java |  19 +-
 .../test/framework/TestEffectorTest.java        |  19 +
 .../brooklyn/test/framework/TestSensorTest.java |  19 +
 .../test/framework/entity/TestEntity.java       |  19 +
 .../test/framework/entity/TestEntityImpl.java   |  19 +
 .../resources/test-framework-examples/README.md |  19 +
 .../example-catalog-test.bom                    |  18 +
 .../test-framework-examples/example-catalog.bom |  18 +
 .../nginx-test-examples.yml                     |  18 +
 .../testhttpcall-examples.yml                   |  18 +
 .../tomcat-test-examples.yml                    |  18 +
 .../brooklyn/test/PerformanceTestUtils.java     |  82 +---
 .../test/performance/FilePersister.java         |  85 +++++
 .../brooklyn/test/performance/Histogram.java    |  89 +++++
 .../performance/MeasurementResultPersister.java |  29 ++
 .../test/performance/PerformanceMeasurer.java   | 156 ++++++++
 .../performance/PerformanceTestDescriptor.java  | 208 ++++++++++
 .../test/performance/PerformanceTestResult.java |  62 +++
 .../test/performance/PerformanceTestUtils.java  | 107 ++++++
 .../brooklyn/util/JavaGroovyEquivalents.java    |   9 +-
 .../brooklyn/util/exceptions/Exceptions.java    |  29 +-
 .../org/apache/brooklyn/util/io/FileUtil.java   |  18 +-
 .../util/exceptions/ExceptionsTest.java         |  22 ++
 .../brooklyn/util/maven/MavenArtifactTest.java  |  10 +-
 .../brooklyn/util/ssh/IptablesCommandsTest.java |   2 +-
 .../osgi/more-entities-v2-evil-twin/pom.xml     |   2 +-
 .../dependencies/osgi/more-entities-v2/pom.xml  |   4 +-
 .../brooklyn-test-osgi-more-entities_0.2.0.jar  | Bin 15745 -> 15646 bytes
 ...-test-osgi-more-entities_evil-twin_0.2.0.jar | Bin 13922 -> 13811 bytes
 .../TestResourceUnavailableException.java       |   3 +-
 118 files changed, 2888 insertions(+), 1433 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/03aacd3e/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
----------------------------------------------------------------------
diff --cc api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
index fe21daa,610967b..795e393
--- a/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
+++ b/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
@@@ -33,9 -26,6 +32,8 @@@ import org.apache.brooklyn.api.mgmt.reb
  import org.apache.brooklyn.api.mgmt.rebind.Rebindable;
  import org.apache.brooklyn.api.mgmt.rebind.mementos.CatalogItemMemento;
  import org.apache.brooklyn.api.objs.BrooklynObject;
- import org.apache.brooklyn.api.objs.SpecParameter;
 +import org.apache.brooklyn.api.policy.Policy;
 +import org.apache.brooklyn.api.policy.PolicySpec;
  import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl;
  
  import com.google.common.annotations.Beta;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/03aacd3e/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
----------------------------------------------------------------------
diff --cc api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
index ed84179,6ffa09c..2674736
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
@@@ -58,12 -48,9 +58,12 @@@ public interface RegisteredType extend
       * such as if the concrete type is private and callers should know only about a particular public interface,
       * or if precise type details are unavailable and all that is known at creation is some higher level interface/supertype
       * (e.g. this may return {@link Entity} even though the spec points at a specific subclass,
 -     * for instance because the YAML has not yet been parsed or OSGi bundles downloaded). 
 +     * for instance because the YAML has not yet been parsed or OSGi bundles downloaded).
 +     * <p>
 +     * This may include other registered types such as marker interfaces.
       */
 -    Class<?> getJavaType();
 +    @Beta
-     @Nullable Set<Object> getSuperTypes();
++    Set<Object> getSuperTypes();
  
      /**
       * @return True if the item has been deprecated (i.e. its use is discouraged)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/03aacd3e/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
index 1b5d381,0a39725..e3fc287
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
@@@ -37,14 -37,13 +37,12 @@@ import org.apache.brooklyn.api.internal
  import org.apache.brooklyn.api.location.Location;
  import org.apache.brooklyn.api.location.LocationSpec;
  import org.apache.brooklyn.api.mgmt.ManagementContext;
 +import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
- import org.apache.brooklyn.api.objs.SpecParameter;
  import org.apache.brooklyn.core.catalog.CatalogPredicates;
  import org.apache.brooklyn.core.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
  import org.apache.brooklyn.core.location.BasicLocationRegistry;
 -import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
  import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
- import org.apache.brooklyn.core.objs.BasicSpecParameter;
 -import org.apache.brooklyn.core.plan.PlanToSpecFactory;
 -import org.apache.brooklyn.core.plan.PlanToSpecTransformer;
 +import org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer;
  import org.apache.brooklyn.util.collections.MutableList;
  import org.apache.brooklyn.util.collections.MutableMap;
  import org.apache.brooklyn.util.collections.MutableSet;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/03aacd3e/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemBuilder.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemBuilder.java
index 59bc3a9,8918a74..8e23329
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemBuilder.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemBuilder.java
@@@ -20,11 -20,8 +20,9 @@@ package org.apache.brooklyn.core.catalo
  
  import java.util.Collection;
  import java.util.Collections;
- import java.util.List;
  
  import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
 +import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemType;
- import org.apache.brooklyn.api.objs.SpecParameter;
  
  import com.google.common.base.Preconditions;
  
@@@ -118,12 -104,7 +116,7 @@@ public class CatalogItemBuilder<CIConcr
          return this;
      }
  
-     public CatalogItemBuilder<CIConcreteType> parameters(List<SpecParameter<?>> inputs) {
-         dto.setParameters(inputs);
-         return this;
-     }
- 
 -    public CatalogItemBuilder<CatalogItemType> libraries(Collection<CatalogBundle> libraries) {
 +    public CatalogItemBuilder<CIConcreteType> libraries(Collection<CatalogBundle> libraries) {
          dto.setLibraries(libraries);
          return this;
      }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/03aacd3e/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/SpecParameterParsingTest.java
----------------------------------------------------------------------
diff --cc usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/SpecParameterParsingTest.java
index 0000000,022a216..fdf5807
mode 000000,100644..100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/SpecParameterParsingTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/SpecParameterParsingTest.java
@@@ -1,0 -1,140 +1,156 @@@
+ /*
+  * 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.camp.brooklyn.catalog;
+ 
+ import static org.testng.Assert.assertEquals;
+ import static org.testng.Assert.assertFalse;
+ import static org.testng.Assert.assertTrue;
+ 
+ import java.util.List;
+ 
+ import org.apache.brooklyn.api.catalog.CatalogItem;
++import org.apache.brooklyn.api.entity.EntitySpec;
+ import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+ import org.apache.brooklyn.api.objs.SpecParameter;
++import org.apache.brooklyn.api.typereg.RegisteredType;
+ import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
 -import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+ import org.apache.brooklyn.entity.stock.BasicApplication;
+ import org.apache.brooklyn.test.support.TestResourceUnavailableException;
+ import org.apache.brooklyn.util.osgi.OsgiTestResources;
++import org.testng.Assert;
+ import org.testng.annotations.Test;
+ 
++import com.google.common.base.Function;
+ import com.google.common.base.Joiner;
+ import com.google.common.collect.Iterables;
+ import com.google.common.reflect.TypeToken;
+ 
+ public class SpecParameterParsingTest  extends AbstractYamlTest {
 -
++    
+     @Test
+     public void testYamlInputsParsed() {
 -        CatalogItem<?, ?> item = add(
++        String itemId = add(
+                 "brooklyn.catalog:",
+                 "  id: test.inputs",
+                 "  version: 0.0.1",
+                 "  item: ",
+                 "    type: "+ BasicApplication.class.getName(),
+                 "    brooklyn.parameters:",
+                 "    - simple",
+                 "    - name: explicit_name",
+                 "    - name: third_input",
+                 "      type: integer");
 -        AbstractBrooklynObjectSpec<?,?> spec = createSpec(item);
 -        List<SpecParameter<?>> inputs = spec.getParameters();
++        EntitySpec<?> item = mgmt().getTypeRegistry().createSpec(mgmt().getTypeRegistry().get(itemId), null, EntitySpec.class);
++        List<SpecParameter<?>> inputs = item.getParameters();
+         assertEquals(inputs.size(), 3);
+         SpecParameter<?> firstInput = inputs.get(0);
+         assertEquals(firstInput.getLabel(), "simple");
+         assertEquals(firstInput.isPinned(), true);
+         assertEquals(firstInput.getType().getName(), "simple");
+         assertEquals(firstInput.getType().getTypeToken(), TypeToken.of(String.class));
+         
+         SpecParameter<?> secondInput = inputs.get(1);
+         assertEquals(secondInput.getLabel(), "explicit_name");
+         assertEquals(secondInput.isPinned(), true);
+         assertEquals(secondInput.getType().getName(), "explicit_name");
+         assertEquals(secondInput.getType().getTypeToken(), TypeToken.of(String.class));
+         
+         SpecParameter<?> thirdInput = inputs.get(2);
+         assertEquals(thirdInput.getLabel(), "third_input");
+         assertEquals(thirdInput.isPinned(), true);
+         assertEquals(thirdInput.getType().getName(), "third_input");
+         assertEquals(thirdInput.getType().getTypeToken(), TypeToken.of(Integer.class));
+     }
+ 
+     @Test
+     public void testOsgiType() {
+         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+ 
 -        CatalogItem<?, ?> item = add(
++        String itemId = add(
+                 "brooklyn.catalog:",
+                 "  id: test.inputs",
+                 "  version: 0.0.1",
+                 "  libraries:",
+                 "  - classpath://" + OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH,
+                 "  item: ",
+                 "    type: "+ BasicApplication.class.getName(),
+                 "    brooklyn.parameters:",
+                 "    - name: simple",
+                 "      type: " + OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_ENTITY);
 -        AbstractBrooklynObjectSpec<?,?> spec = createSpec(item);
++        AbstractBrooklynObjectSpec<?,?> spec = createSpec(itemId);
+         List<SpecParameter<?>> inputs = spec.getParameters();
+         assertEquals(inputs.size(), 1);
+         SpecParameter<?> firstInput = inputs.get(0);
+         assertEquals(firstInput.getLabel(), "simple");
+         assertTrue(firstInput.isPinned());
+         assertEquals(firstInput.getType().getName(), "simple");
+         assertEquals(firstInput.getType().getTypeToken().getRawType().getName(), OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_ENTITY);
+     }
+ 
+     @Test
+     public void testOsgiClassScanned() {
+         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_V2_PATH);
+ 
+         addMulti("brooklyn.catalog:",
+             "    items:",
+             "    - scanJavaAnnotations: true",
+             "      version: 2.0.test_java",
+             "      libraries:",
+             "      - classpath://" + OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH,
+             "      - classpath://" + OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_V2_PATH);
+ 
 -        CatalogItem<?, ?> item = CatalogUtils.getCatalogItemOptionalVersion(mgmt(), OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
++        RegisteredType item = mgmt().getTypeRegistry().get(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
+         assertEquals(item.getVersion(), "2.0.test_java");
+         assertEquals(item.getLibraries().size(), 2);
+         AbstractBrooklynObjectSpec<?,?> spec = createSpec(item);
+         List<SpecParameter<?>> inputs = spec.getParameters();
++        if (inputs.isEmpty()) Assert.fail("no inputs (if you're in the IDE, mvn clean install may need to be run to rebuild osgi test JARs)");
++        assertEquals(inputs.size(), 1);
+         SpecParameter<?> input = inputs.get(0);
+         assertEquals(input.getLabel(), "more_config");
+         assertFalse(input.isPinned());
+         assertEquals(input.getType().getName(), "more_config");
+     }
+ 
 -    private CatalogItem<?,?> add(String... def) {
++    private String add(String... def) {
+         return Iterables.getOnlyElement(addMulti(def));
+     }
+ 
 -    private Iterable<? extends CatalogItem<?, ?>> addMulti(String... def) {
 -        return catalog.addItems(Joiner.on('\n').join(def));
++    private Iterable<String> addMulti(String... def) {
++        return Iterables.transform(catalog.addItems(Joiner.on('\n').join(def)),
++            new Function<CatalogItem<?,?>, String>() {
++                @Override
++                public String apply(CatalogItem<?, ?> input) {
++                    return input.getId();
++                }
++            });
+     }
+ 
 -    @SuppressWarnings({"unchecked", "rawtypes"})
 -    private AbstractBrooklynObjectSpec<?, ?> createSpec(CatalogItem<?, ?> item) {
 -        return (AbstractBrooklynObjectSpec<?,?>) catalog.createSpec((CatalogItem)item);
++    private AbstractBrooklynObjectSpec<?, ?> createSpec(String itemId) {
++        RegisteredType item = mgmt().getTypeRegistry().get(itemId);
++        Assert.assertNotNull(item, "Could not load: "+itemId);
++        return createSpec(item);
++    }
++    
++    private AbstractBrooklynObjectSpec<?, ?> createSpec(RegisteredType item) {
++        return mgmt().getTypeRegistry().createSpec(item, null, EntitySpec.class);
+     }
+ 
+ }


[04/14] incubator-brooklyn git commit: Big refactoring of new type registry code

Posted by he...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java
new file mode 100644
index 0000000..22ea294
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java
@@ -0,0 +1,234 @@
+/*
+ * 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.typereg;
+
+import groovy.xml.Entity;
+
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.api.objs.BrooklynObjectType;
+import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
+import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
+import org.apache.brooklyn.util.collections.MutableSet;
+import org.apache.brooklyn.util.javalang.JavaClassNames;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableSet;
+
+public class RegisteredTypeLoadingContexts {
+
+    private static final Logger log = LoggerFactory.getLogger(RegisteredTypeLoadingContexts.BasicRegisteredTypeLoadingContext.class);
+    
+    /** Immutable (from caller's perspective) record of a constraint */
+    public final static class BasicRegisteredTypeLoadingContext implements RegisteredTypeLoadingContext {
+        @Nullable private RegisteredTypeKind kind;
+        @Nullable private Class<?> expectedSuperType;
+        @Nonnull private Set<String> encounteredTypes = ImmutableSet.of();
+        @Nullable BrooklynClassLoadingContext loader;
+        
+        private BasicRegisteredTypeLoadingContext() {}
+        
+        public BasicRegisteredTypeLoadingContext(@Nullable RegisteredTypeLoadingContext source) {
+            if (source==null) return;
+            
+            this.kind = source.getExpectedKind();
+            this.expectedSuperType = source.getExpectedJavaSuperType();
+            this.encounteredTypes = source.getAlreadyEncounteredTypes();
+            this.loader = (BrooklynClassLoadingContext) source.getLoader();
+        }
+
+        @Override
+        public RegisteredTypeKind getExpectedKind() {
+            return kind;
+        }
+        
+        @Override
+        public Class<?> getExpectedJavaSuperType() {
+            if (expectedSuperType==null) return Object.class;
+            return expectedSuperType;
+        }
+
+        @Override
+        public Set<String> getAlreadyEncounteredTypes() {
+            if (encounteredTypes==null) return ImmutableSet.of();
+            return ImmutableSet.<String>copyOf(encounteredTypes);
+        }
+        
+        @Override
+        public BrooklynClassLoadingContext getLoader() {
+            return loader;
+        }
+        
+        @Override
+        public String toString() {
+            return JavaClassNames.cleanSimpleClassName(this)+"["+kind+","+expectedSuperType+","+encounteredTypes+"]";
+        }
+    }
+
+    /** returns a constraint which allows anything */
+    public static RegisteredTypeLoadingContext any() {
+        return new BasicRegisteredTypeLoadingContext();
+    }
+
+    public static RegisteredTypeLoadingContext alreadyEncountered(Set<String> encounteredTypeSymbolicNames) {
+        BasicRegisteredTypeLoadingContext result = new BasicRegisteredTypeLoadingContext();
+        result.encounteredTypes = encounteredTypeSymbolicNames == null ? ImmutableSet.<String>of() : ImmutableSet.copyOf(encounteredTypeSymbolicNames);
+        return result;
+    }
+    public static RegisteredTypeLoadingContext alreadyEncountered(Set<String> encounteredTypeSymbolicNames, String anotherEncounteredType) {
+        BasicRegisteredTypeLoadingContext result = new BasicRegisteredTypeLoadingContext();
+        MutableSet<String> encounteredTypes = MutableSet.copyOf(encounteredTypeSymbolicNames);
+        encounteredTypes.addIfNotNull(anotherEncounteredType);
+        result.encounteredTypes = encounteredTypes.asUnmodifiable();
+        return result;
+    }
+
+    public static RegisteredTypeLoadingContext loaderAlreadyEncountered(BrooklynClassLoadingContext loader, Set<String> encounteredTypeSymbolicNames) {
+        return loaderAlreadyEncountered(loader, encounteredTypeSymbolicNames, null);
+    }
+    public static RegisteredTypeLoadingContext loaderAlreadyEncountered(BrooklynClassLoadingContext loader, Set<String> encounteredTypeSymbolicNames, String anotherEncounteredType) {
+        return withLoader(alreadyEncountered(encounteredTypeSymbolicNames, anotherEncounteredType), loader);
+    }
+
+    private static RegisteredTypeLoadingContext of(RegisteredTypeKind kind, Class<?> javaSuperType) {
+        BasicRegisteredTypeLoadingContext result = new BasicRegisteredTypeLoadingContext();
+        result.kind = kind;
+        result.expectedSuperType = javaSuperType;
+        return result;
+    }
+
+    public static RegisteredTypeLoadingContext bean(Class<?> javaSuperType) {
+        return of(RegisteredTypeKind.BEAN, javaSuperType);
+    }
+
+    public static RegisteredTypeLoadingContext spec(Class<? extends BrooklynObject> javaSuperType) {
+        return of(RegisteredTypeKind.SPEC, javaSuperType);
+    }
+    
+    public static <T> RegisteredTypeLoadingContext withBeanSuperType(@Nullable RegisteredTypeLoadingContext source, @Nullable Class<T> beanSuperType) {
+        Class<T> superType = beanSuperType;
+        BasicRegisteredTypeLoadingContext constraint = new BasicRegisteredTypeLoadingContext(source);
+        if (source==null) source = constraint;
+        if (superType==null) return source;
+        if (source.getExpectedJavaSuperType()==null || source.getExpectedJavaSuperType().isAssignableFrom( superType )) {
+            // the constraint was weaker than present; return the new constraint
+            return constraint;
+        }
+        if (superType.isAssignableFrom( source.getExpectedJavaSuperType() )) {
+            // the constraint was already for something more specific; ignore what we've inferred here
+            return source;
+        }
+        log.warn("Ambiguous bean supertypes ("+beanSuperType+" for target "+source.getExpectedJavaSuperType()+"); "
+            + "it is recommended that any registered type constraint for a spec be compatible with the spec type");
+        return source;
+    }
+
+    /** Takes a Spec java type and adds an expected java type to the {@link RegisteredTypeLoadingContext} */
+    public static <T extends AbstractBrooklynObjectSpec<?,?>> RegisteredTypeLoadingContext withSpecSuperType(@Nullable RegisteredTypeLoadingContext source, @Nullable Class<T> specSuperType) {
+        Class<?> superType = lookupTargetTypeForSpec(specSuperType);
+        BasicRegisteredTypeLoadingContext constraint = new BasicRegisteredTypeLoadingContext(source);
+        if (source==null) source = constraint;
+        if (superType==null) return source;
+        if (source.getExpectedJavaSuperType()==null || source.getExpectedJavaSuperType().isAssignableFrom( superType )) {
+            // the constraint was weaker than present; return the new constraint
+            return constraint;
+        }
+        if (superType.isAssignableFrom( source.getExpectedJavaSuperType() )) {
+            // the constraint was already for something more specific; ignore what we've inferred here
+            return source;
+        }
+        // trickier situation; the constraint had a type not compatible with the spec type; log a warning and leave alone
+        // (e.g. caller specified some java super type which is not a super or sub of the spec target type;
+        // this may be because the caller specified a Spec as the type supertype, which is wrong;
+        // or they may have specified an interface along a different hierarchy, which we discouraged
+        // as it will make filtering/indexing more complex)
+        log.warn("Ambiguous spec supertypes ("+specSuperType+" for target "+source.getExpectedJavaSuperType()+"); "
+            + "it is recommended that any registered type constraint for a spec be compatible with the spec type");
+        return source;
+    }
+        
+    /** given a spec, returns the class of the item it targets, for instance returns {@link Entity} given {@link EntitySpec};
+     * see also {@link #lookupSpecTypeForTarget(Class)} */
+    static <T extends AbstractBrooklynObjectSpec<?,?>> Class<? extends BrooklynObject> lookupTargetTypeForSpec(Class<T> specSuperType) {
+        if (specSuperType==null) return BrooklynObject.class;
+        BrooklynObjectType best = null;
+
+        for (BrooklynObjectType t: BrooklynObjectType.values()) {
+            if (t.getSpecType()==null) continue;
+            if (!t.getSpecType().isAssignableFrom(specSuperType)) continue;
+            // on equality, exit immediately
+            if (t.getSpecType().equals(specSuperType)) return t.getInterfaceType();
+            // else pick which is best
+            if (best==null) { best = t; continue; }
+            // if t is more specific, it is better (handles case when e.g. a Policy is a subclass of Entity)
+            if (best.getSpecType().isAssignableFrom(t.getSpecType())) { best = t; continue; }
+        }
+        if (best==null) {
+            log.warn("Unexpected spec supertype ("+specSuperType+"); treating as any "+BrooklynObject.class, new Throwable("Trace for unexpected spec supertype"));
+            return BrooklynObject.class;
+        }
+        // the spec is more specific, but we're not familiar with it here; return the best
+        return best.getInterfaceType();
+    }
+
+    /** given a {@link BrooklynObject}, returns the spec class which would generate it, for instance returns {@link EntitySpec} given {@link Entity},
+     * or null if not known */
+    static <BO extends BrooklynObject> Class<? extends AbstractBrooklynObjectSpec<?,?>> lookupSpecTypeForTarget(Class<BO> targetSuperType) {
+        if (targetSuperType==null) return null;
+        BrooklynObjectType best = null;
+
+        for (BrooklynObjectType t: BrooklynObjectType.values()) {
+            if (t.getSpecType()==null) continue;
+            if (!t.getInterfaceType().isAssignableFrom(targetSuperType)) continue;
+            // on equality, exit immediately
+            if (t.getInterfaceType().equals(targetSuperType)) return t.getSpecType();
+            // else pick which is best
+            if (best==null) { best = t; continue; }
+            // if t is more specific, it is better (handles case when e.g. a Policy is a subclass of Entity)
+            if (best.getSpecType().isAssignableFrom(t.getSpecType())) { best = t; continue; }
+        }
+        if (best==null) {
+            log.warn("Unexpected target supertype ("+targetSuperType+"); unable to infer spec type");
+            return null;
+        }
+        // the spec is more specific, but we're not familiar with it here; return the best
+        return best.getSpecType();
+    }
+
+    public static RegisteredTypeLoadingContext loader(BrooklynClassLoadingContext loader) {
+        BasicRegisteredTypeLoadingContext result = new BasicRegisteredTypeLoadingContext();
+        result.loader = loader;
+        return result;
+    }
+    
+    public static RegisteredTypeLoadingContext withLoader(RegisteredTypeLoadingContext constraint, BrooklynClassLoadingContext loader) {
+        BasicRegisteredTypeLoadingContext result = new BasicRegisteredTypeLoadingContext(constraint);
+        result.loader = loader;
+        return result;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
index 0ebbdcd..a4a0460 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
@@ -32,7 +32,7 @@ import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
 import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.api.typereg.RegisteredType.TypeImplementationPlan;
-import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.config.ConfigKeys;
@@ -112,7 +112,7 @@ public class RegisteredTypes {
      * @param mgmt */
     @Beta
     // TODO should this be on the AbstractTypePlanTransformer ?
-    public static Class<?> loadActualJavaType(String javaTypeName, ManagementContext mgmt, RegisteredType type, RegisteredTypeConstraint constraint) throws Exception {
+    public static Class<?> loadActualJavaType(String javaTypeName, ManagementContext mgmt, RegisteredType type, RegisteredTypeLoadingContext constraint) throws Exception {
         Class<?> result = ((BasicRegisteredType)type).getCache().get(ACTUAL_JAVA_TYPE);
         if (result!=null) return result;
         
@@ -152,12 +152,12 @@ public class RegisteredTypes {
     }
 
     /** returns an implementation of the spec class corresponding to the given target type;
-     * for use in {@link BrooklynTypePlanTransformer#create(RegisteredType, RegisteredTypeConstraint)} 
+     * for use in {@link BrooklynTypePlanTransformer#create(RegisteredType, RegisteredTypeLoadingContext)} 
      * implementations when dealing with a spec; returns null if none found
      * @param mgmt */
     @Beta
     public static AbstractBrooklynObjectSpec<?,?> newSpecInstance(ManagementContext mgmt, Class<? extends BrooklynObject> targetType) throws Exception {
-        Class<? extends AbstractBrooklynObjectSpec<?, ?>> specType = RegisteredTypeConstraints.lookupSpecTypeForTarget(targetType);
+        Class<? extends AbstractBrooklynObjectSpec<?, ?>> specType = RegisteredTypeLoadingContexts.lookupSpecTypeForTarget(targetType);
         if (specType==null) return null;
         Method createMethod = specType.getMethod("create", Class.class);
         return (AbstractBrooklynObjectSpec<?, ?>) createMethod.invoke(null, targetType);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java b/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java
index b2b496e..a082a31 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java
@@ -30,7 +30,7 @@ import java.util.TreeMap;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry;
 import org.apache.brooklyn.api.typereg.RegisteredType;
-import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.exceptions.PropagatedRuntimeException;
@@ -88,7 +88,7 @@ public class TypePlanTransformers {
     /** returns a list of {@link BrooklynTypePlanTransformer} instances for this {@link ManagementContext}
      * which may be able to handle the given plan; the list is sorted with highest-score transformer first */
     @Beta
-    public static List<BrooklynTypePlanTransformer> forType(ManagementContext mgmt, RegisteredType type, RegisteredTypeConstraint constraint) {
+    public static List<BrooklynTypePlanTransformer> forType(ManagementContext mgmt, RegisteredType type, RegisteredTypeLoadingContext constraint) {
         Multimap<Double,BrooklynTypePlanTransformer> byScoreMulti = ArrayListMultimap.create(); 
         Collection<BrooklynTypePlanTransformer> transformers = all(mgmt);
         for (BrooklynTypePlanTransformer transformer : transformers) {
@@ -105,7 +105,7 @@ public class TypePlanTransformers {
      * <p>
      * callers should generally use one of the create methods on {@link BrooklynTypeRegistry} rather than using this method directly. */
     @Beta
-    public static Maybe<Object> transform(ManagementContext mgmt, RegisteredType type, RegisteredTypeConstraint constraint) {
+    public static Maybe<Object> transform(ManagementContext mgmt, RegisteredType type, RegisteredTypeLoadingContext constraint) {
         if (type==null) return Maybe.absent("type cannot be null");
         if (type.getPlan()==null) return Maybe.absent("type plan cannot be null, when instantiating "+type);
         

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/main/java/org/apache/brooklyn/util/core/ResourceUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/ResourceUtils.java b/core/src/main/java/org/apache/brooklyn/util/core/ResourceUtils.java
index 35bdb68..d19592f 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/ResourceUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/ResourceUtils.java
@@ -38,10 +38,10 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
 import org.apache.brooklyn.core.internal.BrooklynInitialization;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
@@ -68,6 +68,7 @@ import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.base.Throwables;
 import com.google.common.collect.Lists;
+
 import org.apache.brooklyn.util.osgi.OsgiUtils;
 
 public class ResourceUtils {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/core/src/test/java/org/apache/brooklyn/core/objs/BasicSpecParameterFromListTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/objs/BasicSpecParameterFromListTest.java b/core/src/test/java/org/apache/brooklyn/core/objs/BasicSpecParameterFromListTest.java
index 0f48dad..9f2eaaf 100644
--- a/core/src/test/java/org/apache/brooklyn/core/objs/BasicSpecParameterFromListTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/objs/BasicSpecParameterFromListTest.java
@@ -25,9 +25,9 @@ import static org.testng.Assert.assertTrue;
 import java.util.List;
 
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.api.objs.SpecParameter;
 import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
 import org.apache.brooklyn.core.objs.BasicSpecParameter;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/software/base/src/main/java/org/apache/brooklyn/entity/resolve/ChefEntitySpecResolver.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/resolve/ChefEntitySpecResolver.java b/software/base/src/main/java/org/apache/brooklyn/entity/resolve/ChefEntitySpecResolver.java
index 07d4342..5c513e0 100644
--- a/software/base/src/main/java/org/apache/brooklyn/entity/resolve/ChefEntitySpecResolver.java
+++ b/software/base/src/main/java/org/apache/brooklyn/entity/resolve/ChefEntitySpecResolver.java
@@ -21,7 +21,7 @@ package org.apache.brooklyn.entity.resolve;
 import java.util.Set;
 
 import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.resolve.entity.AbstractEntitySpecResolver;
 import org.apache.brooklyn.entity.chef.ChefConfig;
 import org.apache.brooklyn.entity.chef.ChefEntity;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/software/base/src/main/java/org/apache/brooklyn/entity/resolve/HardcodedCatalogEntitySpecResolver.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/resolve/HardcodedCatalogEntitySpecResolver.java b/software/base/src/main/java/org/apache/brooklyn/entity/resolve/HardcodedCatalogEntitySpecResolver.java
index 5541996..7d48643 100644
--- a/software/base/src/main/java/org/apache/brooklyn/entity/resolve/HardcodedCatalogEntitySpecResolver.java
+++ b/software/base/src/main/java/org/apache/brooklyn/entity/resolve/HardcodedCatalogEntitySpecResolver.java
@@ -23,7 +23,7 @@ import java.util.Set;
 
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.resolve.entity.AbstractEntitySpecResolver;
 import org.apache.brooklyn.entity.brooklynnode.BrooklynNode;
 import org.apache.brooklyn.entity.group.DynamicCluster;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
index 8fb7164..87bd381 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
@@ -23,10 +23,10 @@ import java.util.Set;
 
 import org.apache.brooklyn.api.entity.Application;
 import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.camp.CampPlatform;
 import org.apache.brooklyn.camp.spi.AssemblyTemplate;
 import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 
 public interface AssemblyTemplateSpecInstantiator extends AssemblyTemplateInstantiator {
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
index 5070777..6c7a479 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
@@ -24,6 +24,7 @@ import java.util.Set;
 import org.apache.brooklyn.api.entity.Application;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.camp.CampPlatform;
 import org.apache.brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
 import org.apache.brooklyn.camp.spi.Assembly;
@@ -33,7 +34,6 @@ import org.apache.brooklyn.camp.spi.collection.ResolvableLink;
 import org.apache.brooklyn.core.mgmt.EntityManagementUtils;
 import org.apache.brooklyn.core.mgmt.EntityManagementUtils.CreationResult;
 import org.apache.brooklyn.core.mgmt.HasBrooklynManagementContext;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
 import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.flags.TypeCoercions;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
index 69c9109..5d078a3 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
@@ -33,6 +33,7 @@ import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
 import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
@@ -49,7 +50,6 @@ import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.mgmt.BrooklynTags;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
 import org.apache.brooklyn.core.mgmt.ManagementContextInjectable;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
 import org.apache.brooklyn.core.resolve.entity.EntitySpecResolver;
 import org.apache.brooklyn.util.collections.MutableList;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
index efe2d9d..9458046 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
@@ -33,7 +33,7 @@ import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
 import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator.InstantiatorFromKey;
 import org.apache.brooklyn.core.objs.BasicSpecParameter;
-import org.apache.brooklyn.core.typereg.RegisteredTypeConstraints;
+import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 
@@ -114,7 +114,7 @@ public abstract class BrooklynEntityDecorationResolver<DT> {
             String policyType = decoLoader.getTypeName().get();
             ManagementContext mgmt = instantiator.loader.getManagementContext();
             
-            RegisteredType item = mgmt.getTypeRegistry().get(policyType, RegisteredTypeConstraints.spec(Policy.class));
+            RegisteredType item = mgmt.getTypeRegistry().get(policyType, RegisteredTypeLoadingContexts.spec(Policy.class));
             PolicySpec<?> spec;
             if (item!=null) {
                 spec = mgmt.getTypeRegistry().createSpec(item, null, PolicySpec.class);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
index 07a8267..91a490a 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
@@ -22,6 +22,7 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
 import org.apache.brooklyn.camp.spi.PlatformComponentTemplate;
 import org.apache.brooklyn.camp.spi.PlatformComponentTemplate.Builder;
@@ -29,7 +30,6 @@ import org.apache.brooklyn.camp.spi.pdp.AssemblyTemplateConstructor;
 import org.apache.brooklyn.camp.spi.pdp.Service;
 import org.apache.brooklyn.camp.spi.resolve.PdpMatcher;
 import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.text.Strings;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
index b1b5876..01bfaa2 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
@@ -23,8 +23,8 @@ import java.util.Map;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.exceptions.Exceptions;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampInternalUtils.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampInternalUtils.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampInternalUtils.java
index abd32c6..9096168 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampInternalUtils.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampInternalUtils.java
@@ -32,6 +32,7 @@ import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.location.LocationSpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.api.objs.SpecParameter;
 import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.api.policy.PolicySpec;
@@ -45,7 +46,6 @@ import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
 import org.apache.brooklyn.camp.spi.pdp.DeploymentPlan;
 import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
 import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.objs.BasicSpecParameter;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal.ConfigurationSupportInternal;
 import org.apache.brooklyn.entity.stock.BasicApplicationImpl;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
index 1fc6eaf..3070280 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
@@ -26,16 +26,16 @@ import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.api.typereg.RegisteredType;
-import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
 import org.apache.brooklyn.camp.CampPlatform;
 import org.apache.brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
 import org.apache.brooklyn.camp.spi.AssemblyTemplate;
 import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.mgmt.EntityManagementUtils;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.util.text.Strings;
 
@@ -45,7 +45,7 @@ class CampResolver {
 
     private ManagementContext mgmt;
     private RegisteredType type;
-    private RegisteredTypeConstraint context;
+    private RegisteredTypeLoadingContext context;
 
     /** whether to allow parsing of the 'full' syntax for applications,
      * where items are wrapped in a "services:" block, and if the wrapper is an application,
@@ -62,18 +62,17 @@ class CampResolver {
      * i.e. not wrapped in any "services:" or "brooklyn.{locations,policies}" block */
     boolean allowTypeSyntax = true;
 
-    public CampResolver(ManagementContext mgmt, RegisteredType type, RegisteredTypeConstraint context) {
+    public CampResolver(ManagementContext mgmt, RegisteredType type, RegisteredTypeLoadingContext context) {
         this.mgmt = mgmt;
         this.type = type;
         this.context = context;
     }
 
     public AbstractBrooklynObjectSpec<?, ?> createSpec() {
-        // TODO modern approach
+        // TODO new-style approach:
         //            AbstractBrooklynObjectSpec<?, ?> spec = RegisteredTypes.newSpecInstance(mgmt, /* 'type' key */);
         //            spec.configure(keysAndValues);
-        return createSpecFromFull(mgmt, type, 
-            context.getEncounteredTypes(), (BrooklynClassLoadingContext) context.getLoader());
+        return createSpecFromFull(mgmt, type, context.getAlreadyEncounteredTypes(), context.getLoader());
     }
 
     static AbstractBrooklynObjectSpec<?, ?> createSpecFromFull(ManagementContext mgmt, RegisteredType item, Set<String> parentEncounteredTypes, BrooklynClassLoadingContext loaderO) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
index 39959e0..f2b224c 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
@@ -25,12 +25,12 @@ import org.apache.brooklyn.api.entity.Application;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.camp.CampPlatform;
 import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
 import org.apache.brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
 import org.apache.brooklyn.camp.spi.AssemblyTemplate;
 import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
 import org.apache.brooklyn.core.plan.PlanNotRecognizedException;
 import org.apache.brooklyn.core.plan.PlanToSpecTransformer;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
index dd8a0d5..4793a59 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
@@ -24,7 +24,7 @@ import java.util.Map;
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.api.typereg.RegisteredType.TypeImplementationPlan;
-import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
 import org.apache.brooklyn.core.typereg.AbstractCustomImplementationPlan;
 import org.apache.brooklyn.core.typereg.AbstractTypePlanTransformer;
 import org.apache.brooklyn.core.typereg.BasicTypeImplementationPlan;
@@ -37,12 +37,14 @@ public class CampTypePlanTransformer extends AbstractTypePlanTransformer {
 
     private static final List<String> FORMATS = ImmutableList.of("brooklyn-camp", "camp", "brooklyn");
     
+    public static final String FORMAT = FORMATS.get(0);
+    
     public CampTypePlanTransformer() {
-        super(FORMATS.get(0), "OASIS CAMP / Brooklyn", "The Apache Brooklyn implementation of the OASIS CAMP blueprint plan format and extensions");
+        super(FORMAT, "OASIS CAMP / Brooklyn", "The Apache Brooklyn implementation of the OASIS CAMP blueprint plan format and extensions");
     }
 
     @Override
-    protected double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeConstraint context) {
+    protected double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeLoadingContext context) {
         Maybe<Map<Object, Object>> plan = RegisteredTypes.getAsYamlMap(planData);
         if (plan.isAbsent()) return 0;
         if (plan.get().containsKey("services")) return 0.8;
@@ -50,19 +52,19 @@ public class CampTypePlanTransformer extends AbstractTypePlanTransformer {
     }
 
     @Override
-    protected double scoreForNonmatchingNonnullFormat(String planFormat, Object planData, RegisteredType type, RegisteredTypeConstraint context) {
+    protected double scoreForNonmatchingNonnullFormat(String planFormat, Object planData, RegisteredType type, RegisteredTypeLoadingContext context) {
         if (FORMATS.contains(planFormat.toLowerCase())) return 0.9;
         return 0;
     }
 
     @Override
-    protected AbstractBrooklynObjectSpec<?, ?> createSpec(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
+    protected AbstractBrooklynObjectSpec<?, ?> createSpec(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception {
         // TODO cache
         return new CampResolver(mgmt, type, context).createSpec();
     }
 
     @Override
-    protected Object createBean(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
+    protected Object createBean(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception {
         // beans not supported by this?
         return null;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolverAdaptor.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolverAdaptor.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolverAdaptor.java
index 703a7cf..d4cf6e9 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolverAdaptor.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolverAdaptor.java
@@ -22,8 +22,8 @@ import java.util.Set;
 
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateResolver;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.resolve.entity.AbstractEntitySpecResolver;
 import org.apache.brooklyn.core.resolve.entity.EntitySpecResolver;
 import org.slf4j.Logger;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java
index 1e54f76..3799418 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java
@@ -23,11 +23,11 @@ import java.util.Set;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
 import org.apache.brooklyn.camp.brooklyn.spi.creation.CampTypePlanTransformer;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.resolve.entity.EntitySpecResolver;
-import org.apache.brooklyn.core.typereg.RegisteredTypeConstraints;
+import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.ResourceUtils;
@@ -63,14 +63,13 @@ public class UrlServiceSpecResolver implements EntitySpecResolver {
         if (encounteredTypes.contains(type)) {
             throw new IllegalStateException("URL " + type + " is self referential.");
         }
-        encounteredTypes = MutableSet.<String>builder().addAll(encounteredTypes).add(type).build().asUnmodifiable();
         
         // Referenced specs are expected to be CAMP format as well.
         // XXX somehow specify to allow full syntax for services
-        EntitySpec<?> item = loader.getManagementContext().getTypeRegistry().createSpec(
-            RegisteredTypes.spec(null, null, 
-                new CampTypePlanTransformer.CampTypeImplementationPlan(yaml), Entity.class), 
-            RegisteredTypeConstraints.alreadyVisited(encounteredTypes, loader), 
+        EntitySpec<?> item = loader.getManagementContext().getTypeRegistry().createSpecFromPlan(
+            CampTypePlanTransformer.FORMAT,
+            yaml,
+            RegisteredTypeLoadingContexts.loaderAlreadyEncountered(loader, encounteredTypes, type), 
             EntitySpec.class);
         return item;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
index c13e004..15df062 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
@@ -29,6 +29,7 @@ import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.camp.brooklyn.spi.creation.CampTypePlanTransformer;
 import org.apache.brooklyn.camp.brooklyn.spi.creation.CampTypePlanTransformer.CampTypeImplementationPlan;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.entity.Entities;
@@ -37,7 +38,7 @@ import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
 import org.apache.brooklyn.core.mgmt.EntityManagementUtils;
 import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
-import org.apache.brooklyn.core.typereg.RegisteredTypeConstraints;
+import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.ResourceUtils;
@@ -117,9 +118,8 @@ public abstract class AbstractYamlTest {
     }
 
     protected Entity createAndStartApplication(Reader input) throws Exception {
-        RegisteredType type = RegisteredTypes.spec(null, null, new CampTypeImplementationPlan(Streams.readFully(input)), Application.class);
         EntitySpec<?> spec = 
-            mgmt().getTypeRegistry().createSpec(type, RegisteredTypeConstraints.spec(Application.class), EntitySpec.class);
+            mgmt().getTypeRegistry().createSpecFromPlan(CampTypePlanTransformer.FORMAT, Streams.readFully(input), RegisteredTypeLoadingContexts.spec(Application.class), EntitySpec.class);
         final Entity app = brooklynMgmt.getEntityManager().createEntity(spec);
         // start the app (happens automatically if we use camp to instantiate, but not if we use crate spec approach)
         app.invoke(Startable.START, MutableMap.<String,String>of()).get();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/BrooklynYamlTypeInstantiatorTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/BrooklynYamlTypeInstantiatorTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/BrooklynYamlTypeInstantiatorTest.java
index a94f3a7..c76731b 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/BrooklynYamlTypeInstantiatorTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/BrooklynYamlTypeInstantiatorTest.java
@@ -18,11 +18,11 @@
  */
 package org.apache.brooklyn.camp.brooklyn;
 
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator;
 import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator.Factory;
 import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator.InstantiatorFromKey;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
 import org.testng.Assert;
 import org.testng.annotations.Test;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
index cb0b169..93507aa 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
@@ -54,7 +54,7 @@ import org.apache.brooklyn.core.mgmt.osgi.OsgiStandaloneTest;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
 import org.apache.brooklyn.core.test.entity.TestApplication;
 import org.apache.brooklyn.core.test.entity.TestEntity;
-import org.apache.brooklyn.core.typereg.RegisteredTypeConstraints;
+import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.test.support.TestResourceUnavailableException;
 import org.apache.brooklyn.util.collections.MutableMap;
@@ -232,7 +232,7 @@ public class CampYamlLiteTest {
     }
 
     private void assertMgmtHasSampleMyCatalogApp(String symbolicName, String bundleUrl) {
-        RegisteredType item = mgmt.getTypeRegistry().get(symbolicName, RegisteredTypeConstraints.spec(Entity.class));
+        RegisteredType item = mgmt.getTypeRegistry().get(symbolicName, RegisteredTypeLoadingContexts.spec(Entity.class));
         assertNotNull(item, "failed to load item with id=" + symbolicName + " from catalog. Entries were: " +
                 Joiner.on(",").join(mgmt.getTypeRegistry().getAll()));
         assertEquals(item.getSymbolicName(), symbolicName);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java
index f820597..6f9de6e 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java
@@ -25,6 +25,7 @@ import java.util.Set;
 import org.apache.brooklyn.api.entity.Application;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.camp.CampPlatform;
 import org.apache.brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
 import org.apache.brooklyn.camp.spi.AbstractResource;
@@ -34,7 +35,6 @@ import org.apache.brooklyn.camp.spi.PlatformComponentTemplate;
 import org.apache.brooklyn.camp.spi.collection.ResolvableLink;
 import org.apache.brooklyn.camp.spi.instantiate.BasicAssemblyTemplateInstantiator;
 import org.apache.brooklyn.core.mgmt.HasBrooklynManagementContext;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.test.entity.TestApplication;
 import org.apache.brooklyn.core.test.entity.TestEntity;
 import org.apache.brooklyn.util.collections.MutableMap;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
index 699c860..a0c5d8f 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
@@ -58,7 +58,7 @@ import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements.EntityAndItem;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements.StringAndArgument;
 import org.apache.brooklyn.core.sensor.Sensors;
-import org.apache.brooklyn.core.typereg.RegisteredTypeConstraints;
+import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
 import org.apache.brooklyn.entity.group.AbstractGroup;
 import org.apache.brooklyn.rest.api.ApplicationApi;
 import org.apache.brooklyn.rest.domain.ApplicationSpec;
@@ -402,7 +402,7 @@ public class ApplicationResource extends AbstractBrooklynRestResource implements
     }
 
     private void checkSpecTypeIsValid(String type, Class<? extends BrooklynObject> subType) {
-        if (mgmt().getTypeRegistry().get(type, RegisteredTypeConstraints.spec(subType)) == null) {
+        if (mgmt().getTypeRegistry().get(type, RegisteredTypeLoadingContexts.spec(subType)) == null) {
             try {
                 brooklyn().getCatalogClassLoader().loadClass(type);
             } catch (ClassNotFoundException e) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e932d5fc/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
index 848701f..ddfdc93 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
@@ -49,7 +49,7 @@ import org.apache.brooklyn.core.catalog.internal.CatalogItemComparator;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements.StringAndArgument;
-import org.apache.brooklyn.core.typereg.RegisteredTypeConstraints;
+import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
 import org.apache.brooklyn.core.typereg.RegisteredTypePredicates;
 import org.apache.brooklyn.rest.api.CatalogApi;
 import org.apache.brooklyn.rest.domain.ApiError;
@@ -148,7 +148,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
                 Entitlements.getEntitlementContext().user());
         }
         try {
-            RegisteredType item = mgmt().getTypeRegistry().get(entityId, RegisteredTypeConstraints.spec(Entity.class));
+            RegisteredType item = mgmt().getTypeRegistry().get(entityId, RegisteredTypeLoadingContexts.spec(Entity.class));
             if (item==null) {
                 throw WebResourceUtils.notFound("Entity with id '%s' not found", entityId);
             }


[06/14] incubator-brooklyn git commit: Working CampTypePlanTransformer

Posted by he...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
index 35feb65..39959e0 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
@@ -34,10 +34,13 @@ import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
 import org.apache.brooklyn.core.plan.PlanNotRecognizedException;
 import org.apache.brooklyn.core.plan.PlanToSpecTransformer;
+import org.apache.brooklyn.core.typereg.RegisteredTypes;
+import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+@Deprecated /** @deprecated since 0.9.0 use CampTypePlanTransformer */
 public class CampToSpecTransformer implements PlanToSpecTransformer {
 
     public static final String YAML_CAMP_PLAN_TYPE = "org.apache.brooklyn.camp/yaml";
@@ -59,12 +62,12 @@ public class CampToSpecTransformer implements PlanToSpecTransformer {
     @Override
     public EntitySpec<? extends Application> createApplicationSpec(String plan) {
         try {
-            CampPlatform camp = CampUtils.getCampPlatform(mgmt);
+            CampPlatform camp = CampInternalUtils.getCampPlatform(mgmt);
             BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.create(mgmt);
-            AssemblyTemplate at = CampUtils.registerDeploymentPlan(plan, loader, camp);
-            AssemblyTemplateInstantiator instantiator = CampUtils.getInstantiator(at);
+            AssemblyTemplate at = CampInternalUtils.registerDeploymentPlan(plan, loader, camp);
+            AssemblyTemplateInstantiator instantiator = CampInternalUtils.getInstantiator(at);
             if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
-                return ((AssemblyTemplateSpecInstantiator) instantiator).createApplicationSpec(at, camp, loader);
+                return ((AssemblyTemplateSpecInstantiator) instantiator).createApplicationSpec(at, camp, loader, MutableSet.<String>of());
             } else {
                 // The unknown instantiator can create the app (Assembly), but not a spec.
                 // Currently, all brooklyn plans should produce the above.
@@ -84,7 +87,7 @@ public class CampToSpecTransformer implements PlanToSpecTransformer {
         }
     }
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @SuppressWarnings({ "unchecked" })
     @Override
     public <T, SpecT extends AbstractBrooklynObjectSpec<? extends T, SpecT>> SpecT createCatalogSpec(CatalogItem<T, SpecT> item, Set<String> encounteredTypes) {
         // Ignore old-style java type catalog items - there is a different (deprecated) transformer for that
@@ -96,7 +99,7 @@ public class CampToSpecTransformer implements PlanToSpecTransformer {
         }
 
         // Not really clear what should happen to the top-level attributes, ignored until a good use case appears.
-        return (SpecT) CampCatalogUtils.createSpec(mgmt, (CatalogItem)item, encounteredTypes);
+        return (SpecT) CampResolver.createSpecFromFull(mgmt, RegisteredTypes.of(item), encounteredTypes, null);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
new file mode 100644
index 0000000..dd8a0d5
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
@@ -0,0 +1,90 @@
+/*
+ * 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.camp.brooklyn.spi.creation;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.api.typereg.RegisteredType.TypeImplementationPlan;
+import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.core.typereg.AbstractCustomImplementationPlan;
+import org.apache.brooklyn.core.typereg.AbstractTypePlanTransformer;
+import org.apache.brooklyn.core.typereg.BasicTypeImplementationPlan;
+import org.apache.brooklyn.core.typereg.RegisteredTypes;
+import org.apache.brooklyn.util.guava.Maybe;
+
+import com.google.common.collect.ImmutableList;
+
+public class CampTypePlanTransformer extends AbstractTypePlanTransformer {
+
+    private static final List<String> FORMATS = ImmutableList.of("brooklyn-camp", "camp", "brooklyn");
+    
+    public CampTypePlanTransformer() {
+        super(FORMATS.get(0), "OASIS CAMP / Brooklyn", "The Apache Brooklyn implementation of the OASIS CAMP blueprint plan format and extensions");
+    }
+
+    @Override
+    protected double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeConstraint context) {
+        Maybe<Map<Object, Object>> plan = RegisteredTypes.getAsYamlMap(planData);
+        if (plan.isAbsent()) return 0;
+        if (plan.get().containsKey("services")) return 0.8;
+        return 0;
+    }
+
+    @Override
+    protected double scoreForNonmatchingNonnullFormat(String planFormat, Object planData, RegisteredType type, RegisteredTypeConstraint context) {
+        if (FORMATS.contains(planFormat.toLowerCase())) return 0.9;
+        return 0;
+    }
+
+    @Override
+    protected AbstractBrooklynObjectSpec<?, ?> createSpec(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
+        // TODO cache
+        return new CampResolver(mgmt, type, context).createSpec();
+    }
+
+    @Override
+    protected Object createBean(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
+        // beans not supported by this?
+        return null;
+    }
+
+    @Override
+    public double scoreForTypeDefinition(String formatCode, Object catalogData) {
+        // TODO catalog parsing
+        return 0;
+    }
+
+    @Override
+    public List<RegisteredType> createFromTypeDefinition(String formatCode, Object catalogData) {
+        // TODO catalog parsing
+        return null;
+    }
+
+    public static class CampTypeImplementationPlan extends AbstractCustomImplementationPlan<String> {
+        public CampTypeImplementationPlan(TypeImplementationPlan otherPlan) {
+            super(FORMATS.get(0), String.class, otherPlan);
+        }
+        public CampTypeImplementationPlan(String planData) {
+            this(new BasicTypeImplementationPlan(FORMATS.get(0), planData));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampUtils.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampUtils.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampUtils.java
deleted file mode 100644
index 637a8eb..0000000
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampUtils.java
+++ /dev/null
@@ -1,267 +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.camp.brooklyn.spi.creation;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.StringReader;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.location.LocationSpec;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
-import org.apache.brooklyn.api.objs.SpecParameter;
-import org.apache.brooklyn.api.policy.Policy;
-import org.apache.brooklyn.api.policy.PolicySpec;
-import org.apache.brooklyn.api.typereg.RegisteredType;
-import org.apache.brooklyn.camp.CampPlatform;
-import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
-import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
-import org.apache.brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
-import org.apache.brooklyn.camp.spi.AssemblyTemplate;
-import org.apache.brooklyn.camp.spi.AssemblyTemplate.Builder;
-import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
-import org.apache.brooklyn.camp.spi.pdp.DeploymentPlan;
-import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
-import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
-import org.apache.brooklyn.core.mgmt.EntityManagementUtils;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
-import org.apache.brooklyn.core.objs.BasicSpecParameter;
-import org.apache.brooklyn.core.objs.BrooklynObjectInternal.ConfigurationSupportInternal;
-import org.apache.brooklyn.entity.stock.BasicApplicationImpl;
-import org.apache.brooklyn.util.exceptions.Exceptions;
-import org.apache.brooklyn.util.guava.Maybe;
-import org.apache.brooklyn.util.stream.Streams;
-import org.apache.brooklyn.util.yaml.Yamls;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-
-//TODO-type-registry
-public class CampUtils {
-
-    public static EntitySpec<?> createRootServiceSpec(String plan, BrooklynClassLoadingContext loader, Set<String> encounteredTypes) {
-        CampPlatform camp = getCampPlatform(loader.getManagementContext());
-
-        AssemblyTemplate at = registerDeploymentPlan(plan, loader, camp);
-        AssemblyTemplateInstantiator instantiator = getInstantiator(at);
-        if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
-            List<EntitySpec<?>> serviceSpecs = ((AssemblyTemplateSpecInstantiator)instantiator).createServiceSpecs(at, camp, loader, encounteredTypes);
-            if (serviceSpecs.size() > 1) {
-                throw new UnsupportedOperationException("Single service expected, but got "+serviceSpecs);
-            }
-            EntitySpec<?> rootSpec = serviceSpecs.get(0);
-            EntitySpec<? extends Application> wrapperApp = createWrapperApp(at, loader);
-            EntityManagementUtils.mergeWrapperParentSpecToChildEntity(wrapperApp, rootSpec);
-            return rootSpec;
-        } else {
-            throw new IllegalStateException("Unable to instantiate YAML; incompatible instantiator "+instantiator+" for "+at);
-        }
-    }
-
-    public static EntitySpec<? extends Application> createWrapperApp(AssemblyTemplate template, BrooklynClassLoadingContext loader) {
-        BrooklynComponentTemplateResolver resolver = BrooklynComponentTemplateResolver.Factory.newInstance(
-            loader, buildWrapperAppTemplate(template));
-        EntitySpec<Application> wrapperSpec = resolver.resolveSpec(ImmutableSet.<String>of());
-        // Clear out default parameters (coming from the wrapper app's class) so they don't overwrite the entity's params on unwrap.
-        if (!hasExplicitParams(template)) {
-            wrapperSpec.parameters(ImmutableList.<SpecParameter<?>>of());
-        }
-        return wrapperSpec;
-    }
-
-    private static boolean hasExplicitParams(AssemblyTemplate at) {
-        return at.getCustomAttributes().containsKey(BrooklynCampReservedKeys.BROOKLYN_PARAMETERS);
-    }
-
-    private static AssemblyTemplate buildWrapperAppTemplate(AssemblyTemplate template) {
-        Builder<? extends AssemblyTemplate> builder = AssemblyTemplate.builder();
-        builder.type("brooklyn:" + BasicApplicationImpl.class.getName());
-        builder.id(template.getId());
-        builder.name(template.getName());
-        builder.sourceCode(template.getSourceCode());
-        for (Entry<String, Object> entry : template.getCustomAttributes().entrySet()) {
-            builder.customAttribute(entry.getKey(), entry.getValue());
-        }
-        builder.instantiator(template.getInstantiator());
-        AssemblyTemplate wrapTemplate = builder.build();
-        return wrapTemplate;
-    }
-
-    public static AssemblyTemplateInstantiator getInstantiator(AssemblyTemplate at) {
-        try {
-            return at.getInstantiator().newInstance();
-        } catch (Exception e) {
-            throw Exceptions.propagate(e);
-        }
-    }
-
-    public static AssemblyTemplate registerDeploymentPlan(String plan, BrooklynClassLoadingContext loader, CampPlatform camp) {
-        BrooklynLoaderTracker.setLoader(loader);
-        try {
-            return camp.pdp().registerDeploymentPlan(new StringReader(plan));
-        } finally {
-            BrooklynLoaderTracker.unsetLoader(loader);
-        }
-    }
-
-    public static PolicySpec<?> createPolicySpec(String yamlPlan, BrooklynClassLoadingContext loader, Set<String> encounteredCatalogTypes) {
-        DeploymentPlan plan = makePlanFromYaml(loader.getManagementContext(), yamlPlan);
-
-        //Would ideally re-use the PolicySpecResolver
-        //but it is CAMP specific and there is no easy way to get hold of it.
-        Object policies = checkNotNull(plan.getCustomAttributes().get(BasicBrooklynCatalog.POLICIES_KEY), "policy config");
-        if (!(policies instanceof Iterable<?>)) {
-            throw new IllegalStateException("The value of " + BasicBrooklynCatalog.POLICIES_KEY + " must be an Iterable.");
-        }
-
-        Object policy = Iterables.getOnlyElement((Iterable<?>)policies);
-
-        return createPolicySpec(loader, policy, encounteredCatalogTypes);
-    }
-
-    @SuppressWarnings("unchecked")
-    public static PolicySpec<?> createPolicySpec(BrooklynClassLoadingContext loader, Object policy, Set<String> encounteredCatalogTypes) {
-        Map<String, Object> itemMap;
-        if (policy instanceof String) {
-            itemMap = ImmutableMap.<String, Object>of("type", policy);
-        } else if (policy instanceof Map) {
-            itemMap = (Map<String, Object>) policy;
-        } else {
-            throw new IllegalStateException("Policy expected to be string or map. Unsupported object type " + policy.getClass().getName() + " (" + policy.toString() + ")");
-        }
-
-        String versionedId = (String) checkNotNull(Yamls.getMultinameAttribute(itemMap, "policy_type", "policyType", "type"), "policy type");
-        PolicySpec<? extends Policy> spec = resolvePolicySpec(versionedId, loader, encounteredCatalogTypes);
-        Map<String, Object> brooklynConfig = (Map<String, Object>) itemMap.get(BrooklynCampReservedKeys.BROOKLYN_CONFIG);
-        if (brooklynConfig != null) {
-            spec.configure(brooklynConfig);
-        }
-        List<?> parameters = (List<?>) itemMap.get(BrooklynCampReservedKeys.BROOKLYN_PARAMETERS);
-        initParameters(parameters, spec, loader);
-        return spec;
-    }
-
-    public static LocationSpec<?> createLocationSpec(String yamlPlan, BrooklynClassLoadingContext loader, Set<String> encounteredTypes) {
-        DeploymentPlan plan = makePlanFromYaml(loader.getManagementContext(), yamlPlan);
-        Object locations = checkNotNull(plan.getCustomAttributes().get(BasicBrooklynCatalog.LOCATIONS_KEY), "location config");
-        if (!(locations instanceof Iterable<?>)) {
-            throw new IllegalStateException("The value of " + BasicBrooklynCatalog.LOCATIONS_KEY + " must be an Iterable.");
-        }
-
-        Object location = Iterables.getOnlyElement((Iterable<?>)locations);
-        return createLocationSpec(loader, location);
-    }
-
-    @SuppressWarnings("unchecked")
-    private static LocationSpec<?> createLocationSpec(BrooklynClassLoadingContext loader, Object location) {
-        Map<String, Object> itemMap;
-        if (location instanceof String) {
-            itemMap = ImmutableMap.<String, Object>of("type", location);
-        } else if (location instanceof Map) {
-            itemMap = (Map<String, Object>) location;
-        } else {
-            throw new IllegalStateException("Location expected to be string or map. Unsupported object type " + location.getClass().getName() + " (" + location.toString() + ")");
-        }
-
-        String type = (String) checkNotNull(Yamls.getMultinameAttribute(itemMap, "location_type", "locationType", "type"), "location type");
-        Map<String, Object> brooklynConfig = (Map<String, Object>) itemMap.get("brooklyn.config");
-        LocationSpec<?> locationSpec = resolveLocationSpec(type, brooklynConfig, loader);
-        List<?> explicitParams = (List<?>) itemMap.get(BrooklynCampReservedKeys.BROOKLYN_PARAMETERS);
-        initParameters(explicitParams, locationSpec, loader);
-        return locationSpec;
-    }
-
-    private static void initParameters(List<?> explicitParams, AbstractBrooklynObjectSpec<?, ?> spec, BrooklynClassLoadingContext loader) {
-        if (explicitParams != null) {
-            spec.parameters(BasicSpecParameter.fromConfigList(explicitParams, loader));
-        } else {
-            spec.parameters(BasicSpecParameter.fromSpec(loader.getManagementContext(), spec));
-        }
-    }
-
-    public static DeploymentPlan makePlanFromYaml(ManagementContext mgmt, String yaml) {
-        CampPlatform camp = getCampPlatform(mgmt);
-        return camp.pdp().parseDeploymentPlan(Streams.newReaderWithContents(yaml));
-    }
-
-    public static CampPlatform getCampPlatform(ManagementContext mgmt) {
-        CampPlatform result = mgmt.getConfig().getConfig(BrooklynCampConstants.CAMP_PLATFORM);
-        if (result!=null) {
-            return result;
-        } else {
-            throw new IllegalStateException("No CAMP Platform is registered with this Brooklyn management context.");
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private static PolicySpec<? extends Policy> resolvePolicySpec(
-            String versionedId,
-            BrooklynClassLoadingContext loader,
-            Set<String> encounteredCatalogTypes) {
-        
-        PolicySpec<? extends Policy> spec;
-        RegisteredType item = loader.getManagementContext().getTypeRegistry().get(versionedId);
-        if (item != null && !encounteredCatalogTypes.contains(item.getSymbolicName())) {
-            return loader.getManagementContext().getTypeRegistry().createSpec(item, null, PolicySpec.class);
-        } else {
-            // TODO-type-registry pass the loader in to the above, and allow it to load with the loader
-            spec = PolicySpec.create(loader.loadClass(versionedId, Policy.class));
-        }
-        return spec;
-    }
-
-    private static LocationSpec<?> resolveLocationSpec(
-            String type,
-            Map<String, Object> brooklynConfig,
-            BrooklynClassLoadingContext loader) {
-        Maybe<Class<? extends Location>> javaClass = loader.tryLoadClass(type, Location.class);
-        if (javaClass.isPresent()) {
-            LocationSpec<?> spec = LocationSpec.create(javaClass.get());
-            if (brooklynConfig != null) {
-                spec.configure(brooklynConfig);
-            }
-            return spec;
-        } else {
-            Maybe<Location> loc = loader.getManagementContext().getLocationRegistry().resolve(type, false, brooklynConfig);
-            if (loc.isPresent()) {
-                // TODO extensions?
-                Map<String, Object> locConfig = ((ConfigurationSupportInternal)loc.get().config()).getBag().getAllConfig();
-                Class<? extends Location> locType = loc.get().getClass();
-                Set<Object> locTags = loc.get().tags().getTags();
-                String locDisplayName = loc.get().getDisplayName();
-                return LocationSpec.create(locType)
-                        .configure(locConfig)
-                        .displayName(locDisplayName)
-                        .tags(locTags);
-            } else {
-                throw new IllegalStateException("No class or resolver found for location type "+type);
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java
index 387212c..1e54f76 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java
@@ -20,12 +20,16 @@ package org.apache.brooklyn.camp.brooklyn.spi.creation.service;
 
 import java.util.Set;
 
+import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
-import org.apache.brooklyn.camp.brooklyn.spi.creation.CampUtils;
+import org.apache.brooklyn.camp.brooklyn.spi.creation.CampTypePlanTransformer;
 import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.resolve.entity.EntitySpecResolver;
+import org.apache.brooklyn.core.typereg.RegisteredTypeConstraints;
+import org.apache.brooklyn.core.typereg.RegisteredTypes;
+import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.net.Urls;
 import org.slf4j.Logger;
@@ -56,8 +60,19 @@ public class UrlServiceSpecResolver implements EntitySpecResolver {
             log.warn("AssemblyTemplate type " + type + " looks like a URL that can't be fetched.", e);
             return null;
         }
+        if (encounteredTypes.contains(type)) {
+            throw new IllegalStateException("URL " + type + " is self referential.");
+        }
+        encounteredTypes = MutableSet.<String>builder().addAll(encounteredTypes).add(type).build().asUnmodifiable();
+        
         // Referenced specs are expected to be CAMP format as well.
-        return CampUtils.createRootServiceSpec(yaml, loader, encounteredTypes);
+        // XXX somehow specify to allow full syntax for services
+        EntitySpec<?> item = loader.getManagementContext().getTypeRegistry().createSpec(
+            RegisteredTypes.spec(null, null, 
+                new CampTypePlanTransformer.CampTypeImplementationPlan(yaml), Entity.class), 
+            RegisteredTypeConstraints.alreadyVisited(encounteredTypes, loader), 
+            EntitySpec.class);
+        return item;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/main/resources/META-INF/services/org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/resources/META-INF/services/org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer b/usage/camp/src/main/resources/META-INF/services/org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer
new file mode 100644
index 0000000..0c6fab3
--- /dev/null
+++ b/usage/camp/src/main/resources/META-INF/services/org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+org.apache.brooklyn.camp.brooklyn.spi.creation.CampTypePlanTransformer

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
index a45d272..c13e004 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
@@ -23,29 +23,31 @@ import java.io.StringReader;
 import java.util.Set;
 
 import org.apache.brooklyn.api.catalog.BrooklynCatalog;
+import org.apache.brooklyn.api.entity.Application;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.mgmt.Task;
-import org.apache.brooklyn.camp.spi.Assembly;
-import org.apache.brooklyn.camp.spi.AssemblyTemplate;
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.camp.brooklyn.spi.creation.CampTypePlanTransformer.CampTypeImplementationPlan;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.trait.Startable;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
 import org.apache.brooklyn.core.mgmt.EntityManagementUtils;
 import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.core.typereg.RegisteredTypeConstraints;
+import org.apache.brooklyn.core.typereg.RegisteredTypes;
+import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.ResourceUtils;
-import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.stream.Streams;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 
 import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
 
 public abstract class AbstractYamlTest {
 
@@ -115,25 +117,12 @@ public abstract class AbstractYamlTest {
     }
 
     protected Entity createAndStartApplication(Reader input) throws Exception {
-        AssemblyTemplate at = platform.pdp().registerDeploymentPlan(input);
-        Assembly assembly;
-        try {
-            assembly = at.getInstantiator().newInstance().instantiate(at, platform);
-        } catch (Exception e) {
-            getLogger().warn("Unable to instantiate " + at + " (rethrowing): " + e);
-            throw e;
-        }
-        getLogger().info("Test - created " + assembly);
-        final Entity app = brooklynMgmt.getEntityManager().getEntity(assembly.getId());
-        getLogger().info("App - " + app);
-        
-        // wait for app to have started
-        Set<Task<?>> tasks = brooklynMgmt.getExecutionManager().getTasksWithAllTags(ImmutableList.of(
-                BrooklynTaskTags.EFFECTOR_TAG, 
-                BrooklynTaskTags.tagForContextEntity(app), 
-                BrooklynTaskTags.tagForEffectorCall(app, "start", ConfigBag.newInstance(ImmutableMap.of("locations", ImmutableMap.of())))));
-        Iterables.getOnlyElement(tasks).get();
-        
+        RegisteredType type = RegisteredTypes.spec(null, null, new CampTypeImplementationPlan(Streams.readFully(input)), Application.class);
+        EntitySpec<?> spec = 
+            mgmt().getTypeRegistry().createSpec(type, RegisteredTypeConstraints.spec(Application.class), EntitySpec.class);
+        final Entity app = brooklynMgmt.getEntityManager().createEntity(spec);
+        // start the app (happens automatically if we use camp to instantiate, but not if we use crate spec approach)
+        app.invoke(Startable.START, MutableMap.<String,String>of()).get();
         return app;
     }
 
@@ -141,8 +130,7 @@ public abstract class AbstractYamlTest {
         Entity app = createAndStartApplication(input);
         waitForApplicationTasks(app);
 
-        getLogger().info("App started:");
-        Entities.dumpInfo(app);
+        getLogger().info("App started: "+app);
         
         return app;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java
index a997904..8131208 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java
@@ -81,6 +81,8 @@ public class EntitiesYamlTest extends AbstractYamlTest {
         Entity app = createAndStartApplication(loadYaml("test-entity-basic-template.yaml", extras));
         waitForApplicationTasks(app);
 
+        Entities.dumpInfo(app);
+        
         Assert.assertEquals(app.getDisplayName(), "test-entity-basic-template");
 
         log.info("App started:");

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ReferencedYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ReferencedYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ReferencedYamlTest.java
index 68aef52..bb0ea90 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ReferencedYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ReferencedYamlTest.java
@@ -49,6 +49,7 @@ public class ReferencedYamlTest extends AbstractYamlTest {
             "services:",
             "- type: classpath://yaml-ref-entity.yaml");
         
+        // the name declared at the root trumps the name on the item itself
         checkChildEntitySpec(app, "Basic entity");
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
index c426897..215fd1a 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
@@ -33,6 +33,7 @@ import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityMatcher;
 import org.apache.brooklyn.core.mgmt.osgi.OsgiVersionMoreEntityTest;
 import org.apache.brooklyn.core.objs.BrooklynTypes;
 import org.apache.brooklyn.core.typereg.RegisteredTypePredicates;
+import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.test.support.TestResourceUnavailableException;
 import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.text.Strings;
@@ -239,17 +240,24 @@ public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest {
         Iterable<RegisteredType> items = types.getAll();
         for (RegisteredType item: items) {
             Object spec = types.createSpec(item, null, null);
-            if (Entity.class.isAssignableFrom(item.getJavaType())) {
+            int match = 0;
+            if (RegisteredTypes.isSubTypeOf(item, Entity.class)) {
                 assertTrue(spec instanceof EntitySpec, "Not an EntitySpec: " + spec);
                 BrooklynTypes.getDefinedEntityType(((EntitySpec<?>)spec).getType());
-            } else if (Policy.class.isAssignableFrom(item.getJavaType())) { 
+                match++;
+            }
+            if (RegisteredTypes.isSubTypeOf(item, Policy.class)) {
                 assertTrue(spec instanceof PolicySpec, "Not a PolicySpec: " + spec);
                 BrooklynTypes.getDefinedBrooklynType(((PolicySpec<?>)spec).getType());
-            } else if (Location.class.isAssignableFrom(item.getJavaType())) {
+                match++;
+            }
+            if (RegisteredTypes.isSubTypeOf(item, Location.class)) {
                 assertTrue(spec instanceof LocationSpec, "Not a LocationSpec: " + spec);
                 BrooklynTypes.getDefinedBrooklynType(((LocationSpec<?>)spec).getType());
-            } else {
-                Assert.fail("Unexpected type: "+item.getJavaType()+" / "+item);
+                match++;
+            }
+            if (match==0) {
+                Assert.fail("Unexpected type: "+item+" ("+item.getSuperTypes()+")");
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
index e13792d..52d48e4 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
@@ -34,6 +34,7 @@ import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
 import org.apache.brooklyn.core.config.BasicConfigKey;
 import org.apache.brooklyn.core.mgmt.osgi.OsgiStandaloneTest;
 import org.apache.brooklyn.core.typereg.RegisteredTypePredicates;
+import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
 import org.apache.brooklyn.test.support.TestResourceUnavailableException;
 import org.apache.brooklyn.util.text.StringFunctions;
@@ -110,7 +111,7 @@ public class CatalogYamlLocationTest extends AbstractYamlTest {
     private void assertAdded(String symbolicName, String expectedJavaType) {
         RegisteredType item = mgmt().getTypeRegistry().get(symbolicName, TEST_VERSION);
         assertEquals(item.getSymbolicName(), symbolicName);
-        Assert.assertTrue(Location.class.isAssignableFrom(item.getJavaType()), "Expected Location, not "+item.getJavaType());
+        Assert.assertTrue(RegisteredTypes.isSubTypeOf(item, Location.class), "Expected Location, not "+item.getSuperTypes());
         assertEquals(countCatalogLocations(), 1);
 
         // Item added to catalog should automatically be available in location registry

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java
index 6c0a09a..f820597 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java
@@ -38,6 +38,7 @@ import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.test.entity.TestApplication;
 import org.apache.brooklyn.core.test.entity.TestEntity;
 import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 
 import com.google.common.collect.ImmutableList;
@@ -55,13 +56,18 @@ public class TestAppAssemblyInstantiator extends BasicAssemblyTemplateInstantiat
         }
         ManagementContext mgmt = ((HasBrooklynManagementContext)platform).getBrooklynManagementContext();
         
-        TestApplication app = (TestApplication) mgmt.getEntityManager().createEntity( createApplicationSpec(template, platform, null) );
+        TestApplication app = (TestApplication) mgmt.getEntityManager().createEntity( createApplicationSpec(template, platform, null, MutableSet.<String>of()) );
 
         return new TestAppAssembly(app);
     }
 
     @Override
     public EntitySpec<? extends Application> createApplicationSpec(AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext loader) {
+        return createApplicationSpec(template, platform, loader, MutableSet.<String>of());
+    }
+    @Override
+    public EntitySpec<? extends Application> createApplicationSpec(AssemblyTemplate template, CampPlatform platform,
+        BrooklynClassLoadingContext loader, Set<String> encounteredCatalogTypes) {
         EntitySpec<TestApplication> app = EntitySpec.create(TestApplication.class)
             .configure(TestEntity.CONF_NAME, template.getName())
             .configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", template.getType(), "desc", template.getDescription()));
@@ -87,7 +93,7 @@ public class TestAppAssemblyInstantiator extends BasicAssemblyTemplateInstantiat
 
     @Override
     public List<EntitySpec<?>> createServiceSpecs(AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext itemLoader, Set<String> encounteredCatalogTypes) {
-        EntitySpec<?> createApplicationSpec = createApplicationSpec(template, platform, itemLoader);
+        EntitySpec<?> createApplicationSpec = createApplicationSpec(template, platform, itemLoader, encounteredCatalogTypes);
         return ImmutableList.<EntitySpec<?>>of(createApplicationSpec);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
index e92c5f1..1b9aa77 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
@@ -281,7 +281,7 @@ public class BrooklynRestResourceUtils {
                     //different from the javaType.
                     resultI = mgmt.getTypeRegistry().get(typeName, BrooklynCatalog.DEFAULT_VERSION);
                     if (resultI != null) {
-                        if (resultI.getJavaType() == null) {
+                        if (resultI.getSuperTypes().isEmpty()) {
                             //Catalog items scanned from the classpath (using reflection and annotations) now
                             //get yaml spec rather than a java type. Can't use those when creating apps from
                             //the legacy app spec format.

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/PropagatedRuntimeException.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/PropagatedRuntimeException.java b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/PropagatedRuntimeException.java
index 1b1aa5a..0859ce8 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/PropagatedRuntimeException.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/PropagatedRuntimeException.java
@@ -36,6 +36,12 @@ public class PropagatedRuntimeException extends RuntimeException {
         causeEmbeddedInMessage = message.endsWith(Exceptions.collapseText(getCause()));
     }
 
+    public PropagatedRuntimeException(String messagePart1, String messagePart2PossiblyIncludingPart1, Throwable cause) {
+        super(messagePart2PossiblyIncludingPart1!=null && messagePart2PossiblyIncludingPart1.startsWith(messagePart1) ? messagePart2PossiblyIncludingPart1 : messagePart1+messagePart2PossiblyIncludingPart1, cause);
+        warnIfWrapping(cause);
+        causeEmbeddedInMessage = getMessage().endsWith(Exceptions.collapseText(getCause()));
+    }
+
     public PropagatedRuntimeException(String message, Throwable cause, boolean causeEmbeddedInMessage) {
         super(message, cause);
         warnIfWrapping(cause);



[10/14] incubator-brooklyn git commit: more code review, lots of minor tidies around type registry; thanks @neykov

Posted by he...@apache.org.
more code review, lots of minor tidies around type registry; thanks @neykov


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

Branch: refs/heads/master
Commit: db024f4e3323e803b421c0e808b7649c4b871d35
Parents: 90e8911
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Nov 17 11:07:46 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Nov 17 12:30:39 2015 +0000

----------------------------------------------------------------------
 .../api/typereg/BrooklynTypeRegistry.java       | 12 +--
 .../core/catalog/internal/CatalogUtils.java     |  7 ++
 .../core/mgmt/EntityManagementUtils.java        |  2 +-
 .../AbstractCustomImplementationPlan.java       | 52 -----------
 ...actFormatSpecificTypeImplementationPlan.java | 52 +++++++++++
 .../core/typereg/BasicBrooklynTypeRegistry.java | 28 ++++--
 .../core/typereg/BasicRegisteredType.java       |  2 +
 .../typereg/BrooklynTypePlanTransformer.java    |  8 +-
 .../JavaClassNameTypePlanTransformer.java       |  7 +-
 .../typereg/RegisteredTypeLoadingContexts.java  |  8 +-
 .../core/typereg/RegisteredTypePredicates.java  | 18 +---
 .../brooklyn/core/typereg/RegisteredTypes.java  | 76 ++++++++++-------
 .../core/typereg/TypePlanTransformers.java      |  2 +-
 .../internal/SpecParameterInMetaTest.java       | 16 ++++
 .../internal/StaticTypePlanTransformer.java     | 15 +++-
 .../core/plan/XmlPlanToSpecTransformer.java     |  3 +-
 .../core/test/BrooklynMgmtUnitTestSupport.java  |  3 +
 .../typereg/ExampleXmlTypePlanTransformer.java  |  2 +-
 .../JavaClassNameTypePlanTransformerTest.java   | 90 ++++++++++++++++++++
 .../typereg/JavaTypePlanTransformerTest.java    | 90 --------------------
 .../api/AssemblyTemplateSpecInstantiator.java   |  3 -
 .../BrooklynAssemblyTemplateInstantiator.java   |  8 --
 .../brooklyn/spi/creation/CampResolver.java     | 49 ++++++-----
 .../spi/creation/CampTypePlanTransformer.java   |  6 +-
 .../CatalogOsgiVersionMoreEntityTest.java       |  6 +-
 .../catalog/CatalogYamlLocationTest.java        |  2 +-
 .../test/lite/TestAppAssemblyInstantiator.java  |  4 -
 .../apache/brooklyn/util/text/Identifiers.java  | 16 +++-
 .../brooklyn/util/text/IdentifiersTest.java     | 11 ++-
 29 files changed, 326 insertions(+), 272 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java b/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
index ec5db91..42aa8ec 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
@@ -42,7 +42,7 @@ public interface BrooklynTypeRegistry {
     Iterable<RegisteredType> getAll();
     Iterable<RegisteredType> getAll(Predicate<? super RegisteredType> filter);
 
-    // XXX remove `context` parameter?
+    // TODO should we remove the `context` parameter from all these?  i don't think it's useful
     /** @return The item matching the given given 
      * {@link RegisteredType#getSymbolicName() symbolicName} 
      * and optionally {@link RegisteredType#getVersion()},
@@ -61,10 +61,10 @@ public interface BrooklynTypeRegistry {
 
     // NB the seemingly more correct generics <T,SpecT extends AbstractBrooklynObjectSpec<T,SpecT>> 
     // cause compile errors, not in Eclipse, but in maven (?) 
-    // TODO do these belong here, or in a separate master TypePlanTransformer ?
-    <SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpec(RegisteredType type, @Nullable RegisteredTypeLoadingContext optionalContext, Class<SpecT> optionalSpecSuperType);
-    <SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpecFromPlan(String planFormat, Object planData, @Nullable RegisteredTypeLoadingContext optionalContext, Class<SpecT> optionalSpecSuperType);
-    <T> T createBean(RegisteredType type, @Nullable RegisteredTypeLoadingContext optionalContext, Class<T> optionalResultSuperType);
-    <T> T createBeanFromPlan(String planFormat, Object planData, @Nullable RegisteredTypeLoadingContext optionalConstraint, Class<T> optionalBeanSuperType);
+    // TODO do these belong here, or in a separate master TypePlanTransformer ?  see also BrooklynTypePlanTransformer 
+    <SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpec(RegisteredType type, @Nullable RegisteredTypeLoadingContext optionalContext, @Nullable Class<SpecT> optionalSpecSuperType);
+    <SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpecFromPlan(@Nullable String planFormat, Object planData, @Nullable RegisteredTypeLoadingContext optionalContext, @Nullable Class<SpecT> optionalSpecSuperType);
+    <T> T createBean(RegisteredType type, @Nullable RegisteredTypeLoadingContext optionalContext, @Nullable Class<T> optionalResultSuperType);
+    <T> T createBeanFromPlan(String planFormat, Object planData, @Nullable RegisteredTypeLoadingContext optionalConstraint, @Nullable Class<T> optionalBeanSuperType);
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
index 4a54800..f144b7c 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
@@ -72,6 +72,10 @@ public class CatalogUtils {
         return newClassLoadingContext(mgmt, item.getId(), item.getLibraries(), null);
     }
     
+    /** made @Beta in 0.9.0 because we're not sure to what extent to support stacking loaders; 
+     * only a couple places currently rely on such stacking, in general the item and the bundles *are* the context,
+     * and life gets hard if we support complex stacking! */
+    @Beta 
     public static BrooklynClassLoadingContext newClassLoadingContext(ManagementContext mgmt, RegisteredType item, BrooklynClassLoadingContext loader) {
         return newClassLoadingContext(mgmt, item.getId(), item.getLibraries(), loader);
     }
@@ -92,6 +96,7 @@ public class CatalogUtils {
         return newClassLoadingContext(mgmt, catalogItemId, libraries, null);
     }
     
+    @Deprecated /** @deprecated since 0.9.0; becoming private because we should now always have a registered type callers can pass instead of the catalog item id */
     public static BrooklynClassLoadingContext newClassLoadingContext(@Nullable ManagementContext mgmt, String catalogItemId, Collection<? extends OsgiBundleWithUrl> libraries, BrooklynClassLoadingContext loader) {
         BrooklynClassLoadingContextSequential result = new BrooklynClassLoadingContextSequential(mgmt);
 
@@ -100,10 +105,12 @@ public class CatalogUtils {
         }
 
         if (loader !=null) {
+            // TODO determine whether to support stacking
             result.add(loader);
         }
         BrooklynClassLoadingContext threadLocalLoader = BrooklynLoaderTracker.getLoader();
         if (threadLocalLoader != null) {
+            // TODO and determine if this is needed/wanted
             result.add(threadLocalLoader);
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
index 0f8da61..ef461db 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
@@ -277,7 +277,7 @@ public class EntityManagementUtils {
         return canPromoteChildrenInWrappedApplication(app);
     }
     
-    /** returns true if the spec is for an empty-ish wrapper app, 
+    /** returns true if the spec is for a wrapper app with no important settings, wrapping a single child. 
      * for use when adding from a plan specifying multiple entities but nothing significant at the application level.
      * @see #WRAPPER_APP_MARKER */
     public static boolean canPromoteChildrenInWrappedApplication(EntitySpec<? extends Application> spec) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractCustomImplementationPlan.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractCustomImplementationPlan.java b/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractCustomImplementationPlan.java
deleted file mode 100644
index d9dde39..0000000
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractCustomImplementationPlan.java
+++ /dev/null
@@ -1,52 +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.typereg;
-
-import org.apache.brooklyn.api.typereg.RegisteredType.TypeImplementationPlan;
-
-/** Abstract superclass for plans to create {@link TypeImplementationPlan} with strong types on 
- * {@link #getPlanData()} and ensuring the correct format (or null for no format) */
-public abstract class AbstractCustomImplementationPlan<T> extends BasicTypeImplementationPlan {
-    
-    public AbstractCustomImplementationPlan(String format, T data) {
-        super(format, data);
-    }
-    public AbstractCustomImplementationPlan(String expectedFormat, Class<T> expectedDataType, TypeImplementationPlan otherPlan) {
-        super(expectedFormat!=null ? expectedFormat : otherPlan.getPlanFormat(), otherPlan.getPlanData());
-        if (!expectedDataType.isInstance(otherPlan.getPlanData())) {
-            throw new IllegalArgumentException("Plan "+otherPlan+" does not have "+expectedDataType+" data so cannot cast to "+this);
-        }
-        if (expectedFormat!=null && otherPlan.getPlanFormat()!=null) {
-            if (!otherPlan.getPlanFormat().equals(expectedFormat)) {
-                throw new IllegalArgumentException("Plan "+otherPlan+" in wrong format "+otherPlan.getPlanFormat()+", when expecting "+expectedFormat);
-            }
-        }
-    }
-    
-    @Override
-    public String getPlanFormat() {
-        return format;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public T getPlanData() {
-        return (T)super.getPlanData();
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractFormatSpecificTypeImplementationPlan.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractFormatSpecificTypeImplementationPlan.java b/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractFormatSpecificTypeImplementationPlan.java
new file mode 100644
index 0000000..9ce4e55
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractFormatSpecificTypeImplementationPlan.java
@@ -0,0 +1,52 @@
+/*
+ * 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.typereg;
+
+import org.apache.brooklyn.api.typereg.RegisteredType.TypeImplementationPlan;
+
+/** Abstract superclass for plans to create {@link TypeImplementationPlan} with strong types on 
+ * {@link #getPlanData()} and ensuring the correct format (or null for no format) */
+public abstract class AbstractFormatSpecificTypeImplementationPlan<T> extends BasicTypeImplementationPlan {
+    
+    public AbstractFormatSpecificTypeImplementationPlan(String format, T data) {
+        super(format, data);
+    }
+    public AbstractFormatSpecificTypeImplementationPlan(String expectedFormat, Class<T> expectedDataType, TypeImplementationPlan otherPlan) {
+        super(expectedFormat!=null ? expectedFormat : otherPlan.getPlanFormat(), otherPlan.getPlanData());
+        if (!expectedDataType.isInstance(otherPlan.getPlanData())) {
+            throw new IllegalArgumentException("Plan "+otherPlan+" does not have "+expectedDataType+" data so cannot cast to "+this);
+        }
+        if (expectedFormat!=null && otherPlan.getPlanFormat()!=null) {
+            if (!otherPlan.getPlanFormat().equals(expectedFormat)) {
+                throw new IllegalArgumentException("Plan "+otherPlan+" in wrong format "+otherPlan.getPlanFormat()+", when expecting "+expectedFormat);
+            }
+        }
+    }
+    
+    @Override
+    public String getPlanFormat() {
+        return format;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public T getPlanData() {
+        return (T)super.getPlanData();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
index 1bc4a9f..2f2d4f5 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
@@ -18,6 +18,8 @@
  */
 package org.apache.brooklyn.core.typereg;
 
+import java.util.Set;
+
 import javax.annotation.Nullable;
 
 import org.apache.brooklyn.api.catalog.BrooklynCatalog;
@@ -27,6 +29,7 @@ import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry;
 import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.api.typereg.RegisteredType.TypeImplementationPlan;
 import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
 import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
 import org.apache.brooklyn.core.catalog.internal.CatalogItemBuilder;
@@ -99,18 +102,27 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
         return get(symbolicNameWithOptionalVersion, (RegisteredTypeLoadingContext)null);
     }
 
-    @SuppressWarnings({ "deprecation", "unchecked", "rawtypes" })
     @Override
     public <SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpec(RegisteredType type, @Nullable RegisteredTypeLoadingContext constraint, Class<SpecT> specSuperType) {
         Preconditions.checkNotNull(type, "type");
         if (type.getKind()!=RegisteredTypeKind.SPEC) { 
             throw new IllegalStateException("Cannot create spec from type "+type+" (kind "+type.getKind()+")");
         }
+        return createSpec(type, type.getPlan(), type.getSymbolicName(), type.getVersion(), type.getSuperTypes(), constraint, specSuperType);
+    }
+    
+    @SuppressWarnings({ "deprecation", "unchecked", "rawtypes" })
+    private <SpecT extends AbstractBrooklynObjectSpec<?,?>> SpecT createSpec(
+            RegisteredType type,
+            TypeImplementationPlan plan,
+            @Nullable String symbolicName, @Nullable String version, Set<Object> superTypes,
+            @Nullable RegisteredTypeLoadingContext constraint, Class<SpecT> specSuperType) {
+        // TODO type is only used to call to "transform"; we should perhaps change transform so it doesn't need the type?
         if (constraint!=null) {
             if (constraint.getExpectedKind()!=null && constraint.getExpectedKind()!=RegisteredTypeKind.SPEC) {
                 throw new IllegalStateException("Cannot create spec with constraint "+constraint);
             }
-            if (constraint.getAlreadyEncounteredTypes().contains(type.getSymbolicName())) {
+            if (constraint.getAlreadyEncounteredTypes().contains(symbolicName)) {
                 // avoid recursive cycle
                 // TODO implement using java if permitted
             }
@@ -122,7 +134,7 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
         
         // fallback: look up in (legacy) catalog
         // TODO remove once all transformers are available in the new style
-        CatalogItem item = (CatalogItem) mgmt.getCatalog().getCatalogItem(type.getSymbolicName(), type.getVersion());
+        CatalogItem item = symbolicName!=null ? (CatalogItem) mgmt.getCatalog().getCatalogItem(symbolicName, version) : null;
         if (item==null) {
             // if not in catalog (because loading a new item?) then look up item based on type
             // (only really used in tests; possibly also for any recursive legacy transformers we might have to create a CI; cross that bridge when we come to it)
@@ -132,9 +144,9 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
                 result.get();
             }
             item = CatalogItemBuilder.newItem(ciType, 
-                    type.getSymbolicName()!=null ? type.getSymbolicName() : Identifiers.makeRandomId(8), 
-                        type.getVersion()!=null ? type.getVersion() : BasicBrooklynCatalog.DEFAULT_VERSION)
-                .plan(RegisteredTypes.getImplementationDataStringForSpec(type))
+                    symbolicName!=null ? symbolicName : Identifiers.makeRandomId(8), 
+                        version!=null ? version : BasicBrooklynCatalog.DEFAULT_VERSION)
+                .plan((String)plan.getPlanData())
                 .build();
         }
         try {
@@ -145,10 +157,10 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
             try {
                 result.get();
                 // above will throw -- so won't come here
-                throw new IllegalStateException("should have failed getting type resolution for "+type);
+                throw new IllegalStateException("should have failed getting type resolution for "+symbolicName);
             } catch (Exception e0) {
                 // prefer older exception, until the new transformer is the primary pathway
-                throw Exceptions.create("Unable to instantiate "+type, MutableList.of(e0, e));
+                throw Exceptions.create("Unable to instantiate "+(symbolicName==null ? "item" : symbolicName), MutableList.of(e0, e));
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
index 54b04a3..3905d65 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.javalang.JavaClassNames;
 
+import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableSet;
 
 /** Instances are usually created by methods in {@link RegisteredTypes}. */
@@ -113,6 +114,7 @@ public class BasicRegisteredType implements RegisteredType {
         return ImmutableSet.copyOf(superTypes);
     }
 
+    @Beta  // TODO depending how useful this is, it might be better to replace by a static WeakHashMap in RegisteredTypes
     public ConfigBag getCache() {
         return cache;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
index e185d3f..5609cf9 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynTypePlanTransformer.java
@@ -30,6 +30,8 @@ import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
 import org.apache.brooklyn.core.mgmt.ManagementContextInjectable;
 
+import com.google.common.annotations.Beta;
+
 /**
  * Interface for use by schemes which provide the capability to transform plans
  * (serialized descriptions) to brooklyn objecs and specs.
@@ -75,8 +77,12 @@ public interface BrooklynTypePlanTransformer extends ManagementContextInjectable
      * Implementations should either return null or throw {@link UnsupportedTypePlanException} 
      * if the {@link RegisteredType#getPlan()} is not supported. */
     @Nullable Object create(@Nonnull RegisteredType type, @Nonnull RegisteredTypeLoadingContext context);
-    
+
+    // TODO sketch methods for loading *catalog* definitions.  note some potential overlap
+    // with BrooklynTypeRegistery.createXxxFromPlan
+    @Beta
     double scoreForTypeDefinition(String formatCode, Object catalogData);
+    @Beta
     List<RegisteredType> createFromTypeDefinition(String formatCode, Object catalogData);
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java b/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java
index 5e6877b..29a4ec1 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java
@@ -37,8 +37,8 @@ public class JavaClassNameTypePlanTransformer extends AbstractTypePlanTransforme
     
     public static final String FORMAT = "java-type-name";
 
-    public static class JavaTypeNameImplementation extends AbstractCustomImplementationPlan<String> {
-        public JavaTypeNameImplementation(String javaType) { super(FORMAT, javaType); }
+    public static class JavaClassNameTypeImplementationPlan extends AbstractFormatSpecificTypeImplementationPlan<String> {
+        public JavaClassNameTypeImplementationPlan(String javaType) { super(FORMAT, javaType); }
     }
 
     public JavaClassNameTypePlanTransformer() {
@@ -47,8 +47,9 @@ public class JavaClassNameTypePlanTransformer extends AbstractTypePlanTransforme
 
     @Override
     protected double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeLoadingContext context) {
+        // the "good" regex doesn't allow funny unicode chars; we'll accept that for now 
         if (type.getPlan().getPlanData() instanceof String && 
-                ((String)type.getPlan().getPlanData()).matches(Identifiers.JAVA_BINARY_REGEX)) {
+                ((String)type.getPlan().getPlanData()).matches(Identifiers.JAVA_GOOD_BINARY_REGEX)) {
             return 0.1;
         }
         return 0;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java
index 594bdfd..0368ba3 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java
@@ -41,7 +41,7 @@ import com.google.common.collect.ImmutableSet;
 
 public class RegisteredTypeLoadingContexts {
 
-    private static final Logger log = LoggerFactory.getLogger(RegisteredTypeLoadingContexts.BasicRegisteredTypeLoadingContext.class);
+    private static final Logger log = LoggerFactory.getLogger(RegisteredTypeLoadingContexts.class);
     
     /** Immutable (from caller's perspective) record of a constraint */
     public final static class BasicRegisteredTypeLoadingContext implements RegisteredTypeLoadingContext {
@@ -58,7 +58,7 @@ public class RegisteredTypeLoadingContexts {
             this.kind = source.getExpectedKind();
             this.expectedSuperType = source.getExpectedJavaSuperType();
             this.encounteredTypes = source.getAlreadyEncounteredTypes();
-            this.loader = (BrooklynClassLoadingContext) source.getLoader();
+            this.loader = source.getLoader();
         }
 
         @Override
@@ -204,14 +204,14 @@ public class RegisteredTypeLoadingContexts {
         BrooklynObjectType best = null;
 
         for (BrooklynObjectType t: BrooklynObjectType.values()) {
-            if (t.getSpecType()==null) continue;
+            if (t.getInterfaceType()==null) continue;
             if (!t.getInterfaceType().isAssignableFrom(targetSuperType)) continue;
             // on equality, exit immediately
             if (t.getInterfaceType().equals(targetSuperType)) return t.getSpecType();
             // else pick which is best
             if (best==null) { best = t; continue; }
             // if t is more specific, it is better (handles case when e.g. a Policy is a subclass of Entity)
-            if (best.getSpecType().isAssignableFrom(t.getSpecType())) { best = t; continue; }
+            if (best.getInterfaceType().isAssignableFrom(t.getInterfaceType())) { best = t; continue; }
         }
         if (best==null) {
             log.warn("Unexpected target supertype ("+targetSuperType+"); unable to infer spec type");

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java
index 2e7c038..bc81d8e 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java
@@ -121,31 +121,17 @@ public class RegisteredTypePredicates {
         private final Predicate<Class<?>> filter;
         
         @SuppressWarnings({ "rawtypes", "unchecked" })
-        private <T> AnySuperTypeMatches(Predicate filter) {
+        private AnySuperTypeMatches(Predicate filter) {
             this.filter = filter;
         }
         @Override
         public boolean apply(@Nullable RegisteredType item) {
             if (item==null) return false;
-            for (Object o: item.getSuperTypes()) {
-                if (o instanceof Class) {
-                    if (filter.apply((Class<?>)o)) return true;
-                }
-            }
-            for (Object o: item.getSuperTypes()) {
-                if (o instanceof RegisteredType) {
-                    if (apply((RegisteredType)o)) return true;
-                }
-            }
-            return false;
+            return RegisteredTypes.isAnyTypeOrSuperSatisfying(item.getSuperTypes(), filter);
         }
     }
 
     public static final Predicate<RegisteredType> IS_APPLICATION = assignableFrom(Application.class);
-    // TODO do we need this?  introduced already deprecated in 0.9.0 so can be removed, or enabled
-    @Deprecated
-    public static final Predicate<RegisteredType> IS_TEMPLATE = IS_APPLICATION;
-    
     public static final Predicate<RegisteredType> IS_ENTITY = assignableFrom(Entity.class);
     public static final Predicate<RegisteredType> IS_LOCATION = assignableFrom(Location.class);
     public static final Predicate<RegisteredType> IS_POLICY = assignableFrom(Policy.class);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
index 1e48e46..6fd993a 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
@@ -37,14 +37,15 @@ import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.typereg.JavaClassNameTypePlanTransformer.JavaTypeNameImplementation;
+import org.apache.brooklyn.core.typereg.JavaClassNameTypePlanTransformer.JavaClassNameTypeImplementationPlan;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.yaml.Yamls;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
 import com.google.common.reflect.TypeToken;
 
@@ -54,7 +55,7 @@ import com.google.common.reflect.TypeToken;
  * Use {@link #bean(String, String, TypeImplementationPlan, Class)} and {@link #spec(String, String, TypeImplementationPlan, Class)}
  * to create {@link RegisteredType} instances.
  * <p>
- * See {@link #isSubTypeOf(RegisteredType, Class)} or {@link #isSubTypeOf(RegisteredType, RegisteredType)} to 
+ * See {@link #isAssignableFrom(RegisteredType, Class)} or {@link #isAssignableFrom(RegisteredType, RegisteredType)} to 
  * inspect the type hierarchy.
  */
 public class RegisteredTypes {
@@ -80,7 +81,7 @@ public class RegisteredTypes {
         if (item.getPlanYaml()!=null) {
             impl = new BasicTypeImplementationPlan(null, item.getPlanYaml());
         } else if (item.getJavaType()!=null) {
-            impl = new JavaTypeNameImplementation(item.getJavaType());
+            impl = new JavaClassNameTypeImplementationPlan(item.getJavaType());
         } else {
             throw new IllegalStateException("Unsupported catalog item "+item+" when trying to create RegisteredType");
         }
@@ -99,11 +100,14 @@ public class RegisteredTypes {
         return type;
     }
 
-    /** Preferred mechanism for defining a bean {@link RegisteredType} */
+    /** Preferred mechanism for defining a bean {@link RegisteredType}. */
     public static RegisteredType bean(String symbolicName, String version, TypeImplementationPlan plan, @Nullable Class<?> superType) {
         return addSuperType(new BasicRegisteredType(RegisteredTypeKind.BEAN, symbolicName, version, plan), superType);
     }
     
+    /** Preferred mechanism for defining a spec {@link RegisteredType}. */
+    // TODO we currently allow symbolicName and version to be null for the purposes of creation, internal only in BasicBrooklynTypeRegistry.createSpec
+    // (ideally the API in TypePlanTransformer can be changed so even that is not needed)
     public static RegisteredType spec(String symbolicName, String version, TypeImplementationPlan plan, @Nullable Class<?> superType) {
         return addSuperType(new BasicRegisteredType(RegisteredTypeKind.SPEC, symbolicName, version, plan), superType);
     }
@@ -113,12 +117,11 @@ public class RegisteredTypes {
      * @param mgmt */
     @Beta
     // TODO should this be on the AbstractTypePlanTransformer ?
-    public static Class<?> loadActualJavaType(String javaTypeName, ManagementContext mgmt, RegisteredType type, RegisteredTypeLoadingContext context) throws Exception {
+    public static Class<?> loadActualJavaType(String javaTypeName, ManagementContext mgmt, RegisteredType type, RegisteredTypeLoadingContext context) {
         Class<?> result = ((BasicRegisteredType)type).getCache().get(ACTUAL_JAVA_TYPE);
         if (result!=null) return result;
         
         result = CatalogUtils.newClassLoadingContext(mgmt, type, context==null ? null : context.getLoader()).loadClass( javaTypeName );
-        Preconditions.checkNotNull(result, "Could not load class "+javaTypeName+"; returned null (should have thrown a different exception!)");
         
         ((BasicRegisteredType)type).getCache().put(ACTUAL_JAVA_TYPE, result);
         return result;
@@ -135,7 +138,7 @@ public class RegisteredTypes {
     @Beta
     public static RegisteredType addSuperType(RegisteredType type, @Nullable RegisteredType superType) {
         if (superType!=null) {
-            if (isSubTypeOf(superType, type)) {
+            if (isAssignableFrom(superType, type)) {
                 throw new IllegalStateException(superType+" declares "+type+" as a supertype; cannot set "+superType+" as a supertype of "+type);
             }
             ((BasicRegisteredType)type).superTypes.add(superType);
@@ -143,12 +146,12 @@ public class RegisteredTypes {
         return type;
     }
 
-    /** returns the implementation data for a spec if it is a string (e.g. plan yaml or java class name); else false */
+    /** returns the implementation data for a spec if it is a string (e.g. plan yaml or java class name); else throws */
     @Beta
     public static String getImplementationDataStringForSpec(RegisteredType item) {
         if (item==null || item.getPlan()==null) return null;
         Object data = item.getPlan().getPlanData();
-        if (!(data instanceof String)) return null;
+        if (!(data instanceof String)) throw new IllegalStateException("Expected plan data for "+item+" to be a string");
         return (String)data;
     }
 
@@ -167,7 +170,7 @@ public class RegisteredTypes {
     /** Returns a wrapped map, if the object is YAML which parses as a map; 
      * otherwise returns absent capable of throwing an error with more details */
     @SuppressWarnings("unchecked")
-    public static Maybe<Map<Object,Object>> getAsYamlMap(Object planData) {
+    public static Maybe<Map<?,?>> getAsYamlMap(Object planData) {
         if (!(planData instanceof String)) return Maybe.absent("not a string");
         Iterable<Object> result;
         try {
@@ -180,29 +183,18 @@ public class RegisteredTypes {
         if (!ri.hasNext()) return Maybe.absent("YAML has no elements in it");
         Object r1 = ri.next();
         if (ri.hasNext()) return Maybe.absent("YAML has multiple elements in it");
-        if (r1 instanceof Map) return Maybe.of((Map<Object,Object>)r1);
+        if (r1 instanceof Map) return (Maybe<Map<?,?>>)(Maybe<?>) Maybe.of(r1);
         return Maybe.absent("YAML does not contain a map");
     }
 
     /** 
      * Queries recursively the supertypes of {@link RegisteredType} to see whether it 
-     * declares a supertype compatible with the given {@link Class} */
-    public static boolean isSubTypeOf(RegisteredType type, Class<?> superType) {
-        return isSubTypeOf(type.getSuperTypes(), superType);
-    }
-    
-    /** 
-     * Queries recursively the given types (either {@link Class} or {@link RegisteredType}) 
-     * to see whether any are compatible with the given {@link Class} */
-    public static boolean isSubTypeOf(Set<Object> allKnownTypes, Class<?> superType) {
-        for (Object st: allKnownTypes) {
-            if (st instanceof Class) {
-                if (superType.isAssignableFrom((Class<?>)st)) return true;
-            }
-        }
-        for (Object st: allKnownTypes) {
+     * inherits from the given {@link RegisteredType} */
+    public static boolean isAssignableFrom(RegisteredType type, RegisteredType superType) {
+        if (type.equals(superType)) return true;
+        for (Object st: type.getSuperTypes()) {
             if (st instanceof RegisteredType) {
-                if (isSubTypeOf((RegisteredType)st, superType)) return true;
+                if (isAssignableFrom((RegisteredType)st, superType)) return true;
             }
         }
         return false;
@@ -210,12 +202,30 @@ public class RegisteredTypes {
 
     /** 
      * Queries recursively the supertypes of {@link RegisteredType} to see whether it 
-     * declares a supertype compatible with the given {@link Class} */
-    public static boolean isSubTypeOf(RegisteredType type, RegisteredType superType) {
-        if (type.equals(superType)) return true;
-        for (Object st: type.getSuperTypes()) {
+     * inherits from the given {@link Class} */
+    public static boolean isAssignableFrom(RegisteredType type, Class<?> superType) {
+        return isAnyTypeAssignableFrom(type.getSuperTypes(), superType);
+    }
+    
+    /** 
+     * Queries recursively the given types (either {@link Class} or {@link RegisteredType}) 
+     * to see whether any inherit from the given {@link Class} */
+    public static boolean isAnyTypeAssignableFrom(Set<Object> candidateTypes, Class<?> superType) {
+        return isAnyTypeOrSuperSatisfying(candidateTypes, Predicates.assignableFrom(superType));
+    }
+
+    /** 
+     * Queries recursively the given types (either {@link Class} or {@link RegisteredType}) 
+     * to see whether any java superclasses satisfy the given {@link Predicate} */
+    public static boolean isAnyTypeOrSuperSatisfying(Set<Object> candidateTypes, Predicate<Class<?>> filter) {
+        for (Object st: candidateTypes) {
+            if (st instanceof Class) {
+                if (filter.apply((Class<?>)st)) return true;
+            }
+        }
+        for (Object st: candidateTypes) {
             if (st instanceof RegisteredType) {
-                if (isSubTypeOf((RegisteredType)st, superType)) return true;
+                if (isAnyTypeOrSuperSatisfying(((RegisteredType)st).getSuperTypes(), filter)) return true;
             }
         }
         return false;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java b/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java
index a082a31..b554e09 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java
@@ -98,7 +98,7 @@ public class TypePlanTransformers {
         Map<Double, Collection<BrooklynTypePlanTransformer>> tree = new TreeMap<Double, Collection<BrooklynTypePlanTransformer>>(byScoreMulti.asMap());
         List<Collection<BrooklynTypePlanTransformer>> highestFirst = new ArrayList<Collection<BrooklynTypePlanTransformer>>(tree.values());
         Collections.reverse(highestFirst);
-        return MutableList.copyOf(Iterables.concat(highestFirst)).asUnmodifiable();
+        return ImmutableList.copyOf(Iterables.concat(highestFirst));
     }
 
     /** transforms the given type to an instance, if possible

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/test/java/org/apache/brooklyn/core/catalog/internal/SpecParameterInMetaTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/SpecParameterInMetaTest.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/SpecParameterInMetaTest.java
index 5437765..8fc5dd1 100644
--- a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/SpecParameterInMetaTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/SpecParameterInMetaTest.java
@@ -55,8 +55,12 @@ public class SpecParameterInMetaTest {
     public void setUp() {
         mgmt = LocalManagementContextForTests.newInstanceWithOsgi();
         catalog = mgmt.getCatalog();
+        
+        // TODO ugly, but we need the legacy style TestToSpecTransformer currently to be able to do the transformation;
+        // remove that class and the refs to PlanToSpecFactory here when we're entirely migrated to new-style transformers
         StaticTypePlanTransformer.forceInstall();
         PlanToSpecFactory.forceAvailable(TestToSpecTransformer.class, JavaCatalogToSpecTransformer.class);
+        
         specId = StaticTypePlanTransformer.registerSpec(EntitySpec.create(BasicEntity.class));
     }
 
@@ -79,6 +83,18 @@ public class SpecParameterInMetaTest {
 //        RegisteredType type = mgmt.getTypeRegistry().get(specId);
 //        Assert.assertNotNull(type);
 //    }
+    /* TODO - remove above when @ahgittin and @neykov agree-- discussion from https://github.com/apache/incubator-brooklyn/pull/1017:
+     * 
+     * Being able to create a spec from a plan is different from adding a catalog item so don't agree, it's a separate 
+     * thing. The mechanism could be used for application specs as well, it's not specific to the catalog.
+     * 
+     * Could add a utility method somewhere to add a catalog item for the registered spec, but not useful for the 
+     * following tests.
+     * 
+     * I don't quite follow.  In general if a plan refers to a type, I'd expect that type in the catalog (or a 
+     * java class).  While a transformer can define other rules for instantiating types, I'm not sure that's good 
+     * practice.  (Except it's okay for tests.)
+     */
     
     @Test
     public void testYamlInputsParsed() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformer.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformer.java
index c5568ca..613fe35 100644
--- a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformer.java
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformer.java
@@ -31,19 +31,25 @@ import org.apache.brooklyn.core.typereg.TypePlanTransformers;
 import org.apache.brooklyn.util.text.Identifiers;
 
 /**
- * Resolves previously registered specs by id.
- * First create a spec and register it, keeping the returned ID:
+ * Allows a caller to register a spec (statically) and get a UID for it --
  * <pre> {@code
  * String specId = StaticTypePlanTransformer.registerSpec(EntitySpec.create(BasicEntity.class));
  * }</pre>
- *
- * Then build a plan to be resolved such as:
+ * and then build a plan referring to that type name, such as:
  * <pre> {@code
  *  brooklyn.catalog:
  *    id: test.inputs
  *    version: 0.0.1
  *    item: <specId>
  * } </pre>
+ * <p>
+ * For use when testing type plan resolution. 
+ * <p>
+ * This is different to {@link JavaClassNameTypePlanTransformer} as that one
+ * does a <code>Class.forName(typeName)</code> to create specs, and this one uses a static registry.
+ * <p>
+ * Use {@link #forceInstall()} to set up and {@link #clearForced()} after use (in a finally or "AfterTest" block)
+ * to prevent interference with other tests.
  */
 public class StaticTypePlanTransformer extends AbstractTypePlanTransformer {
     
@@ -59,6 +65,7 @@ public class StaticTypePlanTransformer extends AbstractTypePlanTransformer {
     
     public static void clearForced() {
         TypePlanTransformers.clearForced();
+        REGISTERED_SPECS.clear();
     }
     
     public static String registerSpec(AbstractBrooklynObjectSpec<?, ?> spec) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformer.java b/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformer.java
index 063df64..b31e614 100644
--- a/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformer.java
+++ b/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformer.java
@@ -43,7 +43,8 @@ import org.w3c.dom.Node;
 public class XmlPlanToSpecTransformer implements PlanToSpecTransformer {
     
     // this is REPLACED by ExampleXmlTypePlanTransformer
-
+    // TODO remove when PlanToSpecTransformer is removed
+    
     @SuppressWarnings("unused")
     private ManagementContext mgmt;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/test/java/org/apache/brooklyn/core/test/BrooklynMgmtUnitTestSupport.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/BrooklynMgmtUnitTestSupport.java b/core/src/test/java/org/apache/brooklyn/core/test/BrooklynMgmtUnitTestSupport.java
index 956ad63..9742bce 100644
--- a/core/src/test/java/org/apache/brooklyn/core/test/BrooklynMgmtUnitTestSupport.java
+++ b/core/src/test/java/org/apache/brooklyn/core/test/BrooklynMgmtUnitTestSupport.java
@@ -50,6 +50,9 @@ public class BrooklynMgmtUnitTestSupport {
             if (mgmt != null) Entities.destroyAll(mgmt);
         } catch (Throwable t) {
             LOG.error("Caught exception in tearDown method", t);
+            // we should fail here, except almost always that masks a primary failure in the test itself,
+            // so it would be extremely unhelpful to do so. if we could check if test has not already failed,
+            // that would be ideal, but i'm not sure if that's possible with TestNG. ?
         } finally {
             mgmt = null;
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformer.java b/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformer.java
index 01b80a1..23035c4 100644
--- a/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformer.java
+++ b/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformer.java
@@ -71,7 +71,7 @@ public class ExampleXmlTypePlanTransformer extends AbstractTypePlanTransformer {
     }
 
     private static boolean isApplicationExpected(RegisteredType type, RegisteredTypeLoadingContext context) {
-        return RegisteredTypes.isSubTypeOf(type, Application.class) ||
+        return RegisteredTypes.isAssignableFrom(type, Application.class) ||
             (context.getExpectedJavaSuperType()!=null && context.getExpectedJavaSuperType().isAssignableFrom(Application.class));
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/test/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformerTest.java b/core/src/test/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformerTest.java
new file mode 100644
index 0000000..23dc2f3
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformerTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.typereg;
+
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.core.test.BrooklynMgmtUnitTestSupport;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class JavaClassNameTypePlanTransformerTest extends BrooklynMgmtUnitTestSupport {
+
+    public static class NoArg {
+        public String name() { return "no-arg"; }
+    }
+
+    protected RegisteredType type;
+    protected BrooklynTypePlanTransformer transformer;
+    
+    @BeforeMethod(alwaysRun=true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        type = newNoArgRegisteredType(JavaClassNameTypePlanTransformer.FORMAT);
+        transformer = newTransformer();
+    }
+    
+    protected RegisteredType newNoArgRegisteredType(String format) {
+        return RegisteredTypes.bean("no-arg", "1.0", new BasicTypeImplementationPlan(format, NoArg.class.getName()), null);
+    }
+    
+    protected BrooklynTypePlanTransformer newTransformer() {
+        BrooklynTypePlanTransformer xf = new JavaClassNameTypePlanTransformer();
+        xf.injectManagementContext(mgmt);
+        return xf;
+    }
+    
+    @Test
+    public void testScoreJavaType() {
+        double score = transformer.scoreForType(type, null);
+        Assert.assertEquals(score, 1, 0.00001);
+    }
+
+    @Test
+    public void testCreateJavaType() {
+        Object obj = transformer.create(type, null);
+        Assert.assertTrue(obj instanceof NoArg, "obj is "+obj);
+        Assert.assertEquals(((NoArg)obj).name(), "no-arg");
+    }
+
+    @Test
+    public void testScoreJavaTypeWithNullFormat() {
+        type = newNoArgRegisteredType(null);
+        double score = transformer.scoreForType(type, null);
+        Assert.assertEquals(score, 0.1, 0.00001);
+    }
+
+    @Test
+    public void testCreateJavaTypeWithNullFormat() {
+        type = newNoArgRegisteredType(null);
+        Object obj = transformer.create(type, null);
+        Assert.assertTrue(obj instanceof NoArg, "obj is "+obj);
+        Assert.assertEquals(((NoArg)obj).name(), "no-arg");
+    }
+
+    @Test
+    public void testScoreJavaTypeWithOtherFormat() {
+        type = newNoArgRegisteredType("crazy-format");
+        double score = transformer.scoreForType(type, null);
+        Assert.assertEquals(score, 0, 0.00001);
+        // we don't test creation; it may or may not succeed, but with score 0 it shouldn't get invoked
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java b/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java
deleted file mode 100644
index def79d8..0000000
--- a/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java
+++ /dev/null
@@ -1,90 +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.typereg;
-
-import org.apache.brooklyn.api.typereg.RegisteredType;
-import org.apache.brooklyn.core.test.BrooklynMgmtUnitTestSupport;
-import org.testng.Assert;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-public class JavaTypePlanTransformerTest extends BrooklynMgmtUnitTestSupport {
-
-    public static class NoArg {
-        public String name() { return "no-arg"; }
-    }
-
-    protected RegisteredType type;
-    protected BrooklynTypePlanTransformer transformer;
-    
-    @BeforeMethod(alwaysRun=true)
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        type = newNoArgRegisteredType(JavaClassNameTypePlanTransformer.FORMAT);
-        transformer = newTransformer();
-    }
-    
-    protected RegisteredType newNoArgRegisteredType(String format) {
-        return RegisteredTypes.bean("no-arg", "1.0", new BasicTypeImplementationPlan(format, NoArg.class.getName()), null);
-    }
-    
-    protected BrooklynTypePlanTransformer newTransformer() {
-        BrooklynTypePlanTransformer xf = new JavaClassNameTypePlanTransformer();
-        xf.injectManagementContext(mgmt);
-        return xf;
-    }
-    
-    @Test
-    public void testScoreJavaType() {
-        double score = transformer.scoreForType(type, null);
-        Assert.assertEquals(score, 1, 0.00001);
-    }
-
-    @Test
-    public void testCreateJavaType() {
-        Object obj = transformer.create(type, null);
-        Assert.assertTrue(obj instanceof NoArg, "obj is "+obj);
-        Assert.assertEquals(((NoArg)obj).name(), "no-arg");
-    }
-
-    @Test
-    public void testScoreJavaTypeWithNullFormat() {
-        type = newNoArgRegisteredType(null);
-        double score = transformer.scoreForType(type, null);
-        Assert.assertEquals(score, 0.1, 0.00001);
-    }
-
-    @Test
-    public void testCreateJavaTypeWithNullFormat() {
-        type = newNoArgRegisteredType(null);
-        Object obj = transformer.create(type, null);
-        Assert.assertTrue(obj instanceof NoArg, "obj is "+obj);
-        Assert.assertEquals(((NoArg)obj).name(), "no-arg");
-    }
-
-    @Test
-    public void testScoreJavaTypeWithOtherFormat() {
-        type = newNoArgRegisteredType("crazy-format");
-        double score = transformer.scoreForType(type, null);
-        Assert.assertEquals(score, 0, 0.00001);
-        // we don't test creation; it may or may not succeed, but with score 0 it shouldn't get invoked
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
index 87bd381..8540663 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
@@ -29,9 +29,6 @@ import org.apache.brooklyn.camp.spi.AssemblyTemplate;
 import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
 
 public interface AssemblyTemplateSpecInstantiator extends AssemblyTemplateInstantiator {
-
-    @Deprecated /** @deprecaed since 0.9.0 include encountered types */
-    EntitySpec<? extends Application> createApplicationSpec(AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext loader);
     
     /**
      * Gets the single item returned by {@link #createServiceSpecs}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
index 6c7a479..5840440 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
@@ -77,14 +77,6 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
     public EntitySpec<? extends Application> createApplicationSpec(
             AssemblyTemplate template,
             CampPlatform platform,
-            BrooklynClassLoadingContext loader) {
-        return createApplicationSpec(template, platform, loader, MutableSet.<String>of());
-    }
-    
-    @Override
-    public EntitySpec<? extends Application> createApplicationSpec(
-            AssemblyTemplate template,
-            CampPlatform platform,
             BrooklynClassLoadingContext loader,
             Set<String> encounteredTypeSymbolicNames) {
         log.debug("CAMP creating application instance for {} ({})", template.getId(), template);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
index e6c514a..b9e63d1 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
@@ -39,6 +39,7 @@ import org.apache.brooklyn.core.mgmt.EntityManagementUtils;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.text.Strings;
+import org.python.google.common.collect.Iterables;
 
 import com.google.common.collect.ImmutableSet;
 
@@ -48,20 +49,22 @@ class CampResolver {
     private RegisteredType type;
     private RegisteredTypeLoadingContext context;
 
-    /** whether to allow parsing of the 'full' syntax for applications,
-     * where items are wrapped in a "services:" block, and if the wrapper is an application,
-     * to promote it */
-    boolean allowApplicationFullSyntax = true;
-
-    /** whether to allow parsing of the legacy 'full' syntax, 
-     * where a non-application items are wrapped:
-     * <li> in a "services:" block for entities,
-     * <li> in a "brooklyn.locations" or "brooklyn.policies" block for locations and policies */
-    boolean allowLegacyFullSyntax = true;
-
-    /** whether to allow parsing of the type syntax, where an item is a map with a "type:" field,
-     * i.e. not wrapped in any "services:" or "brooklyn.{locations,policies}" block */
-    boolean allowTypeSyntax = true;
+    // TODO we have a few different modes, detailed below; this logic should be moved to the new transformer
+    // and allow specifying which modes are permitted to be in effect?
+//    /** whether to allow parsing of the 'full' syntax for applications,
+//     * where items are wrapped in a "services:" block, and if the wrapper is an application,
+//     * to promote it */
+//    boolean allowApplicationFullSyntax = true;
+//
+//    /** whether to allow parsing of the legacy 'full' syntax, 
+//     * where a non-application items are wrapped:
+//     * <li> in a "services:" block for entities,
+//     * <li> in a "brooklyn.locations" or "brooklyn.policies" block for locations and policies */
+//    boolean allowLegacyFullSyntax = true;
+//
+//    /** whether to allow parsing of the type syntax, where an item is a map with a "type:" field,
+//     * i.e. not wrapped in any "services:" or "brooklyn.{locations,policies}" block */
+//    boolean allowTypeSyntax = true;
 
     public CampResolver(ManagementContext mgmt, RegisteredType type, RegisteredTypeLoadingContext context) {
         this.mgmt = mgmt;
@@ -97,19 +100,20 @@ class CampResolver {
         String planYaml = RegisteredTypes.getImplementationDataStringForSpec(item);
         MutableSet<Object> supers = MutableSet.copyOf(item.getSuperTypes());
         supers.addIfNotNull(expectedType);
-        if (RegisteredTypes.isSubTypeOf(supers, Policy.class)) {
+        if (RegisteredTypes.isAnyTypeAssignableFrom(supers, Policy.class)) {
             spec = CampInternalUtils.createPolicySpec(planYaml, loader, encounteredTypes);
-        } else if (RegisteredTypes.isSubTypeOf(supers, Location.class)) {
+        } else if (RegisteredTypes.isAnyTypeAssignableFrom(supers, Location.class)) {
             spec = CampInternalUtils.createLocationSpec(planYaml, loader, encounteredTypes);
-        } else if (RegisteredTypes.isSubTypeOf(supers, Application.class)) {
+        } else if (RegisteredTypes.isAnyTypeAssignableFrom(supers, Application.class)) {
             spec = createEntitySpecFromServicesBlock(planYaml, loader, encounteredTypes, true);
-        } else if (RegisteredTypes.isSubTypeOf(supers, Entity.class)) {
+        } else if (RegisteredTypes.isAnyTypeAssignableFrom(supers, Entity.class)) {
             spec = createEntitySpecFromServicesBlock(planYaml, loader, encounteredTypes, false);
         } else {
-            // try any of them???
-            
             throw new IllegalStateException("Cannot detect spec type from "+item.getSuperTypes()+" for "+item+"\n"+planYaml);
         }
+        if (expectedType!=null && !expectedType.isAssignableFrom(spec.getType())) {
+            throw new IllegalStateException("Creating spec from "+item+", got "+spec.getType()+" which is incompatible with expected "+expectedType);                
+        }
 
         ((AbstractBrooklynObjectSpec<?, ?>)spec).catalogItemId(item.getId());
 
@@ -127,9 +131,8 @@ class CampResolver {
         if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
             EntitySpec<? extends Application> appSpec = ((AssemblyTemplateSpecInstantiator)instantiator).createApplicationSpec(at, camp, loader, encounteredTypes);
 
-            if (!isApplication && EntityManagementUtils.canPromoteChildrenInWrappedApplication(appSpec) && appSpec.getChildren().size()==1) {
-                CampInternalUtils.resetSpecIfTemplateHasNoExplicitParameters(at, appSpec);
-                EntitySpec<?> childSpec = appSpec.getChildren().get(0);
+            if (!isApplication && EntityManagementUtils.canPromoteChildrenInWrappedApplication(appSpec)) {
+                EntitySpec<?> childSpec = Iterables.getOnlyElement(appSpec.getChildren());
                 EntityManagementUtils.mergeWrapperParentSpecToChildEntity(appSpec, childSpec);
                 return childSpec;
             }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
index f287fec..afeba41 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
@@ -25,7 +25,7 @@ import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.api.typereg.RegisteredType.TypeImplementationPlan;
 import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
-import org.apache.brooklyn.core.typereg.AbstractCustomImplementationPlan;
+import org.apache.brooklyn.core.typereg.AbstractFormatSpecificTypeImplementationPlan;
 import org.apache.brooklyn.core.typereg.AbstractTypePlanTransformer;
 import org.apache.brooklyn.core.typereg.BasicTypeImplementationPlan;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
@@ -47,7 +47,7 @@ public class CampTypePlanTransformer extends AbstractTypePlanTransformer {
 
     @Override
     protected double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeLoadingContext context) {
-        Maybe<Map<Object, Object>> plan = RegisteredTypes.getAsYamlMap(planData);
+        Maybe<Map<?,?>> plan = RegisteredTypes.getAsYamlMap(planData);
         if (plan.isAbsent()) return 0;
         if (plan.get().containsKey("services")) return 0.8;
         if (plan.get().containsKey("type")) return 0.4;
@@ -87,7 +87,7 @@ public class CampTypePlanTransformer extends AbstractTypePlanTransformer {
         return null;
     }
 
-    public static class CampTypeImplementationPlan extends AbstractCustomImplementationPlan<String> {
+    public static class CampTypeImplementationPlan extends AbstractFormatSpecificTypeImplementationPlan<String> {
         public CampTypeImplementationPlan(TypeImplementationPlan otherPlan) {
             super(FORMATS.get(0), String.class, otherPlan);
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
index 215fd1a..0a1b232 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
@@ -241,17 +241,17 @@ public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest {
         for (RegisteredType item: items) {
             Object spec = types.createSpec(item, null, null);
             int match = 0;
-            if (RegisteredTypes.isSubTypeOf(item, Entity.class)) {
+            if (RegisteredTypes.isAssignableFrom(item, Entity.class)) {
                 assertTrue(spec instanceof EntitySpec, "Not an EntitySpec: " + spec);
                 BrooklynTypes.getDefinedEntityType(((EntitySpec<?>)spec).getType());
                 match++;
             }
-            if (RegisteredTypes.isSubTypeOf(item, Policy.class)) {
+            if (RegisteredTypes.isAssignableFrom(item, Policy.class)) {
                 assertTrue(spec instanceof PolicySpec, "Not a PolicySpec: " + spec);
                 BrooklynTypes.getDefinedBrooklynType(((PolicySpec<?>)spec).getType());
                 match++;
             }
-            if (RegisteredTypes.isSubTypeOf(item, Location.class)) {
+            if (RegisteredTypes.isAssignableFrom(item, Location.class)) {
                 assertTrue(spec instanceof LocationSpec, "Not a LocationSpec: " + spec);
                 BrooklynTypes.getDefinedBrooklynType(((LocationSpec<?>)spec).getType());
                 match++;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
index 52d48e4..7fa8896 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
@@ -111,7 +111,7 @@ public class CatalogYamlLocationTest extends AbstractYamlTest {
     private void assertAdded(String symbolicName, String expectedJavaType) {
         RegisteredType item = mgmt().getTypeRegistry().get(symbolicName, TEST_VERSION);
         assertEquals(item.getSymbolicName(), symbolicName);
-        Assert.assertTrue(RegisteredTypes.isSubTypeOf(item, Location.class), "Expected Location, not "+item.getSuperTypes());
+        Assert.assertTrue(RegisteredTypes.isAssignableFrom(item, Location.class), "Expected Location, not "+item.getSuperTypes());
         assertEquals(countCatalogLocations(), 1);
 
         // Item added to catalog should automatically be available in location registry

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java
index 6f9de6e..91dfb0e 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java
@@ -62,10 +62,6 @@ public class TestAppAssemblyInstantiator extends BasicAssemblyTemplateInstantiat
     }
 
     @Override
-    public EntitySpec<? extends Application> createApplicationSpec(AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext loader) {
-        return createApplicationSpec(template, platform, loader, MutableSet.<String>of());
-    }
-    @Override
     public EntitySpec<? extends Application> createApplicationSpec(AssemblyTemplate template, CampPlatform platform,
         BrooklynClassLoadingContext loader, Set<String> encounteredCatalogTypes) {
         EntitySpec<TestApplication> app = EntitySpec.create(TestApplication.class)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/utils/common/src/main/java/org/apache/brooklyn/util/text/Identifiers.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/text/Identifiers.java b/utils/common/src/main/java/org/apache/brooklyn/util/text/Identifiers.java
index b389f9c..c2ec4a5 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/text/Identifiers.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/text/Identifiers.java
@@ -23,12 +23,20 @@ import java.util.Random;
 public class Identifiers {
     
     private static Random random = new Random();
-    
+
+    /** @see #JAVA_GOOD_PACKAGE_OR_CLASS_REGEX */ 
     public static final String JAVA_GOOD_START_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_";
+    /** @see #JAVA_GOOD_PACKAGE_OR_CLASS_REGEX */ 
     public static final String JAVA_GOOD_NONSTART_CHARS = JAVA_GOOD_START_CHARS+"1234567890";
-    public static final String JAVA_SEGMENT_REGEX = "["+JAVA_GOOD_START_CHARS+"]"+"["+JAVA_GOOD_NONSTART_CHARS+"]*";
-    public static final String JAVA_PACKAGE_OR_CLASS_REGEX = "("+JAVA_SEGMENT_REGEX+"\\."+")*"+JAVA_SEGMENT_REGEX;
-    public static final String JAVA_BINARY_REGEX = JAVA_PACKAGE_OR_CLASS_REGEX+"(\\$["+JAVA_GOOD_NONSTART_CHARS+"]+)*";
+    /** @see #JAVA_GOOD_PACKAGE_OR_CLASS_REGEX */ 
+    public static final String JAVA_GOOD_SEGMENT_REGEX = "["+JAVA_GOOD_START_CHARS+"]"+"["+JAVA_GOOD_NONSTART_CHARS+"]*";
+    /** regex for a java package or class name using "good" chars, that is no accents or funny unicodes.
+     * see http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.8 for the full set supported by the spec;
+     * but it's rare to deviate from this subset and it causes problems when charsets aren't respected (tsk tsk but not uncommon!).
+     * our use cases so far only require testing for "good" names. */
+    public static final String JAVA_GOOD_PACKAGE_OR_CLASS_REGEX = "("+JAVA_GOOD_SEGMENT_REGEX+"\\."+")*"+JAVA_GOOD_SEGMENT_REGEX;
+    /** as {@link #JAVA_GOOD_PACKAGE_OR_CLASS_REGEX} but allowing a dollar sign inside a class name (e.g. Foo$1) */
+    public static final String JAVA_GOOD_BINARY_REGEX = JAVA_GOOD_PACKAGE_OR_CLASS_REGEX+"(\\$["+JAVA_GOOD_NONSTART_CHARS+"]+)*";
     
     public static final String JAVA_GENERATED_IDENTIFIER_START_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
     public static final String JAVA_GENERATED_IDENTIFIERNONSTART_CHARS = JAVA_GENERATED_IDENTIFIER_START_CHARS+"1234567890";

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/db024f4e/utils/common/src/test/java/org/apache/brooklyn/util/text/IdentifiersTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/text/IdentifiersTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/text/IdentifiersTest.java
index 8f4463f..7b4f999 100644
--- a/utils/common/src/test/java/org/apache/brooklyn/util/text/IdentifiersTest.java
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/text/IdentifiersTest.java
@@ -88,8 +88,15 @@ public class IdentifiersTest {
 
     @Test
     public void testJavaClassRegex() {
-        Assert.assertTrue("foo".matches(Identifiers.JAVA_BINARY_REGEX));
-        Assert.assertTrue("foo.bar.Baz$1".matches(Identifiers.JAVA_BINARY_REGEX));
+        Assert.assertTrue("foo".matches(Identifiers.JAVA_GOOD_SEGMENT_REGEX));
+        Assert.assertFalse("foo.bar.Baz".matches(Identifiers.JAVA_GOOD_SEGMENT_REGEX));
+        
+        Assert.assertTrue("foo".matches(Identifiers.JAVA_GOOD_PACKAGE_OR_CLASS_REGEX));
+        Assert.assertTrue("foo.bar.Baz".matches(Identifiers.JAVA_GOOD_PACKAGE_OR_CLASS_REGEX));
+        Assert.assertFalse("foo.bar.Baz$1".matches(Identifiers.JAVA_GOOD_PACKAGE_OR_CLASS_REGEX));
+        
+        Assert.assertTrue("foo".matches(Identifiers.JAVA_GOOD_BINARY_REGEX));
+        Assert.assertTrue("foo.bar.Baz$1".matches(Identifiers.JAVA_GOOD_BINARY_REGEX));
     }
     
 }


[03/14] incubator-brooklyn git commit: XML-based illustration of new-style XML plan creation

Posted by he...@apache.org.
XML-based illustration of new-style XML plan creation

and tidy API and update deprecation


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

Branch: refs/heads/master
Commit: e480402f30237e5af0604eb82606901be2acaa20
Parents: e932d5f
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Nov 9 16:53:17 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Nov 10 17:13:02 2015 +0000

----------------------------------------------------------------------
 .../brooklyn/api/catalog/CatalogItem.java       |  24 ++++
 .../catalog/internal/BasicBrooklynCatalog.java  |  12 +-
 .../catalog/internal/CatalogItemBuilder.java    |  46 +++---
 .../core/typereg/BasicBrooklynTypeRegistry.java |  18 ++-
 .../core/plan/XmlPlanToSpecTransformer.java     |   2 +
 .../core/plan/XmlPlanToSpecTransformerTest.java |   2 +
 .../typereg/ExampleXmlTypePlanTransformer.java  | 140 +++++++++++++++++++
 .../ExampleXmlTypePlanTransformerTest.java      |  67 +++++++++
 .../camp/brooklyn/AbstractYamlTest.java         |   3 -
 9 files changed, 281 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e480402f/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java b/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
index 7f4e3b3..fe21daa 100644
--- a/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
+++ b/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
@@ -23,11 +23,19 @@ import java.util.List;
 
 import javax.annotation.Nullable;
 
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationSpec;
 import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
 import org.apache.brooklyn.api.mgmt.rebind.Rebindable;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.CatalogItemMemento;
 import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.objs.SpecParameter;
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.api.policy.PolicySpec;
 import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl;
 
 import com.google.common.annotations.Beta;
@@ -40,6 +48,22 @@ public interface CatalogItem<T,SpecT> extends BrooklynObject, Rebindable {
         ENTITY, 
         POLICY,
         LOCATION;
+        
+        public static CatalogItemType ofSpecClass(Class<? extends AbstractBrooklynObjectSpec<?, ?>> type) {
+            if (type==null) return null;
+            if (PolicySpec.class.isAssignableFrom(type)) return POLICY;
+            if (LocationSpec.class.isAssignableFrom(type)) return LOCATION;
+            if (EntitySpec.class.isAssignableFrom(type)) return ENTITY;
+            return null;
+        }
+        public static CatalogItemType ofTargetClass(Class<? extends BrooklynObject> type) {
+            if (type==null) return null;
+            if (Policy.class.isAssignableFrom(type)) return POLICY;
+            if (Location.class.isAssignableFrom(type)) return LOCATION;
+            if (Application.class.isAssignableFrom(type)) return TEMPLATE;
+            if (Entity.class.isAssignableFrom(type)) return ENTITY;
+            return null;
+        }
     }
     
     public static interface CatalogBundle extends OsgiBundleWithUrl {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e480402f/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
index 0832b4f..75c727a 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
@@ -63,7 +63,6 @@ import org.slf4j.LoggerFactory;
 import org.yaml.snakeyaml.Yaml;
 
 import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.Collections2;
@@ -849,15 +848,8 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         return Strings.join(lines, "\n");
     }
 
-    private CatalogItemBuilder<?> createItemBuilder(CatalogItemType itemType, String itemId, String version) {
-        Preconditions.checkNotNull(itemType, "itemType required");
-        switch (itemType) {
-        case ENTITY: return CatalogItemBuilder.newEntity(itemId, version);
-        case TEMPLATE: return CatalogItemBuilder.newTemplate(itemId, version);
-        case POLICY: return CatalogItemBuilder.newPolicy(itemId, version);
-        case LOCATION: return CatalogItemBuilder.newLocation(itemId, version);
-        }
-        throw new IllegalStateException("Unexpected itemType: "+itemType);
+    static CatalogItemBuilder<?> createItemBuilder(CatalogItemType itemType, String symbolicName, String version) {
+        return CatalogItemBuilder.newItem(itemType, symbolicName, version);
     }
 
     // these kept as their logic may prove useful; Apr 2015

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e480402f/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemBuilder.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemBuilder.java
index 1f9b9a2..59bc3a9 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemBuilder.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemBuilder.java
@@ -23,12 +23,24 @@ import java.util.Collections;
 import java.util.List;
 
 import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
+import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemType;
 import org.apache.brooklyn.api.objs.SpecParameter;
 
 import com.google.common.base.Preconditions;
 
-public class CatalogItemBuilder<CatalogItemType extends CatalogItemDtoAbstract<?, ?>> {
-    private CatalogItemType dto;
+public class CatalogItemBuilder<CIConcreteType extends CatalogItemDtoAbstract<?, ?>> {
+    private CIConcreteType dto;
+
+    public static CatalogItemBuilder<?> newItem(CatalogItemType itemType, String symbolicName, String version) {
+        Preconditions.checkNotNull(itemType, "itemType required");
+        switch (itemType) {
+        case ENTITY: return newEntity(symbolicName, version);
+        case TEMPLATE: return newTemplate(symbolicName, version);
+        case POLICY: return newPolicy(symbolicName, version);
+        case LOCATION: return newLocation(symbolicName, version);
+        }
+        throw new IllegalStateException("Unexpected itemType: "+itemType);
+    }
 
     public static CatalogItemBuilder<CatalogEntityItemDto> newEntity(String symbolicName, String version) {
         return new CatalogItemBuilder<CatalogEntityItemDto>(new CatalogEntityItemDto())
@@ -54,74 +66,74 @@ public class CatalogItemBuilder<CatalogItemType extends CatalogItemDtoAbstract<?
                 .version(version);
     }
 
-    public CatalogItemBuilder(CatalogItemType dto) {
+    public CatalogItemBuilder(CIConcreteType dto) {
         this.dto = dto;
         this.dto.setLibraries(Collections.<CatalogBundle>emptyList());
     }
 
-    public CatalogItemBuilder<CatalogItemType> symbolicName(String symbolicName) {
+    public CatalogItemBuilder<CIConcreteType> symbolicName(String symbolicName) {
         dto.setSymbolicName(symbolicName);
         return this;
     }
 
     @Deprecated
-    public CatalogItemBuilder<CatalogItemType> javaType(String javaType) {
+    public CatalogItemBuilder<CIConcreteType> javaType(String javaType) {
         dto.setJavaType(javaType);
         return this;
     }
 
     /** @deprecated since 0.7.0 use {@link #displayName}*/
     @Deprecated
-    public CatalogItemBuilder<CatalogItemType> name(String name) {
+    public CatalogItemBuilder<CIConcreteType> name(String name) {
         return displayName(name);
     }
 
-    public CatalogItemBuilder<CatalogItemType> displayName(String displayName) {
+    public CatalogItemBuilder<CIConcreteType> displayName(String displayName) {
         dto.setDisplayName(displayName);
         return this;
     }
 
-    public CatalogItemBuilder<CatalogItemType> description(String description) {
+    public CatalogItemBuilder<CIConcreteType> description(String description) {
         dto.setDescription(description);
         return this;
     }
 
-    public CatalogItemBuilder<CatalogItemType> iconUrl(String iconUrl) {
+    public CatalogItemBuilder<CIConcreteType> iconUrl(String iconUrl) {
         dto.setIconUrl(iconUrl);
         return this;
     }
 
-    public CatalogItemBuilder<CatalogItemType> version(String version) {
+    public CatalogItemBuilder<CIConcreteType> version(String version) {
         dto.setVersion(version);
         return this;
     }
 
-    public CatalogItemBuilder<CatalogItemType> deprecated(boolean deprecated) {
+    public CatalogItemBuilder<CIConcreteType> deprecated(boolean deprecated) {
         dto.setDeprecated(deprecated);
         return this;
     }
 
-    public CatalogItemBuilder<CatalogItemType> disabled(boolean disabled) {
+    public CatalogItemBuilder<CIConcreteType> disabled(boolean disabled) {
         dto.setDisabled(disabled);
         return this;
     }
 
-    public CatalogItemBuilder<CatalogItemType> parameters(List<SpecParameter<?>> inputs) {
+    public CatalogItemBuilder<CIConcreteType> parameters(List<SpecParameter<?>> inputs) {
         dto.setParameters(inputs);
         return this;
     }
 
-    public CatalogItemBuilder<CatalogItemType> libraries(Collection<CatalogBundle> libraries) {
+    public CatalogItemBuilder<CIConcreteType> libraries(Collection<CatalogBundle> libraries) {
         dto.setLibraries(libraries);
         return this;
     }
 
-    public CatalogItemBuilder<CatalogItemType> plan(String yaml) {
+    public CatalogItemBuilder<CIConcreteType> plan(String yaml) {
         dto.setPlanYaml(yaml);
         return this;
     }
 
-    public CatalogItemType build() {
+    public CIConcreteType build() {
         Preconditions.checkNotNull(dto.getSymbolicName());
         Preconditions.checkNotNull(dto.getVersion());
 
@@ -132,7 +144,7 @@ public class CatalogItemBuilder<CatalogItemType extends CatalogItemDtoAbstract<?
             dto.setLibraries(Collections.<CatalogBundle>emptyList());
         }
 
-        CatalogItemType ret = dto;
+        CIConcreteType ret = dto;
 
         //prevent mutations through the builder
         dto = null;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e480402f/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
index cfb9f9b..b5c85c1 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
@@ -22,16 +22,19 @@ import javax.annotation.Nullable;
 
 import org.apache.brooklyn.api.catalog.BrooklynCatalog;
 import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemType;
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
 import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
+import org.apache.brooklyn.core.catalog.internal.CatalogItemBuilder;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.text.Identifiers;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -121,9 +124,18 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
         // TODO remove once all transformers are available in the new style
         CatalogItem item = (CatalogItem) mgmt.getCatalog().getCatalogItem(type.getSymbolicName(), type.getVersion());
         if (item==null) {
-            // if not in catalog (because loading a new item?) then throw original
-            // (NB: to support any recursive legacy transformers we might have to create a CI; cross that bridge when we come to it)
-            result.get();
+            // if not in catalog (because loading a new item?) then look up item based on type
+            // (only really used in tests; possibly also for any recursive legacy transformers we might have to create a CI; cross that bridge when we come to it)
+            CatalogItemType ciType = CatalogItemType.ofTargetClass( (Class)constraint.getExpectedJavaSuperType() );
+            if (ciType==null) {
+                // throw -- not supported for non-spec types
+                result.get();
+            }
+            item = CatalogItemBuilder.newItem(ciType, 
+                    type.getSymbolicName()!=null ? type.getSymbolicName() : Identifiers.makeRandomId(8), 
+                        type.getVersion()!=null ? type.getVersion() : BasicBrooklynCatalog.DEFAULT_VERSION)
+                .plan(RegisteredTypes.getImplementationDataStringForSpec(type))
+                .build();
         }
         try {
             return (SpecT) BasicBrooklynCatalog.internalCreateSpecLegacy(mgmt, item, constraint.getAlreadyEncounteredTypes(), false);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e480402f/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformer.java b/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformer.java
index a4c3766..063df64 100644
--- a/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformer.java
+++ b/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformer.java
@@ -41,6 +41,8 @@ import org.w3c.dom.Node;
 /** Example implementation of {@link PlanToSpecTransformer} showing 
  * how implementations are meant to be written. */
 public class XmlPlanToSpecTransformer implements PlanToSpecTransformer {
+    
+    // this is REPLACED by ExampleXmlTypePlanTransformer
 
     @SuppressWarnings("unused")
     private ManagementContext mgmt;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e480402f/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformerTest.java b/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformerTest.java
index 19a6ba4..ffec32c 100644
--- a/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/plan/XmlPlanToSpecTransformerTest.java
@@ -36,6 +36,8 @@ import org.testng.annotations.Test;
  * which illustrates how the {@link PlanToSpecTransformer} can be used. */
 public class XmlPlanToSpecTransformerTest {
 
+    // TEST is REPLACED by ExampleXmlTypePlanTransformerTest
+   
     private ManagementContext mgmt;
 
     @BeforeMethod(alwaysRun=true)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e480402f/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformer.java b/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformer.java
new file mode 100644
index 0000000..01b80a1
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformer.java
@@ -0,0 +1,140 @@
+/*
+ * 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.typereg;
+
+import java.io.StringReader;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
+import org.apache.brooklyn.entity.stock.BasicApplication;
+import org.apache.brooklyn.entity.stock.BasicEntity;
+import org.apache.brooklyn.util.core.xstream.XmlSerializer;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.stream.ReaderInputStream;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/** Example implementation of {@link BrooklynTypePlanTransformer} showing 
+ * how implementations are meant to be written. */
+public class ExampleXmlTypePlanTransformer extends AbstractTypePlanTransformer {
+
+    protected ExampleXmlTypePlanTransformer() {
+        super("example-xml", "Example XML", "Illustration of writing a transformer");
+    }
+
+    @Override
+    protected double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeLoadingContext context) {
+        if (!(planData instanceof String)) return 0;
+        try {
+            // if it's XML, accept it
+            parseXml((String)planData);
+            return 0.3;
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            return 0;
+        }
+    }
+
+    @Override
+    protected double scoreForNonmatchingNonnullFormat(String planFormat, Object planData, RegisteredType type, RegisteredTypeLoadingContext context) {
+        // only null and xml supported
+        return 0;
+    }
+
+    @Override
+    protected AbstractBrooklynObjectSpec<?, ?> createSpec(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception {
+        return toEntitySpec(parseXml((String)type.getPlan().getPlanData()), 
+            isApplicationExpected(type, context) ? 0 : 1);
+    }
+
+    private static boolean isApplicationExpected(RegisteredType type, RegisteredTypeLoadingContext context) {
+        return RegisteredTypes.isSubTypeOf(type, Application.class) ||
+            (context.getExpectedJavaSuperType()!=null && context.getExpectedJavaSuperType().isAssignableFrom(Application.class));
+    }
+
+    @Override
+    protected Object createBean(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception {
+        return new XmlSerializer<Object>().fromString((String)type.getPlan().getPlanData());
+    }
+
+
+    @Override
+    public double scoreForTypeDefinition(String formatCode, Object catalogData) {
+        // defining types not supported
+        return 0;
+    }
+
+    @Override
+    public List<RegisteredType> createFromTypeDefinition(String formatCode, Object catalogData) {
+        // defining types not supported
+        return null;
+    }
+
+    private Document parseXml(String plan) {
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        Document dom;
+        
+        try {
+            //Using factory get an instance of document builder
+            DocumentBuilder db = dbf.newDocumentBuilder();
+
+            //parse using builder to get DOM representation of the XML file
+            dom = db.parse(new ReaderInputStream(new StringReader(plan)));
+            
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            throw new UnsupportedTypePlanException(e);
+        }
+        return dom;
+    }
+
+    private EntitySpec<?> toEntitySpec(Node dom, int depth) {
+        if (dom.getNodeType()==Node.DOCUMENT_NODE) {
+            if (dom.getChildNodes().getLength()!=1) {
+                // NB: <?...?>  entity preamble might break this
+                throw new IllegalStateException("Document for "+dom+" has "+dom.getChildNodes().getLength()+" nodes; 1 expected.");
+            }
+            return toEntitySpec(dom.getChildNodes().item(0), depth);
+        }
+        
+        EntitySpec<?> result = depth == 0 ? EntitySpec.create(BasicApplication.class) : EntitySpec.create(BasicEntity.class);
+        result.displayName(dom.getNodeName());
+        if (dom.getAttributes()!=null) {
+            for (int i=0; i<dom.getAttributes().getLength(); i++)
+                result.configure(dom.getAttributes().item(i).getNodeName(), dom.getAttributes().item(i).getTextContent());
+        }
+        if (dom.getChildNodes()!=null) {
+            for (int i=0; i<dom.getChildNodes().getLength(); i++) {
+                Node item = dom.getChildNodes().item(i);
+                if (item.getNodeType()==Node.ELEMENT_NODE) {
+                    result.child(toEntitySpec(item, depth+1));
+                }
+            }
+        }
+        return result;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e480402f/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformerTest.java b/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformerTest.java
new file mode 100644
index 0000000..b1b7804
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformerTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.typereg;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.mgmt.EntityManagementUtils;
+import org.apache.brooklyn.core.plan.XmlPlanToSpecTransformer;
+import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Iterables;
+
+/** Tests the sample {@link XmlPlanToSpecTransformer}
+ * which illustrates how the {@link PlanToSpecTransformer} can be used. */
+public class ExampleXmlTypePlanTransformerTest {
+
+    private ManagementContext mgmt;
+
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        TypePlanTransformers.forceAvailable(ExampleXmlTypePlanTransformer.class);
+        mgmt = LocalManagementContextForTests.newInstance();
+    }
+    
+    @AfterMethod(alwaysRun = true)
+    public void tearDown() {
+        TypePlanTransformers.clearForced();
+        if (mgmt!=null) Entities.destroyAll(mgmt);
+    }
+
+    @Test
+    public void testAppSpecXmlPlanParse() {
+        EntitySpec<? extends Application> appSpec = EntityManagementUtils.createEntitySpecForApplication(mgmt, 
+            "<root><a_kid foo=\"bar\"/></root>");
+        Application app = EntityManagementUtils.createStarting(mgmt, appSpec).get();
+        Entities.dumpInfo(app);
+        Assert.assertEquals(app.getDisplayName(), "root");
+        Entity child = Iterables.getOnlyElement(app.getChildren());
+        Assert.assertEquals(child.getDisplayName(), "a_kid");
+        Assert.assertEquals(child.config().get(ConfigKeys.newStringConfigKey("foo")), "bar");
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e480402f/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
index 15df062..06dfaa3 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
@@ -28,9 +28,7 @@ import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.mgmt.Task;
-import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.camp.brooklyn.spi.creation.CampTypePlanTransformer;
-import org.apache.brooklyn.camp.brooklyn.spi.creation.CampTypePlanTransformer.CampTypeImplementationPlan;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.entity.trait.Startable;
@@ -39,7 +37,6 @@ import org.apache.brooklyn.core.mgmt.EntityManagementUtils;
 import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
 import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
-import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.stream.Streams;


[07/14] incubator-brooklyn git commit: Working CampTypePlanTransformer

Posted by he...@apache.org.
Working CampTypePlanTransformer


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

Branch: refs/heads/master
Commit: 904c45e961f5e6b596e6c7238ebf86ee7a6ce7bc
Parents: 817e9bd
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Nov 4 10:47:22 2015 -0500
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Nov 10 17:13:02 2015 +0000

----------------------------------------------------------------------
 .../apache/brooklyn/api/entity/EntitySpec.java  |   2 -
 .../internal/AbstractBrooklynObjectSpec.java    |  16 ++
 .../brooklyn/api/typereg/RegisteredType.java    |  20 +-
 .../api/typereg/RegisteredTypeConstraint.java   |   5 +
 .../core/catalog/internal/CatalogUtils.java     |  17 +-
 .../brooklyn/core/plan/PlanToSpecFactory.java   |   2 +-
 .../entity/DelegatingEntitySpecResolver.java    |   2 +-
 .../core/typereg/BasicBrooklynTypeRegistry.java |   8 +-
 .../core/typereg/BasicRegisteredType.java       |  27 +-
 .../JavaClassNameTypePlanTransformer.java       |  90 +++++++
 .../core/typereg/JavaTypePlanTransformer.java   | 112 --------
 .../core/typereg/RegisteredTypeConstraints.java |  59 +++-
 .../core/typereg/RegisteredTypePredicates.java  |  32 ++-
 .../brooklyn/core/typereg/RegisteredTypes.java  | 143 +++++++++-
 ...lyn.core.typereg.BrooklynTypePlanTransformer |  19 ++
 .../brooklyn/core/sensor/StaticSensorTest.java  |   8 +-
 .../core/test/entity/TestEntityImpl.java        |   1 -
 .../typereg/JavaTypePlanTransformerTest.java    |   6 +-
 .../api/AssemblyTemplateSpecInstantiator.java   |   6 +-
 .../BrooklynAssemblyTemplateInstantiator.java   |  17 +-
 .../brooklyn/spi/creation/CampCatalogUtils.java |  54 +---
 .../spi/creation/CampInternalUtils.java         | 247 +++++++++++++++++
 .../brooklyn/spi/creation/CampResolver.java     | 142 ++++++++++
 .../spi/creation/CampToSpecTransformer.java     |  15 +-
 .../spi/creation/CampTypePlanTransformer.java   |  90 +++++++
 .../camp/brooklyn/spi/creation/CampUtils.java   | 267 -------------------
 .../service/UrlServiceSpecResolver.java         |  19 +-
 ...lyn.core.typereg.BrooklynTypePlanTransformer |  19 ++
 .../camp/brooklyn/AbstractYamlTest.java         |  42 ++-
 .../camp/brooklyn/EntitiesYamlTest.java         |   2 +
 .../camp/brooklyn/ReferencedYamlTest.java       |   1 +
 .../CatalogOsgiVersionMoreEntityTest.java       |  18 +-
 .../catalog/CatalogYamlLocationTest.java        |   3 +-
 .../test/lite/TestAppAssemblyInstantiator.java  |  10 +-
 .../rest/util/BrooklynRestResourceUtils.java    |   2 +-
 .../exceptions/PropagatedRuntimeException.java  |   6 +
 36 files changed, 995 insertions(+), 534 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/api/src/main/java/org/apache/brooklyn/api/entity/EntitySpec.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/EntitySpec.java b/api/src/main/java/org/apache/brooklyn/api/entity/EntitySpec.java
index a38e52e..500952d 100644
--- a/api/src/main/java/org/apache/brooklyn/api/entity/EntitySpec.java
+++ b/api/src/main/java/org/apache/brooklyn/api/entity/EntitySpec.java
@@ -337,8 +337,6 @@ public class EntitySpec<T extends Entity> extends AbstractBrooklynObjectSpec<T,E
         return this;
     }
     
-    /** strings inserted as flags, config keys inserted as config keys; 
-     * if you want to force one or the other, create a ConfigBag and convert to the appropriate map type */
     public EntitySpec<T> configure(Map<?,?> val) {
         checkMutable();
         for (Map.Entry<?, ?> entry: val.entrySet()) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java b/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java
index 6ba5a3c..de2954d 100644
--- a/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java
+++ b/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java
@@ -23,8 +23,11 @@ import static com.google.common.base.Preconditions.checkNotNull;
 import java.io.Serializable;
 import java.lang.reflect.Modifier;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
+import org.apache.brooklyn.api.mgmt.EntityManager;
+import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.objs.SpecParameter;
 import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.exceptions.Exceptions;
@@ -34,6 +37,15 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 
+/** Defines a spec for creating a {@link BrooklynObject}.
+ * <p>
+ * In addition to the contract defined by the code,
+ * subclasses should provide a public static <code>create(Class)</code>
+ * method to create an instance of the spec for the target type indicated by the argument. 
+ * <p>
+ * The spec is then passed to type-specific methods,
+ * e.g. {@link EntityManager#createEntity(org.apache.brooklyn.api.entity.EntitySpec)}
+ * to create a managed instance of the target type. */
 public abstract class AbstractBrooklynObjectSpec<T,SpecT extends AbstractBrooklynObjectSpec<T,SpecT>> implements Serializable {
 
     private static final long serialVersionUID = 3010955277740333030L;
@@ -160,5 +172,9 @@ public abstract class AbstractBrooklynObjectSpec<T,SpecT extends AbstractBrookly
     public int hashCode() {
         return Objects.hashCode(getCatalogItemId(), getDisplayName(), getType(), getTags());
     }
+
+    /** strings inserted as flags, config keys inserted as config keys; 
+     * if you want to force one or the other, create a ConfigBag and convert to the appropriate map type */
+    public abstract SpecT configure(Map<?,?> val);
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
index a1fc5cf..ed84179 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
@@ -19,11 +19,13 @@
 package org.apache.brooklyn.api.typereg;
 
 import java.util.Collection;
+import java.util.Set;
 
 import javax.annotation.Nullable;
 
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.objs.Identifiable;
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
 
@@ -44,22 +46,24 @@ public interface RegisteredType extends Identifiable {
     String getDescription();
     String getIconUrl();
 
-    /** @return the java type or a supertype thereof that this registered type represents.
+    /** @return all declared supertypes or super-interfaces of this registered type,
+     * consisting of a collection of {@link Class} or {@link RegisteredType}
      * <p>
-     * For beans, this is the type that the {@link BrooklynTypeRegistry} will create. 
-     * For specs, this is what the spec that will be created points at 
-     * (e.g. the concrete {@link Entity}, not the {@link EntitySpec});
+     * This should normally include at least one {@link Class} object:
+     * For beans, this should include the java type that the {@link BrooklynTypeRegistry} will create. 
+     * For specs, this should refer to the {@link BrooklynObject} type that the created spec will point at 
+     * (e.g. the concrete {@link Entity}, not the {@link EntitySpec}).
      * <p>
-     * In some cases this may return an interface or a super-type of what will actually be created, 
+     * This may not necessarily return the most specific java class or classes;
      * such as if the concrete type is private and callers should know only about a particular public interface,
      * or if precise type details are unavailable and all that is known at creation is some higher level interface/supertype
      * (e.g. this may return {@link Entity} even though the spec points at a specific subclass,
      * for instance because the YAML has not yet been parsed or OSGi bundles downloaded).
      * <p>
-     * If nothing is known, this will return null, and the item will not participate in type filtering.
+     * This may include other registered types such as marker interfaces.
      */
     @Beta
-    @Nullable Class<?> getJavaType();
+    @Nullable Set<Object> getSuperTypes();
 
     /**
      * @return True if the item has been deprecated (i.e. its use is discouraged)
@@ -84,5 +88,5 @@ public interface RegisteredType extends Identifiable {
         /** data for the implementation; may be more specific */
         Object getPlanData();
     }
-    
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java
index 851d88a..8bcff38 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java
@@ -42,4 +42,9 @@ public interface RegisteredTypeConstraint {
      * if we have already attempted to resolve a given type,
      * the instantiator can avoid recursive cycles */
     @Nonnull public Set<String> getEncounteredTypes();
+    
+    /** A special loader to use, if available.
+     * For internal use only; implementations should be a BrooklynClassLoadingContext */
+    @Nullable public Object getLoader();
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
index db4b72a..2955895 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
@@ -69,7 +69,11 @@ public class CatalogUtils {
     }
     
     public static BrooklynClassLoadingContext newClassLoadingContext(ManagementContext mgmt, RegisteredType item) {
-        return newClassLoadingContext(mgmt, item.getId(), item.getLibraries());
+        return newClassLoadingContext(mgmt, item.getId(), item.getLibraries(), null);
+    }
+    
+    public static BrooklynClassLoadingContext newClassLoadingContext(ManagementContext mgmt, RegisteredType item, BrooklynClassLoadingContext loader) {
+        return newClassLoadingContext(mgmt, item.getId(), item.getLibraries(), loader);
     }
     
     public static BrooklynClassLoadingContext getClassLoadingContext(Entity entity) {
@@ -85,16 +89,23 @@ public class CatalogUtils {
     }
 
     public static BrooklynClassLoadingContext newClassLoadingContext(@Nullable ManagementContext mgmt, String catalogItemId, Collection<? extends OsgiBundleWithUrl> libraries) {
+        return newClassLoadingContext(mgmt, catalogItemId, libraries, null);
+    }
+    
+    public static BrooklynClassLoadingContext newClassLoadingContext(@Nullable ManagementContext mgmt, String catalogItemId, Collection<? extends OsgiBundleWithUrl> libraries, BrooklynClassLoadingContext loader) {
         BrooklynClassLoadingContextSequential result = new BrooklynClassLoadingContextSequential(mgmt);
 
         if (libraries!=null && !libraries.isEmpty()) {
             result.add(new OsgiBrooklynClassLoadingContext(mgmt, catalogItemId, libraries));
         }
 
-        BrooklynClassLoadingContext loader = BrooklynLoaderTracker.getLoader();
-        if (loader != null) {
+        if (loader !=null) {
             result.add(loader);
         }
+        BrooklynClassLoadingContext threadLocalLoader = BrooklynLoaderTracker.getLoader();
+        if (threadLocalLoader != null) {
+            result.add(threadLocalLoader);
+        }
 
         result.addSecondary(JavaBrooklynClassLoadingContext.create(mgmt));
         return result;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java b/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
index 5614b97..7aef313 100644
--- a/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
+++ b/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
@@ -111,7 +111,7 @@ public class PlanToSpecFactory {
                     (Strings.isNonBlank(e.getMessage()) ? " ("+e.getMessage()+")" : ""));
             } catch (Throwable e) {
                 Exceptions.propagateIfFatal(e);
-                otherProblemsFromTransformers.add(new PropagatedRuntimeException("Transformer for "+t.getShortDescription()+" gave an error creating this plan: "+
+                otherProblemsFromTransformers.add(new PropagatedRuntimeException("Transformer for "+t.getShortDescription()+" gave an error creating this plan: ",
                     Exceptions.collapseText(e), e));
             }
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/resolve/entity/DelegatingEntitySpecResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/resolve/entity/DelegatingEntitySpecResolver.java b/core/src/main/java/org/apache/brooklyn/core/resolve/entity/DelegatingEntitySpecResolver.java
index 2ccc468..415f209 100644
--- a/core/src/main/java/org/apache/brooklyn/core/resolve/entity/DelegatingEntitySpecResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/core/resolve/entity/DelegatingEntitySpecResolver.java
@@ -105,7 +105,7 @@ public class DelegatingEntitySpecResolver extends AbstractEntitySpecResolver {
                         resolversWhoDontSupport.add(resolver.getName() + " (returned null)");
                     }
                 } catch (Exception e) {
-                    otherProblemsFromResolvers.add(new PropagatedRuntimeException("Transformer for "+resolver.getName()+" gave an error creating this plan: "+
+                    otherProblemsFromResolvers.add(new PropagatedRuntimeException("Transformer for "+resolver.getName()+" gave an error creating this plan: ",
                             Exceptions.collapseText(e), e));
                 }
             }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
index 08b6103..0ca8bc7 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
@@ -112,7 +112,7 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
                 // TODO implement using java if permitted
             }
         }
-        constraint = RegisteredTypeConstraints.extendedWithSpecSuperType(constraint, specSuperType);
+        constraint = RegisteredTypeConstraints.withSpecSuperType(constraint, specSuperType);
 
         Maybe<Object> result = TypePlanTransformers.transform(mgmt, type, constraint);
         if (result.isPresent()) return (SpecT) result.get();
@@ -120,6 +120,10 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
         // fallback: look up in (legacy) catalog
         // TODO remove once all transformers are available in the new style
         CatalogItem item = (CatalogItem) mgmt.getCatalog().getCatalogItem(type.getSymbolicName(), type.getVersion());
+        if (item==null) {
+            // if not in catalog (because loading new one?) then throw original
+            result.get();
+        }
         try {
             return (SpecT) BasicBrooklynCatalog.internalCreateSpecWithTransformers(mgmt, item, constraint.getEncounteredTypes());
         } catch (Exception e) {
@@ -127,7 +131,7 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
             // for now, combine this failure with the original
             try {
                 result.get();
-                // won't come here
+                // above will throw -- so won't come here
                 throw new IllegalStateException("should have failed getting type resolution for "+type);
             } catch (Exception e0) {
                 // prefer older exception, until the new transformer is the primary pathway

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
index ac0b266..54b04a3 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
@@ -20,19 +20,27 @@ package org.apache.brooklyn.core.typereg;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
 import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl;
 import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.collections.MutableSet;
+import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.javalang.JavaClassNames;
 
+import com.google.common.collect.ImmutableSet;
+
+/** Instances are usually created by methods in {@link RegisteredTypes}. */
 public class BasicRegisteredType implements RegisteredType {
 
     final String symbolicName;
     final String version;
     final RegisteredTypeKind kind;
     
-    List<OsgiBundleWithUrl> bundles;
+    Set<Object> superTypes = MutableSet.of();
+    List<OsgiBundleWithUrl> bundles = MutableList.of();
     String displayName;
     String description;
     String iconUrl;
@@ -41,14 +49,12 @@ public class BasicRegisteredType implements RegisteredType {
     
     TypeImplementationPlan implementationPlan;
 
-    // TODO ensure this is re-populated on rebind?  or remove?
-    transient Class<?> javaType;
+    private transient ConfigBag cache = new ConfigBag();
     
-    public BasicRegisteredType(RegisteredTypeKind kind, String symbolicName, String version, Class<?> javaType, TypeImplementationPlan implementationPlan) {
+    BasicRegisteredType(RegisteredTypeKind kind, String symbolicName, String version, TypeImplementationPlan implementationPlan) {
         this.kind = kind;
         this.symbolicName = symbolicName;
         this.version = version;
-        this.javaType = javaType;
         this.implementationPlan = implementationPlan;
     }
 
@@ -74,7 +80,7 @@ public class BasicRegisteredType implements RegisteredType {
     
     @Override
     public Collection<OsgiBundleWithUrl> getLibraries() {
-        return bundles;
+        return ImmutableSet.copyOf(bundles);
     }
 
     @Override
@@ -103,8 +109,12 @@ public class BasicRegisteredType implements RegisteredType {
     }
     
     @Override
-    public Class<?> getJavaType() {
-        return javaType;
+    public Set<Object> getSuperTypes() {
+        return ImmutableSet.copyOf(superTypes);
+    }
+
+    public ConfigBag getCache() {
+        return cache;
     }
     
     @Override
@@ -117,6 +127,7 @@ public class BasicRegisteredType implements RegisteredType {
         return JavaClassNames.simpleClassName(this)+"["+getId()+
             (isDisabled() ? ";DISABLED" : "")+
             (isDeprecated() ? ";deprecated" : "")+
+            (getPlan()!=null ? ";"+getPlan().getPlanFormat() : "")+
             "]";
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java b/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java
new file mode 100644
index 0000000..a84c9f5
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java
@@ -0,0 +1,90 @@
+/*
+ * 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.typereg;
+
+import java.util.List;
+
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.util.text.Identifiers;
+
+/**
+ * Instantiates classes from a registered type which simply
+ * defines the java class name and OSGi bundles to use.
+ * <p>
+ * This is used where a {@link RegisteredType} is defined simply with the name of a java class
+ * e.g. with a no-arg constructor -- no YAML etc just the name of the class.
+ */
+public class JavaClassNameTypePlanTransformer extends AbstractTypePlanTransformer {
+    
+    public static final String FORMAT = "java-type-name";
+
+    public static class JavaTypeNameImplementation extends AbstractCustomImplementationPlan<String> {
+        public JavaTypeNameImplementation(String javaType) { super(FORMAT, javaType); }
+    }
+
+    public JavaClassNameTypePlanTransformer() {
+        super(FORMAT, "Java type name", "Expects a java type name in a format suitable for use with ClassLoader.loadClass");
+    }
+
+    @Override
+    protected double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeConstraint context) {
+        if (type.getPlan().getPlanData() instanceof String && 
+                ((String)type.getPlan().getPlanData()).matches(Identifiers.JAVA_BINARY_REGEX)) {
+            return 0.1;
+        }
+        return 0;
+    }
+    
+    @Override
+    protected double scoreForNonmatchingNonnullFormat(String planFormat, Object planData, RegisteredType type, RegisteredTypeConstraint context) {
+        return 0;
+    }
+
+    @SuppressWarnings({ "unchecked" })
+    @Override
+    protected AbstractBrooklynObjectSpec<?,?> createSpec(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
+        return RegisteredTypes.newSpecInstance(mgmt, (Class<? extends BrooklynObject>) getType(type, context));
+    }
+
+    @Override
+    protected Object createBean(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
+        return getType(type, context).newInstance();
+    }
+
+    private Class<?> getType(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
+        return RegisteredTypes.loadActualJavaType((String)type.getPlan().getPlanData(), mgmt, type, context);
+    }
+    
+    
+    // not supported as a catalog format (yet? should we?)
+    
+    @Override
+    public double scoreForTypeDefinition(String formatCode, Object catalogData) {
+        return 0;
+    }
+
+    @Override
+    public List<RegisteredType> createFromTypeDefinition(String formatCode, Object catalogData) {
+        throw new UnsupportedTypePlanException("this transformer does not support YAML catalog additions");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformer.java b/core/src/main/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformer.java
deleted file mode 100644
index febf52a..0000000
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformer.java
+++ /dev/null
@@ -1,112 +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.typereg;
-
-import java.util.List;
-
-import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
-import org.apache.brooklyn.api.typereg.RegisteredType;
-import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
-import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
-import org.apache.brooklyn.util.text.Identifiers;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Instantiates classes from a registered type which simply
- * defines the java class name and OSGi bundles to use.
- * <p>
- * This is used where a {@link RegisteredType} is defined simply with the name of a java class
- * e.g. with a no-arg constructor -- no YAML etc just the name of the class.
- */
-public class JavaTypePlanTransformer extends AbstractTypePlanTransformer {
-    
-    private static final Logger log = LoggerFactory.getLogger(JavaTypePlanTransformer.class);
-    public static final String FORMAT = "java-type-name";
-
-    public static class JavaTypeNameImplementation extends AbstractCustomImplementationPlan<String> {
-        private transient Class<?> cachedType;
-        public JavaTypeNameImplementation(String javaType) {
-            super(FORMAT, javaType);
-        }
-        public Class<?> getCachedType() {
-            return cachedType;
-        }
-    }
-
-    public JavaTypePlanTransformer() {
-        super(FORMAT, "Java type name", "Expects a java type name in a format suitable for use with ClassLoader.loadClass");
-    }
-
-    @Override
-    protected double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeConstraint context) {
-        if (type.getPlan().getPlanData() instanceof String && 
-                ((String)type.getPlan().getPlanData()).matches(Identifiers.JAVA_BINARY_REGEX)) {
-            return 0.1;
-        }
-        return 0;
-    }
-    
-    @Override
-    protected double scoreForNonmatchingNonnullFormat(String planFormat, Object planData, RegisteredType type, RegisteredTypeConstraint context) {
-        return 0;
-    }
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    @Override
-    protected AbstractBrooklynObjectSpec<?,?> createSpec(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
-        Class targetType = getType(type, context);
-        Class specType = RegisteredTypeConstraints.spec((Class)targetType).getJavaSuperType();
-        AbstractBrooklynObjectSpec result = (AbstractBrooklynObjectSpec) specType.getConstructor(Class.class).newInstance(targetType);
-        return result;
-    }
-
-    @Override
-    protected Object createBean(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
-        return getType(type, context).newInstance();
-    }
-
-    private Class<?> getType(RegisteredType type, RegisteredTypeConstraint context) {
-        if (type.getPlan() instanceof JavaTypeNameImplementation) {
-            Class<?> cachedType = ((JavaTypeNameImplementation)type.getPlan()).getCachedType();
-            if (cachedType==null) {
-                log.debug("Storing cached type "+cachedType+" for "+type);
-                cachedType = loadType(type, context);
-            }
-            return cachedType;
-        }
-        return loadType(type, context);
-    }
-    private Class<?> loadType(RegisteredType type, RegisteredTypeConstraint context) {
-        return CatalogUtils.newClassLoadingContext(mgmt, type).loadClass( ((String)type.getPlan().getPlanData()) );
-    }
-
-    
-    // TODO not supported as a catalog format (yet)
-    @Override
-    public double scoreForTypeDefinition(String formatCode, Object catalogData) {
-        return 0;
-    }
-
-    @Override
-    public List<RegisteredType> createFromTypeDefinition(String formatCode, Object catalogData) {
-        throw new UnsupportedTypePlanException("this transformer does not support YAML catalog additions");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java
index c880b7e..5b4c0cf 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java
@@ -31,7 +31,9 @@ import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.objs.BrooklynObjectType;
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
 import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.util.collections.MutableSet;
+import org.apache.brooklyn.util.javalang.JavaClassNames;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -46,6 +48,7 @@ public class RegisteredTypeConstraints {
         @Nullable private RegisteredTypeKind kind;
         @Nullable private Class<?> javaSuperType;
         @Nonnull private Set<String> encounteredTypes = ImmutableSet.of();
+        @Nullable BrooklynClassLoadingContext loader;
         
         private BasicRegisteredTypeConstraint() {}
         
@@ -55,6 +58,7 @@ public class RegisteredTypeConstraints {
             this.kind = source.getKind();
             this.javaSuperType = source.getJavaSuperType();
             this.encounteredTypes = source.getEncounteredTypes();
+            this.loader = (BrooklynClassLoadingContext) source.getLoader();
         }
 
         @Override
@@ -75,8 +79,13 @@ public class RegisteredTypeConstraints {
         }
         
         @Override
+        public BrooklynClassLoadingContext getLoader() {
+            return loader;
+        }
+        
+        @Override
         public String toString() {
-            return super.toString()+"["+kind+","+javaSuperType+","+encounteredTypes+"]";
+            return JavaClassNames.cleanSimpleClassName(this)+"["+kind+","+javaSuperType+","+encounteredTypes+"]";
         }
     }
 
@@ -97,7 +106,11 @@ public class RegisteredTypeConstraints {
         result.encounteredTypes = encounteredTypes.asUnmodifiable();
         return result;
     }
-    
+
+    public static RegisteredTypeConstraint alreadyVisited(Set<String> encounteredTypeSymbolicNames, BrooklynClassLoadingContext loader) {
+        return withLoader(alreadyVisited(encounteredTypeSymbolicNames), loader);
+    }
+
     private static RegisteredTypeConstraint of(RegisteredTypeKind kind, Class<? extends BrooklynObject> javaSuperType) {
         BasicRegisteredTypeConstraint result = new BasicRegisteredTypeConstraint();
         result.kind = kind;
@@ -109,7 +122,7 @@ public class RegisteredTypeConstraints {
         return of(RegisteredTypeKind.SPEC, javaSuperType);
     }
 
-    public static <T extends AbstractBrooklynObjectSpec<?,?>> RegisteredTypeConstraint extendedWithSpecSuperType(@Nullable RegisteredTypeConstraint source, @Nullable Class<T> specSuperType) {
+    public static <T extends AbstractBrooklynObjectSpec<?,?>> RegisteredTypeConstraint withSpecSuperType(@Nullable RegisteredTypeConstraint source, @Nullable Class<T> specSuperType) {
         Class<?> superType = lookupTargetTypeForSpec(specSuperType);
         BasicRegisteredTypeConstraint constraint = new BasicRegisteredTypeConstraint(source);
         if (source==null) source = constraint;
@@ -131,8 +144,9 @@ public class RegisteredTypeConstraints {
         return source;
     }
     
-    /** given a spec, returns the class of the item it targets, for instance {@link EntitySpec} for {@link Entity} */
-    private static <T extends AbstractBrooklynObjectSpec<?,?>> Class<? extends BrooklynObject> lookupTargetTypeForSpec(Class<T> specSuperType) {
+    /** given a spec, returns the class of the item it targets, for instance returns {@link Entity} given {@link EntitySpec};
+     * see also {@link #lookupSpecTypeForTarget(Class)} */
+    static <T extends AbstractBrooklynObjectSpec<?,?>> Class<? extends BrooklynObject> lookupTargetTypeForSpec(Class<T> specSuperType) {
         if (specSuperType==null) return BrooklynObject.class;
         BrooklynObjectType best = null;
 
@@ -154,4 +168,39 @@ public class RegisteredTypeConstraints {
         return best.getInterfaceType();
     }
 
+    /** given a {@link BrooklynObject}, returns the spec class which would generate it, for instance returns {@link EntitySpec} given {@link Entity},
+     * or null if not known */
+    static <BO extends BrooklynObject> Class<? extends AbstractBrooklynObjectSpec<?,?>> lookupSpecTypeForTarget(Class<BO> targetSuperType) {
+        if (targetSuperType==null) return null;
+        BrooklynObjectType best = null;
+
+        for (BrooklynObjectType t: BrooklynObjectType.values()) {
+            if (t.getSpecType()==null) continue;
+            if (!t.getInterfaceType().isAssignableFrom(targetSuperType)) continue;
+            // on equality, exit immediately
+            if (t.getInterfaceType().equals(targetSuperType)) return t.getSpecType();
+            // else pick which is best
+            if (best==null) { best = t; continue; }
+            // if t is more specific, it is better (handles case when e.g. a Policy is a subclass of Entity)
+            if (best.getSpecType().isAssignableFrom(t.getSpecType())) { best = t; continue; }
+        }
+        if (best==null) {
+            log.warn("Unexpected target supertype ("+targetSuperType+"); unable to infer spec type");
+            return null;
+        }
+        // the spec is more specific, but we're not familiar with it here; return the best
+        return best.getSpecType();
+    }
+
+    public static RegisteredTypeConstraint loader(BrooklynClassLoadingContext loader) {
+        BasicRegisteredTypeConstraint result = new BasicRegisteredTypeConstraint();
+        result.loader = loader;
+        return result;
+    }
+    
+    public static RegisteredTypeConstraint withLoader(RegisteredTypeConstraint constraint, BrooklynClassLoadingContext loader) {
+        ((BasicRegisteredTypeConstraint)constraint).loader = loader;
+        return constraint;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java
index 3560e47..2e7c038 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java
@@ -109,36 +109,46 @@ public class RegisteredTypePredicates {
         }
     }
 
-    public static <T> Predicate<RegisteredType> javaType(final Predicate<Class<T>> filter) {
-        return new JavaTypeMatches(filter);
+    public static <T> Predicate<RegisteredType> anySuperType(final Predicate<Class<T>> filter) {
+        return new AnySuperTypeMatches(filter);
     }
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    public static Predicate<RegisteredType> javaTypeAssignableFrom(final Class<?> filter) {
-        return javaType((Predicate)Predicates.assignableFrom(filter));
+    public static Predicate<RegisteredType> assignableFrom(final Class<?> filter) {
+        return anySuperType((Predicate)Predicates.assignableFrom(filter));
     }
     
-    private static class JavaTypeMatches implements Predicate<RegisteredType> {
+    private static class AnySuperTypeMatches implements Predicate<RegisteredType> {
         private final Predicate<Class<?>> filter;
         
         @SuppressWarnings({ "rawtypes", "unchecked" })
-        private <T> JavaTypeMatches(Predicate filter) {
+        private <T> AnySuperTypeMatches(Predicate filter) {
             this.filter = filter;
         }
         @Override
         public boolean apply(@Nullable RegisteredType item) {
             if (item==null) return false;
-            return (item != null) && filter.apply(item.getJavaType());
+            for (Object o: item.getSuperTypes()) {
+                if (o instanceof Class) {
+                    if (filter.apply((Class<?>)o)) return true;
+                }
+            }
+            for (Object o: item.getSuperTypes()) {
+                if (o instanceof RegisteredType) {
+                    if (apply((RegisteredType)o)) return true;
+                }
+            }
+            return false;
         }
     }
 
-    public static final Predicate<RegisteredType> IS_APPLICATION = javaTypeAssignableFrom(Application.class);
+    public static final Predicate<RegisteredType> IS_APPLICATION = assignableFrom(Application.class);
     // TODO do we need this?  introduced already deprecated in 0.9.0 so can be removed, or enabled
     @Deprecated
     public static final Predicate<RegisteredType> IS_TEMPLATE = IS_APPLICATION;
     
-    public static final Predicate<RegisteredType> IS_ENTITY = javaTypeAssignableFrom(Entity.class);
-    public static final Predicate<RegisteredType> IS_LOCATION = javaTypeAssignableFrom(Location.class);
-    public static final Predicate<RegisteredType> IS_POLICY = javaTypeAssignableFrom(Policy.class);
+    public static final Predicate<RegisteredType> IS_ENTITY = assignableFrom(Entity.class);
+    public static final Predicate<RegisteredType> IS_LOCATION = assignableFrom(Location.class);
+    public static final Predicate<RegisteredType> IS_POLICY = assignableFrom(Policy.class);
 
     public static Predicate<RegisteredType> entitledToSee(final ManagementContext mgmt) {
         return new EntitledToSee(mgmt);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
index 7e35084..0ebbdcd 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
@@ -18,19 +18,50 @@
  */
 package org.apache.brooklyn.core.typereg;
 
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
 import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
 import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.api.typereg.RegisteredType.TypeImplementationPlan;
-import org.apache.brooklyn.core.typereg.JavaTypePlanTransformer.JavaTypeNameImplementation;
+import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.typereg.JavaClassNameTypePlanTransformer.JavaTypeNameImplementation;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.yaml.Yamls;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
+import com.google.common.reflect.TypeToken;
 
+/**
+ * Utility and preferred creation mechanisms for working with {@link RegisteredType} instances.
+ * <p>
+ * Use {@link #bean(String, String, TypeImplementationPlan, Class)} and {@link #spec(String, String, TypeImplementationPlan, Class)}
+ * to create {@link RegisteredType} instances.
+ * <p>
+ * See {@link #isSubTypeOf(RegisteredType, Class)} or {@link #isSubTypeOf(RegisteredType, RegisteredType)} to 
+ * inspect the type hierarchy.
+ */
 public class RegisteredTypes {
 
+    @SuppressWarnings("serial")
+    static ConfigKey<Class<?>> ACTUAL_JAVA_TYPE = ConfigKeys.newConfigKey(new TypeToken<Class<?>>() {}, "java.type.actual",
+        "The actual Java type which will be instantiated (bean) or pointed at (spec)");
+
     /** @deprecated since it was introduced in 0.9.0; for backwards compatibility only, may be removed at any point */
     @Deprecated
     static final Function<CatalogItem<?,?>,RegisteredType> CI_TO_RT = new Function<CatalogItem<?,?>, RegisteredType>() {
@@ -53,7 +84,7 @@ public class RegisteredTypes {
             throw new IllegalStateException("Unsupported catalog item "+item+" when trying to create RegisteredType");
         }
         
-        BasicRegisteredType type = (BasicRegisteredType) spec(item.getSymbolicName(), item.getVersion(), item.getCatalogItemJavaType(), impl);
+        BasicRegisteredType type = (BasicRegisteredType) spec(item.getSymbolicName(), item.getVersion(), impl, item.getCatalogItemJavaType());
         type.bundles = item.getLibraries()==null ? ImmutableList.<OsgiBundleWithUrl>of() : ImmutableList.<OsgiBundleWithUrl>copyOf(item.getLibraries());
         type.displayName = item.getDisplayName();
         type.description = item.getDescription();
@@ -66,13 +97,49 @@ public class RegisteredTypes {
         // maybe: tags ?
         return type;
     }
-    
-    public static RegisteredType bean(String symbolicName, String version, Class<?> javaType, TypeImplementationPlan plan) {
-        return new BasicRegisteredType(RegisteredTypeKind.BEAN, symbolicName, version, javaType, plan);
+
+    /** Preferred mechanism for defining a bean {@link RegisteredType} */
+    public static RegisteredType bean(String symbolicName, String version, TypeImplementationPlan plan, @Nullable Class<?> superType) {
+        return addSuperType(new BasicRegisteredType(RegisteredTypeKind.BEAN, symbolicName, version, plan), superType);
     }
     
-    public static RegisteredType spec(String symbolicName, String version, Class<?> javaType, TypeImplementationPlan plan) {
-        return new BasicRegisteredType(RegisteredTypeKind.SPEC, symbolicName, version, javaType, plan);
+    public static RegisteredType spec(String symbolicName, String version, TypeImplementationPlan plan, @Nullable Class<?> superType) {
+        return addSuperType(new BasicRegisteredType(RegisteredTypeKind.SPEC, symbolicName, version, plan), superType);
+    }
+
+    /** returns the {@link Class} object corresponding to the given java type name,
+     * using the cache on the type and the loader defined on the type
+     * @param mgmt */
+    @Beta
+    // TODO should this be on the AbstractTypePlanTransformer ?
+    public static Class<?> loadActualJavaType(String javaTypeName, ManagementContext mgmt, RegisteredType type, RegisteredTypeConstraint constraint) throws Exception {
+        Class<?> result = ((BasicRegisteredType)type).getCache().get(ACTUAL_JAVA_TYPE);
+        if (result!=null) return result;
+        
+        result = CatalogUtils.newClassLoadingContext(mgmt, type).loadClass( javaTypeName );
+        Preconditions.checkNotNull(result, "Could not load class "+javaTypeName+"; returned null (should have thrown a different exception!)");
+        
+        ((BasicRegisteredType)type).getCache().put(ACTUAL_JAVA_TYPE, result);
+        return result;
+    }
+
+    @Beta
+    public static RegisteredType addSuperType(RegisteredType type, @Nullable Class<?> superType) {
+        if (superType!=null) {
+            ((BasicRegisteredType)type).superTypes.add(superType);
+        }
+        return type;
+    }
+
+    @Beta
+    public static RegisteredType addSuperType(RegisteredType type, @Nullable RegisteredType superType) {
+        if (superType!=null) {
+            if (isSubTypeOf(superType, type)) {
+                throw new IllegalStateException(superType+" declares "+type+" as a supertype; cannot set "+superType+" as a supertype of "+type);
+            }
+            ((BasicRegisteredType)type).superTypes.add(superType);
+        }
+        return type;
     }
 
     /** returns the implementation data for a spec if it is a string (e.g. plan yaml or java class name); else false */
@@ -84,4 +151,66 @@ public class RegisteredTypes {
         return (String)data;
     }
 
+    /** returns an implementation of the spec class corresponding to the given target type;
+     * for use in {@link BrooklynTypePlanTransformer#create(RegisteredType, RegisteredTypeConstraint)} 
+     * implementations when dealing with a spec; returns null if none found
+     * @param mgmt */
+    @Beta
+    public static AbstractBrooklynObjectSpec<?,?> newSpecInstance(ManagementContext mgmt, Class<? extends BrooklynObject> targetType) throws Exception {
+        Class<? extends AbstractBrooklynObjectSpec<?, ?>> specType = RegisteredTypeConstraints.lookupSpecTypeForTarget(targetType);
+        if (specType==null) return null;
+        Method createMethod = specType.getMethod("create", Class.class);
+        return (AbstractBrooklynObjectSpec<?, ?>) createMethod.invoke(null, targetType);
+    }
+
+    /** Returns a wrapped map, if the object is YAML which parses as a map; 
+     * otherwise returns absent capable of throwing an error with more details */
+    @SuppressWarnings("unchecked")
+    public static Maybe<Map<Object,Object>> getAsYamlMap(Object planData) {
+        if (!(planData instanceof String)) return Maybe.absent("not a string");
+        Iterable<Object> result;
+        try {
+            result = Yamls.parseAll((String)planData);
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            return Maybe.absent(e);
+        }
+        Iterator<Object> ri = result.iterator();
+        if (!ri.hasNext()) return Maybe.absent("YAML has no elements in it");
+        Object r1 = ri.next();
+        if (!ri.hasNext()) return Maybe.absent("YAML has multiple elements in it");
+        if (r1 instanceof Map) return Maybe.of((Map<Object,Object>)r1);
+        return Maybe.absent("YAML does not contain a map");
+    }
+
+    /** 
+     * Queries recursively the supertypes of {@link RegisteredType} to see whether it 
+     * declares a supertype compatible with the given {@link Class} */
+    public static boolean isSubTypeOf(RegisteredType type, Class<?> superType) {
+        for (Object st: type.getSuperTypes()) {
+            if (st instanceof Class) {
+                if (superType.isAssignableFrom((Class<?>)st)) return true;
+            }
+        }
+        for (Object st: type.getSuperTypes()) {
+            if (st instanceof RegisteredType) {
+                if (isSubTypeOf((RegisteredType)st, superType)) return true;
+            }
+        }
+        return false;
+    }
+
+    /** 
+     * Queries recursively the supertypes of {@link RegisteredType} to see whether it 
+     * declares a supertype compatible with the given {@link Class} */
+    public static boolean isSubTypeOf(RegisteredType type, RegisteredType superType) {
+        if (type.equals(superType)) return true;
+        for (Object st: type.getSuperTypes()) {
+            if (st instanceof RegisteredType) {
+                if (isSubTypeOf((RegisteredType)st, superType)) return true;
+            }
+        }
+        return false;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/resources/META-INF/services/org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer
----------------------------------------------------------------------
diff --git a/core/src/main/resources/META-INF/services/org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer b/core/src/main/resources/META-INF/services/org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer
new file mode 100644
index 0000000..48c4a9d
--- /dev/null
+++ b/core/src/main/resources/META-INF/services/org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+org.apache.brooklyn.core.typereg.JavaClassNameTypePlanTransformer

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/test/java/org/apache/brooklyn/core/sensor/StaticSensorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/sensor/StaticSensorTest.java b/core/src/test/java/org/apache/brooklyn/core/sensor/StaticSensorTest.java
index 1e6efb1..a574aeb 100644
--- a/core/src/test/java/org/apache/brooklyn/core/sensor/StaticSensorTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/sensor/StaticSensorTest.java
@@ -19,11 +19,9 @@
 package org.apache.brooklyn.core.sensor;
 
 import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.core.sensor.Sensors;
-import org.apache.brooklyn.core.sensor.StaticSensor;
+import org.apache.brooklyn.core.entity.EntityAsserts;
 import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
 import org.apache.brooklyn.entity.stock.BasicEntity;
-import org.apache.brooklyn.test.EntityTestUtils;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.testng.annotations.Test;
 
@@ -39,7 +37,7 @@ public class StaticSensorTest extends BrooklynAppUnitTestSupport {
                         StaticSensor.SENSOR_TYPE, String.class.getName(),
                         StaticSensor.STATIC_VALUE, "myval")))));
         
-        EntityTestUtils.assertAttributeEquals(entity, Sensors.newSensor(String.class, "myname"), "myval");
+        EntityAsserts.assertAttributeEquals(entity, Sensors.newSensor(String.class, "myname"), "myval");
     }
     
     @Test
@@ -50,6 +48,6 @@ public class StaticSensorTest extends BrooklynAppUnitTestSupport {
                         StaticSensor.SENSOR_TYPE, Integer.class.getName(),
                         StaticSensor.STATIC_VALUE, "1")))));
         
-        EntityTestUtils.assertAttributeEquals(entity, Sensors.newSensor(Integer.class, "myname"), 1);
+        EntityAsserts.assertAttributeEquals(entity, Sensors.newSensor(Integer.class, "myname"), 1);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/test/java/org/apache/brooklyn/core/test/entity/TestEntityImpl.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/entity/TestEntityImpl.java b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestEntityImpl.java
index 6c3b913..77d4672 100644
--- a/core/src/test/java/org/apache/brooklyn/core/test/entity/TestEntityImpl.java
+++ b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestEntityImpl.java
@@ -157,7 +157,6 @@ public class TestEntityImpl extends AbstractEntity implements TestEntity {
     public <T extends Entity> T createAndManageChild(EntitySpec<T> spec) {
         if (!getManagementSupport().isDeployed()) throw new IllegalStateException("Entity "+this+" not managed");
         T child = createChild(spec);
-        getEntityManager().manage(child);
         return child;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java b/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java
index c4d8038..def79d8 100644
--- a/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java
@@ -37,16 +37,16 @@ public class JavaTypePlanTransformerTest extends BrooklynMgmtUnitTestSupport {
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        type = newNoArgRegisteredType(JavaTypePlanTransformer.FORMAT);
+        type = newNoArgRegisteredType(JavaClassNameTypePlanTransformer.FORMAT);
         transformer = newTransformer();
     }
     
     protected RegisteredType newNoArgRegisteredType(String format) {
-        return RegisteredTypes.bean("no-arg", "1.0", null, new BasicTypeImplementationPlan(format, NoArg.class.getName()));
+        return RegisteredTypes.bean("no-arg", "1.0", new BasicTypeImplementationPlan(format, NoArg.class.getName()), null);
     }
     
     protected BrooklynTypePlanTransformer newTransformer() {
-        BrooklynTypePlanTransformer xf = new JavaTypePlanTransformer();
+        BrooklynTypePlanTransformer xf = new JavaClassNameTypePlanTransformer();
         xf.injectManagementContext(mgmt);
         return xf;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
index 1dfc351..8fb7164 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
@@ -30,12 +30,16 @@ import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 
 public interface AssemblyTemplateSpecInstantiator extends AssemblyTemplateInstantiator {
 
+    @Deprecated /** @deprecaed since 0.9.0 include encountered types */
+    EntitySpec<? extends Application> createApplicationSpec(AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext loader);
+    
     /**
      * Gets the single item returned by {@link #createServiceSpecs}
      * and wraps it in an Application if needed, applying top-level
      * attributes and locations to the root entity.
      */
-    EntitySpec<? extends Application> createApplicationSpec(AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext loader);
+    EntitySpec<? extends Application> createApplicationSpec(AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext loader, Set<String> encounteredCatalogTypes);
+    
     /** Returns specs for each item in the services list */
     List<EntitySpec<?>> createServiceSpecs(AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext itemLoader, Set<String> encounteredCatalogTypes);
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
index a400758..5070777 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
@@ -35,12 +35,12 @@ import org.apache.brooklyn.core.mgmt.EntityManagementUtils.CreationResult;
 import org.apache.brooklyn.core.mgmt.HasBrooklynManagementContext;
 import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
+import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.flags.TypeCoercions;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
 
 public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpecInstantiator {
 
@@ -59,7 +59,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
     private Application create(AssemblyTemplate template, CampPlatform platform) {
         ManagementContext mgmt = getManagementContext(platform);
         BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.create(mgmt);
-        EntitySpec<? extends Application> spec = createApplicationSpec(template, platform, loader);
+        EntitySpec<? extends Application> spec = createApplicationSpec(template, platform, loader, MutableSet.<String>of());
         Application instance = mgmt.getEntityManager().createEntity(spec);
         log.info("CAMP created '{}'", instance);
         return instance;
@@ -78,15 +78,24 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
             AssemblyTemplate template,
             CampPlatform platform,
             BrooklynClassLoadingContext loader) {
+        return createApplicationSpec(template, platform, loader, MutableSet.<String>of());
+    }
+    
+    @Override
+    public EntitySpec<? extends Application> createApplicationSpec(
+            AssemblyTemplate template,
+            CampPlatform platform,
+            BrooklynClassLoadingContext loader,
+            Set<String> encounteredTypeSymbolicNames) {
         log.debug("CAMP creating application instance for {} ({})", template.getId(), template);
 
         // AssemblyTemplates created via PDP, _specifying_ then entities to put in
 
-        EntitySpec<? extends Application> app = CampUtils.createWrapperApp(template, loader);
+        EntitySpec<? extends Application> app = CampInternalUtils.createWrapperApp(template, loader);
         app.configure(EntityManagementUtils.WRAPPER_APP_MARKER, Boolean.TRUE);
 
         // first build the children into an empty shell app
-        List<EntitySpec<?>> childSpecs = createServiceSpecs(template, platform, loader, Sets.<String>newLinkedHashSet());
+        List<EntitySpec<?>> childSpecs = createServiceSpecs(template, platform, loader, encounteredTypeSymbolicNames);
         for (EntitySpec<?> childSpec : childSpecs) {
             app.child(childSpec);
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java
index d4c5142..32f7c0e 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java
@@ -24,61 +24,17 @@ import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.camp.CampPlatform;
-import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
-import org.apache.brooklyn.util.text.Strings;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
+import org.apache.brooklyn.core.typereg.RegisteredTypes;
 
+@Deprecated /** @deprecated since 0.9.0 use RegisteredType and CampResolver */
 public class CampCatalogUtils {
 
     public static AbstractBrooklynObjectSpec<?, ?> createSpec(ManagementContext mgmt, CatalogItem<?, ?> item, Set<String> parentEncounteredTypes) {
-        // preferred way is to parse the yaml, to resolve references late;
-        // the parsing on load is to populate some fields, but it is optional.
-        // TODO messy for location and policy that we need brooklyn.{locations,policies} root of the yaml, but it works;
-        // see related comment when the yaml is set, in addAbstractCatalogItems
-        // (not sure if anywhere else relies on that syntax; if not, it should be easy to fix!)
-        BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, item);
-        Preconditions.checkNotNull(item.getCatalogItemType(), "catalog item type for "+item.getPlanYaml());
-
-        Set<String> encounteredTypes;
-        // symbolicName could be null if coming from the catalog parser where it tries to load before knowing the id
-        if (item.getSymbolicName() != null) {
-            encounteredTypes = ImmutableSet.<String>builder()
-                    .addAll(parentEncounteredTypes)
-                    .add(item.getSymbolicName())
-                    .build();
-        } else {
-            encounteredTypes = parentEncounteredTypes;
-        }
-
-        AbstractBrooklynObjectSpec<?, ?> spec;
-        switch (item.getCatalogItemType()) {
-            case TEMPLATE:
-            case ENTITY:
-                spec = CampUtils.createRootServiceSpec(item.getPlanYaml(), loader, encounteredTypes);
-                break;
-            case LOCATION: 
-                spec = CampUtils.createLocationSpec(item.getPlanYaml(), loader, encounteredTypes);
-                break;
-            case POLICY: 
-                spec = CampUtils.createPolicySpec(item.getPlanYaml(), loader, encounteredTypes);
-                break;
-            default:
-                throw new IllegalStateException("Unknown CI Type "+item.getCatalogItemType()+" for "+item.getPlanYaml());
-        }
-
-        ((AbstractBrooklynObjectSpec<?, ?>)spec).catalogItemId(item.getId());
-
-        if (Strings.isBlank( ((AbstractBrooklynObjectSpec<?, ?>)spec).getDisplayName() ))
-            ((AbstractBrooklynObjectSpec<?, ?>)spec).displayName(item.getDisplayName());
-
-        return spec;
+        return CampResolver.createSpecFromFull(mgmt, RegisteredTypes.of(item), parentEncounteredTypes, null);
     }
-
+    
     public static CampPlatform getCampPlatform(ManagementContext mgmt) {
-        return CampUtils.getCampPlatform(mgmt);
+        return CampInternalUtils.getCampPlatform(mgmt);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampInternalUtils.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampInternalUtils.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampInternalUtils.java
new file mode 100644
index 0000000..abd32c6
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampInternalUtils.java
@@ -0,0 +1,247 @@
+/*
+ * 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.camp.brooklyn.spi.creation;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.StringReader;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.objs.SpecParameter;
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.camp.CampPlatform;
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
+import org.apache.brooklyn.camp.spi.AssemblyTemplate;
+import org.apache.brooklyn.camp.spi.AssemblyTemplate.Builder;
+import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
+import org.apache.brooklyn.camp.spi.pdp.DeploymentPlan;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
+import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.core.objs.BasicSpecParameter;
+import org.apache.brooklyn.core.objs.BrooklynObjectInternal.ConfigurationSupportInternal;
+import org.apache.brooklyn.entity.stock.BasicApplicationImpl;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.stream.Streams;
+import org.apache.brooklyn.util.yaml.Yamls;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+/** package-private; as {@link RegisteredType} becomes standard hopefully we can remove this */
+class CampInternalUtils {
+
+    static EntitySpec<? extends Application> createWrapperApp(AssemblyTemplate template, BrooklynClassLoadingContext loader) {
+        BrooklynComponentTemplateResolver resolver = BrooklynComponentTemplateResolver.Factory.newInstance(
+            loader, buildWrapperAppTemplate(template));
+        EntitySpec<Application> wrapperSpec = resolver.resolveSpec(ImmutableSet.<String>of());
+        resetSpecIfTemplateHasNoExplicitParameters(template, wrapperSpec);
+        // caller always sets WRAPPER_APP config; should we do it here?
+        return wrapperSpec;
+    }
+
+    static void resetSpecIfTemplateHasNoExplicitParameters(AssemblyTemplate template, EntitySpec<? extends Application> wrapperSpec) {
+        if (!template.getCustomAttributes().containsKey(BrooklynCampReservedKeys.BROOKLYN_PARAMETERS)) {
+            // Clear out default parameters (coming from the wrapper app's class) so they don't overwrite the entity's params on unwrap.
+            wrapperSpec.parameters(ImmutableList.<SpecParameter<?>>of());
+        }
+    }
+
+    private static AssemblyTemplate buildWrapperAppTemplate(AssemblyTemplate template) {
+        Builder<? extends AssemblyTemplate> builder = AssemblyTemplate.builder();
+        builder.type("brooklyn:" + BasicApplicationImpl.class.getName());
+        builder.id(template.getId());
+        builder.name(template.getName());
+        builder.sourceCode(template.getSourceCode());
+        for (Entry<String, Object> entry : template.getCustomAttributes().entrySet()) {
+            builder.customAttribute(entry.getKey(), entry.getValue());
+        }
+        builder.instantiator(template.getInstantiator());
+        AssemblyTemplate wrapTemplate = builder.build();
+        return wrapTemplate;
+    }
+
+    static AssemblyTemplateInstantiator getInstantiator(AssemblyTemplate at) {
+        try {
+            return at.getInstantiator().newInstance();
+        } catch (Exception e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+
+    static AssemblyTemplate registerDeploymentPlan(String plan, BrooklynClassLoadingContext loader, CampPlatform camp) {
+        BrooklynLoaderTracker.setLoader(loader);
+        try {
+            return camp.pdp().registerDeploymentPlan(new StringReader(plan));
+        } finally {
+            BrooklynLoaderTracker.unsetLoader(loader);
+        }
+    }
+
+    static PolicySpec<?> createPolicySpec(String yamlPlan, BrooklynClassLoadingContext loader, Set<String> encounteredCatalogTypes) {
+        DeploymentPlan plan = makePlanFromYaml(loader.getManagementContext(), yamlPlan);
+
+        //Would ideally re-use the PolicySpecResolver
+        //but it is CAMP specific and there is no easy way to get hold of it.
+        Object policies = checkNotNull(plan.getCustomAttributes().get(BasicBrooklynCatalog.POLICIES_KEY), "policy config");
+        if (!(policies instanceof Iterable<?>)) {
+            throw new IllegalStateException("The value of " + BasicBrooklynCatalog.POLICIES_KEY + " must be an Iterable.");
+        }
+
+        Object policy = Iterables.getOnlyElement((Iterable<?>)policies);
+
+        return createPolicySpec(loader, policy, encounteredCatalogTypes);
+    }
+
+    @SuppressWarnings("unchecked")
+    static PolicySpec<?> createPolicySpec(BrooklynClassLoadingContext loader, Object policy, Set<String> encounteredCatalogTypes) {
+        Map<String, Object> itemMap;
+        if (policy instanceof String) {
+            itemMap = ImmutableMap.<String, Object>of("type", policy);
+        } else if (policy instanceof Map) {
+            itemMap = (Map<String, Object>) policy;
+        } else {
+            throw new IllegalStateException("Policy expected to be string or map. Unsupported object type " + policy.getClass().getName() + " (" + policy.toString() + ")");
+        }
+
+        String versionedId = (String) checkNotNull(Yamls.getMultinameAttribute(itemMap, "policy_type", "policyType", "type"), "policy type");
+        PolicySpec<? extends Policy> spec = resolvePolicySpec(versionedId, loader, encounteredCatalogTypes);
+        Map<String, Object> brooklynConfig = (Map<String, Object>) itemMap.get(BrooklynCampReservedKeys.BROOKLYN_CONFIG);
+        if (brooklynConfig != null) {
+            spec.configure(brooklynConfig);
+        }
+        List<?> parameters = (List<?>) itemMap.get(BrooklynCampReservedKeys.BROOKLYN_PARAMETERS);
+        initParameters(parameters, spec, loader);
+        return spec;
+    }
+
+    static LocationSpec<?> createLocationSpec(String yamlPlan, BrooklynClassLoadingContext loader, Set<String> encounteredTypes) {
+        DeploymentPlan plan = makePlanFromYaml(loader.getManagementContext(), yamlPlan);
+        Object locations = checkNotNull(plan.getCustomAttributes().get(BasicBrooklynCatalog.LOCATIONS_KEY), "location config");
+        if (!(locations instanceof Iterable<?>)) {
+            throw new IllegalStateException("The value of " + BasicBrooklynCatalog.LOCATIONS_KEY + " must be an Iterable.");
+        }
+
+        Object location = Iterables.getOnlyElement((Iterable<?>)locations);
+        return createLocationSpec(loader, location);
+    }
+
+    @SuppressWarnings("unchecked")
+    private static LocationSpec<?> createLocationSpec(BrooklynClassLoadingContext loader, Object location) {
+        Map<String, Object> itemMap;
+        if (location instanceof String) {
+            itemMap = ImmutableMap.<String, Object>of("type", location);
+        } else if (location instanceof Map) {
+            itemMap = (Map<String, Object>) location;
+        } else {
+            throw new IllegalStateException("Location expected to be string or map. Unsupported object type " + location.getClass().getName() + " (" + location.toString() + ")");
+        }
+
+        String type = (String) checkNotNull(Yamls.getMultinameAttribute(itemMap, "location_type", "locationType", "type"), "location type");
+        Map<String, Object> brooklynConfig = (Map<String, Object>) itemMap.get("brooklyn.config");
+        LocationSpec<?> locationSpec = resolveLocationSpec(type, brooklynConfig, loader);
+        List<?> explicitParams = (List<?>) itemMap.get(BrooklynCampReservedKeys.BROOKLYN_PARAMETERS);
+        initParameters(explicitParams, locationSpec, loader);
+        return locationSpec;
+    }
+
+    private static void initParameters(List<?> explicitParams, AbstractBrooklynObjectSpec<?, ?> spec, BrooklynClassLoadingContext loader) {
+        if (explicitParams != null) {
+            spec.parameters(BasicSpecParameter.fromConfigList(explicitParams, loader));
+        } else {
+            spec.parameters(BasicSpecParameter.fromSpec(loader.getManagementContext(), spec));
+        }
+    }
+
+    public static DeploymentPlan makePlanFromYaml(ManagementContext mgmt, String yaml) {
+        CampPlatform camp = getCampPlatform(mgmt);
+        return camp.pdp().parseDeploymentPlan(Streams.newReaderWithContents(yaml));
+    }
+
+    public static CampPlatform getCampPlatform(ManagementContext mgmt) {
+        CampPlatform result = mgmt.getConfig().getConfig(BrooklynCampConstants.CAMP_PLATFORM);
+        if (result!=null) {
+            return result;
+        } else {
+            throw new IllegalStateException("No CAMP Platform is registered with this Brooklyn management context.");
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static PolicySpec<? extends Policy> resolvePolicySpec(
+            String versionedId,
+            BrooklynClassLoadingContext loader,
+            Set<String> encounteredCatalogTypes) {
+        
+        PolicySpec<? extends Policy> spec;
+        RegisteredType item = loader.getManagementContext().getTypeRegistry().get(versionedId);
+        if (item != null && !encounteredCatalogTypes.contains(item.getSymbolicName())) {
+            return loader.getManagementContext().getTypeRegistry().createSpec(item, null, PolicySpec.class);
+        } else {
+            // TODO-type-registry pass the loader in to the above, and allow it to load with the loader
+            spec = PolicySpec.create(loader.loadClass(versionedId, Policy.class));
+        }
+        return spec;
+    }
+
+    private static LocationSpec<?> resolveLocationSpec(
+            String type,
+            Map<String, Object> brooklynConfig,
+            BrooklynClassLoadingContext loader) {
+        Maybe<Class<? extends Location>> javaClass = loader.tryLoadClass(type, Location.class);
+        if (javaClass.isPresent()) {
+            LocationSpec<?> spec = LocationSpec.create(javaClass.get());
+            if (brooklynConfig != null) {
+                spec.configure(brooklynConfig);
+            }
+            return spec;
+        } else {
+            Maybe<Location> loc = loader.getManagementContext().getLocationRegistry().resolve(type, false, brooklynConfig);
+            if (loc.isPresent()) {
+                // TODO extensions?
+                Map<String, Object> locConfig = ((ConfigurationSupportInternal)loc.get().config()).getBag().getAllConfig();
+                Class<? extends Location> locType = loc.get().getClass();
+                Set<Object> locTags = loc.get().tags().getTags();
+                String locDisplayName = loc.get().getDisplayName();
+                return LocationSpec.create(locType)
+                        .configure(locConfig)
+                        .displayName(locDisplayName)
+                        .tags(locTags);
+            } else {
+                throw new IllegalStateException("No class or resolver found for location type "+type);
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
new file mode 100644
index 0000000..1fc6eaf
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
@@ -0,0 +1,142 @@
+/*
+ * 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.camp.brooklyn.spi.creation;
+
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.camp.CampPlatform;
+import org.apache.brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
+import org.apache.brooklyn.camp.spi.AssemblyTemplate;
+import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.mgmt.EntityManagementUtils;
+import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.core.typereg.RegisteredTypes;
+import org.apache.brooklyn.util.text.Strings;
+
+import com.google.common.collect.ImmutableSet;
+
+class CampResolver {
+
+    private ManagementContext mgmt;
+    private RegisteredType type;
+    private RegisteredTypeConstraint context;
+
+    /** whether to allow parsing of the 'full' syntax for applications,
+     * where items are wrapped in a "services:" block, and if the wrapper is an application,
+     * to promote it */
+    boolean allowApplicationFullSyntax = true;
+
+    /** whether to allow parsing of the legacy 'full' syntax, 
+     * where a non-application items are wrapped:
+     * <li> in a "services:" block for entities,
+     * <li> in a "brooklyn.locations" or "brooklyn.policies" block for locations and policies */
+    boolean allowLegacyFullSyntax = true;
+
+    /** whether to allow parsing of the type syntax, where an item is a map with a "type:" field,
+     * i.e. not wrapped in any "services:" or "brooklyn.{locations,policies}" block */
+    boolean allowTypeSyntax = true;
+
+    public CampResolver(ManagementContext mgmt, RegisteredType type, RegisteredTypeConstraint context) {
+        this.mgmt = mgmt;
+        this.type = type;
+        this.context = context;
+    }
+
+    public AbstractBrooklynObjectSpec<?, ?> createSpec() {
+        // TODO modern approach
+        //            AbstractBrooklynObjectSpec<?, ?> spec = RegisteredTypes.newSpecInstance(mgmt, /* 'type' key */);
+        //            spec.configure(keysAndValues);
+        return createSpecFromFull(mgmt, type, 
+            context.getEncounteredTypes(), (BrooklynClassLoadingContext) context.getLoader());
+    }
+
+    static AbstractBrooklynObjectSpec<?, ?> createSpecFromFull(ManagementContext mgmt, RegisteredType item, Set<String> parentEncounteredTypes, BrooklynClassLoadingContext loaderO) {
+        // for this method, a prefix "services" or "brooklyn.{location,policies}" is required at the root;
+        // we now prefer items to come in "{ type: .. }" format, except for application roots which
+        // should have a "services: [ ... ]" block (and which may subsequently be unwrapped)
+        BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, item, loaderO);
+
+        Set<String> encounteredTypes;
+        // symbolicName could be null if coming from the catalog parser where it tries to load before knowing the id
+        if (item.getSymbolicName() != null) {
+            encounteredTypes = ImmutableSet.<String>builder()
+                .addAll(parentEncounteredTypes)
+                .add(item.getSymbolicName())
+                .build();
+        } else {
+            encounteredTypes = parentEncounteredTypes;
+        }
+
+        AbstractBrooklynObjectSpec<?, ?> spec;
+        String planYaml = RegisteredTypes.getImplementationDataStringForSpec(item);
+        if (RegisteredTypes.isSubTypeOf(item, Policy.class)) {
+            spec = CampInternalUtils.createPolicySpec(planYaml, loader, encounteredTypes);
+        } else if (RegisteredTypes.isSubTypeOf(item, Location.class)) {
+            spec = CampInternalUtils.createLocationSpec(planYaml, loader, encounteredTypes);
+        } else if (RegisteredTypes.isSubTypeOf(item, Application.class)) {
+            spec = createEntitySpecFromServicesBlock(planYaml, loader, encounteredTypes, true);
+        } else if (RegisteredTypes.isSubTypeOf(item, Entity.class)) {
+            spec = createEntitySpecFromServicesBlock(planYaml, loader, encounteredTypes, false);
+        } else {
+            // try any of them???
+            
+            throw new IllegalStateException("Cannot detect spec type from "+item.getSuperTypes()+" for "+item+"\n"+planYaml);
+        }
+
+        ((AbstractBrooklynObjectSpec<?, ?>)spec).catalogItemId(item.getId());
+
+        if (Strings.isBlank( ((AbstractBrooklynObjectSpec<?, ?>)spec).getDisplayName() ))
+            ((AbstractBrooklynObjectSpec<?, ?>)spec).displayName(item.getDisplayName());
+
+        return spec;
+    }
+ 
+    private static EntitySpec<?> createEntitySpecFromServicesBlock(String plan, BrooklynClassLoadingContext loader, Set<String> encounteredTypes, boolean isApplication) {
+        CampPlatform camp = CampInternalUtils.getCampPlatform(loader.getManagementContext());
+
+        AssemblyTemplate at = CampInternalUtils.registerDeploymentPlan(plan, loader, camp);
+        AssemblyTemplateInstantiator instantiator = CampInternalUtils.getInstantiator(at);
+        if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
+            EntitySpec<? extends Application> appSpec = ((AssemblyTemplateSpecInstantiator)instantiator).createApplicationSpec(at, camp, loader, encounteredTypes);
+            CampInternalUtils.resetSpecIfTemplateHasNoExplicitParameters(at, appSpec);
+
+            if (!isApplication && EntityManagementUtils.canPromoteChildrenInWrappedApplication(appSpec) && appSpec.getChildren().size()==1) {
+                EntitySpec<?> childSpec = appSpec.getChildren().get(0);
+                EntityManagementUtils.mergeWrapperParentSpecToChildEntity(appSpec, childSpec);
+                return childSpec;
+            }
+            return appSpec;
+            
+        } else {
+            throw new IllegalStateException("Unable to instantiate YAML; incompatible instantiator "+instantiator+" for "+at);
+        }
+
+    }
+
+}
\ No newline at end of file


[08/14] incubator-brooklyn git commit: Merge branch 'master' into type-registry

Posted by he...@apache.org.
Merge branch 'master' into type-registry


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

Branch: refs/heads/master
Commit: 42bf7c414f3fa6fd948ba2c456007ba8d1f8a00f
Parents: c712ad5 78df97a
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Nov 11 17:22:05 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Wed Nov 11 17:22:05 2015 +0000

----------------------------------------------------------------------
 core/pom.xml                                    |   1 +
 pom.xml                                         |   2 +
 usage/test-framework/README.md                  | 109 ++++++++
 usage/test-framework/pom.xml                    |  71 +++++
 .../brooklyn/test/framework/AbstractTest.java   |  50 ++++
 .../brooklyn/test/framework/BaseTest.java       |  45 ++++
 .../test/framework/ParallelTestCase.java        |  14 +
 .../test/framework/ParallelTestCaseImpl.java    | 125 +++++++++
 .../brooklyn/test/framework/TestCase.java       |  12 +
 .../brooklyn/test/framework/TestCaseImpl.java   |  61 +++++
 .../brooklyn/test/framework/TestEffector.java   |  31 +++
 .../test/framework/TestEffectorImpl.java        |  78 ++++++
 .../brooklyn/test/framework/TestHttpCall.java   |  19 ++
 .../test/framework/TestHttpCallImpl.java        | 106 ++++++++
 .../brooklyn/test/framework/TestSensor.java     |  24 ++
 .../brooklyn/test/framework/TestSensorImpl.java | 138 ++++++++++
 .../test/framework/TestEffectorTest.java        | 106 ++++++++
 .../brooklyn/test/framework/TestSensorTest.java | 267 +++++++++++++++++++
 .../test/framework/entity/TestEntity.java       |  55 ++++
 .../test/framework/entity/TestEntityImpl.java   |  40 +++
 .../resources/test-framework-examples/README.md |   9 +
 .../example-catalog-test.bom                    |  22 ++
 .../test-framework-examples/example-catalog.bom |  15 ++
 .../nginx-test-examples.yml                     |  98 +++++++
 .../testhttpcall-examples.yml                   | 124 +++++++++
 .../tomcat-test-examples.yml                    |  45 ++++
 26 files changed, 1667 insertions(+)
----------------------------------------------------------------------



[11/14] incubator-brooklyn git commit: add validation for registered types, and simplify TypeRegistry.get method

Posted by he...@apache.org.
add validation for registered types, and simplify TypeRegistry.get method

as per code review, and improve logging and fix test failure


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

Branch: refs/heads/master
Commit: 5dd940bd12b75305aa1c8e74f45fc2801729754b
Parents: db024f4
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Nov 17 14:14:44 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Nov 17 14:16:59 2015 +0000

----------------------------------------------------------------------
 .../internal/AbstractBrooklynObjectSpec.java    |   2 +-
 .../api/typereg/BrooklynTypeRegistry.java       |  14 +--
 .../core/catalog/internal/CatalogUtils.java     |   5 +-
 .../typereg/AbstractTypePlanTransformer.java    |  19 ++-
 .../core/typereg/BasicBrooklynTypeRegistry.java |  20 ++-
 .../core/typereg/RegisteredTypeKindVisitor.java |  23 ++--
 .../core/typereg/RegisteredTypePredicates.java  |  14 ++-
 .../brooklyn/core/typereg/RegisteredTypes.java  | 122 +++++++++++++++++--
 .../core/typereg/TypePlanTransformers.java      |   9 +-
 .../internal/SpecParameterInMetaTest.java       |  12 +-
 .../typereg/ExampleXmlTypePlanTransformer.java  |   2 +-
 .../BrooklynEntityDecorationResolver.java       |   3 +-
 .../brooklyn/spi/creation/CampResolver.java     |   8 +-
 .../CatalogOsgiVersionMoreEntityTest.java       |   6 +-
 .../catalog/CatalogYamlLocationTest.java        |   2 +-
 .../brooklyn/test/lite/CampYamlLiteTest.java    |   2 +-
 .../rest/resources/ApplicationResource.java     |   3 +-
 .../rest/resources/CatalogResource.java         |   3 +-
 18 files changed, 205 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java b/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java
index 72fa96f..aa3a198 100644
--- a/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java
+++ b/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java
@@ -113,7 +113,7 @@ public abstract class AbstractBrooklynObjectSpec<T,SpecT extends AbstractBrookly
     }
 
     /**
-     * @return The type of the object (or significant interface)
+     * @return The type (often an interface) this spec represents and which will be instantiated from it 
      */
     public Class<? extends T> getType() {
         return type;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java b/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
index 42aa8ec..78c49d8 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java
@@ -42,22 +42,22 @@ public interface BrooklynTypeRegistry {
     Iterable<RegisteredType> getAll();
     Iterable<RegisteredType> getAll(Predicate<? super RegisteredType> filter);
 
-    // TODO should we remove the `context` parameter from all these?  i don't think it's useful
     /** @return The item matching the given given 
      * {@link RegisteredType#getSymbolicName() symbolicName} 
      * and optionally {@link RegisteredType#getVersion()},
-     * filtered for the optionally supplied {@link RegisteredTypeLoadingContext}, 
      * taking the best version if the version is null or a default marker,
      * returning null if no matches are found. */
-    RegisteredType get(String symbolicName, String version, @Nullable RegisteredTypeLoadingContext context);
-    /** as {@link #get(String, String, RegisteredTypeLoadingContext)} with no constraints */
     RegisteredType get(String symbolicName, String version);
-    /** as {@link #get(String, String, RegisteredTypeLoadingContext)} but allows <code>"name:version"</code> 
+    /** as {@link #get(String, String)} but allows <code>"name:version"</code> 
      * (the {@link RegisteredType#getId()}) in addition to the unversioned name,
      * using a default marker if no version can be inferred */
-    RegisteredType get(String symbolicNameWithOptionalVersion, @Nullable RegisteredTypeLoadingContext context);
-    /** as {@link #get(String, RegisteredTypeLoadingContext)} but with no constraints */
     RegisteredType get(String symbolicNameWithOptionalVersion);
+    
+    // TODO remove
+//    /** as {@link #get(String, String)}, but applying the optionally supplied {@link RegisteredTypeLoadingContext} */ 
+//    RegisteredType get(String symbolicName, String version, @Nullable RegisteredTypeLoadingContext context);
+//    /** as {@link #get(String)}, but applying the optionally supplied {@link RegisteredTypeLoadingContext} */ 
+//    RegisteredType get(String symbolicNameWithOptionalVersion, @Nullable RegisteredTypeLoadingContext context);
 
     // NB the seemingly more correct generics <T,SpecT extends AbstractBrooklynObjectSpec<T,SpecT>> 
     // cause compile errors, not in Eclipse, but in maven (?) 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
index f144b7c..ef455c6 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
@@ -43,6 +43,7 @@ import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.mgmt.rebind.RebindManagerImpl.RebindTracker;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
 import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
+import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.time.Time;
@@ -84,7 +85,7 @@ public class CatalogUtils {
         ManagementContext mgmt = ((EntityInternal)entity).getManagementContext();
         String catId = entity.getCatalogItemId();
         if (Strings.isBlank(catId)) return JavaBrooklynClassLoadingContext.create(mgmt);
-        RegisteredType cat = mgmt.getTypeRegistry().get(catId, RegisteredTypeLoadingContexts.spec(Entity.class));
+        RegisteredType cat = RegisteredTypes.validate(mgmt.getTypeRegistry().get(catId), RegisteredTypeLoadingContexts.spec(Entity.class));
         if (cat==null) {
             log.warn("Cannot load "+catId+" to get classloader for "+entity+"; will try with standard loader, but might fail subsequently");
             return JavaBrooklynClassLoadingContext.create(mgmt);
@@ -266,7 +267,7 @@ public class CatalogUtils {
     }
 
     public static boolean isBestVersion(ManagementContext mgmt, CatalogItem<?,?> item) {
-        RegisteredType bestVersion = mgmt.getTypeRegistry().get(item.getSymbolicName(), BrooklynCatalog.DEFAULT_VERSION, null);
+        RegisteredType bestVersion = mgmt.getTypeRegistry().get(item.getSymbolicName(), BrooklynCatalog.DEFAULT_VERSION);
         if (bestVersion==null) return false;
         return (bestVersion.getVersion().equals(item.getVersion()));
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java b/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java
index 2900e20..79085ea 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/AbstractTypePlanTransformer.java
@@ -99,20 +99,20 @@ public abstract class AbstractTypePlanTransformer implements BrooklynTypePlanTra
     public Object create(final RegisteredType type, final RegisteredTypeLoadingContext context) {
         try {
             return validate(new RegisteredTypeKindVisitor<Object>() {
-                @Override protected Object visitSpec(RegisteredType type) {
+                @Override protected Object visitSpec() {
                     try { 
                         AbstractBrooklynObjectSpec<?, ?> result = createSpec(type, context);
                         result.catalogItemId(type.getId());
                         return result;
                     } catch (Exception e) { throw Exceptions.propagate(e); }
                 }
-                @Override protected Object visitBean(RegisteredType type) {
+                @Override protected Object visitBean() {
                     try { 
                         return createBean(type, context);
                     } catch (Exception e) { throw Exceptions.propagate(e); }
                 }
                 
-            }.visit(type), type, context);
+            }.visit(type.getKind()), type, context);
         } catch (Exception e) {
             Exceptions.propagateIfFatal(e);
             if (!(e instanceof UnsupportedTypePlanException)) {
@@ -122,10 +122,17 @@ public abstract class AbstractTypePlanTransformer implements BrooklynTypePlanTra
         }
     }
     
-    protected <T> T validate(T createdObject, RegisteredType type, RegisteredTypeLoadingContext context) {
+    /** Validates the object. Subclasses may do further validation based on the context. 
+     * @throw UnsupportedTypePlanException if we want to quietly abandon this, any other exception to report the problem, when validation fails
+     * @return the created object for fluent usage */
+    protected <T> T validate(T createdObject, RegisteredType type, RegisteredTypeLoadingContext constraint) {
         if (createdObject==null) return null;
-        // TODO validation based on the constraint, throw UnsupportedTypePlanException with details if not matched
-        return createdObject;
+        try {
+            return RegisteredTypes.validate(createdObject, type, constraint);
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            throw new IllegalStateException("Created incompatible object: "+Exceptions.collapseText(e), e);
+        }
     }
 
     protected abstract AbstractBrooklynObjectSpec<?,?> createSpec(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
index 2f2d4f5..b36be34 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
@@ -35,6 +35,7 @@ import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
 import org.apache.brooklyn.core.catalog.internal.CatalogItemBuilder;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.text.Identifiers;
@@ -68,8 +69,8 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
     }
 
     @SuppressWarnings("deprecation")
-    @Override
-    public RegisteredType get(String symbolicName, String version, RegisteredTypeLoadingContext constraint) {
+    private RegisteredType get(String symbolicName, String version, RegisteredTypeLoadingContext constraint) {
+        // probably constraint is not useful?
         if (constraint==null) constraint = RegisteredTypeLoadingContexts.any();
         if (version==null) version = BrooklynCatalog.DEFAULT_VERSION;
         
@@ -86,8 +87,8 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
         return get(symbolicName, version, null);
     }
     
-    @Override
-    public RegisteredType get(String symbolicNameWithOptionalVersion, RegisteredTypeLoadingContext constraint) {
+    private RegisteredType get(String symbolicNameWithOptionalVersion, RegisteredTypeLoadingContext constraint) {
+        // probably constraint is not useful?
         if (CatalogUtils.looksLikeVersionedId(symbolicNameWithOptionalVersion)) {
             String symbolicName = CatalogUtils.getSymbolicNameFromVersionedId(symbolicNameWithOptionalVersion);
             String version = CatalogUtils.getVersionFromVersionedId(symbolicNameWithOptionalVersion);
@@ -159,8 +160,15 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
                 // above will throw -- so won't come here
                 throw new IllegalStateException("should have failed getting type resolution for "+symbolicName);
             } catch (Exception e0) {
-                // prefer older exception, until the new transformer is the primary pathway
-                throw Exceptions.create("Unable to instantiate "+(symbolicName==null ? "item" : symbolicName), MutableList.of(e0, e));
+                Set<Exception> exceptionsInOrder = MutableSet.of();
+                if (e0.toString().indexOf("none of the available transformers")>=0) {
+                    // put the legacy exception first if none of the new transformers support the type
+                    // (until the new transformer is the primary pathway)
+                    exceptionsInOrder.add(e);
+                }
+                exceptionsInOrder.add(e0);
+                exceptionsInOrder.add(e);
+                throw Exceptions.create("Unable to instantiate "+(symbolicName==null ? "item" : symbolicName), exceptionsInOrder); 
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeKindVisitor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeKindVisitor.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeKindVisitor.java
index 530828e..6f781fa 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeKindVisitor.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeKindVisitor.java
@@ -18,7 +18,7 @@
  */
 package org.apache.brooklyn.core.typereg;
 
-import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
 
 /** Visitor adapter which can be used to ensure all kinds are supported
  * <p>
@@ -26,17 +26,20 @@ import org.apache.brooklyn.api.typereg.RegisteredType;
  * and subclasses will be responsible for providing the implementation in order to ensure compatibility. */
 public abstract class RegisteredTypeKindVisitor<T> {
     
-    public T visit(RegisteredType type) {
-        if (type==null) throw new NullPointerException("Registered type must not be null");
-        switch (type.getKind()) {
-        case SPEC: return visitSpec(type);
-        case BEAN: return visitBean(type);
-        // others go here
+    public T visit(RegisteredTypeKind kind) {
+        if (kind==null) return visitNull();
+        switch (kind) {
+        case SPEC: return visitSpec();
+        case BEAN: return visitBean();
         default:
-            throw new IllegalStateException("Unexpected registered type: "+type.getClass());
+            throw new IllegalStateException("Unexpected registered type kind: "+kind);
         }
     }
 
-    protected abstract T visitSpec(RegisteredType type);
-    protected abstract T visitBean(RegisteredType type);
+    protected T visitNull() {
+        throw new NullPointerException("Registered type kind must not be null");
+    }
+
+    protected abstract T visitSpec();
+    protected abstract T visitBean();
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java
index bc81d8e..ebeccd7 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java
@@ -113,7 +113,9 @@ public class RegisteredTypePredicates {
         return new AnySuperTypeMatches(filter);
     }
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    public static Predicate<RegisteredType> assignableFrom(final Class<?> filter) {
+    public static Predicate<RegisteredType> subtypeOf(final Class<?> filter) {
+        // the assignableFrom predicate checks if this class is assignable from the subsequent *input*.
+        // in other words, we're checking if any input is a subtype of this class
         return anySuperType((Predicate)Predicates.assignableFrom(filter));
     }
     
@@ -130,11 +132,11 @@ public class RegisteredTypePredicates {
             return RegisteredTypes.isAnyTypeOrSuperSatisfying(item.getSuperTypes(), filter);
         }
     }
-
-    public static final Predicate<RegisteredType> IS_APPLICATION = assignableFrom(Application.class);
-    public static final Predicate<RegisteredType> IS_ENTITY = assignableFrom(Entity.class);
-    public static final Predicate<RegisteredType> IS_LOCATION = assignableFrom(Location.class);
-    public static final Predicate<RegisteredType> IS_POLICY = assignableFrom(Policy.class);
+    
+    public static final Predicate<RegisteredType> IS_APPLICATION = subtypeOf(Application.class);
+    public static final Predicate<RegisteredType> IS_ENTITY = subtypeOf(Entity.class);
+    public static final Predicate<RegisteredType> IS_LOCATION = subtypeOf(Location.class);
+    public static final Predicate<RegisteredType> IS_POLICY = subtypeOf(Policy.class);
 
     public static Predicate<RegisteredType> entitledToSee(final ManagementContext mgmt) {
         return new EntitledToSee(mgmt);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
index 6fd993a..18f8f43 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
@@ -37,6 +37,7 @@ import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
 import org.apache.brooklyn.core.typereg.JavaClassNameTypePlanTransformer.JavaClassNameTypeImplementationPlan;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
@@ -55,7 +56,7 @@ import com.google.common.reflect.TypeToken;
  * Use {@link #bean(String, String, TypeImplementationPlan, Class)} and {@link #spec(String, String, TypeImplementationPlan, Class)}
  * to create {@link RegisteredType} instances.
  * <p>
- * See {@link #isAssignableFrom(RegisteredType, Class)} or {@link #isAssignableFrom(RegisteredType, RegisteredType)} to 
+ * See {@link #isSubtypeOf(RegisteredType, Class)} or {@link #isSubtypeOf(RegisteredType, RegisteredType)} to 
  * inspect the type hierarchy.
  */
 public class RegisteredTypes {
@@ -138,7 +139,7 @@ public class RegisteredTypes {
     @Beta
     public static RegisteredType addSuperType(RegisteredType type, @Nullable RegisteredType superType) {
         if (superType!=null) {
-            if (isAssignableFrom(superType, type)) {
+            if (isSubtypeOf(superType, type)) {
                 throw new IllegalStateException(superType+" declares "+type+" as a supertype; cannot set "+superType+" as a supertype of "+type);
             }
             ((BasicRegisteredType)type).superTypes.add(superType);
@@ -190,11 +191,11 @@ public class RegisteredTypes {
     /** 
      * Queries recursively the supertypes of {@link RegisteredType} to see whether it 
      * inherits from the given {@link RegisteredType} */
-    public static boolean isAssignableFrom(RegisteredType type, RegisteredType superType) {
+    public static boolean isSubtypeOf(RegisteredType type, RegisteredType superType) {
         if (type.equals(superType)) return true;
         for (Object st: type.getSuperTypes()) {
             if (st instanceof RegisteredType) {
-                if (isAssignableFrom((RegisteredType)st, superType)) return true;
+                if (isSubtypeOf((RegisteredType)st, superType)) return true;
             }
         }
         return false;
@@ -203,14 +204,14 @@ public class RegisteredTypes {
     /** 
      * Queries recursively the supertypes of {@link RegisteredType} to see whether it 
      * inherits from the given {@link Class} */
-    public static boolean isAssignableFrom(RegisteredType type, Class<?> superType) {
-        return isAnyTypeAssignableFrom(type.getSuperTypes(), superType);
+    public static boolean isSubtypeOf(RegisteredType type, Class<?> superType) {
+        return isAnyTypeSubtypeOf(type.getSuperTypes(), superType);
     }
     
     /** 
      * Queries recursively the given types (either {@link Class} or {@link RegisteredType}) 
      * to see whether any inherit from the given {@link Class} */
-    public static boolean isAnyTypeAssignableFrom(Set<Object> candidateTypes, Class<?> superType) {
+    public static boolean isAnyTypeSubtypeOf(Set<Object> candidateTypes, Class<?> superType) {
         return isAnyTypeOrSuperSatisfying(candidateTypes, Predicates.assignableFrom(superType));
     }
 
@@ -231,4 +232,111 @@ public class RegisteredTypes {
         return false;
     }
 
+    public static RegisteredType validate(RegisteredType item, final RegisteredTypeLoadingContext constraint) {
+        if (item==null || constraint==null) return item;
+        if (constraint.getExpectedKind()!=null && !constraint.getExpectedKind().equals(item.getKind()))
+            throw new IllegalStateException(item+" is not the expected kind "+constraint.getExpectedKind());
+        if (constraint.getExpectedJavaSuperType()!=null) {
+            if (!isSubtypeOf(item, constraint.getExpectedJavaSuperType())) {
+                throw new IllegalStateException(item+" is not for the expected type "+constraint.getExpectedJavaSuperType());
+            }
+        }
+        return item;
+    }
+
+    /** 
+     * Checks whether the given object appears to be an instance of the given registered type */
+    private static boolean isSubtypeOf(Class<?> candidate, RegisteredType type) {
+        for (Object st: type.getSuperTypes()) {
+            if (st instanceof RegisteredType) {
+                if (!isSubtypeOf(candidate, (RegisteredType)st)) return false;
+            }
+            if (st instanceof Class) {
+                if (!((Class<?>)st).isAssignableFrom(candidate)) return false;
+            }
+        }
+        return true;
+    }
+
+    public static <T> T validate(final T object, final RegisteredType type, final RegisteredTypeLoadingContext constraint) {
+        RegisteredTypeKind kind = type!=null ? type.getKind() : constraint!=null ? constraint.getExpectedKind() : null;
+        if (kind==null) {
+            if (object instanceof AbstractBrooklynObjectSpec) kind=RegisteredTypeKind.SPEC;
+            else kind=RegisteredTypeKind.BEAN;
+        }
+        return new RegisteredTypeKindVisitor<T>() {
+            @Override
+            protected T visitSpec() {
+                return validateSpec(object, type, constraint);
+            }
+
+            @Override
+            protected T visitBean() {
+                return validateBean(object, type, constraint);
+            }
+        }.visit(kind);
+    }
+
+    private static <T> T validateBean(T object, RegisteredType type, final RegisteredTypeLoadingContext constraint) {
+        if (object==null) return null;
+        
+        if (type!=null) {
+            if (type.getKind()!=RegisteredTypeKind.BEAN)
+                throw new IllegalStateException("Validating a bean when type is "+type.getKind()+" "+type);
+            if (!isSubtypeOf(object.getClass(), type))
+                throw new IllegalStateException(object+" does not have all the java supertypes of "+type);
+        }
+
+        if (constraint!=null) {
+            if (constraint.getExpectedKind()!=RegisteredTypeKind.BEAN)
+                throw new IllegalStateException("Validating a bean when constraint expected "+constraint.getExpectedKind());
+            if (constraint.getExpectedJavaSuperType()!=null && !constraint.getExpectedJavaSuperType().isInstance(object))
+                throw new IllegalStateException(object+" is not of the expected java supertype "+constraint.getExpectedJavaSuperType());
+        }
+        
+        return object;
+    }
+
+    private static <T> T validateSpec(T object, RegisteredType rType, final RegisteredTypeLoadingContext constraint) {
+        if (object==null) return null;
+        
+        if (!(object instanceof AbstractBrooklynObjectSpec)) {
+            throw new IllegalStateException("Found "+object+" when expecting a spec");
+        }
+        Class<?> targetType = ((AbstractBrooklynObjectSpec<?,?>)object).getType();
+        
+        if (targetType==null) {
+            throw new IllegalStateException("Spec "+object+" does not have a target type");
+        }
+        
+        if (rType!=null) {
+            if (rType.getKind()!=RegisteredTypeKind.SPEC)
+                throw new IllegalStateException("Validating a spec when type is "+rType.getKind()+" "+rType);
+            if (!isSubtypeOf(targetType, rType))
+                throw new IllegalStateException(object+" does not have all the java supertypes of "+rType);
+        }
+
+        if (constraint!=null) {
+            if (constraint.getExpectedJavaSuperType()!=null) {
+                if (!constraint.getExpectedJavaSuperType().isAssignableFrom(targetType)) {
+                    throw new IllegalStateException(object+" does not target the expected java supertype "+constraint.getExpectedJavaSuperType());
+                }
+                if (constraint.getExpectedJavaSuperType().isAssignableFrom(BrooklynObjectInternal.class)) {
+                    // don't check spec type; any spec is acceptable
+                } else {
+                    @SuppressWarnings("unchecked")
+                    Class<? extends AbstractBrooklynObjectSpec<?, ?>> specType = RegisteredTypeLoadingContexts.lookupSpecTypeForTarget( (Class<? extends BrooklynObject>) constraint.getExpectedJavaSuperType());
+                    if (specType==null) {
+                        // means a problem in our classification of spec types!
+                        throw new IllegalStateException(object+" is returned as spec for unexpected java supertype "+constraint.getExpectedJavaSuperType());
+                    }
+                    if (!specType.isAssignableFrom(object.getClass())) {
+                        throw new IllegalStateException(object+" is not a spec of the expected java supertype "+constraint.getExpectedJavaSuperType());
+                    }
+                }
+            }
+        }
+        return object;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java b/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java
index b554e09..e24660e 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/TypePlanTransformers.java
@@ -141,7 +141,10 @@ public class TypePlanTransformers {
             if (log.isDebugEnabled()) {
                 log.debug("Failure transforming plan; returning summary failure, but for reference "
                     + "potentially application transformers were "+transformers+", "
-                    + "others available are "+MutableList.builder().addAll(all(mgmt)).removeAll(transformers).build()+"; "
+                    + "available ones are "+MutableList.builder().addAll(all(mgmt))
+                        // when all(mgmt) has a cache, reinstate this and add the word "other" above
+//                        .removeAll(transformers)
+                        .build()+"; "
                     + "failures: "+failuresFromTransformers);
             }
             result = failuresFromTransformers.size()==1 ? Exceptions.create(null, failuresFromTransformers) :
@@ -151,7 +154,9 @@ public class TypePlanTransformers {
                 result = new UnsupportedTypePlanException("Invalid plan; format could not be recognized, none of the available transformers "+all(mgmt)+" support "+type);
             } else {
                 result = new UnsupportedTypePlanException("Invalid plan; potentially applicable transformers "+transformers+" do not support it, and other available transformers "+
-                    MutableList.builder().addAll(all(mgmt)).removeAll(transformers).build()+" do not accept it");
+//                    // the removeAll call below won't work until "all" caches it
+//                    MutableList.builder().addAll(all(mgmt)).removeAll(transformers).build()+" "+
+                    "do not accept it");
             }
         }
         return Maybe.absent(result);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/core/src/test/java/org/apache/brooklyn/core/catalog/internal/SpecParameterInMetaTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/SpecParameterInMetaTest.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/SpecParameterInMetaTest.java
index 8fc5dd1..7c760e6 100644
--- a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/SpecParameterInMetaTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/SpecParameterInMetaTest.java
@@ -173,10 +173,14 @@ public class SpecParameterInMetaTest {
         assertEquals(itemT.getLibraries().size(), 2);
         
         EntitySpec<?> item = mgmt.getTypeRegistry().createSpec(itemT, null, EntitySpec.class);
-        SpecParameter<?> input = item.getParameters().get(0);
-        assertEquals(input.getLabel(), "more_config");
-        assertFalse(input.isPinned());
-        assertEquals(input.getType().getName(), "more_config");
+        Assert.assertNotNull(item);
+        Assert.assertEquals(item.getType().getName(), OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
+        
+        // TODO scanning for catalog parameters is broken
+//        SpecParameter<?> input = item.getParameters().get(0);
+//        assertEquals(input.getLabel(), "more_config");
+//        assertFalse(input.isPinned());
+//        assertEquals(input.getType().getName(), "more_config");
     }
 
     private String add(String... def) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformer.java b/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformer.java
index 23035c4..76570c8 100644
--- a/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformer.java
+++ b/core/src/test/java/org/apache/brooklyn/core/typereg/ExampleXmlTypePlanTransformer.java
@@ -71,7 +71,7 @@ public class ExampleXmlTypePlanTransformer extends AbstractTypePlanTransformer {
     }
 
     private static boolean isApplicationExpected(RegisteredType type, RegisteredTypeLoadingContext context) {
-        return RegisteredTypes.isAssignableFrom(type, Application.class) ||
+        return RegisteredTypes.isSubtypeOf(type, Application.class) ||
             (context.getExpectedJavaSuperType()!=null && context.getExpectedJavaSuperType().isAssignableFrom(Application.class));
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
index 9458046..0147b9d 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
@@ -34,6 +34,7 @@ import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
 import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator.InstantiatorFromKey;
 import org.apache.brooklyn.core.objs.BasicSpecParameter;
 import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
+import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 
@@ -114,7 +115,7 @@ public abstract class BrooklynEntityDecorationResolver<DT> {
             String policyType = decoLoader.getTypeName().get();
             ManagementContext mgmt = instantiator.loader.getManagementContext();
             
-            RegisteredType item = mgmt.getTypeRegistry().get(policyType, RegisteredTypeLoadingContexts.spec(Policy.class));
+            RegisteredType item = RegisteredTypes.validate(mgmt.getTypeRegistry().get(policyType), RegisteredTypeLoadingContexts.spec(Policy.class));
             PolicySpec<?> spec;
             if (item!=null) {
                 spec = mgmt.getTypeRegistry().createSpec(item, null, PolicySpec.class);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
index b9e63d1..4c70332 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
@@ -100,13 +100,13 @@ class CampResolver {
         String planYaml = RegisteredTypes.getImplementationDataStringForSpec(item);
         MutableSet<Object> supers = MutableSet.copyOf(item.getSuperTypes());
         supers.addIfNotNull(expectedType);
-        if (RegisteredTypes.isAnyTypeAssignableFrom(supers, Policy.class)) {
+        if (RegisteredTypes.isAnyTypeSubtypeOf(supers, Policy.class)) {
             spec = CampInternalUtils.createPolicySpec(planYaml, loader, encounteredTypes);
-        } else if (RegisteredTypes.isAnyTypeAssignableFrom(supers, Location.class)) {
+        } else if (RegisteredTypes.isAnyTypeSubtypeOf(supers, Location.class)) {
             spec = CampInternalUtils.createLocationSpec(planYaml, loader, encounteredTypes);
-        } else if (RegisteredTypes.isAnyTypeAssignableFrom(supers, Application.class)) {
+        } else if (RegisteredTypes.isAnyTypeSubtypeOf(supers, Application.class)) {
             spec = createEntitySpecFromServicesBlock(planYaml, loader, encounteredTypes, true);
-        } else if (RegisteredTypes.isAnyTypeAssignableFrom(supers, Entity.class)) {
+        } else if (RegisteredTypes.isAnyTypeSubtypeOf(supers, Entity.class)) {
             spec = createEntitySpecFromServicesBlock(planYaml, loader, encounteredTypes, false);
         } else {
             throw new IllegalStateException("Cannot detect spec type from "+item.getSuperTypes()+" for "+item+"\n"+planYaml);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
index 0a1b232..5a26f7a 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
@@ -241,17 +241,17 @@ public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest {
         for (RegisteredType item: items) {
             Object spec = types.createSpec(item, null, null);
             int match = 0;
-            if (RegisteredTypes.isAssignableFrom(item, Entity.class)) {
+            if (RegisteredTypes.isSubtypeOf(item, Entity.class)) {
                 assertTrue(spec instanceof EntitySpec, "Not an EntitySpec: " + spec);
                 BrooklynTypes.getDefinedEntityType(((EntitySpec<?>)spec).getType());
                 match++;
             }
-            if (RegisteredTypes.isAssignableFrom(item, Policy.class)) {
+            if (RegisteredTypes.isSubtypeOf(item, Policy.class)) {
                 assertTrue(spec instanceof PolicySpec, "Not a PolicySpec: " + spec);
                 BrooklynTypes.getDefinedBrooklynType(((PolicySpec<?>)spec).getType());
                 match++;
             }
-            if (RegisteredTypes.isAssignableFrom(item, Location.class)) {
+            if (RegisteredTypes.isSubtypeOf(item, Location.class)) {
                 assertTrue(spec instanceof LocationSpec, "Not a LocationSpec: " + spec);
                 BrooklynTypes.getDefinedBrooklynType(((LocationSpec<?>)spec).getType());
                 match++;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
index 7fa8896..291a06a 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
@@ -111,7 +111,7 @@ public class CatalogYamlLocationTest extends AbstractYamlTest {
     private void assertAdded(String symbolicName, String expectedJavaType) {
         RegisteredType item = mgmt().getTypeRegistry().get(symbolicName, TEST_VERSION);
         assertEquals(item.getSymbolicName(), symbolicName);
-        Assert.assertTrue(RegisteredTypes.isAssignableFrom(item, Location.class), "Expected Location, not "+item.getSuperTypes());
+        Assert.assertTrue(RegisteredTypes.isSubtypeOf(item, Location.class), "Expected Location, not "+item.getSuperTypes());
         assertEquals(countCatalogLocations(), 1);
 
         // Item added to catalog should automatically be available in location registry

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
index 1558db3..d8e4b1d 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
@@ -230,7 +230,7 @@ public class CampYamlLiteTest {
     }
 
     private void assertMgmtHasSampleMyCatalogApp(String symbolicName, String bundleUrl) {
-        RegisteredType item = mgmt.getTypeRegistry().get(symbolicName, RegisteredTypeLoadingContexts.spec(Entity.class));
+        RegisteredType item = RegisteredTypes.validate(mgmt.getTypeRegistry().get(symbolicName), RegisteredTypeLoadingContexts.spec(Entity.class));
         assertNotNull(item, "failed to load item with id=" + symbolicName + " from catalog. Entries were: " +
                 Joiner.on(",").join(mgmt.getTypeRegistry().getAll()));
         assertEquals(item.getSymbolicName(), symbolicName);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
index c22082b..89f253a 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
@@ -58,6 +58,7 @@ import org.apache.brooklyn.core.mgmt.entitlement.Entitlements.EntityAndItem;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements.StringAndArgument;
 import org.apache.brooklyn.core.sensor.Sensors;
 import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
+import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.entity.group.AbstractGroup;
 import org.apache.brooklyn.rest.api.ApplicationApi;
 import org.apache.brooklyn.rest.domain.ApplicationSpec;
@@ -401,7 +402,7 @@ public class ApplicationResource extends AbstractBrooklynRestResource implements
     }
 
     private void checkSpecTypeIsValid(String type, Class<? extends BrooklynObject> subType) {
-        if (mgmt().getTypeRegistry().get(type, RegisteredTypeLoadingContexts.spec(subType)) == null) {
+        if (RegisteredTypes.validate(mgmt().getTypeRegistry().get(type), RegisteredTypeLoadingContexts.spec(subType)) == null) {
             try {
                 brooklyn().getCatalogClassLoader().loadClass(type);
             } catch (ClassNotFoundException e) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5dd940bd/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
index ddfdc93..ecbeffb 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
@@ -51,6 +51,7 @@ import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements.StringAndArgument;
 import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
 import org.apache.brooklyn.core.typereg.RegisteredTypePredicates;
+import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.rest.api.CatalogApi;
 import org.apache.brooklyn.rest.domain.ApiError;
 import org.apache.brooklyn.rest.domain.CatalogEntitySummary;
@@ -148,7 +149,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
                 Entitlements.getEntitlementContext().user());
         }
         try {
-            RegisteredType item = mgmt().getTypeRegistry().get(entityId, RegisteredTypeLoadingContexts.spec(Entity.class));
+            RegisteredType item = RegisteredTypes.validate(mgmt().getTypeRegistry().get(entityId), RegisteredTypeLoadingContexts.spec(Entity.class));
             if (item==null) {
                 throw WebResourceUtils.notFound("Entity with id '%s' not found", entityId);
             }



[13/14] incubator-brooklyn git commit: relatively simple test for createSpec using the StaticTypePlanTransfomer

Posted by he...@apache.org.
relatively simple test for createSpec using the StaticTypePlanTransfomer


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

Branch: refs/heads/master
Commit: c575708d29f8a4577ce93536724454f3fa9ce736
Parents: 03aacd3
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Nov 17 22:50:24 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Nov 17 22:50:24 2015 +0000

----------------------------------------------------------------------
 .../internal/StaticTypePlanTransformer.java     | 10 ++--
 .../internal/StaticTypePlanTransformerTest.java | 63 ++++++++++++++++++++
 2 files changed, 69 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c575708d/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformer.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformer.java
index 613fe35..b7255e2 100644
--- a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformer.java
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformer.java
@@ -53,8 +53,10 @@ import org.apache.brooklyn.util.text.Identifiers;
  */
 public class StaticTypePlanTransformer extends AbstractTypePlanTransformer {
     
+    public static final String FORMAT = "static-types";
+    
     public StaticTypePlanTransformer() {
-        super("static-types", "Static Type", "Static transformer for use in tests");
+        super(FORMAT, "Static Type", "Static transformer for use in tests");
     }
 
     private static final Map<String, AbstractBrooklynObjectSpec<?, ?>> REGISTERED_SPECS = new ConcurrentHashMap<>();
@@ -101,9 +103,9 @@ public class StaticTypePlanTransformer extends AbstractTypePlanTransformer {
 
     @Override
     protected AbstractBrooklynObjectSpec<?, ?> createSpec(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception {
-        if (REGISTERED_SPECS.containsKey(type.getId()))
-            return get(type.getId());
-        if (REGISTERED_SPECS.containsKey(type.getPlan().getPlanData()))
+        if (REGISTERED_SPECS.containsKey(type.getSymbolicName()))
+            return get(type.getSymbolicName());
+        if (type.getPlan().getPlanData()!=null && REGISTERED_SPECS.containsKey(type.getPlan().getPlanData()))
             return get((String)type.getPlan().getPlanData());
         return null;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c575708d/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformerTest.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformerTest.java
new file mode 100644
index 0000000..db292e0
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformerTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.catalog.internal;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.core.test.BrooklynMgmtUnitTestSupport;
+import org.apache.brooklyn.core.typereg.BasicTypeImplementationPlan;
+import org.apache.brooklyn.core.typereg.RegisteredTypes;
+import org.apache.brooklyn.entity.stock.BasicEntity;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class StaticTypePlanTransformerTest extends BrooklynMgmtUnitTestSupport {
+
+    final static String DISPLAY_NAME = "Static Test";
+    String specId;
+    
+    @BeforeMethod(alwaysRun=true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        StaticTypePlanTransformer.forceInstall();
+        specId = StaticTypePlanTransformer.registerSpec(EntitySpec.create(BasicEntity.class).displayName(DISPLAY_NAME));
+    }
+    
+    @AfterMethod(alwaysRun=true)
+    @Override
+    public void tearDown() throws Exception {
+        StaticTypePlanTransformer.clearForced();
+        super.tearDown();
+    }
+    
+    @Test
+    public void testCreateSpec() {
+        EntitySpec<?> spec = mgmt.getTypeRegistry().createSpec(
+            RegisteredTypes.spec(specId, "1", new BasicTypeImplementationPlan(StaticTypePlanTransformer.FORMAT, null), Entity.class),
+            null, EntitySpec.class);
+        Assert.assertEquals(spec.getDisplayName(), DISPLAY_NAME);
+        Assert.assertEquals(spec.getType(), BasicEntity.class);
+    }
+
+    // there's a lot more which could be tested but at least we have a simple pathway asserting creation
+
+}


[02/14] incubator-brooklyn git commit: More conversion to new-style TypePlanTransformer, and fixes

Posted by he...@apache.org.
More conversion to new-style TypePlanTransformer, and fixes


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

Branch: refs/heads/master
Commit: c712ad5e6ed0b0cc6ea0a4e501091fc0dd77c9d9
Parents: e480402
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Nov 9 21:42:02 2015 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Nov 10 17:13:02 2015 +0000

----------------------------------------------------------------------
 .../catalog/internal/BasicBrooklynCatalog.java  |   2 +-
 .../core/typereg/BasicBrooklynTypeRegistry.java |   2 +-
 .../typereg/RegisteredTypeLoadingContexts.java  |   6 +-
 .../brooklyn/core/typereg/RegisteredTypes.java  |  18 ++-
 .../policy/basic/AbstractEntityAdjunctTest.java |  52 ---------
 .../internal/SpecParameterInMetaTest.java       |  65 +++++++++--
 .../internal/StaticTypePlanTransformer.java     | 115 +++++++++++++++++++
 .../catalog/internal/TestToSpecTransformer.java |  82 ++++++-------
 .../core/objs/AbstractEntityAdjunctTest.java    |  52 +++++++++
 ...che.brooklyn.core.plan.PlanToSpecTransformer |  19 ---
 .../brooklyn/spi/creation/CampCatalogUtils.java |   2 +-
 .../brooklyn/spi/creation/CampResolver.java     |  17 +--
 .../spi/creation/CampToSpecTransformer.java     |   2 +-
 .../spi/creation/CampTypePlanTransformer.java   |   4 +
 .../service/UrlServiceSpecResolver.java         |   2 +-
 .../camp/brooklyn/LocationsYamlTest.java        |   4 +-
 .../brooklyn/catalog/CatalogParametersTest.java |  49 +++++++-
 .../brooklyn/test/lite/CampYamlLiteTest.java    |   2 -
 .../rest/resources/ApplicationResource.java     |   9 +-
 19 files changed, 352 insertions(+), 152 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
index 75c727a..1b5d381 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
@@ -301,7 +301,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         if (loadedItem == null) throw new RuntimeException(item+" not in catalog; cannot create spec");
         if (loadedItem.getSpecType()==null) return null;
 
-        SpecT spec = internalCreateSpecLegacy(mgmt, loadedItem, MutableSet.<String>of(), false);
+        SpecT spec = internalCreateSpecLegacy(mgmt, loadedItem, MutableSet.<String>of(), true);
         if (spec != null) {
             return spec;
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
index b5c85c1..1bc4a9f 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
@@ -148,7 +148,7 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
                 throw new IllegalStateException("should have failed getting type resolution for "+type);
             } catch (Exception e0) {
                 // prefer older exception, until the new transformer is the primary pathway
-                throw Exceptions.create("Unable to instantiate "+type, MutableList.of(e, e0));
+                throw Exceptions.create("Unable to instantiate "+type, MutableList.of(e0, e));
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java
index 22ea294..594bdfd 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeLoadingContexts.java
@@ -134,8 +134,9 @@ public class RegisteredTypeLoadingContexts {
         BasicRegisteredTypeLoadingContext constraint = new BasicRegisteredTypeLoadingContext(source);
         if (source==null) source = constraint;
         if (superType==null) return source;
+        constraint.expectedSuperType = superType;
         if (source.getExpectedJavaSuperType()==null || source.getExpectedJavaSuperType().isAssignableFrom( superType )) {
-            // the constraint was weaker than present; return the new constraint
+            // the old constraint was weaker than present; return the new constraint
             return constraint;
         }
         if (superType.isAssignableFrom( source.getExpectedJavaSuperType() )) {
@@ -153,8 +154,9 @@ public class RegisteredTypeLoadingContexts {
         BasicRegisteredTypeLoadingContext constraint = new BasicRegisteredTypeLoadingContext(source);
         if (source==null) source = constraint;
         if (superType==null) return source;
+        constraint.expectedSuperType = superType;
         if (source.getExpectedJavaSuperType()==null || source.getExpectedJavaSuperType().isAssignableFrom( superType )) {
-            // the constraint was weaker than present; return the new constraint
+            // the old constraint was weaker than present; return the new constraint
             return constraint;
         }
         if (superType.isAssignableFrom( source.getExpectedJavaSuperType() )) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
index a4a0460..1e48e46 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.core.typereg;
 import java.lang.reflect.Method;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 
 import javax.annotation.Nullable;
 
@@ -112,11 +113,11 @@ public class RegisteredTypes {
      * @param mgmt */
     @Beta
     // TODO should this be on the AbstractTypePlanTransformer ?
-    public static Class<?> loadActualJavaType(String javaTypeName, ManagementContext mgmt, RegisteredType type, RegisteredTypeLoadingContext constraint) throws Exception {
+    public static Class<?> loadActualJavaType(String javaTypeName, ManagementContext mgmt, RegisteredType type, RegisteredTypeLoadingContext context) throws Exception {
         Class<?> result = ((BasicRegisteredType)type).getCache().get(ACTUAL_JAVA_TYPE);
         if (result!=null) return result;
         
-        result = CatalogUtils.newClassLoadingContext(mgmt, type).loadClass( javaTypeName );
+        result = CatalogUtils.newClassLoadingContext(mgmt, type, context==null ? null : context.getLoader()).loadClass( javaTypeName );
         Preconditions.checkNotNull(result, "Could not load class "+javaTypeName+"; returned null (should have thrown a different exception!)");
         
         ((BasicRegisteredType)type).getCache().put(ACTUAL_JAVA_TYPE, result);
@@ -178,7 +179,7 @@ public class RegisteredTypes {
         Iterator<Object> ri = result.iterator();
         if (!ri.hasNext()) return Maybe.absent("YAML has no elements in it");
         Object r1 = ri.next();
-        if (!ri.hasNext()) return Maybe.absent("YAML has multiple elements in it");
+        if (ri.hasNext()) return Maybe.absent("YAML has multiple elements in it");
         if (r1 instanceof Map) return Maybe.of((Map<Object,Object>)r1);
         return Maybe.absent("YAML does not contain a map");
     }
@@ -187,12 +188,19 @@ public class RegisteredTypes {
      * Queries recursively the supertypes of {@link RegisteredType} to see whether it 
      * declares a supertype compatible with the given {@link Class} */
     public static boolean isSubTypeOf(RegisteredType type, Class<?> superType) {
-        for (Object st: type.getSuperTypes()) {
+        return isSubTypeOf(type.getSuperTypes(), superType);
+    }
+    
+    /** 
+     * Queries recursively the given types (either {@link Class} or {@link RegisteredType}) 
+     * to see whether any are compatible with the given {@link Class} */
+    public static boolean isSubTypeOf(Set<Object> allKnownTypes, Class<?> superType) {
+        for (Object st: allKnownTypes) {
             if (st instanceof Class) {
                 if (superType.isAssignableFrom((Class<?>)st)) return true;
             }
         }
-        for (Object st: type.getSuperTypes()) {
+        for (Object st: allKnownTypes) {
             if (st instanceof RegisteredType) {
                 if (isSubTypeOf((RegisteredType)st, superType)) return true;
             }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/core/src/test/java/brooklyn/policy/basic/AbstractEntityAdjunctTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/policy/basic/AbstractEntityAdjunctTest.java b/core/src/test/java/brooklyn/policy/basic/AbstractEntityAdjunctTest.java
deleted file mode 100644
index d6d41de..0000000
--- a/core/src/test/java/brooklyn/policy/basic/AbstractEntityAdjunctTest.java
+++ /dev/null
@@ -1,52 +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.policy.basic;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
-import org.apache.brooklyn.core.objs.AbstractEntityAdjunct;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableMap;
-
-public class AbstractEntityAdjunctTest {
-    private static class TestAdjunct extends AbstractEntityAdjunct {
-        public TestAdjunct(Map<?, ?> properties) {
-            super(properties);
-        }
- 
-        @Override
-        public RebindSupport<?> getRebindSupport() {
-            return null;
-        }
-
-        @Override
-        protected void onChanged() {
-        }
-    }
-
-    @Test
-    public void testImmutableFlags() {
-        //shouldn't try to mutate passed flags map (or previous references to it)
-        TestAdjunct testAdjunct = new TestAdjunct(ImmutableMap.of("unusedKey", "unusedValue"));
-        testAdjunct.configure(ImmutableMap.of("finalKey", "finalValue"));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/core/src/test/java/org/apache/brooklyn/core/catalog/internal/SpecParameterInMetaTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/SpecParameterInMetaTest.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/SpecParameterInMetaTest.java
index 2f50c47..5437765 100644
--- a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/SpecParameterInMetaTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/SpecParameterInMetaTest.java
@@ -27,15 +27,21 @@ import java.util.List;
 import org.apache.brooklyn.api.catalog.BrooklynCatalog;
 import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.objs.SpecParameter;
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.core.plan.PlanToSpecFactory;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
 import org.apache.brooklyn.entity.stock.BasicEntity;
 import org.apache.brooklyn.test.support.TestResourceUnavailableException;
 import org.apache.brooklyn.util.osgi.OsgiTestResources;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Function;
 import com.google.common.base.Joiner;
 import com.google.common.collect.Iterables;
 import com.google.common.reflect.TypeToken;
@@ -43,18 +49,40 @@ import com.google.common.reflect.TypeToken;
 public class SpecParameterInMetaTest {
     private ManagementContext mgmt;
     private BrooklynCatalog catalog;
-    private String spec;
+    private String specId;
 
     @BeforeMethod(alwaysRun=true)
     public void setUp() {
         mgmt = LocalManagementContextForTests.newInstanceWithOsgi();
         catalog = mgmt.getCatalog();
-        spec = TestToSpecTransformer.registerSpec(EntitySpec.create(BasicEntity.class));
+        StaticTypePlanTransformer.forceInstall();
+        PlanToSpecFactory.forceAvailable(TestToSpecTransformer.class, JavaCatalogToSpecTransformer.class);
+        specId = StaticTypePlanTransformer.registerSpec(EntitySpec.create(BasicEntity.class));
     }
 
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() {
+        StaticTypePlanTransformer.clearForced();
+        PlanToSpecFactory.clearForced();
+    }
+
+    @Test
+    public void testCanRetrieveWithNew() {
+        AbstractBrooklynObjectSpec<?, ?> spec = mgmt.getTypeRegistry().createSpecFromPlan(null, specId, null, null);
+        Assert.assertNotNull(spec);
+    }
+
+    // it's not actually added to the catalog; probably it would be cleaner if it is;
+    // but for now when we resolve in PlanToSpecFactory we make explicit reference to StaticTypePlanTransformer
+//    @Test
+//    public void testCanLookupNew() {
+//        RegisteredType type = mgmt.getTypeRegistry().get(specId);
+//        Assert.assertNotNull(type);
+//    }
+    
     @Test
     public void testYamlInputsParsed() {
-        CatalogItem<?, ?> item = add(
+        String itemId = add(
                 "brooklyn.catalog:",
                 "  id: test.inputs",
                 "  version: 0.0.1",
@@ -63,7 +91,9 @@ public class SpecParameterInMetaTest {
                 "  - name: explicit_name",
                 "  - name: third_input",
                 "    type: integer",
-                "  item: " + spec);
+                "  item: " + specId);
+        
+        EntitySpec<?> item = mgmt.getTypeRegistry().createSpec(mgmt.getTypeRegistry().get(itemId), null, EntitySpec.class);
         List<SpecParameter<?>> inputs = item.getParameters();
         assertEquals(inputs.size(), 3);
         SpecParameter<?> firstInput = inputs.get(0);
@@ -89,7 +119,7 @@ public class SpecParameterInMetaTest {
     public void testOsgiType() {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
 
-        CatalogItem<?, ?> item = add(
+        String itemId = add(
                 "brooklyn.catalog:",
                 "  id: test.inputs",
                 "  version: 0.0.1",
@@ -98,7 +128,8 @@ public class SpecParameterInMetaTest {
                 "  parameters:",
                 "  - name: simple",
                 "    type: " + OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_ENTITY,
-                "  item: " + spec);
+                "  item: " + specId);
+        EntitySpec<?> item = mgmt.getTypeRegistry().createSpec(mgmt.getTypeRegistry().get(itemId), null, EntitySpec.class);
         List<SpecParameter<?>> inputs = item.getParameters();
         assertEquals(inputs.size(), 1);
         SpecParameter<?> firstInput = inputs.get(0);
@@ -110,6 +141,7 @@ public class SpecParameterInMetaTest {
 
     @Test
     public void testOsgiClassScanned() {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_V2_PATH);
 
         addMulti("brooklyn.catalog:",
@@ -117,23 +149,32 @@ public class SpecParameterInMetaTest {
             "    - scanJavaAnnotations: true",
             "      version: 2.0.test_java",
             "      libraries:",
+            "      - classpath://" + OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH,
             "      - classpath://" + OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_V2_PATH);
 
-        CatalogItem<?, ?> item = CatalogUtils.getCatalogItemOptionalVersion(mgmt, OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
-        assertEquals(item.getVersion(), "2.0.test_java");
-        assertEquals(item.getLibraries().size(), 1);
+        RegisteredType itemT = mgmt.getTypeRegistry().get(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
+        assertEquals(itemT.getVersion(), "2.0.test_java");
+        assertEquals(itemT.getLibraries().size(), 2);
+        
+        EntitySpec<?> item = mgmt.getTypeRegistry().createSpec(itemT, null, EntitySpec.class);
         SpecParameter<?> input = item.getParameters().get(0);
         assertEquals(input.getLabel(), "more_config");
         assertFalse(input.isPinned());
         assertEquals(input.getType().getName(), "more_config");
     }
 
-    private CatalogItem<?,?> add(String... def) {
+    private String add(String... def) {
         return Iterables.getOnlyElement(addMulti(def));
     }
 
-    private Iterable<? extends CatalogItem<?, ?>> addMulti(String... def) {
-        return catalog.addItems(Joiner.on('\n').join(def));
+    private Iterable<String> addMulti(String... def) {
+        return Iterables.transform(catalog.addItems(Joiner.on('\n').join(def)),
+            new Function<CatalogItem<?,?>, String>() {
+                @Override
+                public String apply(CatalogItem<?, ?> input) {
+                    return input.getId();
+                }
+            });
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformer.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformer.java
new file mode 100644
index 0000000..c5568ca
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/StaticTypePlanTransformer.java
@@ -0,0 +1,115 @@
+/*
+ * 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.catalog.internal;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
+import org.apache.brooklyn.core.typereg.AbstractTypePlanTransformer;
+import org.apache.brooklyn.core.typereg.JavaClassNameTypePlanTransformer;
+import org.apache.brooklyn.core.typereg.TypePlanTransformers;
+import org.apache.brooklyn.util.text.Identifiers;
+
+/**
+ * Resolves previously registered specs by id.
+ * First create a spec and register it, keeping the returned ID:
+ * <pre> {@code
+ * String specId = StaticTypePlanTransformer.registerSpec(EntitySpec.create(BasicEntity.class));
+ * }</pre>
+ *
+ * Then build a plan to be resolved such as:
+ * <pre> {@code
+ *  brooklyn.catalog:
+ *    id: test.inputs
+ *    version: 0.0.1
+ *    item: <specId>
+ * } </pre>
+ */
+public class StaticTypePlanTransformer extends AbstractTypePlanTransformer {
+    
+    public StaticTypePlanTransformer() {
+        super("static-types", "Static Type", "Static transformer for use in tests");
+    }
+
+    private static final Map<String, AbstractBrooklynObjectSpec<?, ?>> REGISTERED_SPECS = new ConcurrentHashMap<>();
+
+    public static void forceInstall() {
+        TypePlanTransformers.forceAvailable(StaticTypePlanTransformer.class, JavaClassNameTypePlanTransformer.class);
+    }
+    
+    public static void clearForced() {
+        TypePlanTransformers.clearForced();
+    }
+    
+    public static String registerSpec(AbstractBrooklynObjectSpec<?, ?> spec) {
+        String id = Identifiers.makeRandomId(10);
+        REGISTERED_SPECS.put(id, spec);
+        return id;
+    }
+
+    @Override
+    public double scoreForTypeDefinition(String formatCode, Object catalogData) {
+        // not supported
+        return 0;
+    }
+
+    @Override
+    public List<RegisteredType> createFromTypeDefinition(String formatCode, Object catalogData) {
+        // not supported
+        return null;
+    }
+
+    @Override
+    protected double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeLoadingContext context) {
+        if (REGISTERED_SPECS.containsKey(type.getId())) return 1;
+        if (REGISTERED_SPECS.containsKey(planData)) return 1;
+        return 0;
+    }
+
+    @Override
+    protected double scoreForNonmatchingNonnullFormat(String planFormat, Object planData, RegisteredType type, RegisteredTypeLoadingContext context) {
+        // not supported
+        return 0;
+    }
+
+    @Override
+    protected AbstractBrooklynObjectSpec<?, ?> createSpec(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception {
+        if (REGISTERED_SPECS.containsKey(type.getId()))
+            return get(type.getId());
+        if (REGISTERED_SPECS.containsKey(type.getPlan().getPlanData()))
+            return get((String)type.getPlan().getPlanData());
+        return null;
+    }
+
+    @Override
+    protected Object createBean(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception {
+        // not supported
+        return null;
+    }
+
+    public static AbstractBrooklynObjectSpec<?, ?> get(String typeName) {
+        return REGISTERED_SPECS.get(typeName);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/core/src/test/java/org/apache/brooklyn/core/catalog/internal/TestToSpecTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/TestToSpecTransformer.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/TestToSpecTransformer.java
index 0dfe291..9f9440a 100644
--- a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/TestToSpecTransformer.java
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/TestToSpecTransformer.java
@@ -20,43 +20,36 @@ package org.apache.brooklyn.core.catalog.internal;
 
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
 
+import org.apache.brooklyn.api.catalog.BrooklynCatalog;
 import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.entity.Application;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.core.plan.PlanNotRecognizedException;
 import org.apache.brooklyn.core.plan.PlanToSpecTransformer;
-import org.apache.brooklyn.util.text.Identifiers;
+import org.apache.brooklyn.core.typereg.JavaClassNameTypePlanTransformer;
+import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
+import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.yaml.Yamls;
 
+import com.google.common.collect.Iterables;
+
 /**
- * Resolves previously registered specs by id.
- * First create a spec and register it, keeping the returned ID:
- * <pre> {@code
- * String specId = TestToSpecTransformer.registerSpec(EntitySpec.create(BasicEntity.class));
- * }</pre>
- *
- * Then build a plan to be resolved such as:
- * <pre> {@code
- *  brooklyn.catalog:
- *    id: test.inputs
- *    version: 0.0.1
- *    item: <specId>
- * } </pre>
+ * For use in conjunction with {@link StaticTypePlanTransformer};
+ * this will lookup an item by ID or in a map "type: id".
+ * <p>
+ * Should be removed when catalog is able to function using new-style lookups.
  */
 public class TestToSpecTransformer implements PlanToSpecTransformer {
-    private static final Map<String, AbstractBrooklynObjectSpec<?, ?>> REGISTERED_SPECS = new ConcurrentHashMap<>();
-    public static String registerSpec(AbstractBrooklynObjectSpec<?, ?> spec) {
-        String id = Identifiers.makeRandomId(10);
-        REGISTERED_SPECS.put(id, spec);
-        return id;
-    }
+
+    private ManagementContext mgmt;
 
     @Override
     public void injectManagementContext(ManagementContext managementContext) {
+        mgmt = managementContext;
     }
 
     @Override
@@ -72,47 +65,56 @@ public class TestToSpecTransformer implements PlanToSpecTransformer {
     @SuppressWarnings("unchecked")
     @Override
     public EntitySpec<? extends Application> createApplicationSpec(String plan) throws PlanNotRecognizedException {
-        return (EntitySpec<? extends Application>) getSpec(plan);
+        return (EntitySpec<? extends Application>) getSpec(plan, null, MutableSet.<String>of());
     }
 
     @SuppressWarnings("unchecked")
     @Override
     public <T, SpecT extends AbstractBrooklynObjectSpec<? extends T, SpecT>> SpecT createCatalogSpec(CatalogItem<T, SpecT> item, Set<String> encounteredTypes) 
             throws PlanNotRecognizedException {
-        return (SpecT) getSpecFromPlan(item.getPlanYaml());
+        return (SpecT) getSpecFromPlan(item.getPlanYaml(), item, encounteredTypes);
     }
 
-    private AbstractBrooklynObjectSpec<?,?> getSpecFromPlan(String plan) {
+    @SuppressWarnings("unchecked")
+    private AbstractBrooklynObjectSpec<?,?> getSpecFromPlan(String plan, CatalogItem<?,?> item, Set<String> encounteredTypes) {
         if (plan != null) {
             Object planRaw = Yamls.parseAll(plan).iterator().next();
             if (planRaw instanceof String) {
-                return getSpec((String)planRaw);
+                return getSpec((String)planRaw, item, encounteredTypes);
             } else if (planRaw instanceof Map) {
                 // The catalog parser assumes it's dealing with CAMP specs so will helpfully
                 // prepend "type: " if it's an inline item.
-                return getSpec((String)((Map<?, ?>)planRaw).get("type"));
-            } else {
-                throw notRecognized();
+                Map<?, ?> planMap = (Map<?, ?>)planRaw;
+                if (planMap.size()==1 && planMap.containsKey("services")) {
+                    planMap = Iterables.getOnlyElement( (Iterable<Map<?,?>>)(planMap.get("services")) );
+                }
+                if (planMap.size()==1 && planMap.containsKey("type"))
+                    return getSpec((String)(planMap.get("type")), item, encounteredTypes);
             }
-        } else {
-            throw notRecognized();
         }
+        throw notRecognized("unknown format "+plan);
     }
 
-    private AbstractBrooklynObjectSpec<?,?> getSpec(String plan) {
-        if (plan == null) {
-            throw notRecognized();
+    private AbstractBrooklynObjectSpec<?,?> getSpec(String typeName, CatalogItem<?,?> item, Set<String> encounteredTypes) {
+        if (typeName == null) {
+            throw notRecognized("null type "+typeName);
         }
-        AbstractBrooklynObjectSpec<?, ?> spec = REGISTERED_SPECS.get(plan);
-        if (spec != null) {
-            return spec;
-        } else {
-            throw notRecognized();
+
+        RegisteredType type = mgmt.getTypeRegistry().get(typeName);
+        if (type==null) {
+            AbstractBrooklynObjectSpec<?,?> spec = StaticTypePlanTransformer.get(typeName);
+            if (spec!=null) return spec;
+            
+            throw notRecognized("no type "+typeName);
         }
+        
+        return mgmt.getTypeRegistry().createSpecFromPlan(
+            JavaClassNameTypePlanTransformer.FORMAT,
+            typeName, RegisteredTypeLoadingContexts.loader(CatalogUtils.newClassLoadingContext(mgmt, item)), null);
     }
 
-    private PlanNotRecognizedException notRecognized() {
-        return new PlanNotRecognizedException("Not recognized as registered spec");
+    private PlanNotRecognizedException notRecognized(String message) {
+        return new PlanNotRecognizedException("Not recognized as registered spec: "+message);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/core/src/test/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunctTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunctTest.java b/core/src/test/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunctTest.java
new file mode 100644
index 0000000..73b9d2d
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunctTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.objs;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
+import org.apache.brooklyn.core.objs.AbstractEntityAdjunct;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+
+public class AbstractEntityAdjunctTest {
+    private static class TestAdjunct extends AbstractEntityAdjunct {
+        public TestAdjunct(Map<?, ?> properties) {
+            super(properties);
+        }
+ 
+        @Override
+        public RebindSupport<?> getRebindSupport() {
+            return null;
+        }
+
+        @Override
+        protected void onChanged() {
+        }
+    }
+
+    @Test
+    public void testImmutableFlags() {
+        //shouldn't try to mutate passed flags map (or previous references to it)
+        TestAdjunct testAdjunct = new TestAdjunct(ImmutableMap.of("unusedKey", "unusedValue"));
+        testAdjunct.configure(ImmutableMap.of("finalKey", "finalValue"));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/core/src/test/resources/META-INF/services/org.apache.brooklyn.core.plan.PlanToSpecTransformer
----------------------------------------------------------------------
diff --git a/core/src/test/resources/META-INF/services/org.apache.brooklyn.core.plan.PlanToSpecTransformer b/core/src/test/resources/META-INF/services/org.apache.brooklyn.core.plan.PlanToSpecTransformer
deleted file mode 100644
index 34d91b4..0000000
--- a/core/src/test/resources/META-INF/services/org.apache.brooklyn.core.plan.PlanToSpecTransformer
+++ /dev/null
@@ -1,19 +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.
-#
-org.apache.brooklyn.core.catalog.internal.TestToSpecTransformer

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java
index 32f7c0e..706d6f2 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java
@@ -30,7 +30,7 @@ import org.apache.brooklyn.core.typereg.RegisteredTypes;
 public class CampCatalogUtils {
 
     public static AbstractBrooklynObjectSpec<?, ?> createSpec(ManagementContext mgmt, CatalogItem<?, ?> item, Set<String> parentEncounteredTypes) {
-        return CampResolver.createSpecFromFull(mgmt, RegisteredTypes.of(item), parentEncounteredTypes, null);
+        return CampResolver.createSpecFromFull(mgmt, RegisteredTypes.of(item), item.getCatalogItemJavaType(), parentEncounteredTypes, null);
     }
     
     public static CampPlatform getCampPlatform(ManagementContext mgmt) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
index 3070280..e6c514a 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
@@ -37,6 +37,7 @@ import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.mgmt.EntityManagementUtils;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
+import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.text.Strings;
 
 import com.google.common.collect.ImmutableSet;
@@ -72,10 +73,10 @@ class CampResolver {
         // TODO new-style approach:
         //            AbstractBrooklynObjectSpec<?, ?> spec = RegisteredTypes.newSpecInstance(mgmt, /* 'type' key */);
         //            spec.configure(keysAndValues);
-        return createSpecFromFull(mgmt, type, context.getAlreadyEncounteredTypes(), context.getLoader());
+        return createSpecFromFull(mgmt, type, context.getExpectedJavaSuperType(), context.getAlreadyEncounteredTypes(), context.getLoader());
     }
 
-    static AbstractBrooklynObjectSpec<?, ?> createSpecFromFull(ManagementContext mgmt, RegisteredType item, Set<String> parentEncounteredTypes, BrooklynClassLoadingContext loaderO) {
+    static AbstractBrooklynObjectSpec<?, ?> createSpecFromFull(ManagementContext mgmt, RegisteredType item, Class<?> expectedType, Set<String> parentEncounteredTypes, BrooklynClassLoadingContext loaderO) {
         // for this method, a prefix "services" or "brooklyn.{location,policies}" is required at the root;
         // we now prefer items to come in "{ type: .. }" format, except for application roots which
         // should have a "services: [ ... ]" block (and which may subsequently be unwrapped)
@@ -94,13 +95,15 @@ class CampResolver {
 
         AbstractBrooklynObjectSpec<?, ?> spec;
         String planYaml = RegisteredTypes.getImplementationDataStringForSpec(item);
-        if (RegisteredTypes.isSubTypeOf(item, Policy.class)) {
+        MutableSet<Object> supers = MutableSet.copyOf(item.getSuperTypes());
+        supers.addIfNotNull(expectedType);
+        if (RegisteredTypes.isSubTypeOf(supers, Policy.class)) {
             spec = CampInternalUtils.createPolicySpec(planYaml, loader, encounteredTypes);
-        } else if (RegisteredTypes.isSubTypeOf(item, Location.class)) {
+        } else if (RegisteredTypes.isSubTypeOf(supers, Location.class)) {
             spec = CampInternalUtils.createLocationSpec(planYaml, loader, encounteredTypes);
-        } else if (RegisteredTypes.isSubTypeOf(item, Application.class)) {
+        } else if (RegisteredTypes.isSubTypeOf(supers, Application.class)) {
             spec = createEntitySpecFromServicesBlock(planYaml, loader, encounteredTypes, true);
-        } else if (RegisteredTypes.isSubTypeOf(item, Entity.class)) {
+        } else if (RegisteredTypes.isSubTypeOf(supers, Entity.class)) {
             spec = createEntitySpecFromServicesBlock(planYaml, loader, encounteredTypes, false);
         } else {
             // try any of them???
@@ -123,9 +126,9 @@ class CampResolver {
         AssemblyTemplateInstantiator instantiator = CampInternalUtils.getInstantiator(at);
         if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
             EntitySpec<? extends Application> appSpec = ((AssemblyTemplateSpecInstantiator)instantiator).createApplicationSpec(at, camp, loader, encounteredTypes);
-            CampInternalUtils.resetSpecIfTemplateHasNoExplicitParameters(at, appSpec);
 
             if (!isApplication && EntityManagementUtils.canPromoteChildrenInWrappedApplication(appSpec) && appSpec.getChildren().size()==1) {
+                CampInternalUtils.resetSpecIfTemplateHasNoExplicitParameters(at, appSpec);
                 EntitySpec<?> childSpec = appSpec.getChildren().get(0);
                 EntityManagementUtils.mergeWrapperParentSpecToChildEntity(appSpec, childSpec);
                 return childSpec;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
index f2b224c..a1c8150 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
@@ -99,7 +99,7 @@ public class CampToSpecTransformer implements PlanToSpecTransformer {
         }
 
         // Not really clear what should happen to the top-level attributes, ignored until a good use case appears.
-        return (SpecT) CampResolver.createSpecFromFull(mgmt, RegisteredTypes.of(item), encounteredTypes, null);
+        return (SpecT) CampResolver.createSpecFromFull(mgmt, RegisteredTypes.of(item), item.getCatalogItemJavaType(), encounteredTypes, null);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
index 4793a59..56eeb99 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampTypePlanTransformer.java
@@ -48,6 +48,10 @@ public class CampTypePlanTransformer extends AbstractTypePlanTransformer {
         Maybe<Map<Object, Object>> plan = RegisteredTypes.getAsYamlMap(planData);
         if (plan.isAbsent()) return 0;
         if (plan.get().containsKey("services")) return 0.8;
+        if (plan.get().containsKey("type")) return 0.4;
+        // TODO these should become legacy
+        if (plan.get().containsKey("brooklyn.locations")) return 0.7;
+        if (plan.get().containsKey("brooklyn.policies")) return 0.7;
         return 0;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java
index 3799418..c87626c 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/UrlServiceSpecResolver.java
@@ -65,7 +65,7 @@ public class UrlServiceSpecResolver implements EntitySpecResolver {
         }
         
         // Referenced specs are expected to be CAMP format as well.
-        // XXX somehow specify to allow full syntax for services
+        // TODO somehow specify to allow full syntax for services
         EntitySpec<?> item = loader.getManagementContext().getTypeRegistry().createSpecFromPlan(
             CampTypePlanTransformer.FORMAT,
             yaml,

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/LocationsYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/LocationsYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/LocationsYamlTest.java
index b046a70..269ff16 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/LocationsYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/LocationsYamlTest.java
@@ -162,7 +162,7 @@ public class LocationsYamlTest extends AbstractYamlTest {
         
         try {
             createStartWaitAndLogApplication(new StringReader(yaml));
-        } catch (IllegalStateException e) {
+        } catch (Exception e) {
             if (!e.toString().contains("Conflicting 'location' and 'locations'")) throw e;
         }
     }
@@ -178,7 +178,7 @@ public class LocationsYamlTest extends AbstractYamlTest {
         
         try {
             createStartWaitAndLogApplication(new StringReader(yaml));
-        } catch (IllegalStateException e) {
+        } catch (Exception e) {
             if (!e.toString().contains("must be a string or map")) throw e;
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogParametersTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogParametersTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogParametersTest.java
index 6407d4a..010e42d 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogParametersTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogParametersTest.java
@@ -273,7 +273,54 @@ public class CatalogParametersTest extends AbstractYamlTest {
     }
 
     @Test
-    public void testParametersCoercedOnSetAndReferences() throws Exception {
+    public void testParametersOnItemCoercedOnSetAndReferences() throws Exception {
+        Integer testValue = Integer.valueOf(55);
+        addCatalogItems(
+                "brooklyn.catalog:",
+                "  id: " + SYMBOLIC_NAME,
+                "  version: " + TEST_VERSION,
+                "  item:",
+                "    type: " + BasicApplication.class.getName(),
+                "    brooklyn.parameters:",
+                "    - name: num",
+                "      type: integer",
+                "    brooklyn.children:",
+                "    - type: " + ConfigEntityForTest.class.getName(),
+                "      brooklyn.config:",
+                "        refConfig: $brooklyn:scopeRoot().config(\"num\")",
+                "    - type: " + ConfigEntityForTest.class.getName(),
+                "      brooklyn.config:",
+                "        refConfig: $brooklyn:config(\"num\")"); //inherited config
+
+        Entity app = createAndStartApplication(
+                "services:",
+                "- type: " + BasicApplication.class.getName(),
+                "  brooklyn.children:",
+                "  - type: " + ver(SYMBOLIC_NAME),
+                "    brooklyn.config:",
+                "      num: \"" + testValue + "\"");
+
+        Entity scopeRoot = Iterables.getOnlyElement(app.getChildren());
+
+        ConfigKey<Object> numKey = ConfigKeys.newConfigKey(Object.class, "num");
+        assertEquals(scopeRoot.config().get(numKey), testValue);
+
+        ConfigKey<Object> refConfigKey = ConfigKeys.newConfigKey(Object.class, "refConfig");
+
+        Iterator<Entity> childIter = scopeRoot.getChildren().iterator();
+        Entity c1 = childIter.next();
+        assertEquals(c1.config().get(refConfigKey), testValue);
+        Entity c2 = childIter.next();
+        assertEquals(c2.config().get(refConfigKey), testValue);
+        assertFalse(childIter.hasNext());
+    }
+    
+    // XXX TODO parameters on the root don't work with new type registry; 
+    // they require the CI being able to keep them,
+    // or else modifying the plan. TODO should they be permitted as metadata in this way?
+    // or treaded like a declaration of config keys on the entity?  i (alex) prefer the latter.
+    @Test(groups="WIP")
+    public void testParametersAtRootCoercedOnSetAndReferences() throws Exception {
         Integer testValue = Integer.valueOf(55);
         addCatalogItems(
                 "brooklyn.catalog:",

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
index 93507aa..1558db3 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
@@ -30,11 +30,9 @@ import java.util.Map;
 
 import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
-import org.apache.brooklyn.api.entity.Application;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.mgmt.Task;
-import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry;
 import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.camp.spi.Assembly;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c712ad5e/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
index a0c5d8f..c22082b 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
@@ -45,7 +45,6 @@ import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.api.sensor.Sensor;
-import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
 import org.apache.brooklyn.core.config.ConstraintViolationException;
 import org.apache.brooklyn.core.entity.Attributes;
 import org.apache.brooklyn.core.entity.EntityPredicates;
@@ -372,14 +371,14 @@ public class ApplicationResource extends AbstractBrooklynRestResource implements
     private EntitySpec<? extends Application> createEntitySpecForApplication(String potentialYaml) {
         try {
             return EntityManagementUtils.createEntitySpecForApplication(mgmt(), potentialYaml);
-        } catch (IllegalStateException e) {
-            // An IllegalArgumentException for creating the entity spec gets wrapped in a ISE.
+        } catch (Exception e) {
+            // An IllegalArgumentException for creating the entity spec gets wrapped in a ISE, and possibly a Compound.
             // But we want to return a 400 rather than 500, so ensure we throw IAE.
-            IllegalArgumentException iae = (IllegalArgumentException) Exceptions.getFirstThrowableOfType(e.getCause(), IllegalArgumentException.class);
+            IllegalArgumentException iae = (IllegalArgumentException) Exceptions.getFirstThrowableOfType(e, IllegalArgumentException.class);
             if (iae != null) {
                 throw new IllegalArgumentException("Cannot create spec for app: "+iae.getMessage(), e);
             } else {
-                throw e;
+                throw Exceptions.propagate(e);
             }
         }
     }