    public boolean apply(Object deploymentPlanItem, AssemblyTemplateConstructor atc) {
        Object item = lookup(deploymentPlanItem);
        if (item==null) return false;
        log.debug("Item "+deploymentPlanItem+" being instantiated with "+item);
        Object old = atc.getInstantiator();
        if (old!=null && !old.equals(BrooklynAssemblyTemplateInstantiator.class)) {
            log.warn("Can't mix Brooklyn entities with non-Brooklyn entities (at present): "+old);
            return false;
        }
        Builder<? extends PlatformComponentTemplate> builder = PlatformComponentTemplate.builder();
        if (item instanceof CatalogItem) {
            builder.type( "brooklyn:"+((CatalogItem<?>)item).getJavaType() );
        } else if (item instanceof Class) {
            builder.type( "brooklyn:"+((Class<?>) item).getCanonicalName() );
        } else {
            throw new IllegalStateException("Item "+item+" is not recognised here");
        }
        atc.instantiator(BrooklynAssemblyTemplateInstantiator.class);
        String name = ((Service)deploymentPlanItem).getName();
        if (!Strings.isBlank(name)) builder.name(name);
        Map<String, Object> attrs = MutableMap.copyOf( ((Service)deploymentPlanItem).getCustomAttributes() );
        if (attrs.containsKey("id"))
            builder.customAttribute("planId", attrs.remove("id"));
        Object location = attrs.remove("location");
        if (location!=null)
            builder.customAttribute("location", location);
        Object locations = attrs.remove("locations");
        if (locations!=null)
            builder.customAttribute("locations", locations);
        Map<Object, Object> brooklynConfig = MutableMap.of();
        Object origBrooklynConfig = attrs.remove("brooklyn.config");
        if (origBrooklynConfig!=null) {
            if (!(origBrooklynConfig instanceof Map))
                throw new IllegalArgumentException("brooklyn.config must be a map of brooklyn config keys");
            brooklynConfig.putAll((Map<?,?>)origBrooklynConfig);
        }
        if (!brooklynConfig.isEmpty())
            builder.customAttribute("brooklyn.config", brooklynConfig);
        List<Object> brooklynPolicies = Lists.newArrayList();
        Object origBrooklynPolicies = attrs.remove("brooklyn.policies");
        if (origBrooklynPolicies != null) {
            if (!(origBrooklynPolicies instanceof List))
                throw new IllegalArgumentException("brooklyn.policies must be a list of brooklyn policy definitions");
            brooklynPolicies.addAll((List<?>)origBrooklynPolicies);
        }
        if (!brooklynPolicies.isEmpty())
            builder.customAttribute("brooklyn.policies", brooklynPolicies);
        List<Object> brooklynEnrichers = Lists.newArrayList();
        Object origBrooklynEnrichers = attrs.remove("brooklyn.enrichers");
        if (origBrooklynEnrichers != null) {
            if (!(origBrooklynEnrichers instanceof List))
                throw new IllegalArgumentException("brooklyn.enrichers must be a list of brooklyn enricher definitions");
            brooklynEnrichers.addAll((List<?>)origBrooklynEnrichers);
        }
        if (!brooklynEnrichers.isEmpty())
            builder.customAttribute("brooklyn.enrichers", brooklynEnrichers);
        List<Object> brooklynChildren = Lists.newArrayList();
        Object origBrooklynChildren = attrs.remove("brooklyn.children");
        if (origBrooklynChildren != null) {
            if (!(origBrooklynChildren instanceof List))
                throw new IllegalArgumentException("brooklyn.children must be a list of brooklyn entity definitions");
            brooklynChildren.addAll((List<?>)origBrooklynChildren);
        }
        if (!brooklynChildren.isEmpty())
            builder.customAttribute("brooklyn.children",  brooklynChildren);
        if (!attrs.isEmpty()) {
            log.warn("Ignoring PDP attributes on "+deploymentPlanItem+": "+attrs);
        }
        atc.add(builder.build());
        return true;
    }

    public boolean apply(Object deploymentPlanItem, AssemblyTemplateConstructor atc) {
        Object item = lookup(deploymentPlanItem);
        if (item==null) return false;
        log.debug("Item "+deploymentPlanItem+" being instantiated with "+item);
        Object old = atc.getInstantiator();
        if (old!=null && !old.equals(BrooklynAssemblyTemplateInstantiator.class)) {
            log.warn("Can't mix Brooklyn entities with non-Brooklyn entities (at present): "+old);
            return false;
        }
        Builder<? extends PlatformComponentTemplate> builder = PlatformComponentTemplate.builder();
        if (item instanceof CatalogItem) {
            builder.type( "brooklyn:"+((CatalogItem<?>)item).getJavaType() );
        } else if (item instanceof Class) {
            builder.type( "brooklyn:"+((Class<?>) item).getName() );
        } else {
            throw new IllegalStateException("Item "+item+" is not recognised here");
        }
        atc.instantiator(BrooklynAssemblyTemplateInstantiator.class);
        String name = ((Service)deploymentPlanItem).getName();
        if (!Strings.isBlank(name)) builder.name(name);
        Map<String, Object> attrs = MutableMap.copyOf( ((Service)deploymentPlanItem).getCustomAttributes() );
        if (attrs.containsKey("id"))
            builder.customAttribute("planId", attrs.remove("id"));
        Object location = attrs.remove("location");
        if (location!=null)
            builder.customAttribute("location", location);
        Object locations = attrs.remove("locations");
        if (locations!=null)
            builder.customAttribute("locations", locations);
        Map<Object, Object> brooklynConfig = MutableMap.of();
        Object origBrooklynConfig = attrs.remove("brooklyn.config");
        if (origBrooklynConfig!=null) {
            if (!(origBrooklynConfig instanceof Map))
                throw new IllegalArgumentException("brooklyn.config must be a map of brooklyn config keys");
            brooklynConfig.putAll((Map<?,?>)origBrooklynConfig);
        }
        if (!brooklynConfig.isEmpty())
            builder.customAttribute("brooklyn.config", brooklynConfig);
        List<Object> brooklynPolicies = Lists.newArrayList();
        Object origBrooklynPolicies = attrs.remove("brooklyn.policies");
        if (origBrooklynPolicies != null) {
            if (!(origBrooklynPolicies instanceof List))
                throw new IllegalArgumentException("brooklyn.policies must be a list of brooklyn policy definitions");
            brooklynPolicies.addAll((List<?>)origBrooklynPolicies);
        }
        if (!brooklynPolicies.isEmpty())
            builder.customAttribute("brooklyn.policies", brooklynPolicies);
        List<Object> brooklynEnrichers = Lists.newArrayList();
        Object origBrooklynEnrichers = attrs.remove("brooklyn.enrichers");
        if (origBrooklynEnrichers != null) {
            if (!(origBrooklynEnrichers instanceof List))
                throw new IllegalArgumentException("brooklyn.enrichers must be a list of brooklyn enricher definitions");
            brooklynEnrichers.addAll((List<?>)origBrooklynEnrichers);
        }
        if (!brooklynEnrichers.isEmpty())
            builder.customAttribute("brooklyn.enrichers", brooklynEnrichers);
        List<Object> brooklynChildren = Lists.newArrayList();
        Object origBrooklynChildren = attrs.remove("brooklyn.children");
        if (origBrooklynChildren != null) {
            if (!(origBrooklynChildren instanceof List))
                throw new IllegalArgumentException("brooklyn.children must be a list of brooklyn entity definitions");
            brooklynChildren.addAll((List<?>)origBrooklynChildren);
        }
        if (!brooklynChildren.isEmpty())
            builder.customAttribute("brooklyn.children",  brooklynChildren);
        if (!attrs.isEmpty()) {
            log.warn("Ignoring PDP attributes on "+deploymentPlanItem+": "+attrs);
        }
        atc.add(builder.build());
        return true;
    }
