From c961bd752be1fb2eee707cb5c7c44d1bda0894d2 Mon Sep 17 00:00:00 2001 From: Jan Srnicek Date: Thu, 25 Aug 2016 16:27:23 +0200 Subject: HONEYCOMB-140 - Honeycomb Plugin Archetype Change-Id: I6e04fb769e82fb539dbd6a79bb465974796137a4 Signed-off-by: Jan Srnicek --- .../src/main/java/CrudService.java | 64 +++++++++++ .../src/main/java/ElementCrudService.java | 121 +++++++++++++++++++++ .../src/main/java/Module.java | 81 ++++++++++++++ .../src/main/java/ModuleConfiguration.java | 46 ++++++++ .../src/main/java/init/ConfigDataInitializer.java | 58 ++++++++++ .../src/main/java/read/ElementStateCustomizer.java | 93 ++++++++++++++++ .../main/java/read/ModuleStateReaderFactory.java | 71 ++++++++++++ .../src/main/java/write/ElementCustomizer.java | 69 ++++++++++++ .../src/main/java/write/ModuleWriterFactory.java | 61 +++++++++++ 9 files changed, 664 insertions(+) create mode 100644 tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/CrudService.java create mode 100644 tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/ElementCrudService.java create mode 100644 tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/Module.java create mode 100644 tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/ModuleConfiguration.java create mode 100644 tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/init/ConfigDataInitializer.java create mode 100644 tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/read/ElementStateCustomizer.java create mode 100644 tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/read/ModuleStateReaderFactory.java create mode 100644 tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/write/ElementCustomizer.java create mode 100644 tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java/write/ModuleWriterFactory.java (limited to 'tools/archetype/src/main/resources/archetype-resources/__rootArtifactId__-impl/src/main/java') 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. + *

+ * Shared by all the customizers hiding the ugly details of our data management. + * + * TODO update javadoc + */ +public interface CrudService { + + /** + * Perform write of provided data. + */ + void writeData(@Nonnull final InstanceIdentifier identifier, @Nonnull final T data) + throws WriteFailedException; + + + /** + * Perform delete of existing data. + */ + void deleteData(@Nonnull final InstanceIdentifier identifier, @Nonnull final T data) + throws WriteFailedException; + + /** + * Perform update of existing data. + */ + void updateData(@Nonnull final InstanceIdentifier identifier, @Nonnull final T dataOld, + @Nonnull final T dataNew) + throws WriteFailedException; + + /** + * Read data identified by provided identifier. + */ + T readSpecific(@Nonnull final InstanceIdentifier identifier) throws ReadFailedException; + + /** + * Read all nodes of type {@link T}. + */ + List 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. + *

+ * No real handling, serves just as an illustration. + * + * TODO update javadoc + */ +final class ElementCrudService implements CrudService { + + private static final Logger LOG = LoggerFactory.getLogger(ElementCrudService.class); + + @Override + public void writeData(@Nonnull final InstanceIdentifier 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 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 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 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 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>(){}) + .annotatedWith(Names.named(ELEMENT_SERVICE_NAME)) + .to(ElementCrudService.class); + + // creates reader factory binding + // can hold multiple binding for separate yang modules + final Multibinder 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 writerFactoryBinder = Multibinder.newSetBinder(binder(), WriterFactory.class); + writerFactoryBinder.addBinding().to(ModuleWriterFactory.class); + + // create initializer binding + // can hold multiple binding for separate yang modules + final Multibinder 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,
+ * either loaded from property file ${rootArtifactId}.json from classpath. + *

+ * 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. + *

+ * 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 { + + private final CrudService crudService; + + public ElementStateCustomizer(final CrudService crudService) { + this.crudService = crudService; + } + + @Nonnull + @Override + public List getAllIds(@Nonnull final InstanceIdentifier 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 builder, @Nonnull final List 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 id) { + // return new builder for this data node + return new ElementBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier 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 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 { + + private final CrudService crudService; + + public ElementCustomizer(@Nonnull final CrudService crudService) { + this.crudService = crudService; + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier 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 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 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 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))); + } +} -- cgit 1.2.3-korg