summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Srnicek <jsrnicek@cisco.com>2016-08-25 16:27:23 +0200
committerMaros Marsalek <mmarsale@cisco.com>2016-08-30 15:43:49 +0000
commitc961bd752be1fb2eee707cb5c7c44d1bda0894d2 (patch)
tree780c4f0c9e796f3a8aa4f9116ee83f396de74ccc
parent23f210d1477a4dd43d939714a2f3c78fa30d466c (diff)
HONEYCOMB-140 - Honeycomb Plugin Archetype
Change-Id: I6e04fb769e82fb539dbd6a79bb465974796137a4 Signed-off-by: Jan Srnicek <jsrnicek@cisco.com>
-rw-r--r--common/api-parent/pom.xml3
-rw-r--r--common/impl-parent/pom.xml3
-rw-r--r--pom.xml1
-rw-r--r--samples/interfaces/mapping/pom.xml4
-rw-r--r--tools/archetype/Readme.adoc13
-rw-r--r--tools/archetype/pom.xml17
-rw-r--r--tools/archetype/src/main/resources/META-INF/maven/archetype-metadata.xml53
-rw-r--r--tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/pom.xml62
-rw-r--r--tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/yang/__rootArtifactId__.yang49
-rw-r--r--tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/Readme.adoc3
-rw-r--r--tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/pom.xml75
-rw-r--r--tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/CrudService.java64
-rw-r--r--tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/ElementCrudService.java121
-rw-r--r--tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/Module.java81
-rw-r--r--tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/ModuleConfiguration.java46
-rw-r--r--tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/init/ConfigDataInitializer.java58
-rw-r--r--tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/read/ElementStateCustomizer.java93
-rw-r--r--tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/read/ModuleStateReaderFactory.java71
-rw-r--r--tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/write/ElementCustomizer.java69
-rw-r--r--tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/write/ModuleWriterFactory.java61
-rw-r--r--tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/resources/honeycomb-minimal-resources/config/__rootArtifactId__.json3
-rw-r--r--tools/archetype/src/main/resources/archetype-resources/pom.xml57
-rw-r--r--tools/pom.xml20
23 files changed, 1022 insertions, 5 deletions
diff --git a/common/api-parent/pom.xml b/common/api-parent/pom.xml
index ec7f78dcb..329f4decd 100644
--- a/common/api-parent/pom.xml
+++ b/common/api-parent/pom.xml
@@ -88,7 +88,8 @@
<dependency>
<groupId>io.fd.honeycomb.common</groupId>
<artifactId>honeycomb-checkstyle</artifactId>
- <version>${project.version}</version>
+ <!-- Hardcoded version to prevent archetype generated projects to use their own project version -->
+ <version>1.0.0-SNAPSHOT</version>
</dependency>
<!-- Necessary for logging checks -->
<dependency>
diff --git a/common/impl-parent/pom.xml b/common/impl-parent/pom.xml
index 4cce01f8b..ee5bf7cbd 100644
--- a/common/impl-parent/pom.xml
+++ b/common/impl-parent/pom.xml
@@ -93,7 +93,8 @@
<dependency>
<groupId>io.fd.honeycomb.common</groupId>
<artifactId>honeycomb-checkstyle</artifactId>
- <version>${project.version}</version>
+ <!-- Hardcoded version to prevent archetype generated projects to use their own project version -->
+ <version>1.0.0-SNAPSHOT</version>
</dependency>
<!-- Necessary for logging checks -->
<dependency>
diff --git a/pom.xml b/pom.xml
index 66f728aad..a37da0f51 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,6 +39,7 @@
<module>vpp-integration</module>
<module>lisp</module>
<module>samples</module>
+ <module>tools</module>
</modules>
<distributionManagement>
diff --git a/samples/interfaces/mapping/pom.xml b/samples/interfaces/mapping/pom.xml
index d5f6b07ad..eb1000235 100644
--- a/samples/interfaces/mapping/pom.xml
+++ b/samples/interfaces/mapping/pom.xml
@@ -16,7 +16,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>io.fd.honeycomb.common</groupId>
- <artifactId>api-parent</artifactId>
+ <artifactId>impl-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../../common/api-parent</relativePath>
</parent>
@@ -28,8 +28,6 @@
<packaging>bundle</packaging>
<properties>
- <guice.version>4.1.0</guice.version>
- <guice.config.version>1.2.0</guice.config.version>
<honeycomb.infra.version>1.0.0-SNAPSHOT</honeycomb.infra.version>
</properties>
diff --git a/tools/archetype/Readme.adoc b/tools/archetype/Readme.adoc
new file mode 100644
index 000000000..24040b89a
--- /dev/null
+++ b/tools/archetype/Readme.adoc
@@ -0,0 +1,13 @@
+Honeycomb Plugin Archetype
+
+ This is archetype for creating plugins for Honeycomb platform
+
+How to use it :
+
+ archetype:generate -DarchetypeGroupId=io.fd.honeycomb.tools -DarchetypeArtifactId=honeycomb-plugin-archetype -DarchetypeVersion=1.0.0-SNAPSHOT
+
+This will generate main aggregator project containing two sub-projects
+
+ -api - project that should contain yang model files for restconf/netconf DTO classes
+ -impl - implementation project that should contain plugin translation code + wiring
+
diff --git a/tools/archetype/pom.xml b/tools/archetype/pom.xml
new file mode 100644
index 000000000..e49e031c9
--- /dev/null
+++ b/tools/archetype/pom.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>honeycomb-tools</artifactId>
+ <groupId>io.fd.honeycomb.tools</groupId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>io.fd.honeycomb.tools</groupId>
+ <artifactId>honeycomb-plugin-archetype</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+</project> \ No newline at end of file
diff --git a/tools/archetype/src/main/resources/META-INF/maven/archetype-metadata.xml b/tools/archetype/src/main/resources/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 000000000..c35327187
--- /dev/null
+++ b/tools/archetype/src/main/resources/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archetype-descriptor
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd"
+ name="honeycomb-archetype"
+ xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <requiredProperties>
+ <requiredProperty key="version">
+ <defaultValue>1.0.0-SNAPSHOT</defaultValue>
+ </requiredProperty>
+ </requiredProperties>
+
+ <modules>
+ <module id="${rootArtifactId}-api" dir="__rootArtifactId__-api" name="${rootArtifactId}-api">
+ <fileSets>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*.java</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>src/main/yang</directory>
+ <includes>
+ <include>**/*.yang</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+ </module>
+ <module id="${rootArtifactId}-impl" dir="__rootArtifactId__-impl" name="${rootArtifactId}-impl">
+ <fileSets>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory></directory>
+ <includes>
+ <include>**/*.adoc</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" packaged="true" encoding="UTF-8">
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*.java</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>src/test/java</directory>
+ <includes>
+ <include>**/*.java</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+ </module>
+ </modules>
+</archetype-descriptor> \ No newline at end of file
diff --git a/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/pom.xml b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/pom.xml
new file mode 100644
index 000000000..a88775d8a
--- /dev/null
+++ b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2015 Cisco and/or its affiliates.
+ Licensed 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.
+--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>io.fd.honeycomb.common</groupId>
+ <artifactId>api-parent</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}-api</artifactId>
+ <version>${version}</version>
+ <packaging>bundle</packaging>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>mdsal-model-artifacts</artifactId>
+ <version>0.8.2-Beryllium-SR2</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>iana-if-type-2014-05-08</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-yang-types-20130715</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-interfaces</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-inet-types-2013-07-15</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>yang-ext</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/yang/__rootArtifactId__.yang b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/yang/__rootArtifactId__.yang
new file mode 100644
index 000000000..d5852ebeb
--- /dev/null
+++ b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-api/src/main/yang/__rootArtifactId__.yang
@@ -0,0 +1,49 @@
+module ${rootArtifactId} {
+
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:${rootArtifactId}";
+ prefix "${rootArtifactId}";
+
+ description
+ "This YANG module defines the generic configuration and
+ operational data for ${rootArtifactId} in VPP";
+
+ revision "2016-09-18" {
+ description "Initial revision of ${rootArtifactId} model";
+ }
+
+ container ${rootArtifactId} {
+ uses ${rootArtifactId}-params;
+ description "Configuration data of ${rootArtifactId} in Honeycomb";
+
+ // READ
+ // curl -u admin:admin http://localhost:8181/restconf/config/${rootArtifactId}:${rootArtifactId}
+
+ // WRITE
+ // curl http://localhost:8181/restconf/operational/${rootArtifactId}:${rootArtifactId}
+
+ }
+
+ container ${rootArtifactId}-state {
+ config false;
+ uses ${rootArtifactId}-params;
+ description "Operational data of ${rootArtifactId} persisted in VPP";
+
+ // READ
+ // curl -u admin:admin http://localhost:8181/restconf/operational/${rootArtifactId}:${rootArtifactId}-state
+ }
+
+ grouping ${rootArtifactId}-params {
+ list element {
+
+ key id;
+ leaf id {
+ type uint32;
+ }
+
+ leaf description {
+ type string;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/Readme.adoc b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/Readme.adoc
new file mode 100644
index 000000000..8b4288e55
--- /dev/null
+++ b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/Readme.adoc
@@ -0,0 +1,3 @@
+--Documentation for ${rootArtifactId} --
+
+TODO Replace with general description whats the purpose of ${rootArtifactId} and how it works
diff --git a/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/pom.xml b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/pom.xml
new file mode 100644
index 000000000..faaba62a8
--- /dev/null
+++ b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/pom.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2015 Cisco and/or its affiliates.
+ Licensed 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.
+--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>io.fd.honeycomb.common</groupId>
+ <artifactId>impl-parent</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}-impl</artifactId>
+ <version>${version}</version>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <honeycomb.infra.version>1.0.0-SNAPSHOT</honeycomb.infra.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>${rootArtifactId}-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- Honeycomb infrastructure-->
+ <dependency>
+ <groupId>io.fd.honeycomb</groupId>
+ <artifactId>translate-api</artifactId>
+ <version>${honeycomb.infra.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>io.fd.honeycomb</groupId>
+ <artifactId>translate-spi</artifactId>
+ <version>${honeycomb.infra.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>io.fd.honeycomb</groupId>
+ <artifactId>cfg-init</artifactId>
+ <version>${honeycomb.infra.version}</version>
+ </dependency>
+
+ <!-- DI -->
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ <version>${guice.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>net.jmob</groupId>
+ <artifactId>guice.conf</artifactId>
+ <version>${guice.config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.inject.extensions</groupId>
+ <artifactId>guice-multibindings</artifactId>
+ <version>${guice.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/CrudService.java b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/CrudService.java
new file mode 100644
index 000000000..f5b6614d1
--- /dev/null
+++ b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/CrudService.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed 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 ${package};
+
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Example of an aggregated access interface.
+ * <p/>
+ * Shared by all the customizers hiding the ugly details of our data management.
+ *
+ * TODO update javadoc
+ */
+public interface CrudService<T extends DataObject> {
+
+ /**
+ * Perform write of provided data.
+ */
+ void writeData(@Nonnull final InstanceIdentifier<T> identifier, @Nonnull final T data)
+ throws WriteFailedException;
+
+
+ /**
+ * Perform delete of existing data.
+ */
+ void deleteData(@Nonnull final InstanceIdentifier<T> identifier, @Nonnull final T data)
+ throws WriteFailedException;
+
+ /**
+ * Perform update of existing data.
+ */
+ void updateData(@Nonnull final InstanceIdentifier<T> identifier, @Nonnull final T dataOld,
+ @Nonnull final T dataNew)
+ throws WriteFailedException;
+
+ /**
+ * Read data identified by provided identifier.
+ */
+ T readSpecific(@Nonnull final InstanceIdentifier<T> identifier) throws ReadFailedException;
+
+ /**
+ * Read all nodes of type {@link T}.
+ */
+ List<T> readAll() throws ReadFailedException;
+}
diff --git a/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/ElementCrudService.java b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/ElementCrudService.java
new file mode 100644
index 000000000..33f9ad9dc
--- /dev/null
+++ b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/ElementCrudService.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed 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.
+ */
+
+#macro( ccase $str )
+#foreach( $word in $rootArtifactId.split('-') )$word.substring(0,1).toUpperCase()$word.substring(1)#end
+#end
+#set( $classNamePrefix = "#ccase( $rootArtifactId )" )
+#macro( dotted $str )
+#foreach( $word in $rootArtifactId.split('-') )$word.#end
+#end
+#set( $packageName = "#dotted( $rootArtifactId )" )
+package ${package};
+
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${classNamePrefix}State;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${packageName}params.Element;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${packageName}params.ElementBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${packageName}params.ElementKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Simple example of class handling Crud operations for plugin.
+ * <p/>
+ * No real handling, serves just as an illustration.
+ *
+ * TODO update javadoc
+ */
+final class ElementCrudService implements CrudService<Element> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ElementCrudService.class);
+
+ @Override
+ public void writeData(@Nonnull final InstanceIdentifier<Element> identifier, @Nonnull final Element data)
+ throws WriteFailedException {
+ if (data != null) {
+
+ // identifier.firstKeyOf(SomeClassUpperInHierarchy.class) can be used to identify
+ // relationships such as to which parent these data are related to
+
+ // Performs any logic needed for persisting such data
+ LOG.info("Writing path[{}] / data [{}]", identifier, data);
+ } else {
+ throw new WriteFailedException.CreateFailedException(identifier, data,
+ new NullPointerException("Provided data are null"));
+ }
+ }
+
+ @Override
+ public void deleteData(@Nonnull final InstanceIdentifier<Element> identifier, @Nonnull final Element data)
+ throws WriteFailedException {
+ if (data != null) {
+
+ // identifier.firstKeyOf(SomeClassUpperInHierarchy.class) can be used to identify
+ // relationships such as to which parent these data are related to
+
+ // Performs any logic needed for persisting such data
+ LOG.info("Removing path[{}] / data [{}]", identifier, data);
+ } else {
+ throw new WriteFailedException.DeleteFailedException(identifier,
+ new NullPointerException("Provided data are null"));
+ }
+ }
+
+ @Override
+ public void updateData(@Nonnull final InstanceIdentifier<Element> identifier, @Nonnull final Element dataOld,
+ @Nonnull final Element dataNew) throws WriteFailedException {
+ if (dataOld != null && dataNew != null) {
+
+ // identifier.firstKeyOf(SomeClassUpperInHierarchy.class) can be used to identify
+ // relationships such as to which parent these data are related to
+
+ // Performs any logic needed for persisting such data
+ LOG.info("Update path[{}] from [{}] to [{}]", identifier, dataOld, dataNew);
+ } else {
+ throw new WriteFailedException.DeleteFailedException(identifier,
+ new NullPointerException("Provided data are null"));
+ }
+ }
+
+ @Override
+ public Element readSpecific(@Nonnull final InstanceIdentifier<Element> identifier) throws ReadFailedException {
+
+ // read key specified in path identifier
+ final ElementKey key = identifier.firstKeyOf(Element.class);
+
+ // load data by this key
+ // *Key class will always contain key of entity, in this case long value
+
+ return new ElementBuilder()
+ .setId(key.getId())
+ .setKey(key)
+ .setDescription("This is a example of loaded data")
+ .build();
+ }
+
+ @Override
+ public List<Element> readAll() throws ReadFailedException {
+ // read all data under parent node,in this case {@link ModuleState}
+ return Collections.singletonList(
+ readSpecific(InstanceIdentifier.create(${classNamePrefix}State.class).child(Element.class, new ElementKey(10L))));
+ }
+}
diff --git a/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/Module.java b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/Module.java
new file mode 100644
index 000000000..41373cedc
--- /dev/null
+++ b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/Module.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed 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.
+ */
+
+#macro( dotted $str )
+#foreach( $word in $rootArtifactId.split('-') )$word.#end
+#end
+#set( $packageName = "#dotted( $rootArtifactId )" )
+#macro( dotted $str )
+#foreach( $word in $rootArtifactId.split('-') )$word.#end
+#end
+#set( $packageName = "#dotted( $rootArtifactId )" )
+package ${package};
+
+import static ${package}.ModuleConfiguration.ELEMENT_SERVICE_NAME;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.TypeLiteral;
+import com.google.inject.multibindings.Multibinder;
+import com.google.inject.name.Names;
+import ${package}.init.ConfigDataInitializer;
+import ${package}.read.ModuleStateReaderFactory;
+import ${package}.write.ModuleWriterFactory;
+import io.fd.honeycomb.data.init.DataTreeInitializer;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import net.jmob.guice.conf.core.ConfigurationModule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${packageName}params.Element;
+
+/**
+ * Module class instantiating ${rootArtifactId} plugin components.
+ */
+public final class Module extends AbstractModule {
+
+ // TODO This initiates all the plugin components, but it still needs to be registered/wired into an integration
+ // module producing runnable distributions. There is one such distribution in honeycomb project:
+ // vpp-integration/minimal-distribution
+ // In order to integrate this plugin with the distribution:
+ // 1. Add a dependency on this maven module to the the distribution's pom.xml
+ // 2. Add an instance of this module into the distribution in its Main class
+
+ @Override
+ protected void configure() {
+ // requests injection of properties
+ install(ConfigurationModule.create());
+ requestInjection(ModuleConfiguration.class);
+
+ // creates binding for interface implementation by name
+ bind(new TypeLiteral<CrudService<Element>>(){})
+ .annotatedWith(Names.named(ELEMENT_SERVICE_NAME))
+ .to(ElementCrudService.class);
+
+ // creates reader factory binding
+ // can hold multiple binding for separate yang modules
+ final Multibinder<ReaderFactory> readerFactoryBinder = Multibinder.newSetBinder(binder(), ReaderFactory.class);
+ readerFactoryBinder.addBinding().to(ModuleStateReaderFactory.class);
+
+ // create writer factory binding
+ // can hold multiple binding for separate yang modules
+ final Multibinder<WriterFactory> writerFactoryBinder = Multibinder.newSetBinder(binder(), WriterFactory.class);
+ writerFactoryBinder.addBinding().to(ModuleWriterFactory.class);
+
+ // create initializer binding
+ // can hold multiple binding for separate yang modules
+ final Multibinder<DataTreeInitializer> initializerBinder =
+ Multibinder.newSetBinder(binder(), DataTreeInitializer.class);
+ initializerBinder.addBinding().to(ConfigDataInitializer.class);
+ }
+}
diff --git a/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/ModuleConfiguration.java b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/ModuleConfiguration.java
new file mode 100644
index 000000000..52a317b3b
--- /dev/null
+++ b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/ModuleConfiguration.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed 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 ${package};
+
+import net.jmob.guice.conf.core.BindConfig;
+import net.jmob.guice.conf.core.InjectConfig;
+import net.jmob.guice.conf.core.Syntax;
+
+/**
+ * Class containing static configuration for ${rootArtifactId} module,<br>
+ * either loaded from property file ${rootArtifactId}.json from classpath.
+ * <p/>
+ * Further documentation for the configuration injection can be found at:
+ * https://github.com/yyvess/gconf
+ */
+@BindConfig(value = "${rootArtifactId}", syntax = Syntax.JSON)
+public final class ModuleConfiguration {
+
+ // TODO change the sample property to real plugin configuration
+ // If there is no such configuration, remove this, ${rootArtifactId}.json resource and its wiring from Module class
+
+ /**
+ * Sample property that's injected from external json configuration file.
+ */
+ @InjectConfig("sample-prop")
+ public String sampleProp;
+
+ /**
+ * Constant name used to identify ${rootArtifactId} plugin specific components during dependency injection.
+ */
+ public static final String ELEMENT_SERVICE_NAME = "element-service";
+}
diff --git a/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/init/ConfigDataInitializer.java b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/init/ConfigDataInitializer.java
new file mode 100644
index 000000000..2393a125a
--- /dev/null
+++ b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/init/ConfigDataInitializer.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed 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.
+ */
+
+#macro( ccase $str )
+#foreach( $word in $rootArtifactId.split('-') )$word.substring(0,1).toUpperCase()$word.substring(1)#end
+#end
+#set( $classNamePrefix = "#ccase( $rootArtifactId )" )
+#macro( dotted $str )
+#foreach( $word in $rootArtifactId.split('-') )$word.#end
+#end
+#set( $packageName = "#dotted( $rootArtifactId )" )
+package ${package}.init;
+
+import io.fd.honeycomb.data.init.AbstractDataTreeConverter;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${classNamePrefix};
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${classNamePrefix}Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${classNamePrefix}State;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Initialize configuration data based on operational data.
+ * <p/>
+ * Very useful when a plugin is initiated but the underlying layer already contains some operation state.
+ * Deriving the configuration from existing operational state enables reconciliation in case when Honeycomb's persistence
+ * is not available to do the work for us.
+ */
+public final class ConfigDataInitializer extends AbstractDataTreeConverter<${classNamePrefix}State, ${classNamePrefix}> {
+
+ @Inject
+ public ConfigDataInitializer(@Named("honeycomb-initializer") @Nonnull final DataBroker bindingDataBroker) {
+ super(bindingDataBroker, InstanceIdentifier.create(${classNamePrefix}State.class), InstanceIdentifier.create(${classNamePrefix}.class));
+ }
+
+ @Override
+ public ${classNamePrefix} convert(final ${classNamePrefix}State operationalData) {
+ // Transfer all the operational data into configuration
+ return new ${classNamePrefix}Builder()
+ .setElement(operationalData.getElement())
+ .build();
+ }
+}
diff --git a/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/read/ElementStateCustomizer.java b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/read/ElementStateCustomizer.java
new file mode 100644
index 000000000..8f1c3a79d
--- /dev/null
+++ b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/read/ElementStateCustomizer.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed 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.
+ */
+
+#macro( ccase $str )
+#foreach( $word in $rootArtifactId.split('-') )$word.substring(0,1).toUpperCase()$word.substring(1)#end
+#end
+#set( $classNamePrefix = "#ccase( $rootArtifactId )" )
+#macro( dotted $str )
+#foreach( $word in $rootArtifactId.split('-') )$word.#end
+#end
+#set( $packageName = "#dotted( $rootArtifactId )" )
+package ${package}.read;
+
+import ${package}.CrudService;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${classNamePrefix}StateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${packageName}params.Element;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${packageName}params.ElementBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${packageName}params.ElementKey;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Reader for {@link Element} list node from our YANG model.
+ */
+public final class ElementStateCustomizer implements
+ ListReaderCustomizer<Element, ElementKey, ElementBuilder> {
+
+ private final CrudService<Element> crudService;
+
+ public ElementStateCustomizer(final CrudService<Element> crudService) {
+ this.crudService = crudService;
+ }
+
+ @Nonnull
+ @Override
+ public List<ElementKey> getAllIds(@Nonnull final InstanceIdentifier<Element> id, @Nonnull final ReadContext context)
+ throws ReadFailedException {
+ // perform read operation and extract keys from data
+ return crudService.readAll()
+ .stream()
+ .map(a -> new ElementKey(a.getId()))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final List<Element> readData) {
+ // merge children data to parent builder
+ // used by infrastructure to merge data loaded in separated customizers
+ ((${classNamePrefix}StateBuilder) builder).setElement(readData);
+ }
+
+ @Nonnull
+ @Override
+ public ElementBuilder getBuilder(@Nonnull final InstanceIdentifier<Element> id) {
+ // return new builder for this data node
+ return new ElementBuilder();
+ }
+
+ @Override
+ public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Element> id,
+ @Nonnull final ElementBuilder builder,
+ @Nonnull final ReadContext ctx) throws ReadFailedException {
+ // this stage is used after reading all ids by getAllIds,to read specific details about data
+
+ // perform read of details of data specified by key of Element in id
+ final Element data = crudService.readSpecific(id);
+
+ // and sets it to builder
+ builder.setId(data.getId());
+ builder.setKey(data.getKey());
+ builder.setDescription(data.getDescription());
+ }
+}
diff --git a/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/read/ModuleStateReaderFactory.java b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/read/ModuleStateReaderFactory.java
new file mode 100644
index 000000000..9df03aed2
--- /dev/null
+++ b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/read/ModuleStateReaderFactory.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed 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.
+ */
+
+#macro( ccase $str )
+#foreach( $word in $rootArtifactId.split('-') )$word.substring(0,1).toUpperCase()$word.substring(1)#end
+#end
+#set( $classNamePrefix = "#ccase( $rootArtifactId )" )
+#macro( dotted $str )
+#foreach( $word in $rootArtifactId.split('-') )$word.#end
+#end
+#set( $packageName = "#dotted( $rootArtifactId )" )
+package ${package}.read;
+
+import static ${package}.ModuleConfiguration.ELEMENT_SERVICE_NAME;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import ${package}.CrudService;
+import io.fd.honeycomb.translate.impl.read.GenericListReader;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${classNamePrefix}State;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${classNamePrefix}StateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${packageName}params.Element;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Factory producing readers for ${rootArtifactId} plugin's data.
+ */
+public final class ModuleStateReaderFactory implements ReaderFactory {
+
+ public static final InstanceIdentifier<${classNamePrefix}State> ROOT_STATE_CONTAINER_ID =
+ InstanceIdentifier.create(${classNamePrefix}State.class);
+
+ /**
+ * Injected crud service to be passed to customizers instantiated in this factory.
+ */
+ @Inject
+ @Named(ELEMENT_SERVICE_NAME)
+ private CrudService<Element> crudService;
+
+ @Override
+ public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) {
+
+ // register reader that only delegate read's to its children
+ registry.addStructuralReader(ROOT_STATE_CONTAINER_ID, ${classNamePrefix}StateBuilder.class);
+
+ // just adds reader to the structure
+ // use addAfter/addBefore if you want to add specific order to readers on the same level of tree
+ // use subtreeAdd if you want to handle multiple nodes in single customizer/subtreeAddAfter/subtreeAddBefore if you also want to add order
+ // be aware that instance identifier passes to subtreeAdd/subtreeAddAfter/subtreeAddBefore should define subtree,
+ // therefore it should be relative from handled node down - InstanceIdentifier.create(HandledNode), not parent.child(HandledNode.class)
+ registry.add(
+ new GenericListReader<>(ROOT_STATE_CONTAINER_ID.child(Element.class),
+ new ElementStateCustomizer(crudService)));
+ }
+}
diff --git a/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/write/ElementCustomizer.java b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/write/ElementCustomizer.java
new file mode 100644
index 000000000..62b0c4271
--- /dev/null
+++ b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/write/ElementCustomizer.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed 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.
+ */
+
+#macro( dotted $str )
+#foreach( $word in $rootArtifactId.split('-') )$word.#end
+#end
+#set( $packageName = "#dotted( $rootArtifactId )" )
+package ${package}.write;
+
+import ${package}.CrudService;
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${packageName}params.Element;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${packageName}params.ElementKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Writer for {@link Element} list node from our YANG model.
+ */
+public final class ElementCustomizer implements ListWriterCustomizer<Element, ElementKey> {
+
+ private final CrudService<Element> crudService;
+
+ public ElementCustomizer(@Nonnull final CrudService<Element> crudService) {
+ this.crudService = crudService;
+ }
+
+ @Override
+ public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Element> id, @Nonnull final Element dataAfter,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ //perform write of data,or throw exception
+ //invoked by PUT operation,if provided data doesn't exist in Config data
+ crudService.writeData(id, dataAfter);
+ }
+
+ @Override
+ public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Element> id,
+ @Nonnull final Element dataBefore,
+ @Nonnull final Element dataAfter, @Nonnull final WriteContext writeContext)
+ throws WriteFailedException {
+ //perform update of data,or throw exception
+ //invoked by PUT operation,if provided data does exist in Config data
+ crudService.updateData(id, dataBefore, dataAfter);
+ }
+
+ @Override
+ public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Element> id,
+ @Nonnull final Element dataBefore,
+ @Nonnull final WriteContext writeContext) throws WriteFailedException {
+ //perform delete of data,or throw exception
+ //invoked by DELETE operation
+ crudService.deleteData(id, dataBefore);
+ }
+}
diff --git a/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/write/ModuleWriterFactory.java b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/write/ModuleWriterFactory.java
new file mode 100644
index 000000000..2f1d0a90e
--- /dev/null
+++ b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/write/ModuleWriterFactory.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed 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.
+ */
+
+#macro( ccase $str )
+#foreach( $word in $rootArtifactId.split('-') )$word.substring(0,1).toUpperCase()$word.substring(1)#end
+#end
+#set( $classNamePrefix = "#ccase( $rootArtifactId )" )
+#macro( dotted $str )
+#foreach( $word in $rootArtifactId.split('-') )$word.#end
+#end
+#set( $packageName = "#dotted( $rootArtifactId )" )
+package ${package}.write;
+
+import static ${package}.ModuleConfiguration.ELEMENT_SERVICE_NAME;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import ${package}.CrudService;
+import io.fd.honeycomb.translate.impl.write.GenericWriter;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${classNamePrefix};
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.${packageName}rev160918.${packageName}params.Element;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Factory producing writers for ${rootArtifactId} plugin's data.
+ */
+public final class ModuleWriterFactory implements WriterFactory {
+
+ private static final InstanceIdentifier<${classNamePrefix}> ROOT_CONTAINER_ID = InstanceIdentifier.create(${classNamePrefix}.class);
+
+ /**
+ * Injected crud service to be passed to customizers instantiated in this factory.
+ */
+ @Inject
+ @Named(ELEMENT_SERVICE_NAME)
+ private CrudService<Element> crudService;
+
+ @Override
+ public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) {
+
+ //adds writer for child node
+ //no need to add writers for empty nodes
+ registry.add(new GenericWriter<>(ROOT_CONTAINER_ID.child(Element.class), new ElementCustomizer(crudService)));
+ }
+}
diff --git a/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/resources/honeycomb-minimal-resources/config/__rootArtifactId__.json b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/resources/honeycomb-minimal-resources/config/__rootArtifactId__.json
new file mode 100644
index 000000000..7ee89c674
--- /dev/null
+++ b/tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/resources/honeycomb-minimal-resources/config/__rootArtifactId__.json
@@ -0,0 +1,3 @@
+{
+ "sample-prop": "sample-value"
+} \ No newline at end of file
diff --git a/tools/archetype/src/main/resources/archetype-resources/pom.xml b/tools/archetype/src/main/resources/archetype-resources/pom.xml
new file mode 100644
index 000000000..5445d6e7f
--- /dev/null
+++ b/tools/archetype/src/main/resources/archetype-resources/pom.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2015 Cisco and/or its affiliates.
+ Licensed 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.
+--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.odlparent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.6.2-Beryllium-SR2</version>
+ </parent>
+
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}-aggregator</artifactId>
+ <version>${version}</version>
+ <name>${rootArtifactId}-aggregator</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+
+ <modules>
+ <module>${rootArtifactId}-api</module>
+ <module>${rootArtifactId}-impl</module>
+ </modules>
+
+ <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tools/pom.xml b/tools/pom.xml
new file mode 100644
index 000000000..972f5e75a
--- /dev/null
+++ b/tools/pom.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>honeycomb-aggregator</artifactId>
+ <groupId>io.fd.honeycomb</groupId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>io.fd.honeycomb.tools</groupId>
+ <artifactId>honeycomb-tools</artifactId>
+ <packaging>pom</packaging>
+ <version>1.0.0-SNAPSHOT</version>
+ <modules>
+ <module>archetype</module>
+ </modules>
+
+</project> \ No newline at end of file