brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aleds...@apache.org
Subject [6/9] incubator-brooklyn git commit: BROOKLYN-162 convert camp-base and camp-server to org.apache prefix
Date Tue, 18 Aug 2015 13:25:54 GMT
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/ApplicationComponent.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/ApplicationComponent.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/ApplicationComponent.java
new file mode 100644
index 0000000..6ece4d0
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/ApplicationComponent.java
@@ -0,0 +1,93 @@
+/*
+ * 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.spi;
+
+import org.apache.brooklyn.camp.spi.collection.BasicResourceLookup;
+import org.apache.brooklyn.camp.spi.collection.ResourceLookup;
+import org.apache.brooklyn.camp.spi.collection.ResourceLookup.EmptyResourceLookup;
+
+
+/** Holds the metadata (name, description, etc) for a PCT
+ * as well as fields pointing to behaviour (eg creation of PlatformComponent).
+ * <p>
+ * See {@link AbstractResource} for more general information.
+ */
+public class ApplicationComponent extends AbstractResource {
+
+    public static final String CAMP_TYPE = "ApplicationComponent";
+    static { assert CAMP_TYPE.equals(ApplicationComponent.class.getSimpleName()); }
+    
+    /** Use {@link #builder()} to create */
+    protected ApplicationComponent() {}
+
+    ResourceLookup<ApplicationComponent> applicationComponents;
+    ResourceLookup<PlatformComponent> platformComponents;
+    String externalManagementUri;
+    
+    public ResourceLookup<ApplicationComponent> getApplicationComponents() {
+        return applicationComponents != null ? applicationComponents : new EmptyResourceLookup<ApplicationComponent>();
+    }
+    public ResourceLookup<PlatformComponent> getPlatformComponents() {
+        return platformComponents != null ? platformComponents : new EmptyResourceLookup<PlatformComponent>();
+    }
+
+    private void setApplicationComponents(ResourceLookup<ApplicationComponent> applicationComponents) {
+        this.applicationComponents = applicationComponents;
+    }
+    private void setPlatformComponents(ResourceLookup<PlatformComponent> platformComponents) {
+        this.platformComponents = platformComponents;
+    }
+    
+    // builder
+    
+    public static Builder<? extends ApplicationComponent> builder() {
+        return new ApplicationComponent().new Builder<ApplicationComponent>(CAMP_TYPE);
+    }
+    
+    public class Builder<T extends ApplicationComponent> extends AbstractResource.Builder<T,Builder<T>> {
+        
+        protected Builder(String type) { super(type); }
+
+        public Builder<T> applicationComponentTemplates(ResourceLookup<ApplicationComponent> x) { ApplicationComponent.this.setApplicationComponents(x); return thisBuilder(); }
+        public Builder<T> platformComponentTemplates(ResourceLookup<PlatformComponent> x) { ApplicationComponent.this.setPlatformComponents(x); return thisBuilder(); }
+        
+        public synchronized Builder<T> add(ApplicationComponent x) {
+            if (ApplicationComponent.this.applicationComponents==null) {
+                ApplicationComponent.this.applicationComponents = new BasicResourceLookup<ApplicationComponent>();
+            }
+            if (!(ApplicationComponent.this.applicationComponents instanceof BasicResourceLookup)) {
+                throw new IllegalStateException("Cannot add to resource lookup "+ApplicationComponent.this.applicationComponents);
+            }
+            ((BasicResourceLookup<ApplicationComponent>)ApplicationComponent.this.applicationComponents).add(x);
+            return thisBuilder();
+        }
+        
+        public synchronized Builder<T> add(PlatformComponent x) {
+            if (ApplicationComponent.this.platformComponents==null) {
+                ApplicationComponent.this.platformComponents = new BasicResourceLookup<PlatformComponent>();
+            }
+            if (!(ApplicationComponent.this.platformComponents instanceof BasicResourceLookup)) {
+                throw new IllegalStateException("Cannot add to resource lookup "+ApplicationComponent.this.platformComponents);
+            }
+            ((BasicResourceLookup<PlatformComponent>)ApplicationComponent.this.platformComponents).add(x);
+            return thisBuilder();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/ApplicationComponentTemplate.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/ApplicationComponentTemplate.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/ApplicationComponentTemplate.java
new file mode 100644
index 0000000..bd9d69d
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/ApplicationComponentTemplate.java
@@ -0,0 +1,54 @@
+/*
+ * 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.spi;
+
+
+/** Holds the metadata (name, description, etc) for a PCT
+ * as well as fields pointing to behaviour (eg creation of PlatformComponent).
+ * <p>
+ * See {@link AbstractResource} for more general information.
+ */
+public class ApplicationComponentTemplate extends AbstractResource {
+
+    public static final String CAMP_TYPE = "ApplicationComponentTemplate";
+    static { assert CAMP_TYPE.equals(ApplicationComponentTemplate.class.getSimpleName()); }
+    
+    /** Use {@link #builder()} to create */
+    protected ApplicationComponentTemplate() {}
+
+    
+    // no fields beyond basic resource
+    
+    // TODO platform component templates, maybe other act's too ?
+    
+    
+    // builder
+    
+    public static Builder<? extends ApplicationComponentTemplate> builder() {
+        return new ApplicationComponentTemplate().new Builder<ApplicationComponentTemplate>(CAMP_TYPE);
+    }
+    
+    public class Builder<T extends ApplicationComponentTemplate> extends AbstractResource.Builder<T,Builder<T>> {
+        
+        protected Builder(String type) { super(type); }
+        
+//        public Builder<T> foo(String x) { instance().setFoo(x); return thisBuilder(); }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/Assembly.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/Assembly.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/Assembly.java
new file mode 100644
index 0000000..58b3064
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/Assembly.java
@@ -0,0 +1,109 @@
+/*
+ * 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.spi;
+
+import org.apache.brooklyn.camp.spi.collection.BasicResourceLookup;
+import org.apache.brooklyn.camp.spi.collection.ResourceLookup;
+import org.apache.brooklyn.camp.spi.collection.ResourceLookup.EmptyResourceLookup;
+
+
+/** Holds the metadata (name, description, etc) for an AssemblyTemplate
+ * as well as fields pointing to behaviour (eg list of ACT's).
+ * <p>
+ * See {@link AbstractResource} for more general information.
+ */
+public class Assembly extends AbstractResource {
+
+    public static final String CAMP_TYPE = "Assembly";
+    static { assert CAMP_TYPE.equals(Assembly.class.getSimpleName()); }
+    
+    /** Use {@link #builder()} to create */
+    protected Assembly() {}
+
+    AssemblyTemplate assemblyTemplate;
+    ResourceLookup<ApplicationComponent> applicationComponents;
+    ResourceLookup<PlatformComponent> platformComponents;
+    
+    // TODO
+//    "parameterDefinitionUri": URI,
+//    "pdpUri" : URI ?
+                    
+    public AssemblyTemplate getAssemblyTemplate() {
+        return assemblyTemplate;
+    }
+    public ResourceLookup<ApplicationComponent> getApplicationComponents() {
+        return applicationComponents != null ? applicationComponents : new EmptyResourceLookup<ApplicationComponent>();
+    }
+    public ResourceLookup<PlatformComponent> getPlatformComponents() {
+        return platformComponents != null ? platformComponents : new EmptyResourceLookup<PlatformComponent>();
+    }
+    
+    private void setAssemblyTemplate(AssemblyTemplate assemblyTemplate) {
+        this.assemblyTemplate = assemblyTemplate;
+    }
+    private void setApplicationComponents(ResourceLookup<ApplicationComponent> applicationComponents) {
+        this.applicationComponents = applicationComponents;
+    }
+    private void setPlatformComponents(ResourceLookup<PlatformComponent> platformComponents) {
+        this.platformComponents = platformComponents;
+    }
+    
+    // builder
+    
+    public static Builder<? extends Assembly> builder() {
+        return new Assembly().new Builder<Assembly>(CAMP_TYPE);
+    }
+    
+    public class Builder<T extends Assembly> extends AbstractResource.Builder<T,Builder<T>> {
+        
+        protected Builder(String type) { super(type); }
+        
+        public Builder<T> assemblyTemplate(AssemblyTemplate x) { Assembly.this.setAssemblyTemplate(x); return thisBuilder(); }
+        public Builder<T> applicationComponentTemplates(ResourceLookup<ApplicationComponent> x) { Assembly.this.setApplicationComponents(x); return thisBuilder(); }
+        public Builder<T> platformComponentTemplates(ResourceLookup<PlatformComponent> x) { Assembly.this.setPlatformComponents(x); return thisBuilder(); }
+        
+        public synchronized Builder<T> add(ApplicationComponent x) {
+            if (Assembly.this.applicationComponents==null) {
+                Assembly.this.applicationComponents = new BasicResourceLookup<ApplicationComponent>();
+            }
+            if (!(Assembly.this.applicationComponents instanceof BasicResourceLookup)) {
+                throw new IllegalStateException("Cannot add to resource lookup "+Assembly.this.applicationComponents);
+            }
+            ((BasicResourceLookup<ApplicationComponent>)Assembly.this.applicationComponents).add(x);
+            return thisBuilder();
+        }
+        
+        public synchronized Builder<T> add(PlatformComponent x) {
+            if (Assembly.this.platformComponents==null) {
+                Assembly.this.platformComponents = new BasicResourceLookup<PlatformComponent>();
+            }
+            if (!(Assembly.this.platformComponents instanceof BasicResourceLookup)) {
+                throw new IllegalStateException("Cannot add to resource lookup "+Assembly.this.platformComponents);
+            }
+            ((BasicResourceLookup<PlatformComponent>)Assembly.this.platformComponents).add(x);
+            return thisBuilder();
+        }
+        
+        @Override
+        public synchronized T build() {
+            return super.build();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/AssemblyTemplate.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/AssemblyTemplate.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/AssemblyTemplate.java
new file mode 100644
index 0000000..423c3b4
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/AssemblyTemplate.java
@@ -0,0 +1,118 @@
+/*
+ * 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.spi;
+
+import org.apache.brooklyn.camp.spi.collection.BasicResourceLookup;
+import org.apache.brooklyn.camp.spi.collection.ResourceLookup;
+import org.apache.brooklyn.camp.spi.collection.ResourceLookup.EmptyResourceLookup;
+import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
+
+import com.google.common.base.Preconditions;
+
+
+/** Holds the metadata (name, description, etc) for an AssemblyTemplate
+ * as well as fields pointing to behaviour (eg list of ACT's).
+ * <p>
+ * See {@link AbstractResource} for more general information.
+ */
+public class AssemblyTemplate extends AbstractResource {
+
+    public static final String CAMP_TYPE = "AssemblyTemplate";
+    static { assert CAMP_TYPE.equals(AssemblyTemplate.class.getSimpleName()); }
+    
+    Class<? extends AssemblyTemplateInstantiator> instantiator;
+    ResourceLookup<ApplicationComponentTemplate> applicationComponentTemplates;
+    ResourceLookup<PlatformComponentTemplate> platformComponentTemplates;
+    
+    // TODO
+//    "parameterDefinitionUri": URI,
+//    "pdpUri" : URI ?
+                    
+    /** Use {@link #builder()} to create */
+    protected AssemblyTemplate() {}
+
+    public Class<? extends AssemblyTemplateInstantiator> getInstantiator() {
+        return instantiator;
+    }
+    public ResourceLookup<ApplicationComponentTemplate> getApplicationComponentTemplates() {
+        return applicationComponentTemplates != null ? applicationComponentTemplates : new EmptyResourceLookup<ApplicationComponentTemplate>();
+    }
+    public ResourceLookup<PlatformComponentTemplate> getPlatformComponentTemplates() {
+        return platformComponentTemplates != null ? platformComponentTemplates : new EmptyResourceLookup<PlatformComponentTemplate>();
+    }
+    
+    private void setInstantiator(Class<? extends AssemblyTemplateInstantiator> instantiator) {
+        this.instantiator = instantiator;
+    }
+    private void setApplicationComponentTemplates(ResourceLookup<ApplicationComponentTemplate> applicationComponentTemplates) {
+        this.applicationComponentTemplates = applicationComponentTemplates;
+    }
+    private void setPlatformComponentTemplates(ResourceLookup<PlatformComponentTemplate> platformComponentTemplates) {
+        this.platformComponentTemplates = platformComponentTemplates;
+    }
+    
+    // builder
+    
+    public static Builder<? extends AssemblyTemplate> builder() {
+        return new AssemblyTemplate().new Builder<AssemblyTemplate>(CAMP_TYPE);
+    }
+    
+    public class Builder<T extends AssemblyTemplate> extends AbstractResource.Builder<T,Builder<T>> {
+        
+        protected Builder(String type) { super(type); }
+        
+        public Builder<T> instantiator(Class<? extends AssemblyTemplateInstantiator> x) { AssemblyTemplate.this.setInstantiator(x); return thisBuilder(); }
+        public Builder<T> applicationComponentTemplates(ResourceLookup<ApplicationComponentTemplate> x) { AssemblyTemplate.this.setApplicationComponentTemplates(x); return thisBuilder(); }
+        public Builder<T> platformComponentTemplates(ResourceLookup<PlatformComponentTemplate> x) { AssemblyTemplate.this.setPlatformComponentTemplates(x); return thisBuilder(); }
+
+        /** allows callers to see the partially formed instance when needed, for example to query instantiators;
+         *  could be replaced by specific methods as and when that is preferred */
+        @SuppressWarnings("unchecked")
+        public T peek() { return (T) AssemblyTemplate.this; }
+        
+        public synchronized Builder<T> add(ApplicationComponentTemplate x) {
+            if (AssemblyTemplate.this.applicationComponentTemplates==null) {
+                AssemblyTemplate.this.applicationComponentTemplates = new BasicResourceLookup<ApplicationComponentTemplate>();
+            }
+            if (!(AssemblyTemplate.this.applicationComponentTemplates instanceof BasicResourceLookup)) {
+                throw new IllegalStateException("Cannot add to resource lookup "+AssemblyTemplate.this.applicationComponentTemplates);
+            }
+            ((BasicResourceLookup<ApplicationComponentTemplate>)AssemblyTemplate.this.applicationComponentTemplates).add(x);
+            return thisBuilder();
+        }
+        
+        public synchronized Builder<T> add(PlatformComponentTemplate x) {
+            if (AssemblyTemplate.this.platformComponentTemplates==null) {
+                AssemblyTemplate.this.platformComponentTemplates = new BasicResourceLookup<PlatformComponentTemplate>();
+            }
+            if (!(AssemblyTemplate.this.platformComponentTemplates instanceof BasicResourceLookup)) {
+                throw new IllegalStateException("Cannot add to resource lookup "+AssemblyTemplate.this.platformComponentTemplates);
+            }
+            ((BasicResourceLookup<PlatformComponentTemplate>)AssemblyTemplate.this.platformComponentTemplates).add(x);
+            return thisBuilder();
+        }
+        
+        @Override
+        public synchronized T build() {
+            Preconditions.checkNotNull(AssemblyTemplate.this.instantiator);
+            return super.build();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/Link.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/Link.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/Link.java
new file mode 100644
index 0000000..00a22b6
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/Link.java
@@ -0,0 +1,40 @@
+/*
+ * 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.spi;
+
+public class Link<T> {
+
+    private final String id;
+    private final String name;
+    
+    public Link(String id, String name) {
+        super();
+        this.id = id;
+        this.name = name;
+    }
+
+    public String getId() {
+        return id;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/PlatformComponent.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/PlatformComponent.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/PlatformComponent.java
new file mode 100644
index 0000000..fa5eddb
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/PlatformComponent.java
@@ -0,0 +1,101 @@
+/*
+ * 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.spi;
+
+import org.apache.brooklyn.camp.spi.collection.BasicResourceLookup;
+import org.apache.brooklyn.camp.spi.collection.ResourceLookup;
+import org.apache.brooklyn.camp.spi.collection.ResourceLookup.EmptyResourceLookup;
+
+
+/** Holds the metadata (name, description, etc) for a PCT
+ * as well as fields pointing to behaviour (eg creation of PlatformComponent).
+ * <p>
+ * See {@link AbstractResource} for more general information.
+ */
+public class PlatformComponent extends AbstractResource {
+
+    public static final String CAMP_TYPE = "PlatformComponent";
+    static { assert CAMP_TYPE.equals(PlatformComponent.class.getSimpleName()); }
+    
+    /** Use {@link #builder()} to create */
+    protected PlatformComponent() {}
+
+    ResourceLookup<ApplicationComponent> applicationComponents;
+    ResourceLookup<PlatformComponent> platformComponents;
+    String externalManagementUri;
+    
+    public ResourceLookup<ApplicationComponent> getApplicationComponents() {
+        return applicationComponents != null ? applicationComponents : new EmptyResourceLookup<ApplicationComponent>();
+    }
+    public ResourceLookup<PlatformComponent> getPlatformComponents() {
+        return platformComponents != null ? platformComponents : new EmptyResourceLookup<PlatformComponent>();
+    }
+
+    private void setApplicationComponents(ResourceLookup<ApplicationComponent> applicationComponents) {
+        this.applicationComponents = applicationComponents;
+    }
+    private void setPlatformComponents(ResourceLookup<PlatformComponent> platformComponents) {
+        this.platformComponents = platformComponents;
+    }
+    
+    public String getExternalManagementUri() {
+        return externalManagementUri;
+    }
+    private void setExternalManagementUri(String externalManagementUri) {
+        this.externalManagementUri = externalManagementUri;
+    }
+    
+    // builder
+    
+    public static Builder<? extends PlatformComponent> builder() {
+        return new PlatformComponent().new Builder<PlatformComponent>(CAMP_TYPE);
+    }
+    
+    public class Builder<T extends PlatformComponent> extends AbstractResource.Builder<T,Builder<T>> {
+        
+        protected Builder(String type) { super(type); }
+        
+        public Builder<T> externalManagementUri(String x) { PlatformComponent.this.setExternalManagementUri(x); return thisBuilder(); }
+        public Builder<T> applicationComponentTemplates(ResourceLookup<ApplicationComponent> x) { PlatformComponent.this.setApplicationComponents(x); return thisBuilder(); }
+        public Builder<T> platformComponentTemplates(ResourceLookup<PlatformComponent> x) { PlatformComponent.this.setPlatformComponents(x); return thisBuilder(); }
+        
+        public synchronized Builder<T> add(ApplicationComponent x) {
+            if (PlatformComponent.this.applicationComponents==null) {
+                PlatformComponent.this.applicationComponents = new BasicResourceLookup<ApplicationComponent>();
+            }
+            if (!(PlatformComponent.this.applicationComponents instanceof BasicResourceLookup)) {
+                throw new IllegalStateException("Cannot add to resource lookup "+PlatformComponent.this.applicationComponents);
+            }
+            ((BasicResourceLookup<ApplicationComponent>)PlatformComponent.this.applicationComponents).add(x);
+            return thisBuilder();
+        }
+        
+        public synchronized Builder<T> add(PlatformComponent x) {
+            if (PlatformComponent.this.platformComponents==null) {
+                PlatformComponent.this.platformComponents = new BasicResourceLookup<PlatformComponent>();
+            }
+            if (!(PlatformComponent.this.platformComponents instanceof BasicResourceLookup)) {
+                throw new IllegalStateException("Cannot add to resource lookup "+PlatformComponent.this.platformComponents);
+            }
+            ((BasicResourceLookup<PlatformComponent>)PlatformComponent.this.platformComponents).add(x);
+            return thisBuilder();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/PlatformComponentTemplate.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/PlatformComponentTemplate.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/PlatformComponentTemplate.java
new file mode 100644
index 0000000..2377519
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/PlatformComponentTemplate.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.camp.spi;
+
+
+/** Holds the metadata (name, description, etc) for a PCT
+ * as well as fields pointing to behaviour (eg creation of PlatformComponent).
+ * <p>
+ * See {@link AbstractResource} for more general information.
+ */
+public class PlatformComponentTemplate extends AbstractResource {
+
+    public static final String CAMP_TYPE = "PlatformComponentTemplate";
+    static { assert CAMP_TYPE.equals(PlatformComponentTemplate.class.getSimpleName()); }
+    
+    /** Use {@link #builder()} to create */
+    protected PlatformComponentTemplate() {}
+
+    
+    // no fields beyond basic resource
+    
+    
+    // builder
+    
+    public static Builder<? extends PlatformComponentTemplate> builder() {
+        return new PlatformComponentTemplate().new Builder<PlatformComponentTemplate>(CAMP_TYPE);
+    }
+    
+    public class Builder<T extends PlatformComponentTemplate> extends AbstractResource.Builder<T,Builder<T>> {
+        
+        protected Builder(String type) { super(type); }
+        
+//        public Builder<T> foo(String x) { instance().setFoo(x); return thisBuilder(); }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/PlatformRootSummary.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/PlatformRootSummary.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/PlatformRootSummary.java
new file mode 100644
index 0000000..d8713df
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/PlatformRootSummary.java
@@ -0,0 +1,70 @@
+/*
+ * 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.spi;
+
+/** Holds the metadata (name, description, etc) for a CampPlatform.
+ * Required to initialize a CampPlatform.
+ * <p>
+ * See {@link AbstractResource} for more general information.
+ */
+public class PlatformRootSummary extends AbstractResource {
+
+    public static final String CAMP_TYPE = "Platform";
+    
+    /** Use {@link #builder()} to create */
+    protected PlatformRootSummary() {
+    }
+    
+    // no fields beyond basic resource
+    
+    //TODO:
+    
+    // in the DTO
+    
+//    "supportedFormatsUri": URI, 
+//    "extensionsUri": URI,
+//    "typeDefinitionsUri": URI,
+//    "tags": [ String, + ], ?
+//    "specificationVersion": String[], 
+//    "implementationVersion": String, ? 
+//    "assemblyTemplates": [ Link + ], ? 
+//    "assemblies": [ Link + ], ? 
+//    "platformComponentTemplates": [ Link + ], ? 
+//    "platformComponentCapabilities": [Link + ], ? 
+//    "platformComponents": [ Link + ], ?
+
+    
+    // builder
+    
+    public static Builder<? extends PlatformRootSummary> builder() {
+        return new PlatformRootSummary().new Builder<PlatformRootSummary>(CAMP_TYPE);
+    }
+    
+    public class Builder<T extends PlatformRootSummary> extends AbstractResource.Builder<T,Builder<T>> {
+        
+        protected Builder(String type) { super(type); }
+        
+        protected void initialize() {
+            super.initialize();
+            // TODO a better way not to have an ID here (new subclass BasicIdentifiableResource for other BasicResource instances)
+            id("");
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/PlatformTransaction.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/PlatformTransaction.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/PlatformTransaction.java
new file mode 100644
index 0000000..ae54beb
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/PlatformTransaction.java
@@ -0,0 +1,46 @@
+/*
+ * 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.spi;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class PlatformTransaction {
+
+    protected List<Object> additions = new ArrayList<Object>();
+    
+    /** apply the transaction */
+    public abstract void commit();
+    
+    public PlatformTransaction add(AssemblyTemplate at) {
+        additions.add(at);
+        return this;
+    }
+
+    public PlatformTransaction add(ApplicationComponentTemplate act) {
+        additions.add(act);
+        return this;
+    }
+
+    public PlatformTransaction add(PlatformComponentTemplate pct) {
+        additions.add(pct);
+        return this;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/AbstractResourceLookup.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/AbstractResourceLookup.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/AbstractResourceLookup.java
new file mode 100644
index 0000000..1709087
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/AbstractResourceLookup.java
@@ -0,0 +1,35 @@
+/*
+ * 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.spi.collection;
+
+import org.apache.brooklyn.camp.spi.AbstractResource;
+
+public abstract class AbstractResourceLookup<T extends AbstractResource> implements ResourceLookup<T> {
+
+    /** convenience for concrete subclasses */
+    protected ResolvableLink<T> newLink(String id, String name) {
+        return new ResolvableLink<T>(id, name, this);
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return links().isEmpty();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/AggregatingResourceLookup.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/AggregatingResourceLookup.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/AggregatingResourceLookup.java
new file mode 100644
index 0000000..700aafb
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/AggregatingResourceLookup.java
@@ -0,0 +1,56 @@
+/*
+ * 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.spi.collection;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.brooklyn.camp.spi.AbstractResource;
+
+public class AggregatingResourceLookup<T extends AbstractResource> extends AbstractResourceLookup<T> {
+
+    List<ResourceLookup<T>> targets = new ArrayList<ResourceLookup<T>>();
+    
+    public static <T extends AbstractResource> AggregatingResourceLookup<T> of(ResourceLookup<T> ...targets) {
+        AggregatingResourceLookup<T> result = new AggregatingResourceLookup<T>();
+        for (ResourceLookup<T> item: targets) result.targets.add(item);
+        return result;
+    }
+    
+    public static <T extends AbstractResource> AggregatingResourceLookup<T> of(Iterable<ResourceLookup<T>> targets) {
+        AggregatingResourceLookup<T> result = new AggregatingResourceLookup<T>();
+        for (ResourceLookup<T> item: targets) result.targets.add(item);
+        return result;        
+    }
+
+    public T get(String id) {
+        for (ResourceLookup<T> item: targets) {
+            T result = item.get(id);
+            if (result!=null) return result;
+        }
+        return null;
+    }
+
+    public List<ResolvableLink<T>> links() {
+        List<ResolvableLink<T>> result = new ArrayList<ResolvableLink<T>>();
+        for (ResourceLookup<T> item: targets) result.addAll(item.links());
+        return result;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/BasicResourceLookup.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/BasicResourceLookup.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/BasicResourceLookup.java
new file mode 100644
index 0000000..38405c2
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/BasicResourceLookup.java
@@ -0,0 +1,71 @@
+/*
+ * 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.spi.collection;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.camp.spi.AbstractResource;
+
+import brooklyn.util.collections.MutableMap;
+
+public class BasicResourceLookup<T extends AbstractResource> extends AbstractResourceLookup<T> {
+
+    Map<String,T> items = new MutableMap<String,T>();
+    Map<String,ResolvableLink<T>> links = new MutableMap<String,ResolvableLink<T>>();
+    
+    public T get(String id) {
+        return items.get(id);
+    }
+
+    public synchronized List<ResolvableLink<T>> links() {
+        return new ArrayList<ResolvableLink<T>>(links.values());
+    }
+
+    public synchronized void add(T item) {
+        T old = items.put(item.getId(), item);
+        if (old!=null) {
+            items.put(old.getId(), old);
+            throw new IllegalStateException("Already contains item for "+item.getId()+": "+old+" (adding "+item+")");
+        }
+        links.put(item.getId(), newLink(item.getId(), item.getName()));
+    }
+    
+    public synchronized void addAll(T... items) {
+        for (T item: items) add(item);
+    }
+    
+    public synchronized T update(T item) {
+        T old = items.put(item.getId(), item);
+        links.put(item.getId(), newLink(item.getId(), item.getName()));
+        return old;
+    }
+    
+    public synchronized boolean remove(String id) {
+        items.remove(id);
+        return links.remove(id)!=null;
+    }
+    
+    public static <T extends AbstractResource> BasicResourceLookup<T> of(T ...items) {
+        BasicResourceLookup<T> result = new BasicResourceLookup<T>();
+        for (T item: items) result.add(item);
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/ResolvableLink.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/ResolvableLink.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/ResolvableLink.java
new file mode 100644
index 0000000..81fea30
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/ResolvableLink.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.camp.spi.collection;
+
+import org.apache.brooklyn.camp.spi.AbstractResource;
+import org.apache.brooklyn.camp.spi.Link;
+
+public class ResolvableLink<T extends AbstractResource> extends Link<T> {
+    
+    protected final ResourceLookup<T> provider;
+    
+    public ResolvableLink(String id, String name, ResourceLookup<T> provider) {
+        super(id, name);
+        this.provider = provider;
+    }
+
+    public T resolve() {
+        return provider.get(getId());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/ResourceLookup.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/ResourceLookup.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/ResourceLookup.java
new file mode 100644
index 0000000..7fc5a71
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/collection/ResourceLookup.java
@@ -0,0 +1,47 @@
+/*
+ * 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.spi.collection;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.apache.brooklyn.camp.spi.AbstractResource;
+
+public interface ResourceLookup<T extends AbstractResource> {
+
+    public abstract T get(String id);
+    
+    public abstract List<ResolvableLink<T>> links();
+    
+    public abstract boolean isEmpty();
+
+    public static class EmptyResourceLookup<T extends AbstractResource> implements ResourceLookup<T> {
+        public T get(String id) {
+            throw new NoSuchElementException("no resource: "+id);
+        }
+        public List<ResolvableLink<T>> links() {
+            return Collections.emptyList();
+        }
+        public boolean isEmpty() {
+            return links().isEmpty();
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/instantiate/AssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/instantiate/AssemblyTemplateInstantiator.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/instantiate/AssemblyTemplateInstantiator.java
new file mode 100644
index 0000000..5c0d9d6
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/instantiate/AssemblyTemplateInstantiator.java
@@ -0,0 +1,30 @@
+/*
+ * 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.spi.instantiate;
+
+import org.apache.brooklyn.camp.CampPlatform;
+import org.apache.brooklyn.camp.spi.Assembly;
+import org.apache.brooklyn.camp.spi.AssemblyTemplate;
+
+/** instances of this class should have a public no-arg constructor so the class names can be serialized */
+public interface AssemblyTemplateInstantiator {
+
+    public Assembly instantiate(AssemblyTemplate template, CampPlatform platform);
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/instantiate/BasicAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/instantiate/BasicAssemblyTemplateInstantiator.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/instantiate/BasicAssemblyTemplateInstantiator.java
new file mode 100644
index 0000000..28eac3a
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/instantiate/BasicAssemblyTemplateInstantiator.java
@@ -0,0 +1,36 @@
+/*
+ * 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.spi.instantiate;
+
+import org.apache.brooklyn.camp.CampPlatform;
+import org.apache.brooklyn.camp.spi.Assembly;
+import org.apache.brooklyn.camp.spi.AssemblyTemplate;
+
+/** A simple instantiator which simply invokes the component's instantiators in parallel */
+public class BasicAssemblyTemplateInstantiator implements AssemblyTemplateInstantiator {
+
+    public Assembly instantiate(AssemblyTemplate template, CampPlatform platform) {
+        // TODO this should build it based on the components
+//        template.getPlatformComponentTemplates().links().iterator().next().resolve();
+        
+        // platforms should set a bunch of instantiators, or else let the ComponentTemplates do this!
+        throw new UnsupportedOperationException("Basic instantiator not yet supported");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/Artifact.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/Artifact.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/Artifact.java
new file mode 100644
index 0000000..5ea2a6a
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/Artifact.java
@@ -0,0 +1,99 @@
+/*
+ * 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.spi.pdp;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.yaml.Yamls;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class Artifact {
+
+    String name;
+    String description;
+    String artifactType;
+    
+    ArtifactContent content;
+    List<ArtifactRequirement> requirements;
+    
+    Map<String,Object> customAttributes;
+    
+    @SuppressWarnings("unchecked")
+    public static Artifact of(Map<String, Object> artifact) {
+        Map<String,Object> fields = MutableMap.copyOf(artifact);
+        
+        Artifact result = new Artifact();
+        result.name = (String) fields.remove("name");
+        result.description = (String) fields.remove("description");
+        result.artifactType = (String) (String) Yamls.removeMultinameAttribute(fields, "artifactType", "type");
+        
+        result.content = ArtifactContent.of( fields.remove("content") );
+        
+        result.requirements = new ArrayList<ArtifactRequirement>();
+        Object reqs = fields.remove("requirements");
+        if (reqs instanceof Iterable) {
+            for (Object req: (Iterable<Object>)reqs) {
+                if (req instanceof Map) {
+                    result.requirements.add(ArtifactRequirement.of((Map<String,Object>) req));
+                } else {
+                    throw new IllegalArgumentException("requirement should be a map, not "+req.getClass());
+                }
+            }
+        } else if (reqs!=null) {
+            // TODO "map" short form
+            throw new IllegalArgumentException("artifacts body should be iterable, not "+reqs.getClass());
+        }
+        
+        result.customAttributes = fields;
+        
+        return result;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    public String getDescription() {
+        return description;
+    }
+    public String getArtifactType() {
+        return artifactType;
+    }
+    public ArtifactContent getContent() {
+        return content;
+    }
+    public List<ArtifactRequirement> getRequirements() {
+        return ImmutableList.copyOf(requirements);
+    }
+    public Map<String, Object> getCustomAttributes() {
+        return ImmutableMap.copyOf(customAttributes);
+    }
+    
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/ArtifactContent.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/ArtifactContent.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/ArtifactContent.java
new file mode 100644
index 0000000..e1f093f
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/ArtifactContent.java
@@ -0,0 +1,65 @@
+/*
+ * 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.spi.pdp;
+
+import java.util.Map;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.collect.ImmutableMap;
+
+public class ArtifactContent {
+
+    String href;
+    Map<String,Object> customAttributes;
+    
+    public static ArtifactContent of(Object spec) {
+        if (spec==null) return null;
+        
+        ArtifactContent result = new ArtifactContent();
+        if (spec instanceof String) {
+            result.href = (String)spec;
+        } else if (spec instanceof Map) {
+            @SuppressWarnings("unchecked")
+            Map<String,Object> attrs = MutableMap.copyOf( (Map<String,Object>) spec );
+            result.href = (String) attrs.remove("href");
+            result.customAttributes = attrs;            
+        } else {
+            throw new IllegalArgumentException("artifact content should be map or string, not "+spec.getClass());
+        }
+        
+        return result;
+    }
+
+    public String getHref() {
+        return href;
+    }
+    
+    public Map<String, Object> getCustomAttributes() {
+        return ImmutableMap.copyOf(customAttributes);
+    }
+
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/ArtifactRequirement.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/ArtifactRequirement.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/ArtifactRequirement.java
new file mode 100644
index 0000000..10ad72c
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/ArtifactRequirement.java
@@ -0,0 +1,72 @@
+/*
+ * 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.spi.pdp;
+
+import java.util.Map;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.yaml.Yamls;
+
+import com.google.common.collect.ImmutableMap;
+
+public class ArtifactRequirement {
+
+    String name;
+    String description;
+    String requirementType;
+    
+    Map<String,Object> customAttributes;
+    
+    public static ArtifactRequirement of(Map<String, Object> req) {
+        Map<String,Object> attrs = MutableMap.copyOf(req);
+        
+        ArtifactRequirement result = new ArtifactRequirement();
+        result.name = (String) attrs.remove("name");
+        result.description = (String) attrs.remove("description");
+        result.requirementType = (String) (String) Yamls.removeMultinameAttribute(attrs, "requirementType", "type");
+        
+        // TODO fulfillment
+        
+        result.customAttributes = attrs;
+        
+        return result;
+    }
+
+    public String getName() {
+        return name;
+    }
+    public String getDescription() {
+        return description;
+    }
+    public String getRequirementType() {
+        return requirementType;
+    }
+    
+    public Map<String, Object> getCustomAttributes() {
+        return ImmutableMap.copyOf(customAttributes);
+    }
+    
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/AssemblyTemplateConstructor.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/AssemblyTemplateConstructor.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/AssemblyTemplateConstructor.java
new file mode 100644
index 0000000..a5814fc
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/AssemblyTemplateConstructor.java
@@ -0,0 +1,100 @@
+/*
+ * 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.spi.pdp;
+
+import java.util.Map;
+
+import org.apache.brooklyn.camp.CampPlatform;
+import org.apache.brooklyn.camp.spi.ApplicationComponentTemplate;
+import org.apache.brooklyn.camp.spi.AssemblyTemplate;
+import org.apache.brooklyn.camp.spi.PlatformComponentTemplate;
+import org.apache.brooklyn.camp.spi.PlatformTransaction;
+import org.apache.brooklyn.camp.spi.AssemblyTemplate.Builder;
+import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
+
+public class AssemblyTemplateConstructor {
+
+    private final Builder<? extends AssemblyTemplate> builder;
+    private final CampPlatform campPlatform;
+    protected PlatformTransaction transaction;
+
+    public AssemblyTemplateConstructor(CampPlatform campPlatform) {
+        this.campPlatform = campPlatform;
+        this.builder = AssemblyTemplate.builder();
+        this.transaction = this.campPlatform.transaction();
+    }
+    
+    /** records all the templates to the underlying platform */
+    public AssemblyTemplate commit() {
+        checkState();
+        AssemblyTemplate at = builder.build();
+        transaction.add(at).commit();
+        transaction = null;
+        return at;
+    }
+
+    public void name(String name) {
+        checkState();
+        builder.name(name);
+    }
+
+    public void description(String description) {
+        checkState();
+        builder.description(description);
+    }
+
+
+    public void sourceCode(String sourceCode) {
+        checkState();
+        builder.sourceCode(sourceCode);
+    }
+
+    public void addCustomAttributes(Map<String, Object> attrs) {
+        for (Map.Entry<String, Object> attr : attrs.entrySet())
+            builder.customAttribute(attr.getKey(), attr.getValue());
+    }
+
+    public void instantiator(Class<? extends AssemblyTemplateInstantiator> instantiator) {
+        checkState();
+        builder.instantiator(instantiator);
+    }
+    
+    public Class<? extends AssemblyTemplateInstantiator> getInstantiator() {
+        checkState();
+        return builder.peek().getInstantiator();
+    }
+    
+    public void add(ApplicationComponentTemplate act) {
+        checkState();
+        builder.add(act);
+        transaction.add(act);
+    }
+
+    public void add(PlatformComponentTemplate pct) {
+        checkState();
+        builder.add(pct);
+        transaction.add(pct);
+    }
+
+    protected void checkState() {
+        if (transaction == null)
+            throw new IllegalStateException("transaction already committed");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/DeploymentPlan.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/DeploymentPlan.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/DeploymentPlan.java
new file mode 100644
index 0000000..499a4ee
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/DeploymentPlan.java
@@ -0,0 +1,150 @@
+/*
+ * 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.spi.pdp;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.guava.Maybe;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class DeploymentPlan {
+
+    String name;
+    String origin;
+    String description;
+    String sourceCode;
+    
+    List<Artifact> artifacts;
+    List<Service> services;
+    Map<String,Object> customAttributes;
+
+    @Deprecated /** @deprecated since 0.7.0; supply source code also, for reference */
+    public static DeploymentPlan of(Map<String,Object> root) {
+        return of(root, null);
+    }
+    @SuppressWarnings("unchecked")
+    public static DeploymentPlan of(Map<String,Object> root, String optionalSourceCode) {
+        Map<String,Object> attrs = MutableMap.copyOf(root);
+        
+        DeploymentPlan result = new DeploymentPlan();
+        result.name = (String) attrs.remove("name");
+        result.description = (String) attrs.remove("description");
+        result.origin = (String) attrs.remove("origin");
+        result.sourceCode = optionalSourceCode;
+        // TODO version
+        
+        result.services = new ArrayList<Service>();
+        Object services = attrs.remove("services");
+        if (services instanceof Iterable) {
+            for (Object service: (Iterable<Object>)services) {
+                if (service instanceof Map) {
+                    result.services.add(Service.of((Map<String,Object>) service));
+                } else {
+                    throw new IllegalArgumentException("service should be map, not "+service.getClass());
+                }
+            }
+        } else if (services!=null) {
+            // TODO "map" short form
+            throw new IllegalArgumentException("artifacts body should be iterable, not "+services.getClass());
+        }
+        
+        result.artifacts = new ArrayList<Artifact>();
+        Object artifacts = attrs.remove("artifacts");
+        if (artifacts instanceof Iterable) {
+            for (Object artifact: (Iterable<Object>)artifacts) {
+                if (artifact instanceof Map) {
+                    result.artifacts.add(Artifact.of((Map<String,Object>) artifact));
+                } else {
+                    throw new IllegalArgumentException("artifact should be map, not "+artifact.getClass());
+                }
+            }
+        } else if (artifacts!=null) {
+            // TODO "map" short form
+            throw new IllegalArgumentException("artifacts body should be iterable, not "+artifacts.getClass());
+        }
+        
+        result.customAttributes = attrs;
+        
+        return result;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public String getOrigin() {
+        return origin;
+    }
+
+    public String getSourceCode() {
+        return sourceCode;
+    }
+    
+    public List<Artifact> getArtifacts() {
+        return ImmutableList.copyOf(artifacts);
+    }
+
+    public List<Service> getServices() {
+        return ImmutableList.copyOf(services);
+    }
+
+    public Map<String, Object> getCustomAttributes() {
+        return ImmutableMap.copyOf(customAttributes);
+    }
+
+    /**
+     * Returns a present {@link Maybe} of the custom attribute with the given name if the attribute is
+     * non-null and is an instance of the given type. Otherwise returns absent.
+     * <p/>
+     * Does not remove the attribute from the custom attribute map.
+     */
+    @SuppressWarnings("unchecked")
+    public <T> Maybe<T> getCustomAttribute(String attributeName, Class<T> type, boolean throwIfTypeMismatch) {
+        Object attribute = customAttributes.get(attributeName);
+        if (attribute == null) {
+            return Maybe.absent("Custom attributes does not contain " + attributeName);
+        } else if (!type.isAssignableFrom(attribute.getClass())) {
+            String message = "Custom attribute " + attributeName + " is not of expected type: " +
+                    "expected=" + type.getName() + " actual=" + attribute.getClass().getName();
+            if (throwIfTypeMismatch) {
+                throw new IllegalArgumentException(message);
+            }
+            return Maybe.absent(message);
+        } else {
+            return Maybe.of((T) attribute);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/Service.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/Service.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/Service.java
new file mode 100644
index 0000000..8c05143
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/Service.java
@@ -0,0 +1,94 @@
+/*
+ * 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.spi.pdp;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.yaml.Yamls;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class Service {
+
+    String name;
+    String description;
+    String serviceType;
+    
+    List<ServiceCharacteristic> characteristics;
+    
+    Map<String,Object> customAttributes;
+    
+    @SuppressWarnings("unchecked")
+    public static Service of(Map<String, Object> service) {
+        Map<String,Object> fields = MutableMap.copyOf(service);
+        
+        Service result = new Service();
+        result.name = (String) fields.remove("name");
+        result.description = (String) fields.remove("description");
+        // FIXME _type needed in lots of places
+        result.serviceType = (String) Yamls.removeMultinameAttribute(fields, "service_type", "serviceType", "type");
+        
+        result.characteristics = new ArrayList<ServiceCharacteristic>();
+        Object chars = fields.remove("characteristics");
+        if (chars instanceof Iterable) {
+            for (Object req: (Iterable<Object>)chars) {
+                if (req instanceof Map) {
+                    result.characteristics.add(ServiceCharacteristic.of((Map<String,Object>) req));
+                } else {
+                    throw new IllegalArgumentException("characteristics should be a map, not "+req.getClass());
+                }
+            }
+        } else if (chars!=null) {
+            // TODO "map" short form
+            throw new IllegalArgumentException("services body should be iterable, not "+chars.getClass());
+        }
+        
+        result.customAttributes = fields;
+        
+        return result;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    public String getDescription() {
+        return description;
+    }
+    public String getServiceType() {
+        return serviceType;
+    }
+    public List<ServiceCharacteristic> getCharacteristics() {
+        return ImmutableList.copyOf(characteristics);
+    }
+    public Map<String, Object> getCustomAttributes() {
+        return ImmutableMap.copyOf(customAttributes);
+    }
+    
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/ServiceCharacteristic.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/ServiceCharacteristic.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/ServiceCharacteristic.java
new file mode 100644
index 0000000..bf8009b
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/pdp/ServiceCharacteristic.java
@@ -0,0 +1,72 @@
+/*
+ * 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.spi.pdp;
+
+import java.util.Map;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.yaml.Yamls;
+
+import com.google.common.collect.ImmutableMap;
+
+public class ServiceCharacteristic {
+
+    String name;
+    String description;
+    String characteristicType;
+    
+    Map<String,Object> customAttributes;
+    
+    public static ServiceCharacteristic of(Map<String, Object> req) {
+        Map<String,Object> attrs = MutableMap.copyOf(req);
+        
+        ServiceCharacteristic result = new ServiceCharacteristic();
+        result.name = (String) attrs.remove("name");
+        result.description = (String) attrs.remove("description");
+        result.characteristicType = (String) Yamls.removeMultinameAttribute(attrs, "characteristicType", "type");
+        
+        // TODO fulfillment
+        
+        result.customAttributes = attrs;
+        
+        return result;
+    }
+
+    public String getName() {
+        return name;
+    }
+    public String getDescription() {
+        return description;
+    }
+    public String getCharacteristicType() {
+        return characteristicType;
+    }
+    
+    public Map<String, Object> getCustomAttributes() {
+        return ImmutableMap.copyOf(customAttributes);
+    }
+    
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/resolve/PdpMatcher.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/resolve/PdpMatcher.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/resolve/PdpMatcher.java
new file mode 100644
index 0000000..a574b71
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/resolve/PdpMatcher.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.camp.spi.resolve;
+
+import org.apache.brooklyn.camp.spi.pdp.Artifact;
+import org.apache.brooklyn.camp.spi.pdp.AssemblyTemplateConstructor;
+import org.apache.brooklyn.camp.spi.pdp.Service;
+
+/** Matchers build up the AssemblyTemplate by matching against items in the deployment plan */
+public interface PdpMatcher {
+
+    boolean accepts(Object deploymentPlanItem);
+    boolean apply(Object deploymentPlanItem, AssemblyTemplateConstructor atc);
+
+    public abstract class ArtifactMatcher implements PdpMatcher {
+        private String artifactType;
+        public ArtifactMatcher(String artifactType) {
+            this.artifactType = artifactType;
+        }
+        public boolean accepts(Object art) {
+            return (art instanceof Artifact) && this.artifactType.equals( ((Artifact)art).getArtifactType() );
+        }
+    }
+    
+    public abstract class ServiceMatcher implements PdpMatcher {
+        private String serviceType;
+        public ServiceMatcher(String serviceType) {
+            this.serviceType = serviceType;
+        }
+        public boolean accepts(Object svc) {
+            return (svc instanceof Service) && this.serviceType.equals( ((Service)svc).getServiceType() );
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7d782f34/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/resolve/PdpProcessor.java
----------------------------------------------------------------------
diff --git a/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/resolve/PdpProcessor.java b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/resolve/PdpProcessor.java
new file mode 100644
index 0000000..2763d93
--- /dev/null
+++ b/camp/camp-base/src/main/java/org/apache/brooklyn/camp/spi/resolve/PdpProcessor.java
@@ -0,0 +1,187 @@
+/*
+ * 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.spi.resolve;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.camp.CampPlatform;
+import org.apache.brooklyn.camp.spi.AssemblyTemplate;
+import org.apache.brooklyn.camp.spi.instantiate.BasicAssemblyTemplateInstantiator;
+import org.apache.brooklyn.camp.spi.pdp.Artifact;
+import org.apache.brooklyn.camp.spi.pdp.AssemblyTemplateConstructor;
+import org.apache.brooklyn.camp.spi.pdp.DeploymentPlan;
+import org.apache.brooklyn.camp.spi.pdp.Service;
+import org.apache.brooklyn.camp.spi.resolve.interpret.PlanInterpretationContext;
+import org.apache.brooklyn.camp.spi.resolve.interpret.PlanInterpretationNode;
+import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.archivers.ArchiveInputStream;
+import org.apache.commons.compress.archivers.ArchiveStreamFactory;
+import org.yaml.snakeyaml.error.YAMLException;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.yaml.Yamls;
+
+import com.google.common.annotations.VisibleForTesting;
+
+public class PdpProcessor {
+
+    final CampPlatform campPlatform;
+    
+    final List<PdpMatcher> matchers = new ArrayList<PdpMatcher>();
+    final List<PlanInterpreter> interpreters = new ArrayList<PlanInterpreter>();
+    
+    public PdpProcessor(CampPlatform campPlatform) {
+        this.campPlatform = campPlatform;
+    }
+
+    public DeploymentPlan parseDeploymentPlan(Reader yaml) {
+        return parseDeploymentPlan(Streams.readFully(yaml));
+    }
+    
+    @SuppressWarnings("unchecked")
+    public DeploymentPlan parseDeploymentPlan(String yaml) {
+        Iterable<Object> template = Yamls.parseAll(yaml);
+        
+        Map<String, Object> dpRootUninterpreted = null;
+        try {
+            dpRootUninterpreted = Yamls.getAs(template, Map.class);
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            throw new YAMLException("Plan not in acceptable format: "+(e.getMessage()!=null ? e.getMessage() : ""+e), e);
+        }
+        Map<String, Object> dpRootInterpreted = applyInterpreters(dpRootUninterpreted);
+        
+        return DeploymentPlan.of(dpRootInterpreted, yaml);
+    }
+    
+    /** create and return an AssemblyTemplate based on the given DP (yaml) */
+    public AssemblyTemplate registerDeploymentPlan(Reader yaml) {
+        DeploymentPlan plan = parseDeploymentPlan(yaml);
+        return registerDeploymentPlan(plan);
+    }
+
+    /** applies matchers to the given deployment plan to create an assembly template */
+    public AssemblyTemplate registerDeploymentPlan(DeploymentPlan plan) {
+        AssemblyTemplateConstructor atc = new AssemblyTemplateConstructor(campPlatform);
+        
+        if (plan.getName()!=null) atc.name(plan.getName());
+        if (plan.getDescription()!=null) atc.description(plan.getDescription());
+        if (plan.getSourceCode()!=null) atc.sourceCode(plan.getSourceCode());
+        // nothing done with origin just now...
+        
+        if (plan.getServices()!=null) {
+            for (Service svc: plan.getServices()) {
+                applyMatchers(svc, atc);
+            }
+        }
+
+        if (plan.getArtifacts()!=null) {
+            for (Artifact art: plan.getArtifacts()) {
+                applyMatchers(art, atc);
+            }
+        }
+
+        Map<String, Object> attrs = plan.getCustomAttributes();
+        if (attrs!=null && !attrs.isEmpty()) {
+            Map<String, Object> customAttrs = attrs;
+            if (customAttrs.containsKey("id")) {
+                // id shouldn't be leaking to entities, see InternalEntityFactory.createEntityAndDescendantsUninitialized.
+                // If set it will go through to the spec because AbstractBrooklynObject has @SetFromFlag("id") on the id property.
+                // Follows logic in BrooklynEntityMatcher.apply(...).
+                customAttrs = MutableMap.copyOf(attrs);
+                customAttrs.put("planId", customAttrs.remove("id"));
+            }
+            atc.addCustomAttributes(customAttrs);
+        }
+        
+        if (atc.getInstantiator()==null)
+            // set a default instantiator which just invokes the component's instantiators
+            // (or throws unsupported exceptions, currently!)
+            atc.instantiator(BasicAssemblyTemplateInstantiator.class);
+
+        return atc.commit();
+    }
+    
+    public AssemblyTemplate registerPdpFromArchive(InputStream archiveInput) {
+        try {
+            ArchiveInputStream input = new ArchiveStreamFactory()
+                .createArchiveInputStream(archiveInput);
+            
+            while (true) {
+                ArchiveEntry entry = input.getNextEntry();
+                if (entry==null) break;
+                // TODO unpack entry, create a space on disk holding the archive ?
+            }
+
+            // use yaml...
+            throw new UnsupportedOperationException("in progress");
+            
+        } catch (Exception e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+
+
+    // ----------------------------
+    
+    public void addMatcher(PdpMatcher m) {
+        // TODO a list is a crude way to do matching ... but good enough to start
+        matchers.add(m);
+    }
+
+    public List<PdpMatcher> getMatchers() {
+        return matchers;
+    }
+
+
+    protected void applyMatchers(Object deploymentPlanItem, AssemblyTemplateConstructor atc) {
+        for (PdpMatcher matcher: getMatchers()) {
+            if (matcher.accepts(deploymentPlanItem)) {
+                // TODO first accepting is a crude way to do matching ... but good enough to start
+                if (matcher.apply(deploymentPlanItem, atc))
+                    return;
+            }
+        }
+        throw new UnsupportedOperationException("Deployment plan item "+deploymentPlanItem+" cannot be matched");
+    }
+
+    // ----------------------------
+
+    public void addInterpreter(PlanInterpreter interpreter) {
+        interpreters.add(interpreter);
+    }
+    
+    /** returns a DeploymentPlan object which is the result of running the interpretation
+     * (with all interpreters) against the supplied deployment plan YAML object,
+     * essentially a post-parse processing step before matching */
+    @SuppressWarnings("unchecked")
+    @VisibleForTesting
+    public Map<String, Object> applyInterpreters(Map<String, Object> originalDeploymentPlan) {
+        PlanInterpretationNode interpretation = new PlanInterpretationNode(
+                new PlanInterpretationContext(originalDeploymentPlan, interpreters));
+        return (Map<String, Object>) interpretation.getNewValue();
+    }
+    
+}



Mime
View raw message