From: Tony Tkacik Date: Mon, 26 May 2014 19:48:32 +0000 (+0000) Subject: Merge "Bug 1036 - Allow using container in case stmt to preserve uniqueness." X-Git-Tag: autorelease-tag-v20140601202136_82eb3f9~23 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=aefe82b158bc1694fe633053d04f2364bcbe67d9;hp=3b628b4074fb9bff60af58009c428eb9fbb10551 Merge "Bug 1036 - Allow using container in case stmt to preserve uniqueness." --- diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml index c1dc6ee789..7c47f3644d 100644 --- a/opendaylight/commons/opendaylight/pom.xml +++ b/opendaylight/commons/opendaylight/pom.xml @@ -78,6 +78,7 @@ 0.4.2-SNAPSHOT 0.4.2-SNAPSHOT 2010.09.24.4-SNAPSHOT + 2013.10.19.1-SNAPSHOT 2013.10.21.2-SNAPSHOT 2010.09.24.4-SNAPSHOT 2.3.2 @@ -1476,6 +1477,11 @@ ietf-inet-types ${ietf-inet-types.version} + + org.opendaylight.yangtools.model + ietf-restconf + ${ietf-restconf.version} + org.opendaylight.yangtools.model ietf-topology @@ -1491,6 +1497,11 @@ ietf-yang-types ${ietf-yang-types.version} + + org.opendaylight.yangtools.model + ietf-yang-types-20130715 + 2013.07.15.1-SNAPSHOT + org.opendaylight.yangtools.model opendaylight-l2-types diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/CodecRegistryProvider.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/CodecRegistryProvider.java index 9d0fbd85dc..ec46219aaf 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/CodecRegistryProvider.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/CodecRegistryProvider.java @@ -8,6 +8,7 @@ package org.opendaylight.controller.config.manager.impl.osgi.mapping; import javassist.ClassPool; + import org.opendaylight.controller.config.manager.impl.util.OsgiRegistrationUtil; import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy; import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl; @@ -27,10 +28,8 @@ public class CodecRegistryProvider implements AutoCloseable { private final RuntimeGeneratedMappingServiceImpl service; private final AutoCloseable registration; - public CodecRegistryProvider(ClassLoadingStrategy classLoadingStrategy, BundleContext context) { - service = new RuntimeGeneratedMappingServiceImpl(classLoadingStrategy); - service.setPool(CLASS_POOL); - service.init(); + public CodecRegistryProvider(final ClassLoadingStrategy classLoadingStrategy, final BundleContext context) { + service = new RuntimeGeneratedMappingServiceImpl(CLASS_POOL, classLoadingStrategy); registration = OsgiRegistrationUtil.registerService(context, service, SchemaServiceListener.class, BindingIndependentMappingService.class); } diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index 48e661f196..52aa6d276b 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -1187,6 +1187,10 @@ org.opendaylight.yangtools.model ietf-inet-types + + org.opendaylight.yangtools.model + ietf-restconf + org.opendaylight.yangtools.model ietf-topology @@ -1195,6 +1199,10 @@ org.opendaylight.yangtools.model ietf-yang-types + + org.opendaylight.yangtools.model + ietf-yang-types-20130715 + org.opendaylight.yangtools.model opendaylight-l2-types diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java index 9276238e01..2c95252ac7 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java @@ -7,6 +7,7 @@ */ package org.opendaylight.controller.sal.compatibility; +import java.math.BigInteger; import java.util.Date; import java.util.HashSet; import java.util.List; @@ -334,8 +335,8 @@ public final class NodeMapping { public static MacAddress toADMacAddress(final NodeId id) { final String nodeId = id.getValue().replaceAll("openflow:", ""); - long lNodeId = Long.parseLong(nodeId); - lNodeId = Long.valueOf(lNodeId).longValue(); + BigInteger nodeIdRaw = new BigInteger(nodeId); + long lNodeId = nodeIdRaw.longValue(); byte[] bytesFromDpid = ToSalConversionsUtils.bytesFromDpid(lNodeId); return new MacAddress(bytesFromDpid); } diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/NodeMappingTest.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/NodeMappingTest.java new file mode 100644 index 0000000000..b9a2f5bff0 --- /dev/null +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/NodeMappingTest.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.sal.compatibility.test; + +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.controller.sal.compatibility.NodeMapping; +import org.opendaylight.controller.sal.core.MacAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; + +/** + * test of {@link NodeMapping} utility class + */ +public class NodeMappingTest { + + /** + * Test method for + * {@link org.opendaylight.controller.sal.compatibility.NodeMapping#toADMacAddress(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId)} + * . + */ + @Test + public void testToADMacAddress() { + NodeId[] nodeIds = new NodeId[] { + // 0x0000|0000 0000002a (answer to the ultimate question of life, universe and everything) + new NodeId("42"), + // 0x7fff|ffff ffffffff (max long -> 2**63 - 1) + new NodeId("9223372036854775807"), + // 0x7fff|7fff ffffffff + new NodeId("9223231299366420479"), + // 0x8fff|7fff ffffffff (more than biggest positive long) + new NodeId("10376152803973267455"), + // 0xca13|764a e9ace65a (BUG-770) + new NodeId("14561112084339025498") + }; + + byte[][] expectedMacs = new byte[][] { + {0, 0, 0, 0, 0, 0x2a}, + {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}, + {(byte) 0x7f, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}, + {(byte) 0x7f, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}, + {(byte) 0x76, (byte) 0x4a, (byte) 0xe9, (byte) 0xac, (byte) 0xe6, (byte) 0x5a} + }; + + Assert.assertEquals(expectedMacs.length, nodeIds.length); + + for (int i = 0; i < expectedMacs.length; i++) { + NodeId nodeId = nodeIds[i]; + MacAddress mac = NodeMapping.toADMacAddress(nodeId); + Assert.assertArrayEquals(expectedMacs[i], mac.getMacAddress()); + } + } + +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java index 750defc0e9..0f0ce0dc9d 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java @@ -26,6 +26,8 @@ import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException; import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.base.Optional; import com.google.common.base.Preconditions; @@ -36,6 +38,8 @@ import com.google.common.base.Preconditions; public final class RuntimeMappingModule extends org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractRuntimeMappingModule { + private static final Logger LOG = LoggerFactory.getLogger(RuntimeMappingModule.class); + private BundleContext bundleContext; public RuntimeMappingModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, @@ -163,10 +167,17 @@ public final class RuntimeMappingModule extends } @Override - public void close() throws Exception { + public void close() { if(delegate != null) { delegate = null; - bundleContext.ungetService(reference); + + try { + bundleContext.ungetService(reference); + } catch (IllegalStateException e) { + // Indicates the BundleContext is no longer valid which can happen normally on shutdown. + LOG.debug( "Error unregistering service", e ); + } + bundleContext= null; reference = null; } diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizer.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizer.java index 33a9869a6b..f30c8ddcaa 100644 --- a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizer.java +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizer.java @@ -92,11 +92,11 @@ public class DataNormalizer { } // Write Augmentation data resolution - if (legacyData.getChildren().size() == 1) { + if (legacyData.getValue().size() == 1) { final DataNormalizationOperation potentialOp; try { - final QName childType = legacyData.getChildren().get(0).getNodeType(); + final QName childType = legacyData.getValue().get(0).getNodeType(); potentialOp = currentOp.getChild(childType); } catch (DataNormalizationException e) { throw new IllegalArgumentException(String.format("Failed to get child operation for %s", legacyData), e); diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/SchemaServiceImplSingletonModule.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/SchemaServiceImplSingletonModule.java index ba7414d42e..fd24944018 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/SchemaServiceImplSingletonModule.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/SchemaServiceImplSingletonModule.java @@ -16,28 +16,29 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -/** -* -*/ public final class SchemaServiceImplSingletonModule extends - org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractSchemaServiceImplSingletonModule { +org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractSchemaServiceImplSingletonModule { + + private static final Logger LOG = LoggerFactory.getLogger(SchemaServiceImplSingletonModule.class); BundleContext bundleContext; - public SchemaServiceImplSingletonModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, - org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + public SchemaServiceImplSingletonModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, + final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { super(identifier, dependencyResolver); } - public SchemaServiceImplSingletonModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, - org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, - SchemaServiceImplSingletonModule oldModule, java.lang.AutoCloseable oldInstance) { + public SchemaServiceImplSingletonModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, + final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, + final SchemaServiceImplSingletonModule oldModule, final java.lang.AutoCloseable oldInstance) { super(identifier, dependencyResolver, oldModule, oldInstance); } @Override - public boolean canReuseInstance(AbstractSchemaServiceImplSingletonModule oldModule) { + public boolean canReuseInstance(final AbstractSchemaServiceImplSingletonModule oldModule) { return true; } @@ -45,7 +46,7 @@ public final class SchemaServiceImplSingletonModule extends return bundleContext; } - public void setBundleContext(BundleContext bundleContext) { + public void setBundleContext(final BundleContext bundleContext) { this.bundleContext = bundleContext; } @@ -61,8 +62,7 @@ public final class SchemaServiceImplSingletonModule extends return new GlobalSchemaServiceProxy(getBundleContext(), ref); } - GlobalBundleScanningSchemaServiceImpl newInstance = new GlobalBundleScanningSchemaServiceImpl(); - newInstance.setContext(getBundleContext()); + GlobalBundleScanningSchemaServiceImpl newInstance = new GlobalBundleScanningSchemaServiceImpl(getBundleContext()); newInstance.start(); return newInstance; } @@ -73,7 +73,7 @@ public final class SchemaServiceImplSingletonModule extends private ServiceReference reference; private SchemaService delegate; - public GlobalSchemaServiceProxy(BundleContext bundleContext, ServiceReference ref) { + public GlobalSchemaServiceProxy(final BundleContext bundleContext, final ServiceReference ref) { this.bundleContext = bundleContext; this.reference = ref; this.delegate = bundleContext.getService(reference); @@ -83,29 +83,42 @@ public final class SchemaServiceImplSingletonModule extends public void close() throws Exception { if (delegate != null) { delegate = null; - bundleContext.ungetService(reference); + + try { + bundleContext.ungetService(reference); + } catch (IllegalStateException e) { + // Indicates the service was already unregistered which can happen normally + // on shutdown. + LOG.debug( "Error unregistering service", e ); + } + reference = null; bundleContext = null; } } - public void addModule(Module arg0) { + @Override + public void addModule(final Module arg0) { delegate.addModule(arg0); } + @Override public SchemaContext getGlobalContext() { return delegate.getGlobalContext(); } + @Override public SchemaContext getSessionContext() { return delegate.getSessionContext(); } - public ListenerRegistration registerSchemaServiceListener(SchemaServiceListener arg0) { + @Override + public ListenerRegistration registerSchemaServiceListener(final SchemaServiceListener arg0) { return delegate.registerSchemaServiceListener(arg0); } - public void removeModule(Module arg0) { + @Override + public void removeModule(final Module arg0) { delegate.removeModule(arg0); } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/TranslatingDataChangeEvent.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/TranslatingDataChangeEvent.java index 827e4ca63d..3de07fc2ab 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/TranslatingDataChangeEvent.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/TranslatingDataChangeEvent.java @@ -23,7 +23,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import com.google.common.collect.Maps; public abstract class TranslatingDataChangeEvent implements - DataChangeEvent { +DataChangeEvent { private TranslatingDataChangeEvent() { } @@ -98,7 +98,6 @@ public abstract class TranslatingDataChangeEvent implements return null; } - @SuppressWarnings({ "rawtypes", "unchecked" }) private final static class OperationalChangeEvent extends TranslatingDataChangeEvent { private final AsyncDataChangeEvent> delegate; @@ -106,7 +105,7 @@ public abstract class TranslatingDataChangeEvent implements private Map updatedCache; public OperationalChangeEvent(final AsyncDataChangeEvent> change, - final DataNormalizer normalizer) { + final DataNormalizer normalizer) { this.delegate = change; this.normalizer = normalizer; } @@ -179,7 +178,7 @@ public abstract class TranslatingDataChangeEvent implements private Map updatedCache; public ConfigurationChangeEvent(final AsyncDataChangeEvent> change, - final DataNormalizer normalizer) { + final DataNormalizer normalizer) { this.delegate = change; this.normalizer = normalizer; } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AlwaysFailOperation.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AlwaysFailOperation.java index 4e3aa49113..15479be462 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AlwaysFailOperation.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/AlwaysFailOperation.java @@ -1,21 +1,27 @@ package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import com.google.common.base.Optional; -import com.google.common.primitives.UnsignedLong; +/** + * An implementation of apply operation which fails to do anything, + * consistently. An instance of this class is used by the data tree + * if it does not have a SchemaContext attached and hence cannot + * perform anything meaningful. + */ final class AlwaysFailOperation implements ModificationApplyOperation { - @Override - public Optional apply(final NodeModification modification, - final Optional storeMeta, final UnsignedLong subtreeVersion) { + public Optional apply(final ModifiedNode modification, + final Optional storeMeta, final Version subtreeVersion) { throw new IllegalStateException("Schema Context is not available."); } @Override - public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional storeMetadata) { + public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional storeMetadata) { throw new IllegalStateException("Schema Context is not available."); } @@ -25,7 +31,7 @@ final class AlwaysFailOperation implements ModificationApplyOperation { } @Override - public void verifyStructure(final NodeModification modification) throws IllegalArgumentException { + public void verifyStructure(final ModifiedNode modification) { throw new IllegalStateException("Schema Context is not available."); } } \ No newline at end of file diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/DataNodeContainerModificationStrategy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/DataNodeContainerModificationStrategy.java new file mode 100644 index 0000000000..dc891482ab --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/DataNodeContainerModificationStrategy.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ExecutionException; + +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.AugmentationTarget; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; + +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +/** + * Base strategy for applying changes to a ContainerNode, irrespective of its + * actual type. + * + * @param Type of the container node + */ +abstract class DataNodeContainerModificationStrategy extends NormalizedNodeContainerModificationStrategy { + + private final T schema; + private final LoadingCache childCache = CacheBuilder.newBuilder() + .build(CacheLoader.from(new Function() { + + @Override + public ModificationApplyOperation apply(final PathArgument identifier) { + if (identifier instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) { + return from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) identifier); + } + + DataSchemaNode child = schema.getDataChildByName(identifier.getNodeType()); + if (child == null) { + return null; + } + return from(child); + } + })); + + protected DataNodeContainerModificationStrategy(final T schema, + final Class> nodeClass) { + super(nodeClass); + this.schema = schema; + } + + protected T getSchema() { + return schema; + } + + @Override + public Optional getChild(final PathArgument identifier) { + try { + return Optional. fromNullable(childCache.get(identifier)); + } catch (ExecutionException e) { + return Optional.absent(); + } + } + + @Override + @SuppressWarnings("rawtypes") + protected abstract DataContainerNodeBuilder createBuilder(NormalizedNode original); + + @Override + public String toString() { + return getClass().getSimpleName() + " [" + schema + "]"; + } + + public static class AugmentationModificationStrategy extends DataNodeContainerModificationStrategy { + + protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) { + super(createAugmentProxy(schema,resolved), AugmentationNode.class); + } + + @Override + @SuppressWarnings("rawtypes") + protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof AugmentationNode); + return ImmutableAugmentationNodeBuilder.create((AugmentationNode) original); + } + + + private static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) { + Set realChildSchemas = new HashSet<>(); + for(DataSchemaNode augChild : schema.getChildNodes()) { + realChildSchemas.add(resolved.getDataChildByName(augChild.getQName())); + } + return new AugmentationSchemaProxy(schema, realChildSchemas); + } + } + + public static class ContainerModificationStrategy extends DataNodeContainerModificationStrategy { + + public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) { + super(schemaNode, ContainerNode.class); + } + + @Override + @SuppressWarnings("rawtypes") + protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof ContainerNode); + return ImmutableContainerNodeBuilder.create((ContainerNode) original); + } + } + + public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy { + + protected ListEntryModificationStrategy(final ListSchemaNode schema) { + super(schema, MapEntryNode.class); + } + + @Override + @SuppressWarnings("rawtypes") + protected final DataContainerNodeBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof MapEntryNode); + return ImmutableMapEntryNodeBuilder.create((MapEntryNode) original); + } + } + + public static class UnkeyedListItemModificationStrategy extends DataNodeContainerModificationStrategy { + + public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) { + super(schemaNode, UnkeyedListEntryNode.class); + } + + @Override + @SuppressWarnings("rawtypes") + protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof UnkeyedListEntryNode); + return ImmutableUnkeyedListEntryNodeBuilder.create((UnkeyedListEntryNode) original); + } + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTree.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTree.java index f04e379dd9..d3495b542a 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTree.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTree.java @@ -16,6 +16,7 @@ import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate; import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification; import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType; import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.slf4j.Logger; @@ -34,9 +35,9 @@ final class InMemoryDataTree implements DataTree { private final ReadWriteLock rwLock = new ReentrantReadWriteLock(true); private ModificationApplyOperation applyOper = new AlwaysFailOperation(); private SchemaContext currentSchemaContext; - private StoreMetadataNode rootNode; + private TreeNode rootNode; - public InMemoryDataTree(StoreMetadataNode rootNode, final SchemaContext schemaContext) { + public InMemoryDataTree(final TreeNode rootNode, final SchemaContext schemaContext) { this.rootNode = Preconditions.checkNotNull(rootNode); if (schemaContext != null) { @@ -80,28 +81,28 @@ final class InMemoryDataTree implements DataTree { } @Override - public void validate(DataTreeModification modification) throws DataPreconditionFailedException { + public void validate(final DataTreeModification modification) throws DataPreconditionFailedException { Preconditions.checkArgument(modification instanceof InMemoryDataTreeModification, "Invalid modification class %s", modification.getClass()); final InMemoryDataTreeModification m = (InMemoryDataTreeModification)modification; - m.getStrategy().checkApplicable(PUBLIC_ROOT_PATH, m.getRootModification(), Optional.of(rootNode)); + m.getStrategy().checkApplicable(PUBLIC_ROOT_PATH, m.getRootModification(), Optional.of(rootNode)); } @Override - public synchronized DataTreeCandidate prepare(DataTreeModification modification) { + public synchronized DataTreeCandidate prepare(final DataTreeModification modification) { Preconditions.checkArgument(modification instanceof InMemoryDataTreeModification, "Invalid modification class %s", modification.getClass()); final InMemoryDataTreeModification m = (InMemoryDataTreeModification)modification; - final NodeModification root = m.getRootModification(); + final ModifiedNode root = m.getRootModification(); - if (root.getModificationType() == ModificationType.UNMODIFIED) { + if (root.getType() == ModificationType.UNMODIFIED) { return new NoopDataTreeCandidate(PUBLIC_ROOT_PATH, root); } rwLock.writeLock().lock(); try { - // FIXME: rootNode needs to be a read-write snapshot here... - final Optional newRoot = m.getStrategy().apply(m.getRootModification(), Optional.of(rootNode), StoreUtils.increase(rootNode.getSubtreeVersion())); + final Optional newRoot = m.getStrategy().apply(m.getRootModification(), + Optional.of(rootNode), rootNode.getSubtreeVersion().next()); Preconditions.checkState(newRoot.isPresent(), "Apply strategy failed to produce root node"); return new InMemoryDataTreeCandidate(PUBLIC_ROOT_PATH, root, rootNode, newRoot.get()); } finally { @@ -110,7 +111,7 @@ final class InMemoryDataTree implements DataTree { } @Override - public synchronized void commit(DataTreeCandidate candidate) { + public synchronized void commit(final DataTreeCandidate candidate) { if (candidate instanceof NoopDataTreeCandidate) { return; } @@ -118,7 +119,7 @@ final class InMemoryDataTree implements DataTree { Preconditions.checkArgument(candidate instanceof InMemoryDataTreeCandidate, "Invalid candidate class %s", candidate.getClass()); final InMemoryDataTreeCandidate c = (InMemoryDataTreeCandidate)candidate; - LOG.debug("Updating Store snapshot version: {} with version:{}", rootNode.getSubtreeVersion(), c.getAfterRoot().getSubtreeVersion()); + LOG.debug("Updating datastore from {} to {}", rootNode, c.getAfterRoot()); if (LOG.isTraceEnabled()) { LOG.trace("Data Tree is {}", StoreUtils.toStringTree(c.getAfterRoot().getData())); diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeCandidate.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeCandidate.java index 72562f0a72..bafea6bd97 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeCandidate.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeCandidate.java @@ -2,6 +2,7 @@ package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidateNode; import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; @@ -13,38 +14,42 @@ import com.google.common.collect.Iterables; final class InMemoryDataTreeCandidate extends AbstractDataTreeCandidate { private static abstract class AbstractNode implements DataTreeCandidateNode { - private final StoreMetadataNode newMeta; - private final StoreMetadataNode oldMeta; - private final NodeModification mod; + private final ModifiedNode mod; + private final TreeNode newMeta; + private final TreeNode oldMeta; - protected AbstractNode(final NodeModification mod, - final StoreMetadataNode oldMeta, final StoreMetadataNode newMeta) { + protected AbstractNode(final ModifiedNode mod, + final TreeNode oldMeta, final TreeNode newMeta) { this.newMeta = newMeta; this.oldMeta = oldMeta; this.mod = Preconditions.checkNotNull(mod); } - protected final NodeModification getMod() { + protected final ModifiedNode getMod() { return mod; } - protected final StoreMetadataNode getNewMeta() { + protected final TreeNode getNewMeta() { return newMeta; } - protected final StoreMetadataNode getOldMeta() { + protected final TreeNode getOldMeta() { return oldMeta; } - private static final StoreMetadataNode childMeta(final StoreMetadataNode parent, final PathArgument id) { - return parent == null ? null : parent.getChild(id).orNull(); + private static final TreeNode childMeta(final TreeNode parent, final PathArgument id) { + if (parent != null) { + return parent.getChild(id).orNull(); + } else { + return null; + } } @Override public Iterable getChildNodes() { - return Iterables.transform(mod.getModifications(), new Function() { + return Iterables.transform(mod.getChildren(), new Function() { @Override - public DataTreeCandidateNode apply(final NodeModification input) { + public DataTreeCandidateNode apply(final ModifiedNode input) { final PathArgument id = input.getIdentifier(); return new ChildNode(input, childMeta(oldMeta, id), childMeta(newMeta, id)); } @@ -53,14 +58,15 @@ final class InMemoryDataTreeCandidate extends AbstractDataTreeCandidate { @Override public ModificationType getModificationType() { - return mod.getModificationType(); + return mod.getType(); } - private Optional> optionalData(StoreMetadataNode meta) { - if (meta == null) { + private Optional> optionalData(final TreeNode meta) { + if (meta != null) { + return Optional.>of(meta.getData()); + } else { return Optional.absent(); } - return Optional.>of(meta.getData()); } @Override @@ -75,7 +81,7 @@ final class InMemoryDataTreeCandidate extends AbstractDataTreeCandidate { } private static final class ChildNode extends AbstractNode { - public ChildNode(NodeModification mod, StoreMetadataNode oldMeta, StoreMetadataNode newMeta) { + public ChildNode(final ModifiedNode mod, final TreeNode oldMeta, final TreeNode newMeta) { super(mod, oldMeta, newMeta); } @@ -86,7 +92,7 @@ final class InMemoryDataTreeCandidate extends AbstractDataTreeCandidate { } private static final class RootNode extends AbstractNode { - public RootNode(NodeModification mod, StoreMetadataNode oldMeta, StoreMetadataNode newMeta) { + public RootNode(final ModifiedNode mod, final TreeNode oldMeta, final TreeNode newMeta) { super(mod, oldMeta, newMeta); } @@ -98,17 +104,17 @@ final class InMemoryDataTreeCandidate extends AbstractDataTreeCandidate { private final RootNode root; - InMemoryDataTreeCandidate(final InstanceIdentifier rootPath, final NodeModification modificationRoot, - final StoreMetadataNode oldRoot, final StoreMetadataNode newRoot) { + InMemoryDataTreeCandidate(final InstanceIdentifier rootPath, final ModifiedNode modificationRoot, + final TreeNode beforeRoot, final TreeNode afterRoot) { super(rootPath); - this.root = new RootNode(modificationRoot, oldRoot, newRoot); + this.root = new RootNode(modificationRoot, beforeRoot, afterRoot); } - StoreMetadataNode getAfterRoot() { + TreeNode getAfterRoot() { return root.getNewMeta(); } - StoreMetadataNode getBeforeRoot() { + TreeNode getBeforeRoot() { return root.getOldMeta(); } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeFactory.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeFactory.java index 7614611ab2..4640be43e7 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeFactory.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeFactory.java @@ -1,6 +1,8 @@ package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeFactory; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.impl.schema.Builders; @@ -10,26 +12,26 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext; * A factory for creating in-memory data trees. */ public final class InMemoryDataTreeFactory implements DataTreeFactory { - private static final InMemoryDataTreeFactory INSTANCE = new InMemoryDataTreeFactory(); + private static final InMemoryDataTreeFactory INSTANCE = new InMemoryDataTreeFactory(); - private InMemoryDataTreeFactory() { - // Never instantiated externally - } + private InMemoryDataTreeFactory() { + // Never instantiated externally + } - @Override - public InMemoryDataTree create() { - final NodeIdentifier root = new NodeIdentifier(SchemaContext.NAME); - final NormalizedNode data = Builders.containerBuilder().withNodeIdentifier(root).build(); + @Override + public InMemoryDataTree create() { + final NodeIdentifier root = new NodeIdentifier(SchemaContext.NAME); + final NormalizedNode data = Builders.containerBuilder().withNodeIdentifier(root).build(); - return new InMemoryDataTree(StoreMetadataNode.createEmpty(data), null); - } + return new InMemoryDataTree(TreeNodeFactory.createTreeNode(data, Version.initial()), null); + } - /** - * Get an instance of this factory. This method cannot fail. - * - * @return Data tree factory instance. - */ - public static final InMemoryDataTreeFactory getInstance() { - return INSTANCE; - } + /** + * Get an instance of this factory. This method cannot fail. + * + * @return Data tree factory instance. + */ + public static final InMemoryDataTreeFactory getInstance() { + return INSTANCE; + } } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeModification.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeModification.java index 1540feca66..c05ed4b442 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeModification.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeModification.java @@ -7,14 +7,13 @@ */ package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; -import static com.google.common.base.Preconditions.checkState; - import java.util.Map.Entry; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; + +import javax.annotation.concurrent.GuardedBy; import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification; -import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils; import org.opendaylight.controller.md.sal.dom.store.impl.tree.TreeNodeUtils; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; @@ -28,26 +27,20 @@ import com.google.common.base.Preconditions; final class InMemoryDataTreeModification implements DataTreeModification { private static final Logger LOG = LoggerFactory.getLogger(InMemoryDataTreeModification.class); - - /* - * FIXME: the thread safety of concurrent write/delete/read/seal operations - * needs to be evaluated. - */ - private static final AtomicIntegerFieldUpdater SEALED_UPDATER = - AtomicIntegerFieldUpdater.newUpdater(InMemoryDataTreeModification.class, "sealed"); - private volatile int sealed = 0; - private final ModificationApplyOperation strategyTree; private final InMemoryDataTreeSnapshot snapshot; - private final NodeModification rootNode; + private final ModifiedNode rootNode; + + @GuardedBy("this") + private boolean sealed = false; InMemoryDataTreeModification(final InMemoryDataTreeSnapshot snapshot, final ModificationApplyOperation resolver) { this.snapshot = Preconditions.checkNotNull(snapshot); this.strategyTree = Preconditions.checkNotNull(resolver); - this.rootNode = NodeModification.createUnmodified(snapshot.getRootNode()); + this.rootNode = ModifiedNode.createUnmodified(snapshot.getRootNode()); } - NodeModification getRootModification() { + ModifiedNode getRootModification() { return rootNode; } @@ -56,13 +49,13 @@ final class InMemoryDataTreeModification implements DataTreeModification { } @Override - public void write(final InstanceIdentifier path, final NormalizedNode value) { + public synchronized void write(final InstanceIdentifier path, final NormalizedNode value) { checkSealed(); resolveModificationFor(path).write(value); } @Override - public void merge(final InstanceIdentifier path, final NormalizedNode data) { + public synchronized void merge(final InstanceIdentifier path, final NormalizedNode data) { checkSealed(); mergeImpl(resolveModificationFor(path),data); } @@ -81,23 +74,23 @@ final class InMemoryDataTreeModification implements DataTreeModification { } @Override - public void delete(final InstanceIdentifier path) { + public synchronized void delete(final InstanceIdentifier path) { checkSealed(); resolveModificationFor(path).delete(); } @Override - public Optional> readNode(final InstanceIdentifier path) { + public synchronized Optional> readNode(final InstanceIdentifier path) { /* * Walk the tree from the top, looking for the first node between root and * the requested path which has been modified. If no such node exists, * we use the node itself. */ - final Entry entry = TreeNodeUtils.findClosestsOrFirstMatch(rootNode, path, NodeModification.IS_TERMINAL_PREDICATE); + final Entry entry = TreeNodeUtils.findClosestsOrFirstMatch(rootNode, path, ModifiedNode.IS_TERMINAL_PREDICATE); final InstanceIdentifier key = entry.getKey(); - final NodeModification mod = entry.getValue(); + final ModifiedNode mod = entry.getValue(); - final Optional result = resolveSnapshot(key, mod); + final Optional result = resolveSnapshot(key, mod); if (result.isPresent()) { NormalizedNode data = result.get().getData(); return NormalizedNodeUtils.findNode(key, data, path); @@ -106,15 +99,16 @@ final class InMemoryDataTreeModification implements DataTreeModification { } } - private Optional resolveSnapshot(final InstanceIdentifier path, - final NodeModification modification) { + private Optional resolveSnapshot(final InstanceIdentifier path, + final ModifiedNode modification) { + final Optional> potentialSnapshot = modification.getSnapshotCache(); + if(potentialSnapshot.isPresent()) { + return potentialSnapshot.get(); + } + try { - Optional> potentialSnapshot = modification.getSnapshotCache(); - if(potentialSnapshot.isPresent()) { - return potentialSnapshot.get(); - } return resolveModificationStrategy(path).apply(modification, modification.getOriginal(), - StoreUtils.increase(snapshot.getRootNode().getSubtreeVersion())); + snapshot.getRootNode().getSubtreeVersion().next()); } catch (Exception e) { LOG.error("Could not create snapshot for {}:{}", path,modification,e); throw e; @@ -127,7 +121,7 @@ final class InMemoryDataTreeModification implements DataTreeModification { } private OperationWithModification resolveModificationFor(final InstanceIdentifier path) { - NodeModification modification = rootNode; + ModifiedNode modification = rootNode; // We ensure strategy is present. ModificationApplyOperation operation = resolveModificationStrategy(path); for (PathArgument pathArg : path.getPath()) { @@ -137,14 +131,15 @@ final class InMemoryDataTreeModification implements DataTreeModification { } @Override - public void seal() { - final boolean success = SEALED_UPDATER.compareAndSet(this, 0, 1); - Preconditions.checkState(success, "Attempted to seal an already-sealed Data Tree."); + public synchronized void seal() { + Preconditions.checkState(!sealed, "Attempted to seal an already-sealed Data Tree."); + sealed = true; rootNode.seal(); } + @GuardedBy("this") private void checkSealed() { - checkState(sealed == 0, "Data Tree is sealed. No further modifications allowed."); + Preconditions.checkState(!sealed, "Data Tree is sealed. No further modifications allowed."); } @Override @@ -153,7 +148,9 @@ final class InMemoryDataTreeModification implements DataTreeModification { } @Override - public DataTreeModification newModification() { + public synchronized DataTreeModification newModification() { + Preconditions.checkState(sealed, "Attempted to chain on an unsealed modification"); + // FIXME: transaction chaining throw new UnsupportedOperationException("Implement this as part of transaction chaining"); } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeSnapshot.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeSnapshot.java index ce2d8c9bd4..ee91e62518 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeSnapshot.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTreeSnapshot.java @@ -1,6 +1,7 @@ package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeSnapshot; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils; @@ -12,16 +13,16 @@ import com.google.common.base.Preconditions; final class InMemoryDataTreeSnapshot implements DataTreeSnapshot { private final ModificationApplyOperation applyOper; private final SchemaContext schemaContext; - private final StoreMetadataNode rootNode; + private final TreeNode rootNode; - InMemoryDataTreeSnapshot(final SchemaContext schemaContext, final StoreMetadataNode rootNode, + InMemoryDataTreeSnapshot(final SchemaContext schemaContext, final TreeNode rootNode, final ModificationApplyOperation applyOper) { this.schemaContext = Preconditions.checkNotNull(schemaContext); this.rootNode = Preconditions.checkNotNull(rootNode); this.applyOper = Preconditions.checkNotNull(applyOper); } - StoreMetadataNode getRootNode() { + TreeNode getRootNode() { return rootNode; } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationApplyOperation.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationApplyOperation.java index 5b4cd565e5..10f39a8cef 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationApplyOperation.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationApplyOperation.java @@ -9,15 +9,16 @@ package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException; import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import com.google.common.base.Optional; -import com.google.common.primitives.UnsignedLong; /** * - * Operation responsible for applying {@link NodeModification} on tree. + * Operation responsible for applying {@link ModifiedNode} on tree. * * Operation is composite - operation on top level node consists of * suboperations on child nodes. This allows to walk operation hierarchy and @@ -29,7 +30,7 @@ import com.google.common.primitives.UnsignedLong; * Implementations MUST expose all nested suboperations which operates on child * nodes expose via {@link #getChild(PathArgument)} method. *
  • Same suboperations SHOULD be used when invoked via - * {@link #apply(NodeModification, Optional)} if applicable. + * {@link #apply(ModifiedNode, Optional)} if applicable. * * * Hierarchical composite operation which is responsible for applying @@ -54,10 +55,10 @@ interface ModificationApplyOperation extends StoreTreeNode apply(NodeModification modification, Optional storeMeta, UnsignedLong subtreeVersion); + Optional apply(ModifiedNode modification, Optional storeMeta, Version subtreeVersion); /** * @@ -67,7 +68,7 @@ interface ModificationApplyOperation extends StoreTreeNode current) throws DataPreconditionFailedException; + void checkApplicable(InstanceIdentifier path, NodeModification modification, Optional current) throws DataPreconditionFailedException; } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModifiedNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModifiedNode.java new file mode 100644 index 0000000000..f83ea1a2de --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModifiedNode.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; + +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.annotation.concurrent.GuardedBy; + +import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode; +import org.opendaylight.yangtools.concepts.Identifiable; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +import com.google.common.base.Optional; +import com.google.common.base.Predicate; + +/** + * Node Modification Node and Tree + * + * Tree which structurally resembles data tree and captures client modifications + * to the data store tree. + * + * This tree is lazily created and populated via {@link #modifyChild(PathArgument)} + * and {@link StoreMetadataNode} which represents original state {@link #getOriginal()}. + */ +final class ModifiedNode implements StoreTreeNode, Identifiable, NodeModification { + + public static final Predicate IS_TERMINAL_PREDICATE = new Predicate() { + @Override + public boolean apply(final ModifiedNode input) { + switch (input.getType()) { + case DELETE: + case MERGE: + case WRITE: + return true; + case SUBTREE_MODIFIED: + case UNMODIFIED: + return false; + } + + throw new IllegalArgumentException(String.format("Unhandled modification type %s", input.getType())); + } + }; + + private final Map children = new LinkedHashMap<>(); + private final Optional original; + private final PathArgument identifier; + private ModificationType modificationType = ModificationType.UNMODIFIED; + private Optional snapshotCache; + private NormalizedNode value; + + private ModifiedNode(final PathArgument identifier, final Optional original) { + this.identifier = identifier; + this.original = original; + } + + /** + * + * + * @return + */ + public NormalizedNode getWrittenValue() { + return value; + } + + @Override + public PathArgument getIdentifier() { + return identifier; + } + + /** + * + * Returns original store metadata + * @return original store metadata + */ + @Override + public Optional getOriginal() { + return original; + } + + /** + * Returns modification type + * + * @return modification type + */ + @Override + public ModificationType getType() { + return modificationType; + } + + /** + * + * Returns child modification if child was modified + * + * @return Child modification if direct child or it's subtree + * was modified. + * + */ + @Override + public Optional getChild(final PathArgument child) { + return Optional. fromNullable(children.get(child)); + } + + /** + * + * Returns child modification if child was modified, creates {@link ModifiedNode} + * for child otherwise. + * + * If this node's {@link ModificationType} is {@link ModificationType#UNMODIFIED} + * changes modification type to {@link ModificationType#SUBTREE_MODIFIED} + * + * @param child + * @return {@link ModifiedNode} for specified child, with {@link #getOriginal()} + * containing child metadata if child was present in original data. + */ + public ModifiedNode modifyChild(final PathArgument child) { + clearSnapshot(); + if (modificationType == ModificationType.UNMODIFIED) { + updateModificationType(ModificationType.SUBTREE_MODIFIED); + } + final ModifiedNode potential = children.get(child); + if (potential != null) { + return potential; + } + + final Optional currentMetadata; + if (original.isPresent()) { + final TreeNode orig = original.get(); + currentMetadata = orig.getChild(child); + } else { + currentMetadata = Optional.absent(); + } + + ModifiedNode newlyCreated = new ModifiedNode(child, currentMetadata); + children.put(child, newlyCreated); + return newlyCreated; + } + + /** + * + * Returns all recorded direct child modification + * + * @return all recorded direct child modifications + */ + @Override + public Iterable getChildren() { + return children.values(); + } + + /** + * + * Records a delete for associated node. + * + */ + public void delete() { + clearSnapshot(); + updateModificationType(ModificationType.DELETE); + children.clear(); + this.value = null; + } + + /** + * + * Records a write for associated node. + * + * @param value + */ + public void write(final NormalizedNode value) { + clearSnapshot(); + updateModificationType(ModificationType.WRITE); + children.clear(); + this.value = value; + } + + public void merge(final NormalizedNode data) { + clearSnapshot(); + updateModificationType(ModificationType.MERGE); + // FIXME: Probably merge with previous value. + this.value = data; + } + + void seal() { + clearSnapshot(); + for (ModifiedNode child : children.values()) { + child.seal(); + } + } + + private void clearSnapshot() { + snapshotCache = null; + } + + public Optional storeSnapshot(final Optional snapshot) { + snapshotCache = snapshot; + return snapshot; + } + + public Optional> getSnapshotCache() { + return Optional.fromNullable(snapshotCache); + } + + @GuardedBy("this") + private void updateModificationType(final ModificationType type) { + modificationType = type; + clearSnapshot(); + } + + @Override + public String toString() { + return "NodeModification [identifier=" + identifier + ", modificationType=" + + modificationType + ", childModification=" + children + "]"; + } + + public static ModifiedNode createUnmodified(final TreeNode metadataTree) { + return new ModifiedNode(metadataTree.getIdentifier(), Optional.of(metadataTree)); + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NodeModification.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NodeModification.java index f2720b57ae..2639d050ef 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NodeModification.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NodeModification.java @@ -7,228 +7,15 @@ */ package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; -import static com.google.common.base.Preconditions.checkState; - -import java.util.LinkedHashMap; -import java.util.Map; - -import javax.annotation.concurrent.GuardedBy; - import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType; -import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode; import org.opendaylight.yangtools.concepts.Identifiable; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; -import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import com.google.common.base.Optional; -import com.google.common.base.Predicate; - -/** - * Node Modification Node and Tree - * - * Tree which structurally resembles data tree and captures client modifications - * to the data store tree. - * - * This tree is lazily created and populated via {@link #modifyChild(PathArgument)} - * and {@link StoreMetadataNode} which represents original state {@link #getOriginal()}. - */ -final class NodeModification implements StoreTreeNode, Identifiable { - - public static final Predicate IS_TERMINAL_PREDICATE = new Predicate() { - @Override - public boolean apply(final NodeModification input) { - return input.getModificationType() == ModificationType.WRITE // - || input.getModificationType() == ModificationType.DELETE // - || input.getModificationType() == ModificationType.MERGE; - } - }; - private final PathArgument identifier; - private ModificationType modificationType = ModificationType.UNMODIFIED; - - - private final Optional original; - - private NormalizedNode value; - - private Optional snapshotCache; - - private final Map childModification; - - @GuardedBy("this") - private boolean sealed = false; - - protected NodeModification(final PathArgument identifier, final Optional original) { - this.identifier = identifier; - this.original = original; - childModification = new LinkedHashMap<>(); - } - - /** - * - * - * @return - */ - public NormalizedNode getWrittenValue() { - return value; - } - - @Override - public PathArgument getIdentifier() { - return identifier; - } - - /** - * - * Returns original store metadata - * @return original store metadata - */ - public final Optional getOriginal() { - return original; - } - - /** - * Returns modification type - * - * @return modification type - */ - public final ModificationType getModificationType() { - return modificationType; - } - - /** - * - * Returns child modification if child was modified - * - * @return Child modification if direct child or it's subtree - * was modified. - * - */ - @Override - public Optional getChild(final PathArgument child) { - return Optional. fromNullable(childModification.get(child)); - } - - /** - * - * Returns child modification if child was modified, creates {@link NodeModification} - * for child otherwise. - * - * If this node's {@link ModificationType} is {@link ModificationType#UNMODIFIED} - * changes modification type to {@link ModificationType#SUBTREE_MODIFIED} - * - * @param child - * @return {@link NodeModification} for specified child, with {@link #getOriginal()} - * containing child metadata if child was present in original data. - */ - public synchronized NodeModification modifyChild(final PathArgument child) { - checkSealed(); - clearSnapshot(); - if(modificationType == ModificationType.UNMODIFIED) { - updateModificationType(ModificationType.SUBTREE_MODIFIED); - } - final NodeModification potential = childModification.get(child); - if (potential != null) { - return potential; - } - Optional currentMetadata = Optional.absent(); - if(original.isPresent()) { - currentMetadata = original.get().getChild(child); - } - NodeModification newlyCreated = new NodeModification(child,currentMetadata); - childModification.put(child, newlyCreated); - return newlyCreated; - } - - /** - * - * Returns all recorded direct child modification - * - * @return all recorded direct child modifications - */ - public Iterable getModifications() { - return childModification.values(); - } - - - /** - * - * Records a delete for associated node. - * - */ - public synchronized void delete() { - checkSealed(); - clearSnapshot(); - updateModificationType(ModificationType.DELETE); - childModification.clear(); - this.value = null; - } - - /** - * - * Records a write for associated node. - * - * @param value - */ - public synchronized void write(final NormalizedNode value) { - checkSealed(); - clearSnapshot(); - updateModificationType(ModificationType.WRITE); - childModification.clear(); - this.value = value; - } - - public synchronized void merge(final NormalizedNode data) { - checkSealed(); - clearSnapshot(); - updateModificationType(ModificationType.MERGE); - // FIXME: Probably merge with previous value. - this.value = data; - } - - @GuardedBy("this") - private void checkSealed() { - checkState(!sealed, "Node Modification is sealed. No further changes allowed."); - } - - public synchronized void seal() { - sealed = true; - clearSnapshot(); - for(NodeModification child : childModification.values()) { - child.seal(); - } - } - - private void clearSnapshot() { - snapshotCache = null; - } - - public Optional storeSnapshot(final Optional snapshot) { - snapshotCache = snapshot; - return snapshot; - } - - public Optional> getSnapshotCache() { - return Optional.fromNullable(snapshotCache); - } - - public boolean hasAdditionalModifications() { - return !childModification.isEmpty(); - } - - @GuardedBy("this") - private void updateModificationType(final ModificationType type) { - modificationType = type; - clearSnapshot(); - } - - @Override - public String toString() { - return "NodeModification [identifier=" + identifier + ", modificationType=" - + modificationType + ", childModification=" + childModification + "]"; - } - - public static NodeModification createUnmodified(final StoreMetadataNode metadataTree) { - return new NodeModification(metadataTree.getIdentifier(), Optional.of(metadataTree)); - } +interface NodeModification extends Identifiable { + ModificationType getType(); + Optional getOriginal(); + Iterable getChildren(); } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NoopDataTreeCandidate.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NoopDataTreeCandidate.java index 8a46748414..2ef85cbcb7 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NoopDataTreeCandidate.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NoopDataTreeCandidate.java @@ -46,9 +46,9 @@ final class NoopDataTreeCandidate extends AbstractDataTreeCandidate { } }; - protected NoopDataTreeCandidate(final InstanceIdentifier rootPath, final NodeModification modificationRoot) { + protected NoopDataTreeCandidate(final InstanceIdentifier rootPath, final ModifiedNode modificationRoot) { super(rootPath); - Preconditions.checkArgument(modificationRoot.getModificationType() == ModificationType.UNMODIFIED); + Preconditions.checkArgument(modificationRoot.getType() == ModificationType.UNMODIFIED); } @Override diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NormalizedNodeContainerModificationStrategy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NormalizedNodeContainerModificationStrategy.java new file mode 100644 index 0000000000..3a3af5ecab --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/NormalizedNodeContainerModificationStrategy.java @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.util.Map; + +import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.DataNodeContainerModificationStrategy.ListEntryModificationStrategy; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ValueNodeModificationStrategy.LeafSetEntryModificationStrategy; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.MutableTreeNode; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer; +import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode; +import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder; +import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; +import org.opendaylight.yangtools.yang.model.api.ChoiceNode; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; + +abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation { + + private final Class> nodeClass; + + protected NormalizedNodeContainerModificationStrategy(final Class> nodeClass) { + this.nodeClass = nodeClass; + } + + @Override + public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException { + if (modification.getType() == ModificationType.WRITE) { + + } + for (ModifiedNode childModification : modification.getChildren()) { + resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification); + } + } + + @Override + protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { + // FIXME: Implement proper write check for replacement of node container + // prerequisite is to have transaction chain available for clients + // otherwise this will break chained writes to same node. + } + + @SuppressWarnings("rawtypes") + @Override + protected void verifyWrittenStructure(final NormalizedNode writtenValue) { + checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass); + checkArgument(writtenValue instanceof NormalizedNodeContainer); + + NormalizedNodeContainer container = (NormalizedNodeContainer) writtenValue; + for (Object child : container.getValue()) { + checkArgument(child instanceof NormalizedNode); + + /* + * FIXME: fail-fast semantics: + * + * We can validate the data structure here, aborting the commit + * before it ever progresses to being committed. + */ + } + } + + @Override + protected TreeNode applyWrite(final ModifiedNode modification, + final Optional currentMeta, final Version subtreeVersion) { + final Version nodeVersion; + if (currentMeta.isPresent()) { + nodeVersion = currentMeta.get().getVersion().next(); + } else { + nodeVersion = subtreeVersion; + } + + final NormalizedNode newValue = modification.getWrittenValue(); + final TreeNode newValueMeta = TreeNodeFactory.createTreeNode(newValue, nodeVersion); + + if (Iterables.isEmpty(modification.getChildren())) { + return newValueMeta; + } + + /* + * This is where things get interesting. The user has performed a write and + * then she applied some more modifications to it. So we need to make sense + * of that an apply the operations on top of the written value. We could have + * done it during the write, but this operation is potentially expensive, so + * we have left it out of the fast path. + * + * As it turns out, once we materialize the written data, we can share the + * code path with the subtree change. So let's create an unsealed TreeNode + * and run the common parts on it -- which end with the node being sealed. + */ + final MutableTreeNode mutable = newValueMeta.mutable(); + mutable.setSubtreeVersion(subtreeVersion); + + @SuppressWarnings("rawtypes") + final NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue); + + return mutateChildren(mutable, dataBuilder, nodeVersion, modification.getChildren()); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private TreeNode mutateChildren(final MutableTreeNode meta, final NormalizedNodeContainerBuilder data, + final Version nodeVersion, final Iterable modifications) { + + for (ModifiedNode mod : modifications) { + final PathArgument id = mod.getIdentifier(); + final Optional cm = meta.getChild(id); + + Optional result = resolveChildOperation(id).apply(mod, cm, nodeVersion); + if (result.isPresent()) { + final TreeNode tn = result.get(); + meta.addChild(tn); + data.addChild(tn.getData()); + } else { + meta.removeChild(id); + data.removeChild(id); + } + } + + meta.setData(data.build()); + return meta.seal(); + } + + @Override + protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta, + final Version subtreeVersion) { + // For Node Containers - merge is same as subtree change - we only replace children. + return applySubtreeChange(modification, currentMeta, subtreeVersion); + } + + @Override + public TreeNode applySubtreeChange(final ModifiedNode modification, + final TreeNode currentMeta, final Version subtreeVersion) { + // Bump subtree version to its new target + final Version updatedSubtreeVersion = currentMeta.getSubtreeVersion().next(); + + final MutableTreeNode newMeta = currentMeta.mutable(); + newMeta.setSubtreeVersion(updatedSubtreeVersion); + + @SuppressWarnings("rawtypes") + NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData()); + + return mutateChildren(newMeta, dataBuilder, updatedSubtreeVersion, modification.getChildren()); + } + + @Override + protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { + checkDataPrecondition(path, current.isPresent(), "Node was deleted by other transaction."); + checkChildPreconditions(path, modification, current); + } + + private void checkChildPreconditions(final InstanceIdentifier path, final NodeModification modification, final Optional current) throws DataPreconditionFailedException { + final TreeNode currentMeta = current.get(); + for (NodeModification childMod : modification.getChildren()) { + final PathArgument childId = childMod.getIdentifier(); + final Optional childMeta = currentMeta.getChild(childId); + + InstanceIdentifier childPath = StoreUtils.append(path, childId); + resolveChildOperation(childId).checkApplicable(childPath, childMod, childMeta); + } + } + + @Override + protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { + if(current.isPresent()) { + checkChildPreconditions(path, modification,current); + } + } + + @SuppressWarnings("rawtypes") + protected abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode original); + + public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy { + + private final Map childNodes; + + public ChoiceModificationStrategy(final ChoiceNode schemaNode) { + super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class); + ImmutableMap.Builder child = ImmutableMap.builder(); + + for (ChoiceCaseNode caze : schemaNode.getCases()) { + for (DataSchemaNode cazeChild : caze.getChildNodes()) { + SchemaAwareApplyOperation childNode = from(cazeChild); + child.put(new NodeIdentifier(cazeChild.getQName()), childNode); + } + } + childNodes = child.build(); + } + + @Override + public Optional getChild(final PathArgument child) { + return Optional.fromNullable(childNodes.get(child)); + } + + @Override + @SuppressWarnings("rawtypes") + protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode); + return ImmutableChoiceNodeBuilder.create((org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode) original); + } + } + + public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy { + + private final Optional entryStrategy; + + @SuppressWarnings({ "unchecked", "rawtypes" }) + protected OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) { + super((Class) LeafSetNode.class); + entryStrategy = Optional. of(new LeafSetEntryModificationStrategy(schema)); + } + + @SuppressWarnings("rawtypes") + @Override + protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof OrderedLeafSetNode); + return ImmutableOrderedLeafSetNodeBuilder.create((OrderedLeafSetNode) original); + } + + @Override + public Optional getChild(final PathArgument identifier) { + if (identifier instanceof NodeWithValue) { + return entryStrategy; + } + return Optional.absent(); + } + } + + public static class OrderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy { + + private final Optional entryStrategy; + + protected OrderedMapModificationStrategy(final ListSchemaNode schema) { + super(OrderedMapNode.class); + entryStrategy = Optional. of(new ListEntryModificationStrategy(schema)); + } + + @SuppressWarnings("rawtypes") + @Override + protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof OrderedMapNode); + return ImmutableOrderedMapNodeBuilder.create((OrderedMapNode) original); + } + + @Override + public Optional getChild(final PathArgument identifier) { + if (identifier instanceof NodeIdentifierWithPredicates) { + return entryStrategy; + } + return Optional.absent(); + } + + @Override + public String toString() { + return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]"; + } + } + + public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy { + + private final Optional entryStrategy; + + @SuppressWarnings({ "unchecked", "rawtypes" }) + protected UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) { + super((Class) LeafSetNode.class); + entryStrategy = Optional. of(new LeafSetEntryModificationStrategy(schema)); + } + + @SuppressWarnings("rawtypes") + @Override + protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof LeafSetNode); + return ImmutableLeafSetNodeBuilder.create((LeafSetNode) original); + } + + @Override + public Optional getChild(final PathArgument identifier) { + if (identifier instanceof NodeWithValue) { + return entryStrategy; + } + return Optional.absent(); + } + } + + public static class UnorderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy { + + private final Optional entryStrategy; + + protected UnorderedMapModificationStrategy(final ListSchemaNode schema) { + super(MapNode.class); + entryStrategy = Optional. of(new ListEntryModificationStrategy(schema)); + } + + @SuppressWarnings("rawtypes") + @Override + protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { + checkArgument(original instanceof MapNode); + return ImmutableMapNodeBuilder.create((MapNode) original); + } + + @Override + public Optional getChild(final PathArgument identifier) { + if (identifier instanceof NodeIdentifierWithPredicates) { + return entryStrategy; + } + return Optional.absent(); + } + + @Override + public String toString() { + return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]"; + } + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/OperationWithModification.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/OperationWithModification.java index fda8407a95..ff90d57f49 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/OperationWithModification.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/OperationWithModification.java @@ -7,19 +7,20 @@ */ package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import com.google.common.base.Optional; -import com.google.common.primitives.UnsignedLong; final class OperationWithModification { - private final NodeModification modification; + private final ModifiedNode modification; private final ModificationApplyOperation applyOperation; - private OperationWithModification(final ModificationApplyOperation op, final NodeModification mod) { + private OperationWithModification(final ModificationApplyOperation op, final ModifiedNode mod) { this.modification = mod; this.applyOperation = op; } @@ -35,7 +36,7 @@ final class OperationWithModification { return this; } - public NodeModification getModification() { + public ModifiedNode getModification() { return modification; } @@ -43,12 +44,12 @@ final class OperationWithModification { return applyOperation; } - public Optional apply(final Optional data, final UnsignedLong subtreeVersion) { + public Optional apply(final Optional data, final Version subtreeVersion) { return applyOperation.apply(modification, data, subtreeVersion); } public static OperationWithModification from(final ModificationApplyOperation operation, - final NodeModification modification) { + final ModifiedNode modification) { return new OperationWithModification(operation, modification); } @@ -60,7 +61,7 @@ final class OperationWithModification { } public OperationWithModification forChild(final PathArgument childId) { - NodeModification childMod = modification.modifyChild(childId); + ModifiedNode childMod = modification.modifyChild(childId); Optional childOp = applyOperation.getChild(childId); return from(childOp.get(),childMod); } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperation.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperation.java index 620c00791c..bdf5667b67 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperation.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperation.java @@ -9,49 +9,28 @@ package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; import static com.google.common.base.Preconditions.checkArgument; -import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ExecutionException; import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException; import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType; -import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.DataNodeContainerModificationStrategy.ContainerModificationStrategy; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.DataNodeContainerModificationStrategy.UnkeyedListItemModificationStrategy; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.ChoiceModificationStrategy; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.OrderedLeafSetModificationStrategy; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.OrderedMapModificationStrategy; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.NormalizedNodeContainerModificationStrategy.UnorderedLeafSetModificationStrategy; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.data.ValueNodeModificationStrategy.LeafModificationStrategy; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier; -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates; -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; -import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; -import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; -import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; -import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode; -import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode; -import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; -import org.opendaylight.yangtools.yang.data.api.schema.MapNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer; -import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode; -import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode; -import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedLeafSetNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy; import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; import org.opendaylight.yangtools.yang.model.api.AugmentationTarget; -import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; import org.opendaylight.yangtools.yang.model.api.ChoiceNode; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; @@ -59,17 +38,14 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Preconditions; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.collect.ImmutableMap; -import com.google.common.primitives.UnsignedLong; abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { + private static final Logger LOG = LoggerFactory.getLogger(SchemaAwareApplyOperation.class); public static SchemaAwareApplyOperation from(final DataSchemaNode schemaNode) { if (schemaNode instanceof ContainerSchemaNode) { @@ -86,6 +62,33 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { throw new IllegalArgumentException("Not supported schema node type for " + schemaNode.getClass()); } + public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree, + final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) { + AugmentationSchema augSchema = null; + + allAugments: + for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) { + for (DataSchemaNode child : potential.getChildNodes()) { + if (identifier.getPossibleChildNames().contains(child.getQName())) { + augSchema = potential; + break allAugments; + } + } + } + + if (augSchema != null) { + return new DataNodeContainerModificationStrategy.AugmentationModificationStrategy(augSchema, resolvedTree); + } + return null; + } + + public static boolean checkDataPrecondition(final InstanceIdentifier path, final boolean condition, final String message) throws DataPreconditionFailedException { + if(!condition) { + throw new DataPreconditionFailedException(path, message); + } + return condition; + } + private static SchemaAwareApplyOperation fromListSchemaNode(final ListSchemaNode schemaNode) { List keyDefinition = schemaNode.getKeyDefinition(); if (keyDefinition == null || keyDefinition.isEmpty()) { @@ -95,7 +98,7 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { return new OrderedMapModificationStrategy(schemaNode); } - return new UnorderedMapModificationStrategy(schemaNode); + return new NormalizedNodeContainerModificationStrategy.UnorderedMapModificationStrategy(schemaNode); } private static SchemaAwareApplyOperation fromLeafListSchemaNode(final LeafListSchemaNode schemaNode) { @@ -106,25 +109,11 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { } } - - public static SchemaAwareApplyOperation from(final DataNodeContainer resolvedTree, - final AugmentationTarget augSchemas, final AugmentationIdentifier identifier) { - AugmentationSchema augSchema = null; - - allAugments: - for (AugmentationSchema potential : augSchemas.getAvailableAugmentations()) { - for (DataSchemaNode child : potential.getChildNodes()) { - if (identifier.getPossibleChildNames().contains(child.getQName())) { - augSchema = potential; - break allAugments; - } - } - } - - if (augSchema != null) { - return new AugmentationModificationStrategy(augSchema, resolvedTree); - } - return null; + private static final void checkNotConflicting(final InstanceIdentifier path, final TreeNode original, final TreeNode current) throws DataPreconditionFailedException { + checkDataPrecondition(path, original.getVersion().equals(current.getVersion()), + "Node was replaced by other transaction."); + checkDataPrecondition(path, original.getSubtreeVersion().equals(current.getSubtreeVersion()), + "Node children was modified by other transaction"); } protected final ModificationApplyOperation resolveChildOperation(final PathArgument child) { @@ -134,38 +123,36 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { } @Override - public void verifyStructure(final NodeModification modification) throws IllegalArgumentException { - if (modification.getModificationType() == ModificationType.WRITE) { + public void verifyStructure(final ModifiedNode modification) throws IllegalArgumentException { + if (modification.getType() == ModificationType.WRITE) { verifyWrittenStructure(modification.getWrittenValue()); } } - protected abstract void verifyWrittenStructure(NormalizedNode writtenValue); - @Override - public void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional current) throws DataPreconditionFailedException { - switch (modification.getModificationType()) { + public final void checkApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional current) throws DataPreconditionFailedException { + switch (modification.getType()) { case DELETE: checkDeleteApplicable(modification, current); case SUBTREE_MODIFIED: - checkSubtreeModificationApplicable(path,modification, current); + checkSubtreeModificationApplicable(path, modification, current); return; case WRITE: - checkWriteApplicable(path,modification, current); + checkWriteApplicable(path, modification, current); return; case MERGE: - checkMergeApplicable(path,modification,current); + checkMergeApplicable(path, modification, current); return; case UNMODIFIED: return; default: - throw new UnsupportedOperationException("Suplied modification type "+modification.getModificationType()+ "is not supported."); + throw new UnsupportedOperationException("Suplied modification type "+ modification.getType()+ "is not supported."); } } - protected void checkMergeApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional current) throws DataPreconditionFailedException { - Optional original = modification.getOriginal(); + protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification, final Optional current) throws DataPreconditionFailedException { + Optional original = modification.getOriginal(); if (original.isPresent() && current.isPresent()) { /* * We need to do conflict detection only and only if the value of leaf changed @@ -174,39 +161,34 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { * leads to same data. */ if(!original.get().getData().equals(current.get().getData())) { - - checkNotConflicting(path,original.get(), current.get()); + checkNotConflicting(path, original.get(), current.get()); } } } - protected void checkWriteApplicable(final InstanceIdentifier path,final NodeModification modification, final Optional current) throws DataPreconditionFailedException { - Optional original = modification.getOriginal(); + protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification, final Optional current) throws DataPreconditionFailedException { + Optional original = modification.getOriginal(); if (original.isPresent() && current.isPresent()) { - checkNotConflicting(path,original.get(), current.get()); + checkNotConflicting(path, original.get(), current.get()); } else if(original.isPresent()) { throw new DataPreconditionFailedException(path,"Node was deleted by other transaction."); } } - protected static final void checkNotConflicting(final InstanceIdentifier path,final StoreMetadataNode original, final StoreMetadataNode current) throws DataPreconditionFailedException { - checkDataPrecondition(path, original.getNodeVersion().equals(current.getNodeVersion()),"Node was replaced by other transaction."); - checkDataPrecondition(path,original.getSubtreeVersion().equals(current.getSubtreeVersion()), "Node children was modified by other transaction"); - } - - protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path,final NodeModification modification, - final Optional current) throws DataPreconditionFailedException; - - private void checkDeleteApplicable(final NodeModification modification, final Optional current) { + private void checkDeleteApplicable(final NodeModification modification, final Optional current) { + // Delete is always applicable, we do not expose it to subclasses + if (current.isPresent()) { + LOG.trace("Delete operation turned to no-op on missing node {}", modification); + } } @Override - public final Optional apply(final NodeModification modification, - final Optional currentMeta, final UnsignedLong subtreeVersion) { + public final Optional apply(final ModifiedNode modification, + final Optional currentMeta, final Version subtreeVersion) { - switch (modification.getModificationType()) { + switch (modification.getType()) { case DELETE: - return modification.storeSnapshot(Optional. absent()); + return modification.storeSnapshot(Optional. absent()); case SUBTREE_MODIFIED: Preconditions.checkArgument(currentMeta.isPresent(), "Metadata not available for modification", modification); @@ -225,409 +207,19 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { } } - protected abstract StoreMetadataNode applyMerge(NodeModification modification, - StoreMetadataNode currentMeta, UnsignedLong subtreeVersion); - - protected abstract StoreMetadataNode applyWrite(NodeModification modification, - Optional currentMeta, UnsignedLong subtreeVersion); - - protected abstract StoreMetadataNode applySubtreeChange(NodeModification modification, - StoreMetadataNode currentMeta, UnsignedLong subtreeVersion); - - public static abstract class ValueNodeModificationStrategy extends SchemaAwareApplyOperation { + protected abstract TreeNode applyMerge(ModifiedNode modification, + TreeNode currentMeta, Version subtreeVersion); - private final T schema; - private final Class> nodeClass; - - protected ValueNodeModificationStrategy(final T schema, final Class> nodeClass) { - super(); - this.schema = schema; - this.nodeClass = nodeClass; - } - - @Override - protected void verifyWrittenStructure(final NormalizedNode writtenValue) { - checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass); - } - - @Override - public Optional getChild(final PathArgument child) { - throw new UnsupportedOperationException("Node " + schema.getPath() - + "is leaf type node. Child nodes not allowed"); - } - - @Override - protected StoreMetadataNode applySubtreeChange(final NodeModification modification, - final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) { - throw new UnsupportedOperationException("Node " + schema.getPath() - + "is leaf type node. Subtree change is not allowed."); - } - - @Override - protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta, - final UnsignedLong subtreeVersion) { - return applyWrite(modification, Optional.of(currentMeta), subtreeVersion); - } + protected abstract TreeNode applyWrite(ModifiedNode modification, + Optional currentMeta, Version subtreeVersion); - @Override - protected StoreMetadataNode applyWrite(final NodeModification modification, - final Optional currentMeta, final UnsignedLong subtreeVersion) { - return StoreMetadataNode.builder(subtreeVersion).setSubtreeVersion(subtreeVersion) - .setData(modification.getWrittenValue()).build(); - } - - @Override - protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification, - final Optional current) throws DataPreconditionFailedException { - throw new DataPreconditionFailedException(path, "Subtree modification is not allowed."); - } - - } - - public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy { - - @SuppressWarnings({ "unchecked", "rawtypes" }) - protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) { - super(schema, (Class) LeafSetEntryNode.class); - } - } - - public static class LeafModificationStrategy extends ValueNodeModificationStrategy { - - @SuppressWarnings({ "unchecked", "rawtypes" }) - protected LeafModificationStrategy(final LeafSchemaNode schema) { - super(schema, (Class) LeafNode.class); - } - } - - public static abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation { - - private final Class> nodeClass; - - protected NormalizedNodeContainerModificationStrategy(final Class> nodeClass) { - this.nodeClass = nodeClass; - } - - @Override - public void verifyStructure(final NodeModification modification) throws IllegalArgumentException { - if (modification.getModificationType() == ModificationType.WRITE) { - - } - for (NodeModification childModification : modification.getModifications()) { - resolveChildOperation(childModification.getIdentifier()).verifyStructure(childModification); - } - } - - @Override - protected void checkWriteApplicable(final InstanceIdentifier path, final NodeModification modification, - final Optional current) throws DataPreconditionFailedException { - // FIXME: Implement proper write check for replacement of node container - // prerequisite is to have transaction chain available for clients - // otherwise this will break chained writes to same node. - } - - @SuppressWarnings("rawtypes") - @Override - protected void verifyWrittenStructure(final NormalizedNode writtenValue) { - checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass); - checkArgument(writtenValue instanceof NormalizedNodeContainer); - - NormalizedNodeContainer container = (NormalizedNodeContainer) writtenValue; - for (Object child : container.getValue()) { - checkArgument(child instanceof NormalizedNode); - - /* - * FIXME: fail-fast semantics: - * - * We can validate the data structure here, aborting the commit - * before it ever progresses to being committed. - */ - } - } - - @Override - protected StoreMetadataNode applyWrite(final NodeModification modification, - final Optional currentMeta, final UnsignedLong subtreeVersion) { - - NormalizedNode newValue = modification.getWrittenValue(); - - final UnsignedLong nodeVersion; - if (currentMeta.isPresent()) { - nodeVersion = StoreUtils.increase(currentMeta.get().getNodeVersion()); - } else { - nodeVersion = subtreeVersion; - } - - final StoreMetadataNode newValueMeta = StoreMetadataNode.createRecursively(newValue, nodeVersion); - if (!modification.hasAdditionalModifications()) { - return newValueMeta; - } - - @SuppressWarnings("rawtypes") - NormalizedNodeContainerBuilder dataBuilder = createBuilder(newValue); - StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.create(nodeVersion, dataBuilder) // - .setSubtreeVersion(subtreeVersion); - - return mutateChildren(modification.getModifications(), newValueMeta, builder, nodeVersion); - } - - @Override - protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta, - final UnsignedLong subtreeVersion) { - // For Node Containers - merge is same as subtree change - we only replace children. - return applySubtreeChange(modification, currentMeta, subtreeVersion); - } - - @Override - public StoreMetadataNode applySubtreeChange(final NodeModification modification, - final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) { - // Bump subtree version to its new target - final UnsignedLong updatedSubtreeVersion = StoreUtils.increase(currentMeta.getSubtreeVersion()); - - @SuppressWarnings("rawtypes") - NormalizedNodeContainerBuilder dataBuilder = createBuilder(currentMeta.getData()); - StoreNodeCompositeBuilder builder = StoreNodeCompositeBuilder.create(dataBuilder, currentMeta) - .setIdentifier(modification.getIdentifier()) - .setSubtreeVersion(updatedSubtreeVersion); - - return mutateChildren(modification.getModifications(), currentMeta, builder, updatedSubtreeVersion); - } - - private StoreMetadataNode mutateChildren(final Iterable modifications, final StoreMetadataNode meta, - final StoreNodeCompositeBuilder builder, final UnsignedLong nodeVersion) { - - for (NodeModification mod : modifications) { - final PathArgument id = mod.getIdentifier(); - final Optional cm = meta.getChild(id); - - Optional result = resolveChildOperation(id).apply(mod, cm, nodeVersion); - if (result.isPresent()) { - builder.add(result.get()); - } else { - builder.remove(id); - } - } - - return builder.build(); - } - - @Override - protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification, - final Optional current) throws DataPreconditionFailedException { - checkDataPrecondition(path, current.isPresent(), "Node was deleted by other transaction."); - checkChildPreconditions(path,modification,current); - - } - - private void checkChildPreconditions(final InstanceIdentifier path, final NodeModification modification, final Optional current) throws DataPreconditionFailedException { - StoreMetadataNode currentMeta = current.get(); - for (NodeModification childMod : modification.getModifications()) { - PathArgument childId = childMod.getIdentifier(); - Optional childMeta = currentMeta.getChild(childId); - InstanceIdentifier childPath = StoreUtils.append(path, childId); - resolveChildOperation(childId).checkApplicable(childPath,childMod, childMeta); - } - } - - @Override - protected void checkMergeApplicable(final InstanceIdentifier path, final NodeModification modification, - final Optional current) throws DataPreconditionFailedException { - if(current.isPresent()) { - checkChildPreconditions(path,modification,current); - } - } - - @SuppressWarnings("rawtypes") - protected abstract NormalizedNodeContainerBuilder createBuilder(NormalizedNode original); - } + protected abstract TreeNode applySubtreeChange(ModifiedNode modification, + TreeNode currentMeta, Version subtreeVersion); - public static abstract class DataNodeContainerModificationStrategy extends NormalizedNodeContainerModificationStrategy { + protected abstract void checkSubtreeModificationApplicable(InstanceIdentifier path, final NodeModification modification, + final Optional current) throws DataPreconditionFailedException; - private final T schema; - private final LoadingCache childCache = CacheBuilder.newBuilder() - .build(CacheLoader.from(new Function() { - - @Override - public ModificationApplyOperation apply(final PathArgument identifier) { - if (identifier instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) { - return from(schema, (AugmentationTarget) schema, (AugmentationIdentifier) identifier); - } - - DataSchemaNode child = schema.getDataChildByName(identifier.getNodeType()); - if (child == null) { - return null; - } - return from(child); - } - })); - - protected DataNodeContainerModificationStrategy(final T schema, - final Class> nodeClass) { - super(nodeClass); - this.schema = schema; - } - - protected T getSchema() { - return schema; - } - - @Override - public Optional getChild(final PathArgument identifier) { - try { - return Optional. fromNullable(childCache.get(identifier)); - } catch (ExecutionException e) { - return Optional.absent(); - } - } - - @Override - @SuppressWarnings("rawtypes") - protected abstract DataContainerNodeBuilder createBuilder(NormalizedNode original); - - @Override - public String toString() { - return getClass().getSimpleName() + " [" + schema + "]"; - } - - } - - public static class ContainerModificationStrategy extends DataNodeContainerModificationStrategy { - - public ContainerModificationStrategy(final ContainerSchemaNode schemaNode) { - super(schemaNode, ContainerNode.class); - } - - @Override - @SuppressWarnings("rawtypes") - protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { - checkArgument(original instanceof ContainerNode); - return ImmutableContainerNodeBuilder.create((ContainerNode) original); - } - } - - public static class UnkeyedListItemModificationStrategy extends DataNodeContainerModificationStrategy { - - public UnkeyedListItemModificationStrategy(final ListSchemaNode schemaNode) { - super(schemaNode, UnkeyedListEntryNode.class); - } - - @Override - @SuppressWarnings("rawtypes") - protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { - checkArgument(original instanceof UnkeyedListEntryNode); - return ImmutableUnkeyedListEntryNodeBuilder.create((UnkeyedListEntryNode) original); - } - } - - public static class AugmentationModificationStrategy extends DataNodeContainerModificationStrategy { - - protected AugmentationModificationStrategy(final AugmentationSchema schema, final DataNodeContainer resolved) { - super(createAugmentProxy(schema,resolved), AugmentationNode.class); - } - - @Override - @SuppressWarnings("rawtypes") - protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { - checkArgument(original instanceof AugmentationNode); - return ImmutableAugmentationNodeBuilder.create((AugmentationNode) original); - } - } - - public static class ChoiceModificationStrategy extends NormalizedNodeContainerModificationStrategy { - - private final Map childNodes; - - public ChoiceModificationStrategy(final ChoiceNode schemaNode) { - super(org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode.class); - ImmutableMap.Builder child = ImmutableMap.builder(); - - for (ChoiceCaseNode caze : schemaNode.getCases()) { - for (DataSchemaNode cazeChild : caze.getChildNodes()) { - SchemaAwareApplyOperation childNode = from(cazeChild); - child.put(new NodeIdentifier(cazeChild.getQName()), childNode); - } - } - childNodes = child.build(); - } - - @Override - public Optional getChild(final PathArgument child) { - return Optional.fromNullable(childNodes.get(child)); - } - - @Override - @SuppressWarnings("rawtypes") - protected DataContainerNodeBuilder createBuilder(final NormalizedNode original) { - checkArgument(original instanceof org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode); - return ImmutableChoiceNodeBuilder.create((org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode) original); - } - } - - public static class ListEntryModificationStrategy extends DataNodeContainerModificationStrategy { - - protected ListEntryModificationStrategy(final ListSchemaNode schema) { - super(schema, MapEntryNode.class); - } - - @Override - @SuppressWarnings("rawtypes") - protected final DataContainerNodeBuilder createBuilder(final NormalizedNode original) { - checkArgument(original instanceof MapEntryNode); - return ImmutableMapEntryNodeBuilder.create((MapEntryNode) original); - } - } - - public static class UnorderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy { - - private final Optional entryStrategy; - - @SuppressWarnings({ "unchecked", "rawtypes" }) - protected UnorderedLeafSetModificationStrategy(final LeafListSchemaNode schema) { - super((Class) LeafSetNode.class); - entryStrategy = Optional. of(new LeafSetEntryModificationStrategy(schema)); - } - - @SuppressWarnings("rawtypes") - @Override - protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { - checkArgument(original instanceof LeafSetNode); - return ImmutableLeafSetNodeBuilder.create((LeafSetNode) original); - } - - @Override - public Optional getChild(final PathArgument identifier) { - if (identifier instanceof NodeWithValue) { - return entryStrategy; - } - return Optional.absent(); - } - } - - public static class OrderedLeafSetModificationStrategy extends NormalizedNodeContainerModificationStrategy { - - private final Optional entryStrategy; - - @SuppressWarnings({ "unchecked", "rawtypes" }) - protected OrderedLeafSetModificationStrategy(final LeafListSchemaNode schema) { - super((Class) LeafSetNode.class); - entryStrategy = Optional. of(new LeafSetEntryModificationStrategy(schema)); - } - - @SuppressWarnings("rawtypes") - @Override - protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { - checkArgument(original instanceof OrderedLeafSetNode); - return ImmutableOrderedLeafSetNodeBuilder.create((OrderedLeafSetNode) original); - } - - @Override - public Optional getChild(final PathArgument identifier) { - if (identifier instanceof NodeWithValue) { - return entryStrategy; - } - return Optional.absent(); - } - } + protected abstract void verifyWrittenStructure(NormalizedNode writtenValue); public static class UnkeyedListModificationStrategy extends SchemaAwareApplyOperation { @@ -638,21 +230,21 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { } @Override - protected StoreMetadataNode applyMerge(final NodeModification modification, final StoreMetadataNode currentMeta, - final UnsignedLong subtreeVersion) { + protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta, + final Version subtreeVersion) { return applyWrite(modification, Optional.of(currentMeta), subtreeVersion); } @Override - protected StoreMetadataNode applySubtreeChange(final NodeModification modification, - final StoreMetadataNode currentMeta, final UnsignedLong subtreeVersion) { + protected TreeNode applySubtreeChange(final ModifiedNode modification, + final TreeNode currentMeta, final Version subtreeVersion) { throw new UnsupportedOperationException("UnkeyedList does not support subtree change."); } @Override - protected StoreMetadataNode applyWrite(final NodeModification modification, - final Optional currentMeta, final UnsignedLong subtreeVersion) { - return StoreMetadataNode.createRecursively(modification.getWrittenValue(), subtreeVersion); + protected TreeNode applyWrite(final ModifiedNode modification, + final Optional currentMeta, final Version subtreeVersion) { + return TreeNodeFactory.createTreeNode(modification.getWrittenValue(), subtreeVersion); } @Override @@ -669,86 +261,9 @@ abstract class SchemaAwareApplyOperation implements ModificationApplyOperation { } @Override - protected void checkSubtreeModificationApplicable(final InstanceIdentifier path,final NodeModification modification, - final Optional current) throws DataPreconditionFailedException { + protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { throw new DataPreconditionFailedException(path, "Subtree modification is not allowed."); } - - } - - public static class UnorderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy { - - private final Optional entryStrategy; - - protected UnorderedMapModificationStrategy(final ListSchemaNode schema) { - super(MapNode.class); - entryStrategy = Optional. of(new ListEntryModificationStrategy(schema)); - } - - @SuppressWarnings("rawtypes") - @Override - protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { - checkArgument(original instanceof MapNode); - return ImmutableMapNodeBuilder.create((MapNode) original); - } - - @Override - public Optional getChild(final PathArgument identifier) { - if (identifier instanceof NodeIdentifierWithPredicates) { - return entryStrategy; - } - return Optional.absent(); - } - - @Override - public String toString() { - return "UnorderedMapModificationStrategy [entry=" + entryStrategy + "]"; - } } - - public static class OrderedMapModificationStrategy extends NormalizedNodeContainerModificationStrategy { - - private final Optional entryStrategy; - - protected OrderedMapModificationStrategy(final ListSchemaNode schema) { - super(OrderedMapNode.class); - entryStrategy = Optional. of(new ListEntryModificationStrategy(schema)); - } - - @SuppressWarnings("rawtypes") - @Override - protected NormalizedNodeContainerBuilder createBuilder(final NormalizedNode original) { - checkArgument(original instanceof OrderedMapNode); - return ImmutableOrderedMapNodeBuilder.create((OrderedMapNode) original); - } - - @Override - public Optional getChild(final PathArgument identifier) { - if (identifier instanceof NodeIdentifierWithPredicates) { - return entryStrategy; - } - return Optional.absent(); - } - - @Override - public String toString() { - return "OrderedMapModificationStrategy [entry=" + entryStrategy + "]"; - } - } - - public static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) { - Set realChildSchemas = new HashSet<>(); - for(DataSchemaNode augChild : schema.getChildNodes()) { - realChildSchemas.add(resolved.getDataChildByName(augChild.getQName())); - } - return new AugmentationSchemaProxy(schema, realChildSchemas); - } - - public static boolean checkDataPrecondition(final InstanceIdentifier path, final boolean condition, final String message) throws DataPreconditionFailedException { - if(!condition) { - throw new DataPreconditionFailedException(path, message); - } - return condition; - } - } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/StoreMetadataNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/StoreMetadataNode.java deleted file mode 100644 index 695a1f1dd3..0000000000 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/StoreMetadataNode.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; - -import static com.google.common.base.Preconditions.checkState; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.opendaylight.yangtools.concepts.Identifiable; -import org.opendaylight.yangtools.concepts.Immutable; -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; -import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer; - -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.primitives.UnsignedLong; - -class StoreMetadataNode implements Immutable, Identifiable { - private final Map children; - private final UnsignedLong nodeVersion; - private final UnsignedLong subtreeVersion; - private final NormalizedNode data; - - /** - * - * @param data - * @param nodeVersion - * @param subtreeVersion - * @param children Map of children, must not be modified externally - */ - private StoreMetadataNode(final NormalizedNode data, final UnsignedLong nodeVersion, - final UnsignedLong subtreeVersion, final Map children) { - this.nodeVersion = Preconditions.checkNotNull(nodeVersion); - this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion); - this.data = Preconditions.checkNotNull(data); - this.children = Preconditions.checkNotNull(children); - } - - public static StoreMetadataNode createEmpty(final NormalizedNode data) { - return new StoreMetadataNode(data, UnsignedLong.ZERO, UnsignedLong.ZERO, - Collections.emptyMap()); - } - - public static Builder builder(final UnsignedLong version) { - return new Builder(version); - } - - public static Builder builder(final StoreMetadataNode node) { - return new Builder(node); - } - - public UnsignedLong getNodeVersion() { - return this.nodeVersion; - } - - @Override - public PathArgument getIdentifier() { - return data.getIdentifier(); - } - - public UnsignedLong getSubtreeVersion() { - return subtreeVersion; - } - - public NormalizedNode getData() { - return this.data; - } - - Optional getChild(final PathArgument key) { - return Optional.fromNullable(children.get(key)); - } - - @Override - public String toString() { - return "StoreMetadataNode [identifier=" + getIdentifier() + ", nodeVersion=" + nodeVersion + "]"; - } - - public static final StoreMetadataNode createRecursively(final NormalizedNode node, - final UnsignedLong version) { - Builder builder = builder(version) // - .setSubtreeVersion(version) // - .setData(node); - if (node instanceof NormalizedNodeContainer) { - - @SuppressWarnings("unchecked") - NormalizedNodeContainer> nodeContainer = (NormalizedNodeContainer>) node; - for (NormalizedNode subNode : nodeContainer.getValue()) { - builder.add(createRecursively(subNode, version)); - } - } - return builder.build(); - } - - public static class Builder { - - private final UnsignedLong nodeVersion; - private UnsignedLong subtreeVersion; - private NormalizedNode data; - private Map children; - private boolean dirty = false; - - private Builder(final UnsignedLong version) { - this.nodeVersion = Preconditions.checkNotNull(version); - children = new HashMap<>(); - } - - private Builder(final StoreMetadataNode node) { - this.nodeVersion = node.getNodeVersion(); - children = new HashMap<>(node.children); - } - - public Builder setSubtreeVersion(final UnsignedLong version) { - this.subtreeVersion = version; - return this; - } - - public Builder setData(final NormalizedNode data) { - this.data = data; - return this; - } - - public Builder add(final StoreMetadataNode node) { - if (dirty) { - children = new HashMap<>(children); - dirty = false; - } - children.put(node.getIdentifier(), node); - return this; - } - - public Builder remove(final PathArgument id) { - if (dirty) { - children = new HashMap<>(children); - dirty = false; - } - children.remove(id); - return this; - } - - public StoreMetadataNode build() { - checkState(data != null, "Data node should not be null."); - checkState(subtreeVersion.compareTo(nodeVersion) >= 0, - "Subtree version must be equals or greater than node version."); - dirty = true; - return new StoreMetadataNode(data, nodeVersion, subtreeVersion, children); - } - } - -} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/StoreNodeCompositeBuilder.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/StoreNodeCompositeBuilder.java deleted file mode 100644 index 19debbb990..0000000000 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/StoreNodeCompositeBuilder.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; - -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder; - -import com.google.common.base.Preconditions; -import com.google.common.primitives.UnsignedLong; - -/** - * - * Helper builder - * - * - */ -@SuppressWarnings("rawtypes") -class StoreNodeCompositeBuilder { - - private final StoreMetadataNode.Builder metadata; - - private final NormalizedNodeContainerBuilder data; - - private StoreNodeCompositeBuilder(final UnsignedLong version, final NormalizedNodeContainerBuilder nodeBuilder) { - this.metadata = StoreMetadataNode.builder(version); - this.data = Preconditions.checkNotNull(nodeBuilder); - } - - private StoreNodeCompositeBuilder(final NormalizedNodeContainerBuilder nodeBuilder, final StoreMetadataNode currentMeta) { - this.metadata = StoreMetadataNode.builder(currentMeta); - this.data = Preconditions.checkNotNull(nodeBuilder); - } - - @SuppressWarnings("unchecked") - public StoreNodeCompositeBuilder add(final StoreMetadataNode node) { - metadata.add(node); - data.addChild(node.getData()); - return this; - } - - @SuppressWarnings("unchecked") - public StoreNodeCompositeBuilder remove(final PathArgument id) { - metadata.remove(id); - data.removeChild(id); - return this; - } - - public StoreMetadataNode build() { - return metadata.setData(data.build()).build(); - } - - public static StoreNodeCompositeBuilder create(final UnsignedLong version, final NormalizedNodeContainerBuilder nodeBuilder) { - return new StoreNodeCompositeBuilder(version, nodeBuilder); - } - - public static StoreNodeCompositeBuilder create(final NormalizedNodeContainerBuilder nodeBuilder, final StoreMetadataNode currentMeta) { - return new StoreNodeCompositeBuilder(nodeBuilder, currentMeta); - } - - @SuppressWarnings("unchecked") - public StoreNodeCompositeBuilder setIdentifier(final PathArgument identifier) { - data.withNodeIdentifier(identifier); - return this; - } - - public StoreNodeCompositeBuilder setSubtreeVersion(final UnsignedLong updatedSubtreeVersion) { - metadata.setSubtreeVersion(updatedSubtreeVersion); - return this; - } -} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ValueNodeModificationStrategy.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ValueNodeModificationStrategy.java new file mode 100644 index 0000000000..5f68782a2e --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ValueNodeModificationStrategy.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.dom.store.impl.tree.data; + +import static com.google.common.base.Preconditions.checkArgument; + +import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataPreconditionFailedException; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; +import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; + +import com.google.common.base.Optional; + +abstract class ValueNodeModificationStrategy extends SchemaAwareApplyOperation { + + private final T schema; + private final Class> nodeClass; + + protected ValueNodeModificationStrategy(final T schema, final Class> nodeClass) { + super(); + this.schema = schema; + this.nodeClass = nodeClass; + } + + @Override + protected void verifyWrittenStructure(final NormalizedNode writtenValue) { + checkArgument(nodeClass.isInstance(writtenValue), "Node should must be of type %s", nodeClass); + } + + @Override + public Optional getChild(final PathArgument child) { + throw new UnsupportedOperationException("Node " + schema.getPath() + + "is leaf type node. Child nodes not allowed"); + } + + @Override + protected TreeNode applySubtreeChange(final ModifiedNode modification, + final TreeNode currentMeta, final Version subtreeVersion) { + throw new UnsupportedOperationException("Node " + schema.getPath() + + "is leaf type node. Subtree change is not allowed."); + } + + @Override + protected TreeNode applyMerge(final ModifiedNode modification, final TreeNode currentMeta, + final Version subtreeVersion) { + // Just overwrite whatever was there + return applyWrite(modification, null, subtreeVersion); + } + + @Override + protected TreeNode applyWrite(final ModifiedNode modification, + final Optional currentMeta, final Version subtreeVersion) { + return TreeNodeFactory.createTreeNode(modification.getWrittenValue(), subtreeVersion); + } + + @Override + protected void checkSubtreeModificationApplicable(final InstanceIdentifier path, final NodeModification modification, + final Optional current) throws DataPreconditionFailedException { + throw new DataPreconditionFailedException(path, "Subtree modification is not allowed."); + } + + public static class LeafSetEntryModificationStrategy extends ValueNodeModificationStrategy { + @SuppressWarnings({ "unchecked", "rawtypes" }) + protected LeafSetEntryModificationStrategy(final LeafListSchemaNode schema) { + super(schema, (Class) LeafSetEntryNode.class); + } + } + + public static class LeafModificationStrategy extends ValueNodeModificationStrategy { + @SuppressWarnings({ "unchecked", "rawtypes" }) + protected LeafModificationStrategy(final LeafSchemaNode schema) { + super(schema, (Class) LeafNode.class); + } + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/AbstractTreeNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/AbstractTreeNode.java new file mode 100644 index 0000000000..1444f0c6a8 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/AbstractTreeNode.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.dom.store.impl.tree.spi; + +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +import com.google.common.base.Preconditions; + +/* + * A very basic data tree node. + */ +abstract class AbstractTreeNode implements TreeNode { + private final NormalizedNode data; + private final Version version; + + protected AbstractTreeNode(final NormalizedNode data, final Version version) { + this.data = Preconditions.checkNotNull(data); + this.version = Preconditions.checkNotNull(version); + } + + @Override + public PathArgument getIdentifier() { + return data.getIdentifier(); + } + + @Override + public final Version getVersion() { + return version; + } + + @Override + public final NormalizedNode getData() { + return data; + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ContainerNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ContainerNode.java new file mode 100644 index 0000000000..8f74f60498 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ContainerNode.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.dom.store.impl.tree.spi; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer; +import org.opendaylight.yangtools.yang.data.api.schema.OrderedNodeContainer; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; + +/** + * A TreeNode capable of holding child nodes. The fact that any of the children + * changed is tracked by the subtree version. + */ +final class ContainerNode extends AbstractTreeNode { + private final Map children; + private final Version subtreeVersion; + + protected ContainerNode(final NormalizedNode data, final Version version, + final Map children, final Version subtreeVersion) { + super(data, version); + this.children = Preconditions.checkNotNull(children); + this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion); + } + + @Override + public Version getSubtreeVersion() { + return subtreeVersion; + } + + @Override + public Optional getChild(final PathArgument key) { + return Optional.fromNullable(children.get(key)); + } + + @Override + public MutableTreeNode mutable() { + return new Mutable(this); + } + + private static final class Mutable implements MutableTreeNode { + private final Map children; + private final Version version; + private NormalizedNode data; + private Version subtreeVersion; + + private Mutable(final ContainerNode parent) { + this.data = parent.getData(); + this.children = new HashMap<>(parent.children); + this.subtreeVersion = parent.getSubtreeVersion(); + this.version = parent.getVersion(); + } + + @Override + public Optional getChild(final PathArgument child) { + return Optional.fromNullable(children.get(child)); + } + + @Override + public void setSubtreeVersion(final Version subtreeVersion) { + this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion); + } + + @Override + public void addChild(final TreeNode child) { + children.put(child.getIdentifier(), child); + } + + @Override + public void removeChild(final PathArgument id) { + children.remove(id); + } + + @Override + public TreeNode seal() { + final Map realChildren; + + if (children.isEmpty()) { + realChildren = Collections.emptyMap(); + } else { + realChildren = children; + } + + return new ContainerNode(data, version, realChildren, subtreeVersion); + } + + @Override + public void setData(final NormalizedNode data) { + this.data = Preconditions.checkNotNull(data); + } + } + + private static ContainerNode create(final Version version, final NormalizedNode data, + final Iterable> children) { + final Map map = new HashMap<>(); + + for (NormalizedNode child : children) { + map.put(child.getIdentifier(), TreeNodeFactory.createTreeNode(child, version)); + } + + return new ContainerNode(data, version, map, version); + } + + public static ContainerNode create(final Version version, final NormalizedNodeContainer> container) { + return create(version, container, container.getValue()); + } + + public static ContainerNode create(final Version version, final OrderedNodeContainer> container) { + return create(version, container, container.getValue()); + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/MutableTreeNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/MutableTreeNode.java new file mode 100644 index 0000000000..dd3672cf11 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/MutableTreeNode.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.dom.store.impl.tree.spi; + +import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +public interface MutableTreeNode extends StoreTreeNode { + void setData(NormalizedNode data); + void setSubtreeVersion(Version subtreeVersion); + void addChild(TreeNode child); + void removeChild(PathArgument id); + TreeNode seal(); +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNode.java new file mode 100644 index 0000000000..b0beb8168b --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNode.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.dom.store.impl.tree.spi; + +import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode; +import org.opendaylight.yangtools.concepts.Identifiable; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +/* + * A very basic data tree node. It has a version (when it was last modified), + * a subtree version (when any of its children were modified) and some read-only + * data. + */ +public interface TreeNode extends Identifiable, StoreTreeNode { + /** + * Get the data node version. + * + * @return Current data node version. + */ + Version getVersion(); + + /** + * Get the subtree version. + * + * @return Current subtree version. + */ + Version getSubtreeVersion(); + + /** + * Get a read-only view of the underlying data. + * + * @return Unmodifiable view of the underlying data. + */ + NormalizedNode getData(); + + /** + * Get a mutable, isolated copy of the node. + * + * @return Mutable copy + */ + MutableTreeNode mutable(); +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNodeFactory.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNodeFactory.java new file mode 100644 index 0000000000..c5d174caad --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/TreeNodeFactory.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.dom.store.impl.tree.spi; + +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer; +import org.opendaylight.yangtools.yang.data.api.schema.OrderedNodeContainer; + +public final class TreeNodeFactory { + private TreeNodeFactory() { + throw new UnsupportedOperationException("Utility class should not be instantiated"); + } + + /** + * Create a new AbstractTreeNode from a data node, descending recursively as needed. + * This method should only ever be used for new data. + * + * @param data data node + * @param version data node version + * @return new AbstractTreeNode instance, covering the data tree provided + */ + public static final TreeNode createTreeNode(final NormalizedNode data, final Version version) { + if (data instanceof NormalizedNodeContainer) { + @SuppressWarnings("unchecked") + NormalizedNodeContainer> container = (NormalizedNodeContainer>) data; + return ContainerNode.create(version, container); + + } + if (data instanceof OrderedNodeContainer) { + @SuppressWarnings("unchecked") + OrderedNodeContainer> container = (OrderedNodeContainer>) data; + return ContainerNode.create(version, container); + } + + return new ValueNode(data, version); + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ValueNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ValueNode.java new file mode 100644 index 0000000000..7194faadf6 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/ValueNode.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.dom.store.impl.tree.spi; + +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; + +final class ValueNode extends AbstractTreeNode { + private static final Logger LOG = LoggerFactory.getLogger(ValueNode.class); + + protected ValueNode(final NormalizedNode data, final Version version) { + super(data, version); + } + + @Override + public Optional getChild(final PathArgument childId) { + LOG.warn("Attempted to access child {} of value-node {}", childId, this); + return Optional.absent(); + } + + @Override + public Version getSubtreeVersion() { + return getVersion(); + } + + @Override + public MutableTreeNode mutable() { + /** + * Value nodes can only we read/written/delete, which does a straight + * replace. That means they don't haver need to be made mutable. + */ + throw new UnsupportedOperationException(String.format("Attempted to mutate value-node %s", this)); + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/Version.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/Version.java new file mode 100644 index 0000000000..09a35d3b1a --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/spi/Version.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.dom.store.impl.tree.spi; + +/** + * The concept of a version, either node version, or a subtree version. The + * only interface contract this class has is that no two versions are the + * same. + */ +public final class Version { + private Version() { + + } + + /** + * Create a new version, distinct from any other version. + * + * @return a new version. + */ + public Version next() { + return new Version(); + } + + /** + * Create an initial version. + * + * @return a new version. + */ + public static final Version initial() { + return new Version(); + } +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/GlobalBundleScanningSchemaServiceImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/GlobalBundleScanningSchemaServiceImpl.java index dab8fd5cd1..430963a884 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/GlobalBundleScanningSchemaServiceImpl.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/GlobalBundleScanningSchemaServiceImpl.java @@ -10,7 +10,10 @@ package org.opendaylight.controller.sal.dom.broker; import static com.google.common.base.Preconditions.checkState; import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; import java.util.Enumeration; +import java.util.List; import org.opendaylight.controller.sal.core.api.model.SchemaService; import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProvider; @@ -33,54 +36,34 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Optional; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSet.Builder; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; -public class GlobalBundleScanningSchemaServiceImpl implements // - SchemaContextProvider, // - SchemaService, // - ServiceTrackerCustomizer, // - AutoCloseable { - private static final Logger logger = LoggerFactory.getLogger(GlobalBundleScanningSchemaServiceImpl.class); - - private ListenerRegistry listeners; - - private BundleContext context; - private final BundleScanner scanner = new BundleScanner(); - - private BundleTracker>> bundleTracker; +public class GlobalBundleScanningSchemaServiceImpl implements SchemaContextProvider, SchemaService, ServiceTrackerCustomizer, AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(GlobalBundleScanningSchemaServiceImpl.class); + private final ListenerRegistry listeners = new ListenerRegistry<>(); private final URLSchemaContextResolver contextResolver = new URLSchemaContextResolver(); + private final BundleScanner scanner = new BundleScanner(); + private final BundleContext context; private ServiceTracker listenerTracker; - + private BundleTracker>> bundleTracker; private boolean starting = true; - public ListenerRegistry getListeners() { - return listeners; - } - - public void setListeners(final ListenerRegistry listeners) { - this.listeners = listeners; + public GlobalBundleScanningSchemaServiceImpl(final BundleContext context) { + this.context = Preconditions.checkNotNull(context); } public BundleContext getContext() { return context; } - public void setContext(final BundleContext context) { - this.context = context; - } - public void start() { checkState(context != null); - if (listeners == null) { - listeners = new ListenerRegistry<>(); - } listenerTracker = new ServiceTracker<>(context, SchemaServiceListener.class, GlobalBundleScanningSchemaServiceImpl.this); - bundleTracker = new BundleTracker>>(context, BundleEvent.RESOLVED - | BundleEvent.UNRESOLVED, scanner); + bundleTracker = new BundleTracker<>(context, BundleEvent.RESOLVED | BundleEvent.UNRESOLVED, scanner); bundleTracker.open(); listenerTracker.open(); starting = false; @@ -139,7 +122,7 @@ public class GlobalBundleScanningSchemaServiceImpl implements // try { listener.getInstance().onGlobalContextUpdated(snapshot); } catch (Exception e) { - logger.error("Exception occured during invoking listener", e); + LOG.error("Exception occured during invoking listener", e); } } if (services != null) { @@ -148,37 +131,47 @@ public class GlobalBundleScanningSchemaServiceImpl implements // try { listener.onGlobalContextUpdated(snapshot); } catch (Exception e) { - logger.error("Exception occured during invoking listener", e); + LOG.error("Exception occured during invoking listener {}", listener, e); } } } } - private class BundleScanner implements BundleTrackerCustomizer>> { + private class BundleScanner implements BundleTrackerCustomizer>> { @Override - public ImmutableSet> addingBundle(final Bundle bundle, final BundleEvent event) { + public Iterable> addingBundle(final Bundle bundle, final BundleEvent event) { if (bundle.getBundleId() == 0) { - return ImmutableSet.of(); + return Collections.emptyList(); } - Enumeration enumeration = bundle.findEntries("META-INF/yang", "*.yang", false); - Builder> builder = ImmutableSet.> builder(); - while (enumeration != null && enumeration.hasMoreElements()) { - Registration reg = contextResolver.registerSource(enumeration.nextElement()); - builder.add(reg); + final Enumeration enumeration = bundle.findEntries("META-INF/yang", "*.yang", false); + if (enumeration == null) { + return Collections.emptyList(); } - ImmutableSet> urls = builder.build(); - if(urls.isEmpty()) { - return urls; + + final List> urls = new ArrayList<>(); + while (enumeration.hasMoreElements()) { + final URL u = enumeration.nextElement(); + try { + urls.add(contextResolver.registerSource(u)); + LOG.debug("Registered {}", u); + } catch (Exception e) { + LOG.warn("Failed to register {}, ignoring it", e); + } } - tryToUpdateSchemaContext(); - return urls; + + if (!urls.isEmpty()) { + LOG.debug("Loaded {} new URLs, rebuilding schema context", urls.size()); + tryToUpdateSchemaContext(); + } + + return ImmutableList.copyOf(urls); } @Override - public void modifiedBundle(final Bundle bundle, final BundleEvent event, final ImmutableSet> object) { - logger.debug("Modified bundle {} {} {}", bundle, event, object); + public void modifiedBundle(final Bundle bundle, final BundleEvent event, final Iterable> object) { + LOG.debug("Modified bundle {} {} {}", bundle, event, object); } /** @@ -188,12 +181,12 @@ public class GlobalBundleScanningSchemaServiceImpl implements // */ @Override - public synchronized void removedBundle(final Bundle bundle, final BundleEvent event, final ImmutableSet> urls) { + public synchronized void removedBundle(final Bundle bundle, final BundleEvent event, final Iterable> urls) { for (Registration url : urls) { try { url.close(); } catch (Exception e) { - e.printStackTrace(); + LOG.warn("Failed do unregister URL {}, proceeding", url, e); } } tryToUpdateSchemaContext(); @@ -212,7 +205,7 @@ public class GlobalBundleScanningSchemaServiceImpl implements // } public synchronized void tryToUpdateSchemaContext() { - if(starting ) { + if (starting) { return; } Optional schema = contextResolver.tryToUpdateSchemaContext(); diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java index d8315568be..1a572d157d 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java @@ -45,9 +45,9 @@ import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableSet; public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator implements // - DataStore, // - SchemaContextListener, // - AutoCloseable { +DataStore, // +SchemaContextListener, // +AutoCloseable { private final static Logger LOG = LoggerFactory.getLogger(SchemaAwareDataStoreAdapter.class); @@ -56,7 +56,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator reader = new MergeFirstLevelReader(); @Override - public boolean containsConfigurationPath(InstanceIdentifier path) { + public boolean containsConfigurationPath(final InstanceIdentifier path) { try { getDelegateReadLock().lock(); return getDelegate().containsConfigurationPath(path); @@ -67,7 +67,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator requestCommit( - DataModification modification) { + final DataModification modification) { validateAgainstSchema(modification); NormalizedDataModification cleanedUp = prepareMergedTransaction(modification); cleanedUp.status = TransactionStatus.SUBMITED; @@ -122,11 +122,11 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator modification) { + private void validateAgainstSchema(final DataModification modification) { if (!validationEnabled) { return; } @@ -138,12 +138,12 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator original) { + final DataModification original) { NormalizedDataModification normalized = new NormalizedDataModification(original); LOG.trace("Transaction: {} Removed Configuration {}, Removed Operational {}", original.getIdentifier(), original.getRemovedConfigurationData(), original.getRemovedConfigurationData()); @@ -194,7 +194,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator getConfigurationSubpaths(InstanceIdentifier entry) { + private Iterable getConfigurationSubpaths(final InstanceIdentifier entry) { // FIXME: This should be replaced by index Iterable paths = getStoredConfigurationPaths(); @@ -202,15 +202,15 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator getOperationalSubpaths(InstanceIdentifier entry) { + public Iterable getOperationalSubpaths(final InstanceIdentifier entry) { // FIXME: This should be indexed Iterable paths = getStoredOperationalPaths(); return getChildrenPaths(entry, paths); } - private static final Iterable getChildrenPaths(InstanceIdentifier entry, - Iterable paths) { + private static final Iterable getChildrenPaths(final InstanceIdentifier entry, + final Iterable paths) { ImmutableSet.Builder children = ImmutableSet.builder(); for (InstanceIdentifier potential : paths) { if (entry.contains(potential)) { @@ -222,7 +222,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator> preparationComparator = new Comparator>() { @Override - public int compare(Entry o1, Entry o2) { + public int compare(final Entry o1, final Entry o2) { InstanceIdentifier o1Key = o1.getKey(); InstanceIdentifier o2Key = o2.getKey(); return Integer.compare(o1Key.getPath().size(), o2Key.getPath().size()); @@ -242,7 +242,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator> childNodes = new ArrayList>(); if (original != null) { - childNodes.addAll(original.getChildren()); + childNodes.addAll(original.getValue()); qname = original.getNodeType(); } else { qname = path.getPath().get(path.getPath().size() - 1).getNodeType(); @@ -251,7 +251,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator directChildren = FluentIterable.from(getStoredConfigurationPaths()) .filter(new Predicate() { @Override - public boolean apply(InstanceIdentifier input) { + public boolean apply(final InstanceIdentifier input) { if (path.contains(input)) { int nesting = input.getPath().size() - path.getPath().size(); if (nesting == 1) { @@ -285,7 +285,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator> childNodes = new ArrayList>(); if (original != null) { - childNodes.addAll(original.getChildren()); + childNodes.addAll(original.getValue()); qname = original.getNodeType(); } else { qname = path.getPath().get(path.getPath().size() - 1).getNodeType(); @@ -294,7 +294,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator directChildren = FluentIterable.from(getStoredOperationalPaths()) .filter(new Predicate() { @Override - public boolean apply(InstanceIdentifier input) { + public boolean apply(final InstanceIdentifier input) { if (path.contains(input)) { int nesting = input.getPath().size() - path.getPath().size(); if (nesting == 1) { @@ -326,7 +326,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator original) { + public NormalizedDataModification(final DataModification original) { super(getDelegate()); identifier = original; status = TransactionStatus.NEW; @@ -339,7 +339,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator paths = getOperationalSubpaths(entry); removeOperationalData(entry); for (InstanceIdentifier potential : paths) { @@ -347,7 +347,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator paths = getConfigurationSubpaths(entry); removeConfigurationData(entry); for (InstanceIdentifier potential : paths) { @@ -355,11 +355,11 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator child : entryData.getChildren()) { + for (Node child : entryData.getValue()) { InstanceIdentifier subEntryId = InstanceIdentifier.builder(entryKey).node(child.getNodeType()) .toInstance(); if (child instanceof CompositeNode) { @@ -438,7 +438,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator getValuesFromListSchema(ListSchemaNode listSchema, CompositeNode entryData) { + private Map getValuesFromListSchema(final ListSchemaNode listSchema, final CompositeNode entryData) { List keyDef = listSchema.getKeyDefinition(); if (keyDef != null && !keyDef.isEmpty()) { Map map = new HashMap(); diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceActivator.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceActivator.java index 344b3f3276..f893f96d18 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceActivator.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/SchemaServiceActivator.java @@ -17,20 +17,19 @@ import org.osgi.framework.ServiceRegistration; public class SchemaServiceActivator implements BundleActivator { - + private ServiceRegistration schemaServiceReg; private GlobalBundleScanningSchemaServiceImpl schemaService; @Override - public void start(BundleContext context) throws Exception { - schemaService = new GlobalBundleScanningSchemaServiceImpl(); - schemaService.setContext(context); + public void start(final BundleContext context) { + schemaService = new GlobalBundleScanningSchemaServiceImpl(context); schemaService.start(); schemaServiceReg = context.registerService(SchemaService.class, schemaService, new Hashtable()); } - + @Override - public void stop(BundleContext context) throws Exception { + public void stop(final BundleContext context) throws Exception { schemaServiceReg.unregister(); schemaService.close(); } diff --git a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationMetadataTreeTest.java b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationMetadataTreeTest.java index 8940e55d32..4fb190fc82 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationMetadataTreeTest.java +++ b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/ModificationMetadataTreeTest.java @@ -29,6 +29,8 @@ import org.junit.Test; import org.opendaylight.controller.md.sal.dom.store.impl.TestModel; import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTree; import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNodeFactory; +import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.Version; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; @@ -40,7 +42,6 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableCo import org.opendaylight.yangtools.yang.model.api.SchemaContext; import com.google.common.base.Optional; -import com.google.common.primitives.UnsignedLong; /** * @@ -149,7 +150,7 @@ public class ModificationMetadataTreeTest { @Test public void basicReadWrites() { DataTreeModification modificationTree = new InMemoryDataTreeModification(new InMemoryDataTreeSnapshot(schemaContext, - StoreMetadataNode.createRecursively(createDocumentOne(), UnsignedLong.valueOf(5)), applyOper), + TreeNodeFactory.createTreeNode(createDocumentOne(), Version.initial()), applyOper), new SchemaAwareApplyOperationRoot(schemaContext)); Optional> originalBarNode = modificationTree.readNode(OUTER_LIST_2_PATH); assertTrue(originalBarNode.isPresent()); diff --git a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperationRoot.java b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperationRoot.java index f2cc533207..03ece2f5e0 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperationRoot.java +++ b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/SchemaAwareApplyOperationRoot.java @@ -14,7 +14,7 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableCo import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaContext; -public class SchemaAwareApplyOperationRoot extends SchemaAwareApplyOperation.DataNodeContainerModificationStrategy { +public class SchemaAwareApplyOperationRoot extends DataNodeContainerModificationStrategy { private final SchemaContext context; public SchemaAwareApplyOperationRoot(final SchemaContext context) { diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTwoPhaseCommitTransaction.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTwoPhaseCommitTransaction.java index 8a74b17ac4..34cd9aa47b 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTwoPhaseCommitTransaction.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTwoPhaseCommitTransaction.java @@ -35,7 +35,6 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifie import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.Node; import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode; -import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl; import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,9 +51,9 @@ class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransaction modification, - boolean candidateSupported, boolean rollbackOnErrorSupported) { + public NetconfDeviceTwoPhaseCommitTransaction(final NetconfDevice device, + final DataModification modification, + final boolean candidateSupported, final boolean rollbackOnErrorSupported) { this.device = Preconditions.checkNotNull(device); this.modification = Preconditions.checkNotNull(modification); this.candidateSupported = candidateSupported; @@ -70,15 +69,15 @@ class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransactionabsent(), Optional.of(value))); } - private void sendDelete(InstanceIdentifier toDelete) throws InterruptedException, ExecutionException { + private void sendDelete(final InstanceIdentifier toDelete) throws InterruptedException, ExecutionException { sendEditRpc(createEditStructure(toDelete, Optional.of("delete"), Optional. absent())); } - private void sendEditRpc(CompositeNode editStructure) throws InterruptedException, ExecutionException { + private void sendEditRpc(final CompositeNode editStructure) throws InterruptedException, ExecutionException { CompositeNodeBuilder builder = configurationRpcBuilder(); builder.setQName(NETCONF_EDIT_CONFIG_QNAME); builder.add(editStructure); @@ -108,8 +107,8 @@ class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransaction operation, - Optional lastChildOverride) { + private CompositeNode createEditStructure(final InstanceIdentifier dataPath, final Optional operation, + final Optional lastChildOverride) { List path = dataPath.getPath(); List reversed = Lists.reverse(path); CompositeNode previous = null; @@ -130,7 +129,7 @@ class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransaction> children = lastChildOverride.get().getChildren(); + List> children = lastChildOverride.get().getValue(); for(Node child : children) { if(!predicates.containsKey(child.getKey())) { builder.add(child); diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java index f76ec28624..2b3a992fc1 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.java @@ -7,12 +7,6 @@ */ package org.opendaylight.controller.sal.connect.netconf; -import com.google.common.base.Optional; -import com.google.common.base.Predicate; -import com.google.common.collect.Collections2; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; import java.net.URI; import java.util.ArrayList; import java.util.Collections; @@ -20,8 +14,10 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; + import javax.activation.UnsupportedDataTypeException; import javax.annotation.Nullable; + import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil; @@ -41,11 +37,16 @@ import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl; import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils; import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder; import org.opendaylight.yangtools.yang.model.api.NotificationDefinition; -import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.w3c.dom.Document; import org.w3c.dom.Element; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; + public class NetconfMapping { public static URI NETCONF_URI = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0"); @@ -91,7 +92,7 @@ public class NetconfMapping { static AtomicInteger messageId = new AtomicInteger(0); - static Node toFilterStructure(InstanceIdentifier identifier) { + static Node toFilterStructure(final InstanceIdentifier identifier) { Node previous = null; if (identifier.getPath().isEmpty()) { return null; @@ -108,7 +109,7 @@ public class NetconfMapping { return filter("subtree", previous); } - static Node toNode(NodeIdentifierWithPredicates argument, Node node) { + static Node toNode(final NodeIdentifierWithPredicates argument, final Node node) { List> list = new ArrayList<>(); for (Map.Entry arg : argument.getKeyValues().entrySet()) { list.add(new SimpleNodeTOImpl(arg.getKey(), null, arg.getValue())); @@ -119,7 +120,7 @@ public class NetconfMapping { return new CompositeNodeTOImpl(argument.getNodeType(), null, list); } - static Node toNode(PathArgument argument, Node node) { + static Node toNode(final PathArgument argument, final Node node) { if (node != null) { return new CompositeNodeTOImpl(argument.getNodeType(), null, Collections.> singletonList(node)); } else { @@ -127,14 +128,14 @@ public class NetconfMapping { } } - static CompositeNode toCompositeNode(NetconfMessage message, Optional ctx) { + static CompositeNode toCompositeNode(final NetconfMessage message, final Optional ctx) { // TODO: implement general normalization to normalize incoming Netconf // Message // for Schema Context counterpart return null; } - static CompositeNode toNotificationNode(NetconfMessage message, Optional ctx) { + static CompositeNode toNotificationNode(final NetconfMessage message, final Optional ctx) { if (ctx.isPresent()) { SchemaContext schemaContext = ctx.get(); Set notifications = schemaContext.getNotifications(); @@ -144,7 +145,7 @@ public class NetconfMapping { return null; } - static NetconfMessage toRpcMessage(QName rpc, CompositeNode node, Optional ctx) { + static NetconfMessage toRpcMessage(final QName rpc, final CompositeNode node, final Optional ctx) { CompositeNodeTOImpl rpcPayload = wrap(NETCONF_RPC_QNAME, flattenInput(node)); Document w3cPayload = null; try { @@ -164,8 +165,8 @@ public class NetconfMapping { if (input instanceof CompositeNode) { List> nodes = ImmutableList.> builder() // - .addAll(input.getChildren()) // - .addAll(Collections2.filter(node.getChildren(), new Predicate>() { + .addAll(input.getValue()) // + .addAll(Collections2.filter(node.getValue(), new Predicate>() { @Override public boolean apply(@Nullable final Node input) { return input.getNodeType() != inputQName; @@ -179,7 +180,7 @@ public class NetconfMapping { return input; } - static RpcResult toRpcResult(NetconfMessage message, final QName rpc, Optional context) { + static RpcResult toRpcResult(final NetconfMessage message, final QName rpc, final Optional context) { CompositeNode rawRpc; if (context.isPresent()) if (isDataRetrieQNameReply(rpc)) { @@ -196,7 +197,7 @@ public class NetconfMapping { rawRpc = it.toInstance(); // sys(xmlData) } else { - rawRpc = (CompositeNode) toCompositeNode(message, context); + rawRpc = toCompositeNode(message, context); } else { rawRpc = (CompositeNode) toCompositeNode(message.getDocument()); @@ -205,17 +206,17 @@ public class NetconfMapping { return Rpcs.getRpcResult(true, rawRpc, Collections. emptySet()); } - static Element getDataSubtree(Document doc) { + static Element getDataSubtree(final Document doc) { return (Element) doc.getElementsByTagNameNS(NETCONF_URI.toString(), "data").item(0); } - static boolean isDataRetrieQNameReply(QName it) { + static boolean isDataRetrieQNameReply(final QName it) { return NETCONF_URI == it.getNamespace() && (it.getLocalName() == NETCONF_GET_CONFIG_QNAME.getLocalName() || it.getLocalName() == NETCONF_GET_QNAME - .getLocalName()); + .getLocalName()); } - static CompositeNodeTOImpl wrap(QName name, Node node) { + static CompositeNodeTOImpl wrap(final QName name, final Node node) { if (node != null) { return new CompositeNodeTOImpl(name, null, Collections.> singletonList(node)); } else { @@ -223,7 +224,7 @@ public class NetconfMapping { } } - static CompositeNodeTOImpl wrap(QName name, Node additional, Node node) { + static CompositeNodeTOImpl wrap(final QName name, final Node additional, final Node node) { if (node != null) { return new CompositeNodeTOImpl(name, null, ImmutableList.of(additional, node)); } else { @@ -231,7 +232,7 @@ public class NetconfMapping { } } - static ImmutableCompositeNode filter(String type, Node node) { + static ImmutableCompositeNode filter(final String type, final Node node) { CompositeNodeBuilder it = ImmutableCompositeNode.builder(); // it.setQName(NETCONF_FILTER_QNAME); it.setAttribute(NETCONF_TYPE_QNAME, type); @@ -242,11 +243,11 @@ public class NetconfMapping { } } - public static Node toCompositeNode(Document document) { + public static Node toCompositeNode(final Document document) { return XmlDocumentUtils.toDomNode(document); } - public static void checkValidReply(NetconfMessage input, NetconfMessage output) { + public static void checkValidReply(final NetconfMessage input, final NetconfMessage output) { String inputMsgId = input.getDocument().getDocumentElement().getAttribute("message-id"); String outputMsgId = output.getDocument().getDocumentElement().getAttribute("message-id"); @@ -257,7 +258,7 @@ public class NetconfMapping { } } - public static void checkSuccessReply(NetconfMessage output) throws NetconfDocumentedException { + public static void checkSuccessReply(final NetconfMessage output) throws NetconfDocumentedException { if(NetconfMessageUtil.isErrorMessage(output)) { throw new IllegalStateException(String.format("Response contains error: %s", XmlUtil.toString(output.getDocument()))); } diff --git a/opendaylight/md-sal/sal-rest-connector/pom.xml b/opendaylight/md-sal/sal-rest-connector/pom.xml index c17a4b70cc..e4c7c0c647 100644 --- a/opendaylight/md-sal/sal-rest-connector/pom.xml +++ b/opendaylight/md-sal/sal-rest-connector/pom.xml @@ -47,6 +47,14 @@ org.opendaylight.yangtools yang-parser-impl + + org.opendaylight.yangtools.model + ietf-restconf + + + org.opendaylight.yangtools.model + ietf-yang-types-20130715 + org.slf4j slf4j-api diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java index d1441d7b9d..ea0f149d29 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java @@ -57,7 +57,7 @@ class JsonMapper { private MountInstance mountPoint; private final Logger logger = LoggerFactory.getLogger(JsonMapper.class); - public void write(JsonWriter writer, CompositeNode data, DataNodeContainer schema, MountInstance mountPoint) + public void write(final JsonWriter writer, final CompositeNode data, final DataNodeContainer schema, final MountInstance mountPoint) throws IOException { Preconditions.checkNotNull(writer); Preconditions.checkNotNull(data); @@ -81,12 +81,12 @@ class JsonMapper { foundLists.clear(); } - private void writeChildrenOfParent(JsonWriter writer, CompositeNode parent, DataNodeContainer parentSchema) + private void writeChildrenOfParent(final JsonWriter writer, final CompositeNode parent, final DataNodeContainer parentSchema) throws IOException { checkNotNull(parent); checkNotNull(parentSchema); - for (Node child : parent.getChildren()) { + for (Node child : parent.getValue()) { DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchema.getChildNodes()); if (childSchema == null) { @@ -122,17 +122,17 @@ class JsonMapper { } } - for (Node child : parent.getChildren()) { + for (Node child : parent.getValue()) { DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchema.getChildNodes()); if (childSchema instanceof LeafListSchemaNode) { - foundLeafLists.remove((LeafListSchemaNode) childSchema); + foundLeafLists.remove(childSchema); } else if (childSchema instanceof ListSchemaNode) { - foundLists.remove((ListSchemaNode) childSchema); + foundLists.remove(childSchema); } } } - private DataSchemaNode findFirstSchemaForNode(Node node, Set dataSchemaNode) { + private DataSchemaNode findFirstSchemaForNode(final Node node, final Set dataSchemaNode) { for (DataSchemaNode dsn : dataSchemaNode) { if (node.getNodeType().equals(dsn.getQName())) { return dsn; @@ -148,14 +148,14 @@ class JsonMapper { return null; } - private void writeContainer(JsonWriter writer, CompositeNode node, ContainerSchemaNode schema) throws IOException { + private void writeContainer(final JsonWriter writer, final CompositeNode node, final ContainerSchemaNode schema) throws IOException { writeName(node, schema, writer); writer.beginObject(); writeChildrenOfParent(writer, node, schema); writer.endObject(); } - private void writeList(JsonWriter writer, CompositeNode nodeParent, CompositeNode node, ListSchemaNode schema) + private void writeList(final JsonWriter writer, final CompositeNode nodeParent, final CompositeNode node, final ListSchemaNode schema) throws IOException { writeName(node, schema, writer); writer.beginArray(); @@ -176,8 +176,8 @@ class JsonMapper { writer.endArray(); } - private void writeLeafList(JsonWriter writer, CompositeNode nodeParent, SimpleNode node, - LeafListSchemaNode schema) throws IOException { + private void writeLeafList(final JsonWriter writer, final CompositeNode nodeParent, final SimpleNode node, + final LeafListSchemaNode schema) throws IOException { writeName(node, schema, writer); writer.beginArray(); @@ -188,13 +188,13 @@ class JsonMapper { writer.endArray(); } - private void writeLeaf(JsonWriter writer, SimpleNode node, LeafSchemaNode schema) throws IOException { + private void writeLeaf(final JsonWriter writer, final SimpleNode node, final LeafSchemaNode schema) throws IOException { writeName(node, schema, writer); writeValueOfNodeByType(writer, node, schema.getType(), schema); } - private void writeValueOfNodeByType(JsonWriter writer, SimpleNode node, TypeDefinition type, - DataSchemaNode schema) throws IOException { + private void writeValueOfNodeByType(final JsonWriter writer, final SimpleNode node, final TypeDefinition type, + final DataSchemaNode schema) throws IOException { TypeDefinition baseType = RestUtil.resolveBaseTypeFrom(type); @@ -245,7 +245,7 @@ class JsonMapper { } } - private void writeIdentityValuesDTOToJson(JsonWriter writer, IdentityValuesDTO valueDTO) throws IOException { + private void writeIdentityValuesDTOToJson(final JsonWriter writer, final IdentityValuesDTO valueDTO) throws IOException { StringBuilder result = new StringBuilder(); for (IdentityValue identityValue : valueDTO.getValuesWithNamespaces()) { result.append("/"); @@ -271,7 +271,7 @@ class JsonMapper { writer.value(result.toString()); } - private void writeModuleNameAndIdentifier(StringBuilder result, IdentityValue identityValue) { + private void writeModuleNameAndIdentifier(final StringBuilder result, final IdentityValue identityValue) { String moduleName = ControllerContext.getInstance().findModuleNameByNamespace( URI.create(identityValue.getNamespace())); if (moduleName != null && !moduleName.isEmpty()) { @@ -281,8 +281,8 @@ class JsonMapper { result.append(identityValue.getValue()); } - private void writeStringRepresentation(JsonWriter writer, SimpleNode node, TypeDefinition baseType, - Class requiredType) throws IOException { + private void writeStringRepresentation(final JsonWriter writer, final SimpleNode node, final TypeDefinition baseType, + final Class requiredType) throws IOException { Object value = node.getValue(); logger.debug("Value of " + baseType.getQName().getNamespace() + ":" + baseType.getQName().getLocalName() + " is not instance of " + requiredType.getClass() + " but is " + node.getValue().getClass()); @@ -293,13 +293,13 @@ class JsonMapper { } } - private void writeEmptyDataTypeToJson(JsonWriter writer) throws IOException { + private void writeEmptyDataTypeToJson(final JsonWriter writer) throws IOException { writer.beginArray(); writer.nullValue(); writer.endArray(); } - private void writeName(Node node, DataSchemaNode schema, JsonWriter writer) throws IOException { + private void writeName(final Node node, final DataSchemaNode schema, final JsonWriter writer) throws IOException { String nameForOutput = node.getNodeType().getLocalName(); if (schema.isAugmenting()) { ControllerContext contContext = ControllerContext.getInstance(); @@ -323,7 +323,7 @@ class JsonMapper { private static final long serialVersionUID = -3147729419814417666L; private final String value; - public NumberForJsonWriter(String value) { + public NumberForJsonWriter(final String value) { this.value = value; } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfProvider.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfProvider.java index 1870bdf0bf..2abd4b6a3a 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfProvider.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/RestconfProvider.java @@ -34,7 +34,6 @@ public class RestconfProvider implements BundleActivator, Provider, ServiceTrack private ListenerRegistration listenerRegistration; private ServiceTracker brokerServiceTrancker; private BundleContext bundleContext; - private ProviderSession session; private Thread webSocketServerThread; @Override @@ -70,7 +69,6 @@ public class RestconfProvider implements BundleActivator, Provider, ServiceTrack } } webSocketServerThread.interrupt(); - session.close(); brokerServiceTrancker.close(); } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java index e0ae788703..96ad528a0d 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/CompositeNodeWrapper.java @@ -34,21 +34,21 @@ public final class CompositeNodeWrapper implements NodeWrapper, C private QName name; private List> values = new ArrayList<>(); - public CompositeNodeWrapper(String localName) { + public CompositeNodeWrapper(final String localName) { this.localName = Preconditions.checkNotNull(localName); } - public CompositeNodeWrapper(URI namespace, String localName) { + public CompositeNodeWrapper(final URI namespace, final String localName) { this(localName); this.namespace = namespace; } - + @Override - public void setQname(QName name) { + public void setQname(final QName name) { Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies."); this.name = name; } - + @Override public QName getQname() { return name; @@ -71,26 +71,26 @@ public final class CompositeNodeWrapper implements NodeWrapper, C } @Override - public void setNamespace(URI namespace) { + public void setNamespace(final URI namespace) { Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies."); this.namespace = namespace; } - public void addValue(NodeWrapper value) { + public void addValue(final NodeWrapper value) { Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies."); values.add(value); } - public void removeValue(NodeWrapper value) { + public void removeValue(final NodeWrapper value) { Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies."); values.remove(value); } - + public List> getValues() { Preconditions.checkState(compositeNode == null, "Data can be inconsistent."); return Collections.unmodifiableList(values); } - + @Override public boolean isChangeAllowed() { return compositeNode == null ? true : false; @@ -103,13 +103,13 @@ public final class CompositeNodeWrapper implements NodeWrapper, C Preconditions.checkNotNull(namespace); name = new QName(namespace, localName); } - + List> nodeValues = new ArrayList<>(); for (NodeWrapper nodeWrapper : values) { nodeValues.add(nodeWrapper.unwrap()); } compositeNode = NodeFactory.createMutableCompositeNode(name, null, nodeValues, null, null); - + values = null; namespace = null; localName = null; @@ -123,6 +123,7 @@ public final class CompositeNodeWrapper implements NodeWrapper, C return unwrap().getNodeType(); } + @Deprecated @Override public CompositeNode getParent() { return unwrap().getParent(); @@ -138,38 +139,42 @@ public final class CompositeNodeWrapper implements NodeWrapper, C return unwrap().getModificationAction(); } + /** + * @deprecated Use {@link #getValue()} instead. + */ + @Deprecated @Override public List> getChildren() { - return unwrap().getChildren(); + return unwrap().getValue(); } @Override - public List getCompositesByName(QName children) { + public List getCompositesByName(final QName children) { return unwrap().getCompositesByName(children); } @Override - public List getCompositesByName(String children) { + public List getCompositesByName(final String children) { return unwrap().getCompositesByName(children); } @Override - public List> getSimpleNodesByName(QName children) { + public List> getSimpleNodesByName(final QName children) { return unwrap().getSimpleNodesByName(children); } @Override - public List> getSimpleNodesByName(String children) { + public List> getSimpleNodesByName(final String children) { return unwrap().getSimpleNodesByName(children); } @Override - public CompositeNode getFirstCompositeByName(QName container) { + public CompositeNode getFirstCompositeByName(final QName container) { return unwrap().getFirstCompositeByName(container); } @Override - public SimpleNode getFirstSimpleByName(QName leaf) { + public SimpleNode getFirstSimpleByName(final QName leaf) { return unwrap().getFirstSimpleByName(leaf); } @@ -184,7 +189,7 @@ public final class CompositeNodeWrapper implements NodeWrapper, C } @Override - public List> setValue(List> value) { + public List> setValue(final List> value) { return unwrap().setValue(value); } @@ -199,32 +204,32 @@ public final class CompositeNodeWrapper implements NodeWrapper, C } @Override - public boolean containsKey(Object key) { + public boolean containsKey(final Object key) { return unwrap().containsKey(key); } @Override - public boolean containsValue(Object value) { + public boolean containsValue(final Object value) { return unwrap().containsValue(value); } @Override - public List> get(Object key) { + public List> get(final Object key) { return unwrap().get(key); } @Override - public List> put(QName key, List> value) { + public List> put(final QName key, final List> value) { return unwrap().put(key, value); } @Override - public List> remove(Object key) { + public List> remove(final Object key) { return unwrap().remove(key); } @Override - public void putAll(Map>> m) { + public void putAll(final Map>> m) { unwrap().putAll(m); } diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnJsonBasicYangTypesTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnJsonBasicYangTypesTest.java index 874e8b0d1f..d978a2f0de 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnJsonBasicYangTypesTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnJsonBasicYangTypesTest.java @@ -85,7 +85,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { verifyJsonOutput(jsonOutput); } - private void verifyJsonOutputForEmptyData(String jsonOutput) { + private void verifyJsonOutputForEmptyData(final String jsonOutput) { assertNotNull(jsonOutput); StringReader strReader = new StringReader(jsonOutput); JsonReader jReader = new JsonReader(strReader); @@ -104,7 +104,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { assertNull("Error during reading Json output: " + exception, exception); } - private void verifyJsonOutput(String jsonOutput) { + private void verifyJsonOutput(final String jsonOutput) { assertNotNull(jsonOutput); StringReader strReader = new StringReader(jsonOutput); JsonReader jReader = new JsonReader(strReader); @@ -123,7 +123,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { assertNull("Error during reading Json output: " + exception, exception); } - private Cont jsonReadCont1(JsonReader jReader) throws IOException { + private Cont jsonReadCont1(final JsonReader jReader) throws IOException { jReader.beginObject(); assertNotNull("cont1 is missing.", jReader.hasNext()); @@ -136,7 +136,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { } - private Cont jsonReadCont1Elements(JsonReader jReader, Cont redData) throws IOException { + private Cont jsonReadCont1Elements(final JsonReader jReader, final Cont redData) throws IOException { jReader.beginObject(); while (jReader.hasNext()) { String keyName = jReader.nextName(); @@ -163,7 +163,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { } - private Lst jsonReadLst11(JsonReader jReader, Lst lst) throws IOException { + private Lst jsonReadLst11(final JsonReader jReader, final Lst lst) throws IOException { jReader.beginArray(); while (jReader.hasNext()) { @@ -174,7 +174,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { return lst; } - private LstItem jsonReadLst11Elements(JsonReader jReader) throws IOException { + private LstItem jsonReadLst11Elements(final JsonReader jReader) throws IOException { LstItem lstItem = new LstItem(); jReader.beginObject(); while (jReader.hasNext()) { @@ -203,7 +203,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { return lstItem; } - private Lst jsonReadLst112(JsonReader jReader, Lst lst) throws IOException { + private Lst jsonReadLst112(final JsonReader jReader, final Lst lst) throws IOException { jReader.beginArray(); while (jReader.hasNext()) { LstItem lstItem = jsonReadLst112Elements(jReader); @@ -213,7 +213,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { return lst; } - private LstItem jsonReadLst112Elements(JsonReader jReader) throws IOException { + private LstItem jsonReadLst112Elements(final JsonReader jReader) throws IOException { LstItem lstItem = new LstItem(); jReader.beginObject(); if (jReader.hasNext()) { @@ -227,7 +227,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { } - private Lst jsonReadLst111(JsonReader jReader, Lst lst) throws IOException { + private Lst jsonReadLst111(final JsonReader jReader, final Lst lst) throws IOException { jReader.beginArray(); while (jReader.hasNext()) { LstItem lstItem = jsonReadLst111Elements(jReader); @@ -237,7 +237,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { return lst; } - private LstItem jsonReadLst111Elements(JsonReader jReader) throws IOException { + private LstItem jsonReadLst111Elements(final JsonReader jReader) throws IOException { LstItem lstItem = new LstItem(); jReader.beginObject(); if (jReader.hasNext()) { @@ -250,7 +250,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { return lstItem; } - private Object nextValue(JsonReader jReader) throws IOException { + private Object nextValue(final JsonReader jReader) throws IOException { if (jReader.peek().equals(JsonToken.NULL)) { jReader.nextNull(); return null; @@ -261,14 +261,14 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { } } - private Cont jsonReadCont111(JsonReader jReader, Cont cont) throws IOException { + private Cont jsonReadCont111(final JsonReader jReader, Cont cont) throws IOException { jReader.beginObject(); cont = jsonReadCont111Elements(jReader, cont); jReader.endObject(); return cont; } - private Cont jsonReadCont111Elements(JsonReader jReader, Cont cont) throws IOException { + private Cont jsonReadCont111Elements(final JsonReader jReader, final Cont cont) throws IOException { while (jReader.hasNext()) { String keyName = jReader.nextName(); if (keyName.equals("lf1111")) { @@ -289,7 +289,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { } - private Lst jsonReadLst1111(JsonReader jReader, Lst lst) throws IOException { + private Lst jsonReadLst1111(final JsonReader jReader, final Lst lst) throws IOException { jReader.beginArray(); while (jReader.hasNext()) { LstItem lstItem = jsonReadLst1111Elements(jReader); @@ -299,7 +299,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { return lst; } - private LstItem jsonReadLst1111Elements(JsonReader jReader) throws IOException { + private LstItem jsonReadLst1111Elements(final JsonReader jReader) throws IOException { jReader.beginObject(); LstItem lstItem = new LstItem(); while (jReader.hasNext()) { @@ -312,7 +312,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { return lstItem; } - private LfLst jsonReadLflstValues(JsonReader jReader, LfLst lfLst) throws IOException { + private LfLst jsonReadLflstValues(final JsonReader jReader, final LfLst lfLst) throws IOException { jReader.beginArray(); while (jReader.hasNext()) { lfLst.addLf(new Lf(nextValue(jReader))); @@ -321,7 +321,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { return lfLst; } - private void checkDataFromJsonEmpty(Cont dataFromJson) { + private void checkDataFromJsonEmpty(final Cont dataFromJson) { assertTrue(dataFromJson.getLfs().isEmpty()); assertTrue(dataFromJson.getLfLsts().isEmpty()); assertTrue(dataFromJson.getConts().isEmpty()); @@ -357,9 +357,9 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { assertEquals(1, lst11_1.getLsts().size()); assertEquals( lst11_1.getLsts().get("lst111"), - new Lst("lst111").addLstItem(new LstItem().addLf("lf1111", (int) 35)) - .addLstItem(new LstItem().addLf("lf1111", (int) 34)).addLstItem(new LstItem()) - .addLstItem(new LstItem())); + new Lst("lst111").addLstItem(new LstItem().addLf("lf1111", 35)) + .addLstItem(new LstItem().addLf("lf1111", 34)).addLstItem(new LstItem()) + .addLstItem(new LstItem())); assertEquals(lst11_1.getConts().get("cont111"), new Cont("cont111")); // : lst11_1 @@ -378,10 +378,10 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { assertEquals(1, lst11_2_cont111.getLsts().size()); assertTrue(lst11_2_cont111.getConts().isEmpty()); - assertEquals(new LfLst("lflst1111").addLf((int) 1024).addLf((int) 4096), + assertEquals(new LfLst("lflst1111").addLf(1024).addLf(4096), lst11_2_cont111.getLfLsts().get("lflst1111")); assertEquals( - new Lst("lst1111").addLstItem(new LstItem().addLf("lf1111B", (int) 4)).addLstItem( + new Lst("lst1111").addLstItem(new LstItem().addLf("lf1111B", 4)).addLstItem( new LstItem().addLf("lf1111A", "lf1111A str12")), lst11_2_cont111.getLsts().get("lst1111")); // :-cont111 assertEquals(lst11_2.getLsts().get("lst112"), new Lst("lst112").addLstItem(new LstItem())); @@ -407,7 +407,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { } - private void checkDataFromJson(Cont dataFromJson) { + private void checkDataFromJson(final Cont dataFromJson) { assertNotNull(dataFromJson.getLfs().get("lf11")); assertEquals(dataFromJson.getLfs().get("lf11"), new Lf("lf11", "lf")); @@ -450,7 +450,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { checkLst11_2(lst11_2); } - private void checkLst11_2(LstItem lst11_2) { + private void checkLst11_2(final LstItem lst11_2) { assertNotNull(lst11_2); assertEquals(2, lst11_2.getLfs().size()); assertEquals(1, lst11_2.getConts().size()); @@ -479,7 +479,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { new LstItem().addLf(new Lf("lf1121", "lf1121 str21"))); } - private void checkLst11_1(LstItem lst11_1) { + private void checkLst11_1(final LstItem lst11_1) { assertNotNull(lst11_1); assertEquals(2, lst11_1.getLfs().size()); @@ -507,7 +507,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { checkLst11x(lst11_1.getLsts().get("lst112"), new LstItem().addLf(new Lf("lf1121", "lf1121 str11"))); } - private void checkLst11x(Lst lst, LstItem... lstItems) { + private void checkLst11x(final Lst lst, final LstItem... lstItems) { assertNotNull(lst); Lst requiredLst = new Lst(lst.getName()); @@ -519,7 +519,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { } - private void checkLst1111(Set lstItems, Lf lf11, Lf lf12, Lf lf21, Lf lf22) { + private void checkLst1111(final Set lstItems, final Lf lf11, final Lf lf12, final Lf lf21, final Lf lf22) { LstItem lst11_1_cont_lst1111_1 = null; LstItem lst11_1_cont_lst1111_2 = null; for (LstItem lstItem : lstItems) { @@ -541,49 +541,49 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { // lst11_1 MutableCompositeNode lst11_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst11","simple:yang:types","2013-11-5"), cont1, null, ModifyAction.CREATE, null); - cont1.getChildren().add(lst11_1); + cont1.getValue().add(lst11_1); MutableSimpleNode lf111_1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111","simple:yang:types","2013-11-5"), lst11_1, (short) 1, ModifyAction.CREATE, null); - lst11_1.getChildren().add(lf111_1); + lst11_1.getValue().add(lf111_1); // lst111_1_1 MutableCompositeNode lst111_1_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst111","simple:yang:types","2013-11-5"), lst11_1, null, ModifyAction.CREATE, null); - lst11_1.getChildren().add(lst111_1_1); + lst11_1.getValue().add(lst111_1_1); MutableSimpleNode lf1111_1_1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111","simple:yang:types","2013-11-5"), - lst111_1_1, (int) 34, ModifyAction.CREATE, null); - lst111_1_1.getChildren().add(lf1111_1_1); + lst111_1_1, 34, ModifyAction.CREATE, null); + lst111_1_1.getValue().add(lf1111_1_1); lst111_1_1.init(); // :lst111_1_1 // lst111_1_2 MutableCompositeNode lst111_1_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst111","simple:yang:types","2013-11-5"), lst11_1, null, ModifyAction.CREATE, null); - lst11_1.getChildren().add(lst111_1_2); + lst11_1.getValue().add(lst111_1_2); MutableSimpleNode lf1111_1_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111","simple:yang:types","2013-11-5"), - lst111_1_2, (int) 35, ModifyAction.CREATE, null); - lst111_1_2.getChildren().add(lf1111_1_2); + lst111_1_2, 35, ModifyAction.CREATE, null); + lst111_1_2.getValue().add(lf1111_1_2); lst111_1_2.init(); // :lst111_1_2 // lst111_1_3 MutableCompositeNode lst111_1_3 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst111","simple:yang:types","2013-11-5"), lst11_1, null, ModifyAction.CREATE, null); - lst11_1.getChildren().add(lst111_1_3); + lst11_1.getValue().add(lst111_1_3); lst111_1_2.init(); // :lst111_1_3 // lst111_1_4 MutableCompositeNode lst111_1_4 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst111","simple:yang:types","2013-11-5"), lst11_1, null, ModifyAction.CREATE, null); - lst11_1.getChildren().add(lst111_1_4); + lst11_1.getValue().add(lst111_1_4); lst111_1_2.init(); // :lst111_1_4 MutableCompositeNode cont111_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont111","simple:yang:types","2013-11-5"), lst11_1, null, ModifyAction.CREATE, null); - lst11_1.getChildren().add(cont111_1); + lst11_1.getValue().add(cont111_1); lst11_1.init(); // :lst11_1 @@ -591,39 +591,39 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { // lst11_2 MutableCompositeNode lst11_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst11","simple:yang:types","2013-11-5"), cont1, null, ModifyAction.CREATE, null); - cont1.getChildren().add(lst11_2); + cont1.getValue().add(lst11_2); MutableSimpleNode lf111_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111","simple:yang:types","2013-11-5"), lst11_2, (short) 2, ModifyAction.CREATE, null); - lst11_2.getChildren().add(lf111_2); + lst11_2.getValue().add(lf111_2); // cont111_2 MutableCompositeNode cont111_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont111","simple:yang:types","2013-11-5"), lst11_2, null, ModifyAction.CREATE, null); - lst11_2.getChildren().add(cont111_2); + lst11_2.getValue().add(cont111_2); MutableSimpleNode lflst1111_2_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lflst1111","simple:yang:types","2013-11-5"), - cont111_2, (int) 1024, ModifyAction.CREATE, null); - cont111_2.getChildren().add(lflst1111_2_2); + cont111_2, 1024, ModifyAction.CREATE, null); + cont111_2.getValue().add(lflst1111_2_2); MutableSimpleNode lflst1111_2_3 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lflst1111","simple:yang:types","2013-11-5"), - cont111_2, (int) 4096, ModifyAction.CREATE, null); - cont111_2.getChildren().add(lflst1111_2_3); + cont111_2, 4096, ModifyAction.CREATE, null); + cont111_2.getValue().add(lflst1111_2_3); // lst1111_2 MutableCompositeNode lst1111_2_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst1111","simple:yang:types","2013-11-5"), cont111_2, null, ModifyAction.CREATE, null); - cont111_2.getChildren().add(lst1111_2_1); + cont111_2.getValue().add(lst1111_2_1); MutableSimpleNode lf1111B_2_1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111B","simple:yang:types","2013-11-5"), lst1111_2_1, (short) 4, ModifyAction.CREATE, null); - lst1111_2_1.getChildren().add(lf1111B_2_1); + lst1111_2_1.getValue().add(lf1111B_2_1); lst1111_2_1.init(); MutableCompositeNode lst1111_2_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst1111","simple:yang:types","2013-11-5"), cont111_2, null, ModifyAction.CREATE, null); - cont111_2.getChildren().add(lst1111_2_2); + cont111_2.getValue().add(lst1111_2_2); MutableSimpleNode lf1111A_2_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111A","simple:yang:types","2013-11-5"), lst1111_2_2, "lf1111A str12", ModifyAction.CREATE, null); - lst1111_2_2.getChildren().add(lf1111A_2_2); + lst1111_2_2.getValue().add(lf1111A_2_2); lst1111_2_2.init(); // :lst1111_2 @@ -632,7 +632,7 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { MutableCompositeNode lst112_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst112","simple:yang:types","2013-11-5"), lst11_2, null, ModifyAction.CREATE, null); - lst11_2.getChildren().add(lst112_2); + lst11_2.getValue().add(lst112_2); lst112_2.init(); lst11_2.init(); @@ -641,25 +641,25 @@ public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader { // lst11_3 MutableCompositeNode lst11_3 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst11","simple:yang:types","2013-11-5"), cont1, null, ModifyAction.CREATE, null); - cont1.getChildren().add(lst11_3); + cont1.getValue().add(lst11_3); MutableSimpleNode lf111_3 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111","simple:yang:types","2013-11-5"), lst11_3, (short) 3, ModifyAction.CREATE, null); - lst11_3.getChildren().add(lf111_3); + lst11_3.getValue().add(lf111_3); // cont111_3 MutableCompositeNode cont111_3 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont111","simple:yang:types","2013-11-5"), lst11_3, null, ModifyAction.CREATE, null); - lst11_3.getChildren().add(cont111_3); + lst11_3.getValue().add(cont111_3); MutableCompositeNode lst1111_3_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst1111","simple:yang:types","2013-11-5"), cont111_3, null, ModifyAction.CREATE, null); - cont111_3.getChildren().add(lst1111_3_1); + cont111_3.getValue().add(lst1111_3_1); lst1111_3_1.init(); MutableCompositeNode lst1111_3_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst1111","simple:yang:types","2013-11-5"), cont111_3, null, ModifyAction.CREATE, null); - cont111_3.getChildren().add(lst1111_3_2); + cont111_3.getValue().add(lst1111_3_2); lst1111_3_2.init(); cont111_3.init(); diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonIdentityrefTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonIdentityrefTest.java index 745f11c210..fdd3aa6684 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonIdentityrefTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonIdentityrefTest.java @@ -73,17 +73,17 @@ public class CnSnToJsonIdentityrefTest extends YangAndXmlAndDataSchemaLoader { assertTrue(mtch.matches()); } - private CompositeNode prepareCompositeNode(Object value) { + private CompositeNode prepareCompositeNode(final Object value) { MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont","identityref:module","2013-12-2"), null, null, ModifyAction.CREATE, null); MutableCompositeNode cont1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont1","identityref:module","2013-12-2"), cont, null, ModifyAction.CREATE, null); - cont.getChildren().add(cont1); + cont.getValue().add(cont1); MutableSimpleNode lf1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1","identityref:module","2013-12-2"), cont1, value, ModifyAction.CREATE, null); - cont1.getChildren().add(lf1); + cont1.getValue().add(lf1); cont1.init(); cont.init(); diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonNotExistingLeafTypeTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonNotExistingLeafTypeTest.java index dd1502ba79..42e1e3f739 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonNotExistingLeafTypeTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonNotExistingLeafTypeTest.java @@ -27,6 +27,7 @@ import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode; import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode; import org.opendaylight.yangtools.yang.data.impl.NodeFactory; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder; import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder; import org.slf4j.Logger; @@ -46,7 +47,7 @@ public class CnSnToJsonNotExistingLeafTypeTest extends YangAndXmlAndDataSchemaLo String jsonOutput = null; jsonOutput = TestUtils .writeCompNodeWithSchemaContextToOutput(prepareCompositeNode(), - Collections.EMPTY_SET, prepareDataSchemaNode(), + Collections.emptySet(), prepareDataSchemaNode(), StructuredDataToJsonProvider.INSTANCE); assertNotNull(jsonOutput); assertTrue(jsonOutput.contains("\"lf1\": \"\"")); @@ -57,7 +58,7 @@ public class CnSnToJsonNotExistingLeafTypeTest extends YangAndXmlAndDataSchemaLo TestUtils.buildQName("cont", "simple:uri", "2012-12-17"), null, null, ModifyAction.CREATE, null); MutableSimpleNode lf1 = NodeFactory.createMutableSimpleNode( TestUtils.buildQName("lf1", "simple:uri", "2012-12-17"), cont, "any value", ModifyAction.CREATE, null); - cont.getChildren().add(lf1); + cont.getValue().add(lf1); cont.init(); return cont; } diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonWithDataFromSeveralModulesTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonWithDataFromSeveralModulesTest.java index 348edbd294..052bb1a2be 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonWithDataFromSeveralModulesTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonWithDataFromSeveralModulesTest.java @@ -99,32 +99,32 @@ public class CnSnToJsonWithDataFromSeveralModulesTest extends YangAndXmlAndDataS MutableCompositeNode cont_m1 = NodeFactory.createMutableCompositeNode( TestUtils.buildQName("cont_m1", uri1, rev1), data, null, null, null); - data.getChildren().add(cont_m1); + data.getValue().add(cont_m1); MutableSimpleNode lf1_m1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1_m1", uri1, rev1), cont_m1, "lf1 m1 value", null, null); - cont_m1.getChildren().add(lf1_m1); + cont_m1.getValue().add(lf1_m1); cont_m1.init(); MutableCompositeNode contB_m1 = NodeFactory.createMutableCompositeNode( TestUtils.buildQName("contB_m1", uri1, rev1), data, null, null, null); - data.getChildren().add(contB_m1); + data.getValue().add(contB_m1); contB_m1.init(); String uri2 = "module:two"; String rev2 = "2014-01-17"; MutableCompositeNode cont_m2 = NodeFactory.createMutableCompositeNode( TestUtils.buildQName("cont_m2", uri2, rev2), data, null, null, null); - data.getChildren().add(cont_m2); + data.getValue().add(cont_m2); MutableSimpleNode lf1_m2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1_m2", uri2, rev2), cont_m1, "lf1 m2 value", null, null); - cont_m2.getChildren().add(lf1_m2); + cont_m2.getValue().add(lf1_m2); cont_m2.init(); MutableCompositeNode contB_m2 = NodeFactory.createMutableCompositeNode( TestUtils.buildQName("contB_m2", uri2, rev2), data, null, null, null); - data.getChildren().add(contB_m2); + data.getValue().add(contB_m2); contB_m2.init(); data.init(); diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlNotExistingLeafTypeTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlNotExistingLeafTypeTest.java index f81c1d63f5..2ada6e13e9 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlNotExistingLeafTypeTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlNotExistingLeafTypeTest.java @@ -25,6 +25,7 @@ import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode; import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode; import org.opendaylight.yangtools.yang.data.impl.NodeFactory; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder; import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder; import org.slf4j.Logger; @@ -41,7 +42,7 @@ public class CnSnToXmlNotExistingLeafTypeTest { boolean nullPointerExceptionRaised = false; try { TestUtils.writeCompNodeWithSchemaContextToOutput(prepareCompositeNode(), - Collections.EMPTY_SET, prepareDataSchemaNode(), StructuredDataToXmlProvider.INSTANCE); + Collections.emptySet(), prepareDataSchemaNode(), StructuredDataToXmlProvider.INSTANCE); } catch (WebApplicationException | IOException e) { LOG.error("WebApplicationException or IOException was raised"); } catch (NullPointerException e) { @@ -56,7 +57,7 @@ public class CnSnToXmlNotExistingLeafTypeTest { TestUtils.buildQName("cont", "simple:uri", "2012-12-17"), null, null, ModifyAction.CREATE, null); MutableSimpleNode lf1 = NodeFactory.createMutableSimpleNode( TestUtils.buildQName("lf1", "simple:uri", "2012-12-17"), cont, "any value", ModifyAction.CREATE, null); - cont.getChildren().add(lf1); + cont.getValue().add(lf1); cont.init(); return cont; } diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlTest.java index 6b4b153252..fc54795fcc 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlTest.java @@ -28,11 +28,11 @@ import org.opendaylight.yangtools.yang.data.impl.NodeFactory; import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec; /** - * + * * CnSn = Composite node and Simple node data structure Class contains test of * serializing simple nodes data values according data types from YANG schema to * XML file - * + * */ public class CnSnToXmlTest extends YangAndXmlAndDataSchemaLoader { @BeforeClass @@ -139,9 +139,9 @@ public class CnSnToXmlTest extends YangAndXmlAndDataSchemaLoader { serializeToXml( prepareCnStructForYangData( TypeDefinitionAwareCodec.BINARY_DEFAULT_CODEC - .deserialize("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567"), + .deserialize("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567"), elName), "<" + elName + ">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567"); + + elName + ">"); } @Test @@ -198,7 +198,7 @@ public class CnSnToXmlTest extends YangAndXmlAndDataSchemaLoader { + elName + ">str"); } - private void serializeToXml(CompositeNode compositeNode, String... xmlRepresentation) + private void serializeToXml(final CompositeNode compositeNode, final String... xmlRepresentation) throws TransformerFactoryConfigurationError { String xmlString = ""; try { @@ -220,12 +220,12 @@ public class CnSnToXmlTest extends YangAndXmlAndDataSchemaLoader { } - private CompositeNode prepareIdentityrefData(String prefix, boolean valueAsQName) { + private CompositeNode prepareIdentityrefData(final String prefix, final boolean valueAsQName) { MutableCompositeNode cont = NodeFactory.createMutableCompositeNode( TestUtils.buildQName("cont", "basic:module", "2013-12-2"), null, null, ModifyAction.CREATE, null); MutableCompositeNode cont1 = NodeFactory.createMutableCompositeNode( TestUtils.buildQName("cont1", "basic:module", "2013-12-2"), cont, null, ModifyAction.CREATE, null); - cont.getChildren().add(cont1); + cont.getValue().add(cont1); Object value = null; if (valueAsQName) { @@ -235,20 +235,20 @@ public class CnSnToXmlTest extends YangAndXmlAndDataSchemaLoader { } MutableSimpleNode lf11 = NodeFactory.createMutableSimpleNode( TestUtils.buildQName("lf11", "basic:module", "2013-12-2"), cont1, value, ModifyAction.CREATE, null); - cont1.getChildren().add(lf11); + cont1.getValue().add(lf11); cont1.init(); cont.init(); return cont; } - private CompositeNode prepareCnStructForYangData(Object data, String leafName) { + private CompositeNode prepareCnStructForYangData(final Object data, final String leafName) { MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont"), null, null, ModifyAction.CREATE, null); MutableSimpleNode lf1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName(leafName), cont, data, ModifyAction.CREATE, null); - cont.getChildren().add(lf1); + cont.getValue().add(lf1); cont.init(); return cont; @@ -262,8 +262,8 @@ public class CnSnToXmlTest extends YangAndXmlAndDataSchemaLoader { cont, Boolean.TRUE, ModifyAction.CREATE, null); MutableSimpleNode lfLfref = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfLfref"), cont, "true", ModifyAction.CREATE, null); - cont.getChildren().add(lfBoolean); - cont.getChildren().add(lfLfref); + cont.getValue().add(lfBoolean); + cont.getValue().add(lfLfref); cont.init(); return cont; diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlWithChoiceTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlWithChoiceTest.java index a3e33ce30b..ac7fe20818 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlWithChoiceTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/xml/test/CnSnToXmlWithChoiceTest.java @@ -18,15 +18,18 @@ import org.junit.Test; import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider; import org.opendaylight.controller.sal.restconf.impl.test.TestUtils; import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader; -import org.opendaylight.yangtools.yang.data.api.*; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.ModifyAction; +import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode; +import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode; import org.opendaylight.yangtools.yang.data.impl.NodeFactory; /** - * + * * CnSn = Composite node and Simple node data structure Class contains test of * serializing simple nodes data values according data types from YANG schema to * XML file - * + * */ public class CnSnToXmlWithChoiceTest extends YangAndXmlAndDataSchemaLoader { @BeforeClass @@ -56,13 +59,13 @@ public class CnSnToXmlWithChoiceTest extends YangAndXmlAndDataSchemaLoader { } - private CompositeNode prepareCnStructForYangData(String lfName, Object data) { + private CompositeNode prepareCnStructForYangData(final String lfName, final Object data) { MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont"), null, null, ModifyAction.CREATE, null); MutableSimpleNode lf1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName(lfName), cont, data, ModifyAction.CREATE, null); - cont.getChildren().add(lf1); + cont.getValue().add(lf1); cont.init(); return cont; diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonIdentityrefToCnSnTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonIdentityrefToCnSnTest.java index 9e726baf55..0c9e95173f 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonIdentityrefToCnSnTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonIdentityrefToCnSnTest.java @@ -7,7 +7,9 @@ */ package org.opendaylight.controller.sal.restconf.impl.json.to.cnsn.test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import java.util.List; @@ -17,7 +19,9 @@ import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider; import org.opendaylight.controller.sal.restconf.impl.test.TestUtils; import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader; import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.data.api.*; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.Node; +import org.opendaylight.yangtools.yang.data.api.SimpleNode; public class JsonIdentityrefToCnSnTest extends YangAndXmlAndDataSchemaLoader { @@ -36,13 +40,13 @@ public class JsonIdentityrefToCnSnTest extends YangAndXmlAndDataSchemaLoader { assertEquals("cont", compositeNode.getNodeType().getLocalName()); - List> childs = compositeNode.getChildren(); + List> childs = compositeNode.getValue(); assertEquals(1, childs.size()); Node nd = childs.iterator().next(); assertTrue(nd instanceof CompositeNode); assertEquals("cont1", nd.getNodeType().getLocalName()); - childs = ((CompositeNode) nd).getChildren(); + childs = ((CompositeNode) nd).getValue(); assertEquals(4, childs.size()); SimpleNode lf11 = null; SimpleNode lf12 = null; diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonLeafrefToCnSnTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonLeafrefToCnSnTest.java index 2030d9125a..79dd026fd0 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonLeafrefToCnSnTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonLeafrefToCnSnTest.java @@ -7,14 +7,18 @@ */ package org.opendaylight.controller.sal.restconf.impl.json.to.cnsn.test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import org.junit.BeforeClass; import org.junit.Test; import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider; import org.opendaylight.controller.sal.restconf.impl.test.TestUtils; import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader; -import org.opendaylight.yangtools.yang.data.api.*; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.Node; +import org.opendaylight.yangtools.yang.data.api.SimpleNode; public class JsonLeafrefToCnSnTest extends YangAndXmlAndDataSchemaLoader { @@ -37,7 +41,7 @@ public class JsonLeafrefToCnSnTest extends YangAndXmlAndDataSchemaLoader { assertEquals("cont", compositeNode.getNodeType().getLocalName()); SimpleNode lf2 = null; - for (Node childNode : compositeNode.getChildren()) { + for (Node childNode : compositeNode.getValue()) { if (childNode instanceof SimpleNode) { if (childNode.getNodeType().getLocalName().equals("lf2")) { lf2 = (SimpleNode) childNode; @@ -48,7 +52,7 @@ public class JsonLeafrefToCnSnTest extends YangAndXmlAndDataSchemaLoader { assertNotNull(lf2); assertTrue(lf2.getValue() instanceof String); - assertEquals("121", (String) lf2.getValue()); + assertEquals("121", lf2.getValue()); } diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonToCnSnTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonToCnSnTest.java index 8b1dc3475f..415d58e53d 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonToCnSnTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonToCnSnTest.java @@ -58,13 +58,13 @@ public class JsonToCnSnTest { CompositeNode compositeNode = TestUtils.readInputToCnSn("/json-to-cnsn/multiple-leaflist-items.json", true, JsonToCompositeNodeProvider.INSTANCE); assertNotNull(compositeNode); - assertEquals(3, compositeNode.getChildren().size()); + assertEquals(3, compositeNode.getValue().size()); boolean lflst1_1 = false; boolean lflst1_2 = false; boolean lflst1_3 = false; - for (Node node : compositeNode.getChildren()) { + for (Node node : compositeNode.getValue()) { assertEquals("lflst1", node.getNodeType().getLocalName()); assertTrue(node instanceof SimpleNode); SimpleNode simpleNode = (SimpleNode) node; @@ -105,9 +105,9 @@ public class JsonToCnSnTest { assertNotNull(compositeNode); assertEquals("cont", compositeNode.getNodeType().getLocalName()); - assertNotNull(compositeNode.getChildren()); - assertEquals(1, compositeNode.getChildren().size()); - Node lfNode = compositeNode.getChildren().iterator().next(); + assertNotNull(compositeNode.getValue()); + assertEquals(1, compositeNode.getValue().size()); + Node lfNode = compositeNode.getValue().iterator().next(); assertTrue(lfNode instanceof SimpleNode); assertEquals(null, ((SimpleNode) lfNode).getValue()); @@ -119,7 +119,7 @@ public class JsonToCnSnTest { Throwable cause1 = null; try { TestUtils - .readInputToCnSn("/json-to-cnsn/wrong-top-level1.json", true, JsonToCompositeNodeProvider.INSTANCE); + .readInputToCnSn("/json-to-cnsn/wrong-top-level1.json", true, JsonToCompositeNodeProvider.INSTANCE); } catch (WebApplicationException e) { cause1 = e; } @@ -134,7 +134,7 @@ public class JsonToCnSnTest { Throwable cause2 = null; try { TestUtils - .readInputToCnSn("/json-to-cnsn/wrong-top-level2.json", true, JsonToCompositeNodeProvider.INSTANCE); + .readInputToCnSn("/json-to-cnsn/wrong-top-level2.json", true, JsonToCompositeNodeProvider.INSTANCE); } catch (WebApplicationException e) { cause2 = e; } @@ -144,7 +144,7 @@ public class JsonToCnSnTest { Throwable cause3 = null; try { TestUtils - .readInputToCnSn("/json-to-cnsn/wrong-top-level3.json", true, JsonToCompositeNodeProvider.INSTANCE); + .readInputToCnSn("/json-to-cnsn/wrong-top-level3.json", true, JsonToCompositeNodeProvider.INSTANCE); } catch (WebApplicationException e) { cause3 = e; } @@ -170,7 +170,7 @@ public class JsonToCnSnTest { assertEquals("cont", compositeNode.getNodeType().getLocalName()); assertTrue(compositeNode instanceof CompositeNode); - List> children = ((CompositeNode) compositeNode).getChildren(); + List> children = compositeNode.getValue(); assertEquals(1, children.size()); assertEquals("lflst2", children.get(0).getNodeType().getLocalName()); assertEquals("45", children.get(0).getValue()); @@ -190,7 +190,7 @@ public class JsonToCnSnTest { * Tests whether namespace stay unchanged if concrete values are * present in composite or simple node and if the method for update is * called. - * + * */ @Test public void notSupplyNamespaceIfAlreadySupplied() { @@ -233,13 +233,13 @@ public class JsonToCnSnTest { assertEquals("cont", compositeNode.getNodeType().getLocalName()); - List> childs = compositeNode.getChildren(); + List> childs = compositeNode.getValue(); assertEquals(1, childs.size()); Node nd = childs.iterator().next(); assertTrue(nd instanceof CompositeNode); assertEquals("cont1", nd.getNodeType().getLocalName()); - childs = ((CompositeNode) nd).getChildren(); + childs = ((CompositeNode) nd).getValue(); assertEquals(4, childs.size()); SimpleNode lf11 = null; SimpleNode lf12 = null; @@ -274,7 +274,7 @@ public class JsonToCnSnTest { assertEquals("iden_local", ((QName) lf14.getValue()).getLocalName()); assertEquals("identity:module", ((QName) lf14.getValue()).getNamespace().toString()); } - + @Ignore @Test public void loadDataAugmentedSchemaMoreEqualNamesTest() { @@ -285,17 +285,17 @@ public class JsonToCnSnTest { } catch (ResponseException e) { exceptionCaught = true; } - + assertFalse(exceptionCaught); } - private void simpleTest(String jsonPath, String yangPath, String topLevelElementName, String namespace, - String moduleName) { + private void simpleTest(final String jsonPath, final String yangPath, final String topLevelElementName, final String namespace, + final String moduleName) { CompositeNode compNode = loadAndNormalizeData(jsonPath, yangPath, topLevelElementName, moduleName); verifyCompositeNode(compNode, namespace); } - private CompositeNode loadAndNormalizeData(String jsonPath, String yangPath, String topLevelElementName, String moduleName) { + private CompositeNode loadAndNormalizeData(final String jsonPath, final String yangPath, final String topLevelElementName, final String moduleName) { CompositeNode compositeNode = TestUtils.readInputToCnSn(jsonPath, false, JsonToCompositeNodeProvider.INSTANCE); assertNotNull(compositeNode); @@ -312,8 +312,8 @@ public class JsonToCnSnTest { return compNode; } - private void verityMultipleItemsInList(CompositeNode compositeNode) { - List> childrenNodes = compositeNode.getChildren(); + private void verityMultipleItemsInList(final CompositeNode compositeNode) { + List> childrenNodes = compositeNode.getValue(); assertEquals(4, childrenNodes.size()); boolean lf11Found = false; boolean cont11Found = false; @@ -322,7 +322,7 @@ public class JsonToCnSnTest { assertEquals("lst1", lst1Item.getNodeType().getLocalName()); assertTrue(lst1Item instanceof CompositeNode); - List> childrenLst1 = ((CompositeNode) lst1Item).getChildren(); + List> childrenLst1 = ((CompositeNode) lst1Item).getValue(); assertEquals(1, childrenLst1.size()); String localName = childrenLst1.get(0).getNodeType().getLocalName(); if (localName.equals("lf11")) { @@ -338,7 +338,7 @@ public class JsonToCnSnTest { } else if (localName.equals("lst11")) { lst11Found = true; assertTrue(childrenLst1.get(0) instanceof CompositeNode); - assertEquals(0, ((CompositeNode) childrenLst1.get(0)).getChildren().size()); + assertEquals(0, ((CompositeNode) childrenLst1.get(0)).getValue().size()); } } @@ -347,7 +347,7 @@ public class JsonToCnSnTest { assertTrue(lst11Found); } - private void verifyCompositeNode(CompositeNode compositeNode, String namespace) { + private void verifyCompositeNode(final CompositeNode compositeNode, final String namespace) { boolean cont1Found = false; boolean lst1Found = false; boolean lflst1_1Found = false; @@ -357,16 +357,16 @@ public class JsonToCnSnTest { // assertEquals(namespace, // compositeNode.getNodeType().getNamespace().toString()); - for (Node node : compositeNode.getChildren()) { + for (Node node : compositeNode.getValue()) { if (node.getNodeType().getLocalName().equals("cont1")) { if (node instanceof CompositeNode) { cont1Found = true; - assertEquals(0, ((CompositeNode) node).getChildren().size()); + assertEquals(0, ((CompositeNode) node).getValue().size()); } } else if (node.getNodeType().getLocalName().equals("lst1")) { if (node instanceof CompositeNode) { lst1Found = true; - assertEquals(0, ((CompositeNode) node).getChildren().size()); + assertEquals(0, ((CompositeNode) node).getValue().size()); } } else if (node.getNodeType().getLocalName().equals("lflst1")) { if (node instanceof SimpleNode) { diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/CnSnToXmlAndJsonInstanceIdentifierTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/CnSnToXmlAndJsonInstanceIdentifierTest.java index 0492b3efd4..07d781028b 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/CnSnToXmlAndJsonInstanceIdentifierTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/CnSnToXmlAndJsonInstanceIdentifierTest.java @@ -64,7 +64,7 @@ public class CnSnToXmlAndJsonInstanceIdentifierTest extends YangAndXmlAndDataSch @Ignore @Test public void saveCnSnWithLeafListInstIdentifierToXmlTest() throws WebApplicationException, IOException, - URISyntaxException, XMLStreamException { + URISyntaxException, XMLStreamException { CompositeNode cnSn = prepareCnSn(createInstanceIdentifierWithLeafList()); String output = TestUtils.writeCompNodeWithSchemaContextToOutput(cnSn, modules, dataSchemaNode, StructuredDataToXmlProvider.INSTANCE); @@ -94,7 +94,7 @@ public class CnSnToXmlAndJsonInstanceIdentifierTest extends YangAndXmlAndDataSch @Test public void saveCnSnWithLeafListInstIdentifierToJsonTest() throws WebApplicationException, IOException, - URISyntaxException { + URISyntaxException { CompositeNode cnSn = prepareCnSn(createInstanceIdentifierWithLeafList()); String output = TestUtils.writeCompNodeWithSchemaContextToOutput(cnSn, modules, dataSchemaNode, StructuredDataToJsonProvider.INSTANCE); @@ -111,7 +111,7 @@ public class CnSnToXmlAndJsonInstanceIdentifierTest extends YangAndXmlAndDataSch assertTrue(strInOutput); } - private void validateXmlOutput(String xml) throws XMLStreamException { + private void validateXmlOutput(final String xml) throws XMLStreamException { XMLInputFactory xmlInFactory = XMLInputFactory.newInstance(); XMLEventReader eventReader; @@ -152,7 +152,7 @@ public class CnSnToXmlAndJsonInstanceIdentifierTest extends YangAndXmlAndDataSch } - private void validateXmlOutputWithLeafList(String xml) throws XMLStreamException { + private void validateXmlOutputWithLeafList(final String xml) throws XMLStreamException { XMLInputFactory xmlInFactory = XMLInputFactory.newInstance(); XMLEventReader eventReader; @@ -188,7 +188,7 @@ public class CnSnToXmlAndJsonInstanceIdentifierTest extends YangAndXmlAndDataSch } - private CompositeNode prepareCnSn(InstanceIdentifier instanceIdentifier) throws URISyntaxException { + private CompositeNode prepareCnSn(final InstanceIdentifier instanceIdentifier) throws URISyntaxException { MutableCompositeNode cont = NodeFactory.createMutableCompositeNode( TestUtils.buildQName("cont", "instance:identifier:module", "2014-01-17"), null, null,null,null); MutableCompositeNode cont1 = NodeFactory.createMutableCompositeNode( @@ -200,13 +200,13 @@ public class CnSnToXmlAndJsonInstanceIdentifierTest extends YangAndXmlAndDataSch lst11, instanceIdentifier,null,null); - lst11.getChildren().add(lf111); + lst11.getValue().add(lf111); lst11.init(); - cont1.getChildren().add(lst11); + cont1.getValue().add(lst11); cont1.init(); - cont.getChildren().add(cont1); + cont.getValue().add(cont1); cont.init(); return cont; diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java index b42178a9c6..018a235718 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java @@ -63,7 +63,7 @@ public class InvokeRpcMethodTest { private class AnswerImpl implements Answer> { @Override - public RpcResult answer(InvocationOnMock invocation) throws Throwable { + public RpcResult answer(final InvocationOnMock invocation) throws Throwable { CompositeNode compNode = (CompositeNode) invocation.getArguments()[1]; return new DummyRpcResult.Builder().result(compNode).isSuccessful(true).build(); } @@ -123,7 +123,7 @@ public class InvokeRpcMethodTest { TestUtils.buildQName("cont", "nmspc", "2013-12-04"), null, null, ModifyAction.CREATE, null); MutableSimpleNode lf = NodeFactory.createMutableSimpleNode( TestUtils.buildQName("lf", "nmspc", "2013-12-04"), cont, "any value", ModifyAction.CREATE, null); - cont.getChildren().add(lf); + cont.getValue().add(lf); cont.init(); return cont; @@ -150,7 +150,7 @@ public class InvokeRpcMethodTest { } catch (ResponseException e) { assertEquals(e.getMessage(), Status.INTERNAL_SERVER_ERROR.getStatusCode(), e - .getResponse().getStatus()); + .getResponse().getStatus()); } } @@ -216,7 +216,7 @@ public class InvokeRpcMethodTest { } catch (ResponseException e) { assertEquals(e.getMessage(), Status.UNSUPPORTED_MEDIA_TYPE.getStatusCode(), e - .getResponse().getStatus()); + .getResponse().getStatus()); } } @@ -273,8 +273,8 @@ public class InvokeRpcMethodTest { BrokerFacade brokerFacade = mock(BrokerFacade.class); when( brokerFacade.invokeRpc( - eq(QName.create("(http://netconfcentral.org/ns/toaster?revision=2009-11-20)testOutput")), - any( CompositeNode.class ))).thenReturn(rpcResult); + eq(QName.create("(http://netconfcentral.org/ns/toaster?revision=2009-11-20)testOutput")), + any( CompositeNode.class ))).thenReturn(rpcResult); restconfImpl.setBroker(brokerFacade); @@ -301,7 +301,7 @@ public class InvokeRpcMethodTest { MountInstance mockMountPoint = mock( MountInstance.class ); when( mockMountPoint.rpc( eq( cancelToastQName ), any( CompositeNode.class ) ) ) - .thenReturn( mockListener ); + .thenReturn( mockListener ); InstanceIdWithSchemaNode mockedInstanceId = mock( InstanceIdWithSchemaNode.class ); when( mockedInstanceId.getMountPoint() ).thenReturn( mockMountPoint ); @@ -315,8 +315,8 @@ public class InvokeRpcMethodTest { restconfImpl.setControllerContext( mockedContext ); StructuredData output = restconfImpl.invokeRpc( - "opendaylight-inventory:nodes/node/REMOTE_HOST/yang-ext:mount/toaster:cancel-toast", - ""); + "opendaylight-inventory:nodes/node/REMOTE_HOST/yang-ext:mount/toaster:cancel-toast", + ""); assertEquals(null, output); //additional validation in the fact that the restconfImpl does not throw an exception. diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/xml/to/cnsn/test/XmlLeafrefToCnSnTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/xml/to/cnsn/test/XmlLeafrefToCnSnTest.java index 7a949b8f2d..e5b0bf507d 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/xml/to/cnsn/test/XmlLeafrefToCnSnTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/xml/to/cnsn/test/XmlLeafrefToCnSnTest.java @@ -50,13 +50,13 @@ public class XmlLeafrefToCnSnTest { verifyCommonPartAOfXml(compNode, "", nameSpace); } - private void verifyNullAndEmptyStringSingleNode(CompositeNode compNode, String nameSpace) { + private void verifyNullAndEmptyStringSingleNode(final CompositeNode compNode, final String nameSpace) { assertEquals("cont", compNode.getNodeType().getLocalName()); SimpleNode lf2 = null; SimpleNode lf3 = null; int found = 0; - for (Node child : compNode.getChildren()) { + for (Node child : compNode.getValue()) { if (found == 0x3) break; if (child instanceof SimpleNode) { @@ -91,11 +91,11 @@ public class XmlLeafrefToCnSnTest { String nameSpaceCont = "data:container:yang"; assertEquals(nameSpaceCont, compNode.getNodeType().getNamespace().toString()); assertEquals("cont", compNode.getNodeType().getLocalName()); - assertEquals(3, compNode.getChildren().size()); + assertEquals(3, compNode.getValue().size()); CompositeNode lst1_1 = null; CompositeNode lst1_2 = null; int loopCount = 0; - for (Node node : compNode.getChildren()) { + for (Node node : compNode.getValue()) { if (node.getNodeType().getLocalName().equals("lf1")) { assertEquals(nameSpaceList, node.getNodeType().getNamespace().toString()); assertTrue(node instanceof SimpleNode); @@ -120,7 +120,7 @@ public class XmlLeafrefToCnSnTest { // lst1_2 SimpleNode lflst11 = null; CompositeNode cont11 = null; - for (Node node : lst1_2.getChildren()) { + for (Node node : lst1_2.getValue()) { String nodeName = node.getNodeType().getLocalName(); if (nodeName.equals("lflst11")) { assertTrue(node instanceof SimpleNode); @@ -134,9 +134,9 @@ public class XmlLeafrefToCnSnTest { } assertEquals("221", lflst11.getValue()); - assertEquals(1, cont11.getChildren().size()); - assertTrue(cont11.getChildren().get(0) instanceof SimpleNode); - SimpleNode cont11_lf111 = (SimpleNode) cont11.getChildren().get(0); + assertEquals(1, cont11.getValue().size()); + assertTrue(cont11.getValue().get(0) instanceof SimpleNode); + SimpleNode cont11_lf111 = (SimpleNode) cont11.getValue().get(0); assertEquals(nameSpaceCont, cont11_lf111.getNodeType().getNamespace().toString()); assertEquals("lf111", cont11_lf111.getNodeType().getLocalName()); assertEquals((short) 100, cont11_lf111.getValue()); @@ -154,7 +154,7 @@ public class XmlLeafrefToCnSnTest { SimpleNode lflst1_2 = null; CompositeNode lst1 = null; int lflst1Count = 0; - for (Node node : compNode.getChildren()) { + for (Node node : compNode.getValue()) { if (node.getNodeType().getLocalName().equals("lf1")) { assertTrue(node instanceof SimpleNode); lf1 = (SimpleNode) node; @@ -183,11 +183,11 @@ public class XmlLeafrefToCnSnTest { assertEquals("", lf1.getValue()); assertEquals("", lflst1_1.getValue()); assertEquals("", lflst1_2.getValue()); - assertEquals(1, lst1.getChildren().size()); - assertEquals("lf11", lst1.getChildren().get(0).getNodeType().getLocalName()); + assertEquals(1, lst1.getValue().size()); + assertEquals("lf11", lst1.getValue().get(0).getNodeType().getLocalName()); - assertTrue(lst1.getChildren().get(0) instanceof SimpleNode); - assertEquals("", lst1.getChildren().get(0).getValue()); + assertTrue(lst1.getValue().get(0) instanceof SimpleNode); + assertEquals("", lst1.getValue().get(0).getValue()); } @@ -201,7 +201,7 @@ public class XmlLeafrefToCnSnTest { } /** - * + * * Test case like identity */ @@ -213,7 +213,7 @@ public class XmlLeafrefToCnSnTest { } /** - * + * * Test case like identity */ @@ -224,7 +224,7 @@ public class XmlLeafrefToCnSnTest { } /** - * + * * Test case like * x:identity */ @@ -236,7 +236,7 @@ public class XmlLeafrefToCnSnTest { } /** - * + * * Test case like (without namespace in xml) x:identity * */ @@ -247,7 +247,7 @@ public class XmlLeafrefToCnSnTest { } /** - * + * * Test case like (without namespace in xml) identity * */ @@ -257,7 +257,7 @@ public class XmlLeafrefToCnSnTest { "/xml-to-cnsn/identityref", "identityref-module", "cont", 2, "iden", "identityref:module"); } - private void verifyCommonPartAOfXml(CompositeNode compNode, String suf, String nameSpace) { + private void verifyCommonPartAOfXml(final CompositeNode compNode, final String suf, final String nameSpace) { SimpleNode lf1suf = null; SimpleNode lflst1suf_1 = null; SimpleNode lflst1suf_2 = null; @@ -267,7 +267,7 @@ public class XmlLeafrefToCnSnTest { int lflstCount = 0; - for (Node node : compNode.getChildren()) { + for (Node node : compNode.getValue()) { String localName = node.getNodeType().getLocalName(); if (localName.equals("lf1" + suf)) { assertTrue(node instanceof SimpleNode); @@ -307,23 +307,23 @@ public class XmlLeafrefToCnSnTest { assertEquals("131", lflst1suf_2.getValue()); assertEquals("str1", lflst1suf_3.getValue()); - assertEquals(1, lst1suf.getChildren().size()); + assertEquals(1, lst1suf.getValue().size()); - assertTrue(lst1suf.getChildren().get(0) instanceof SimpleNode); - SimpleNode lst11_lf11 = (SimpleNode) lst1suf.getChildren().get(0); + assertTrue(lst1suf.getValue().get(0) instanceof SimpleNode); + SimpleNode lst11_lf11 = (SimpleNode) lst1suf.getValue().get(0); assertEquals(nameSpace, lst11_lf11.getNodeType().getNamespace().toString()); assertEquals("lf11" + suf, lst11_lf11.getNodeType().getLocalName()); assertEquals("str2", lst11_lf11.getValue()); - assertTrue(cont1suf.getChildren().get(0) instanceof SimpleNode); - SimpleNode cont1_lf11 = (SimpleNode) cont1suf.getChildren().get(0); + assertTrue(cont1suf.getValue().get(0) instanceof SimpleNode); + SimpleNode cont1_lf11 = (SimpleNode) cont1suf.getValue().get(0); assertEquals(nameSpace, cont1_lf11.getNodeType().getNamespace().toString()); assertEquals("lf11" + suf, cont1_lf11.getNodeType().getLocalName()); assertEquals((short) 100, cont1_lf11.getValue()); } - private void testIdentityrefToCnSn(String xmlPath, String yangPath, String moduleName, String schemaName, - int moduleCount, String resultLocalName, String resultNamespace) { + private void testIdentityrefToCnSn(final String xmlPath, final String yangPath, final String moduleName, final String schemaName, + final int moduleCount, final String resultLocalName, final String resultNamespace) { CompositeNode compositeNode = TestUtils.readInputToCnSn(xmlPath, false, XmlToCompositeNodeProvider.INSTANCE); assertNotNull(compositeNode); @@ -339,16 +339,16 @@ public class XmlLeafrefToCnSnTest { assertEquals(resultNamespace, qName.getNamespace().toString()); } - private SimpleNode getLf11(CompositeNode compositeNode) { + private SimpleNode getLf11(final CompositeNode compositeNode) { assertEquals("cont", compositeNode.getNodeType().getLocalName()); - List> childs = compositeNode.getChildren(); + List> childs = compositeNode.getValue(); assertEquals(1, childs.size()); Node nd = childs.iterator().next(); assertTrue(nd instanceof CompositeNode); assertEquals("cont1", nd.getNodeType().getLocalName()); - childs = ((CompositeNode) nd).getChildren(); + childs = ((CompositeNode) nd).getValue(); SimpleNode lf11 = null; for (Node child : childs) { assertTrue(child instanceof SimpleNode); diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/xml/to/cnsn/test/XmlToCnSnTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/xml/to/cnsn/test/XmlToCnSnTest.java index f1a18d56a8..5008d28bbf 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/xml/to/cnsn/test/XmlToCnSnTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/xml/to/cnsn/test/XmlToCnSnTest.java @@ -7,14 +7,18 @@ */ package org.opendaylight.controller.sal.restconf.impl.xml.to.cnsn.test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import org.junit.BeforeClass; import org.junit.Test; import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider; import org.opendaylight.controller.sal.restconf.impl.test.TestUtils; import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader; -import org.opendaylight.yangtools.yang.data.api.*; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.Node; +import org.opendaylight.yangtools.yang.data.api.SimpleNode; public class XmlToCnSnTest extends YangAndXmlAndDataSchemaLoader { @@ -34,7 +38,7 @@ public class XmlToCnSnTest extends YangAndXmlAndDataSchemaLoader { assertEquals("cont", compositeNode.getNodeType().getLocalName()); SimpleNode lf2 = null; - for (Node childNode : compositeNode.getChildren()) { + for (Node childNode : compositeNode.getValue()) { if (childNode instanceof SimpleNode) { if (childNode.getNodeType().getLocalName().equals("lf2")) { lf2 = (SimpleNode) childNode; @@ -45,7 +49,7 @@ public class XmlToCnSnTest extends YangAndXmlAndDataSchemaLoader { assertNotNull(lf2); assertTrue(lf2.getValue() instanceof String); - assertEquals("121", (String) lf2.getValue()); + assertEquals("121", lf2.getValue()); } } diff --git a/opendaylight/md-sal/samples/l2switch/implementation/src/main/java/org/opendaylight/controller/sample/l2switch/md/util/InstanceIdentifierUtils.java b/opendaylight/md-sal/samples/l2switch/implementation/src/main/java/org/opendaylight/controller/sample/l2switch/md/util/InstanceIdentifierUtils.java index ea08f94ebc..c2be488d93 100644 --- a/opendaylight/md-sal/samples/l2switch/implementation/src/main/java/org/opendaylight/controller/sample/l2switch/md/util/InstanceIdentifierUtils.java +++ b/opendaylight/md-sal/samples/l2switch/implementation/src/main/java/org/opendaylight/controller/sample/l2switch/md/util/InstanceIdentifierUtils.java @@ -28,130 +28,129 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; /* InstanceIdentifierUtils provides utility functions related to InstanceIdentifiers. */ -public class InstanceIdentifierUtils { - - /** - * Creates an Instance Identifier (path) for node with specified id - * - * @param nodeId - * @return - */ - public static final InstanceIdentifier createNodePath(NodeId nodeId) { - return InstanceIdentifier.builder(Nodes.class) // - .child(Node.class, new NodeKey(nodeId)) // - .build(); - } - - /** - * Shorten's node child path to node path. - * - * @param nodeChild child of node, from which we want node path. - * @return - */ - public static final InstanceIdentifier getNodePath(InstanceIdentifier nodeChild) { - return nodeChild.firstIdentifierOf(Node.class); - } - - - /** - * Creates a table path by appending table specific location to node path - * - * @param nodePath - * @param tableKey - * @return - */ - public static final InstanceIdentifier createTablePath(InstanceIdentifier nodePath, TableKey tableKey) { - return InstanceIdentifier.builder(nodePath) - .augmentation(FlowCapableNode.class) - .child(Table.class, tableKey) - .build(); - } - - /** - * Creates a path for particular flow, by appending flow-specific information - * to table path. - * - * @param table - * @param flowKey - * @return - */ - public static InstanceIdentifier createFlowPath(InstanceIdentifier
    table, FlowKey flowKey) { - return InstanceIdentifier.builder(table) - .child(Flow.class, flowKey) - .build(); - } - - /** - * Extract table id from table path. - * - * @param tablePath - * @return - */ - public static Short getTableId(InstanceIdentifier
    tablePath) { - return tablePath.firstKeyOf(Table.class, TableKey.class).getId(); - } - - /** - * Extracts NodeConnectorKey from node connector path. - */ - public static NodeConnectorKey getNodeConnectorKey(InstanceIdentifier nodeConnectorPath) { - return nodeConnectorPath.firstKeyOf(NodeConnector.class, NodeConnectorKey.class); - } - - /** - * Extracts NodeKey from node path. - */ - public static NodeKey getNodeKey(InstanceIdentifier nodePath) { - return nodePath.firstKeyOf(Node.class, NodeKey.class); - } - - - // - public static final InstanceIdentifier createNodeConnectorIdentifier(String nodeIdValue, - String nodeConnectorIdValue) { - return InstanceIdentifier.builder(createNodePath(new NodeId(nodeIdValue))) // - .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId(nodeConnectorIdValue))) // - .build(); - } - - /** - * @param nodeConnectorRef - * @return - */ - public static InstanceIdentifier generateNodeInstanceIdentifier(NodeConnectorRef nodeConnectorRef) { - return nodeConnectorRef.getValue().firstIdentifierOf(Node.class); - } - - /** - * @param nodeConnectorRef - * @param flowTableKey - * @return - */ - public static InstanceIdentifier
    generateFlowTableInstanceIdentifier(NodeConnectorRef nodeConnectorRef, TableKey flowTableKey) { - return InstanceIdentifier.builder(generateNodeInstanceIdentifier(nodeConnectorRef)) - .augmentation(FlowCapableNode.class) - .child(Table.class, flowTableKey) - .build(); - } - - /** - * @param nodeConnectorRef - * @param flowTableKey - * @param flowKey - * @return - */ - public static InstanceIdentifier generateFlowInstanceIdentifier(NodeConnectorRef nodeConnectorRef, - TableKey flowTableKey, - FlowKey flowKey) { - return InstanceIdentifier.builder(generateFlowTableInstanceIdentifier(nodeConnectorRef, flowTableKey)) - .child(Flow.class, flowKey) - .build(); - } - - public static InstanceIdentifier generateTopologyInstanceIdentifier(String topologyId) { - return InstanceIdentifier.builder(NetworkTopology.class) - .child(Topology.class, new TopologyKey(new TopologyId(topologyId))) - .build(); - } +public final class InstanceIdentifierUtils { + + private InstanceIdentifierUtils() { + throw new UnsupportedOperationException("Utility class should never be instantiated"); + } + + /** + * Creates an Instance Identifier (path) for node with specified id + * + * @param nodeId + * @return + */ + public static final InstanceIdentifier createNodePath(final NodeId nodeId) { + return InstanceIdentifier.builder(Nodes.class) // + .child(Node.class, new NodeKey(nodeId)) // + .build(); + } + + /** + * Shorten's node child path to node path. + * + * @param nodeChild child of node, from which we want node path. + * @return + */ + public static final InstanceIdentifier getNodePath(final InstanceIdentifier nodeChild) { + return nodeChild.firstIdentifierOf(Node.class); + } + + + /** + * Creates a table path by appending table specific location to node path + * + * @param nodePath + * @param tableKey + * @return + */ + public static final InstanceIdentifier
    createTablePath(final InstanceIdentifier nodePath, final TableKey tableKey) { + return nodePath.builder() + .augmentation(FlowCapableNode.class) + .child(Table.class, tableKey) + .build(); + } + + /** + * Creates a path for particular flow, by appending flow-specific information + * to table path. + * + * @param table + * @param flowKey + * @return + */ + public static InstanceIdentifier createFlowPath(final InstanceIdentifier
    table, final FlowKey flowKey) { + return table.child(Flow.class, flowKey); + } + + /** + * Extract table id from table path. + * + * @param tablePath + * @return + */ + public static Short getTableId(final InstanceIdentifier
    tablePath) { + return tablePath.firstKeyOf(Table.class, TableKey.class).getId(); + } + + /** + * Extracts NodeConnectorKey from node connector path. + */ + public static NodeConnectorKey getNodeConnectorKey(final InstanceIdentifier nodeConnectorPath) { + return nodeConnectorPath.firstKeyOf(NodeConnector.class, NodeConnectorKey.class); + } + + /** + * Extracts NodeKey from node path. + */ + public static NodeKey getNodeKey(final InstanceIdentifier nodePath) { + return nodePath.firstKeyOf(Node.class, NodeKey.class); + } + + + // + public static final InstanceIdentifier createNodeConnectorIdentifier(final String nodeIdValue, + final String nodeConnectorIdValue) { + return createNodePath(new NodeId(nodeIdValue)) + .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId(nodeConnectorIdValue))); + } + + /** + * @param nodeConnectorRef + * @return + */ + public static InstanceIdentifier generateNodeInstanceIdentifier(final NodeConnectorRef nodeConnectorRef) { + return nodeConnectorRef.getValue().firstIdentifierOf(Node.class); + } + + /** + * @param nodeConnectorRef + * @param flowTableKey + * @return + */ + public static InstanceIdentifier
    generateFlowTableInstanceIdentifier(final NodeConnectorRef nodeConnectorRef, final TableKey flowTableKey) { + return generateNodeInstanceIdentifier(nodeConnectorRef).builder() + .augmentation(FlowCapableNode.class) + .child(Table.class, flowTableKey) + .build(); + } + + /** + * @param nodeConnectorRef + * @param flowTableKey + * @param flowKey + * @return + */ + public static InstanceIdentifier generateFlowInstanceIdentifier(final NodeConnectorRef nodeConnectorRef, + final TableKey flowTableKey, + final FlowKey flowKey) { + return generateFlowTableInstanceIdentifier(nodeConnectorRef, flowTableKey).child(Flow.class, flowKey); + } + + public static InstanceIdentifier generateTopologyInstanceIdentifier(final String topologyId) { + return InstanceIdentifier.builder(NetworkTopology.class) + .child(Topology.class, new TopologyKey(new TopologyId(topologyId))) + .build(); + } } diff --git a/opendaylight/md-sal/samples/l2switch/implementation/src/test/java/org/opendaylight/controller/sample/l2switch/md/flow/FlowWriterServiceImplTest.java b/opendaylight/md-sal/samples/l2switch/implementation/src/test/java/org/opendaylight/controller/sample/l2switch/md/flow/FlowWriterServiceImplTest.java index 3520d812d7..50f74cc33f 100644 --- a/opendaylight/md-sal/samples/l2switch/implementation/src/test/java/org/opendaylight/controller/sample/l2switch/md/flow/FlowWriterServiceImplTest.java +++ b/opendaylight/md-sal/samples/l2switch/implementation/src/test/java/org/opendaylight/controller/sample/l2switch/md/flow/FlowWriterServiceImplTest.java @@ -7,11 +7,19 @@ */ package org.opendaylight.controller.sample.l2switch.md.flow; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import org.junit.Before; import org.junit.Test; -import org.opendaylight.controller.sample.l2switch.md.topology.NetworkGraphService; import org.opendaylight.controller.sal.binding.api.data.DataBrokerService; import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; +import org.opendaylight.controller.sample.l2switch.md.topology.NetworkGraphService; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef; @@ -23,128 +31,110 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - /** */ public class FlowWriterServiceImplTest { - private DataBrokerService dataBrokerService; - private NodeConnectorRef srcNodeConnectorRef; - private NodeConnectorRef destNodeConnectorRef; - private MacAddress destMacAddress; - private MacAddress srcMacAddress; - private DataModificationTransaction dataModificationTransaction; - private NetworkGraphService networkGraphService; + private DataBrokerService dataBrokerService; + private NodeConnectorRef srcNodeConnectorRef; + private NodeConnectorRef destNodeConnectorRef; + private MacAddress destMacAddress; + private MacAddress srcMacAddress; + private DataModificationTransaction dataModificationTransaction; + private NetworkGraphService networkGraphService; - @Before - public void init() { - dataBrokerService = mock(DataBrokerService.class); - networkGraphService = mock(NetworkGraphService.class); - //build source node connector ref - InstanceIdentifier srcNodesInstanceIdentifier - = InstanceIdentifier.builder(Nodes.class) - .build(); - InstanceIdentifier srcNodeInstanceIdentifier - = InstanceIdentifier.builder(srcNodesInstanceIdentifier) - .child(Node.class, new NodeKey(new NodeId("openflow:1"))) - .build(); - InstanceIdentifier srcNodeConnectorInstanceIdentifier - = InstanceIdentifier.builder(srcNodeInstanceIdentifier) - .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:1:2"))) - .build(); - srcNodeConnectorRef = new NodeConnectorRef(srcNodeConnectorInstanceIdentifier); + @Before + public void init() { + dataBrokerService = mock(DataBrokerService.class); + networkGraphService = mock(NetworkGraphService.class); + //build source node connector ref + InstanceIdentifier srcNodesInstanceIdentifier = InstanceIdentifier.create(Nodes.class); + InstanceIdentifier srcNodeInstanceIdentifier = srcNodesInstanceIdentifier + .child(Node.class, new NodeKey(new NodeId("openflow:1"))); + InstanceIdentifier srcNodeConnectorInstanceIdentifier = srcNodeInstanceIdentifier + .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:1:2"))); + srcNodeConnectorRef = new NodeConnectorRef(srcNodeConnectorInstanceIdentifier); - //build dest node connector ref - InstanceIdentifier nodesInstanceIdentifier + //build dest node connector ref + InstanceIdentifier nodesInstanceIdentifier = InstanceIdentifier.builder(Nodes.class) .build(); - InstanceIdentifier nodeInstanceIdentifier - = InstanceIdentifier.builder(nodesInstanceIdentifier) - .child(Node.class, new NodeKey(new NodeId("openflow:2"))) - .build(); - InstanceIdentifier nodeConnectorInstanceIdentifier - = InstanceIdentifier.builder(nodeInstanceIdentifier) - .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:2:2"))) - .build(); - destNodeConnectorRef = new NodeConnectorRef(nodeConnectorInstanceIdentifier); - destMacAddress = new MacAddress("00:0a:95:9d:68:16"); - srcMacAddress = new MacAddress("00:0a:95:8c:97:24"); - dataModificationTransaction = mock(DataModificationTransaction.class); - when(dataBrokerService.beginTransaction()).thenReturn(dataModificationTransaction); - } + InstanceIdentifier nodeInstanceIdentifier = + nodesInstanceIdentifier.child(Node.class, new NodeKey(new NodeId("openflow:2"))); + InstanceIdentifier nodeConnectorInstanceIdentifier = + nodeInstanceIdentifier.child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:2:2"))); + destNodeConnectorRef = new NodeConnectorRef(nodeConnectorInstanceIdentifier); + destMacAddress = new MacAddress("00:0a:95:9d:68:16"); + srcMacAddress = new MacAddress("00:0a:95:8c:97:24"); + dataModificationTransaction = mock(DataModificationTransaction.class); + when(dataBrokerService.beginTransaction()).thenReturn(dataModificationTransaction); + } - @Test - public void testFlowWriterServiceImpl_NPEWhenDataBrokerServiceIsNull() throws Exception { - try { - new FlowWriterServiceImpl(null, networkGraphService); - fail("Expected null pointer exception."); - } catch(NullPointerException npe) { - assertEquals("dataBrokerService should not be null.", npe.getMessage()); + @Test + public void testFlowWriterServiceImpl_NPEWhenDataBrokerServiceIsNull() throws Exception { + try { + new FlowWriterServiceImpl(null, networkGraphService); + fail("Expected null pointer exception."); + } catch(NullPointerException npe) { + assertEquals("dataBrokerService should not be null.", npe.getMessage()); + } } - } - @Test - public void testAddMacToMacFlow_NPEWhenNullSourceMacDestMacAndNodeConnectorRef() throws Exception { - FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService); - try { - flowWriterService.addMacToMacFlow(null, null, null); - fail("Expected null pointer exception."); - } catch(NullPointerException npe) { - assertEquals("Destination mac address should not be null.", npe.getMessage()); + @Test + public void testAddMacToMacFlow_NPEWhenNullSourceMacDestMacAndNodeConnectorRef() throws Exception { + FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService); + try { + flowWriterService.addMacToMacFlow(null, null, null); + fail("Expected null pointer exception."); + } catch(NullPointerException npe) { + assertEquals("Destination mac address should not be null.", npe.getMessage()); + } } - } - @Test - public void testAddMacToMacFlow_NPEWhenSourceMacNullMac() throws Exception { - FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService); - try { - flowWriterService.addMacToMacFlow(null, null, destNodeConnectorRef); - fail("Expected null pointer exception."); - } catch(NullPointerException npe) { - assertEquals("Destination mac address should not be null.", npe.getMessage()); + @Test + public void testAddMacToMacFlow_NPEWhenSourceMacNullMac() throws Exception { + FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService); + try { + flowWriterService.addMacToMacFlow(null, null, destNodeConnectorRef); + fail("Expected null pointer exception."); + } catch(NullPointerException npe) { + assertEquals("Destination mac address should not be null.", npe.getMessage()); + } } - } - @Test - public void testAddMacToMacFlow_NPEWhenNullSourceMacNodeConnectorRef() throws Exception { - FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService); - try { - flowWriterService.addMacToMacFlow(null, destMacAddress, null); - fail("Expected null pointer exception."); - } catch(NullPointerException npe) { - assertEquals("Destination port should not be null.", npe.getMessage()); + @Test + public void testAddMacToMacFlow_NPEWhenNullSourceMacNodeConnectorRef() throws Exception { + FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService); + try { + flowWriterService.addMacToMacFlow(null, destMacAddress, null); + fail("Expected null pointer exception."); + } catch(NullPointerException npe) { + assertEquals("Destination port should not be null.", npe.getMessage()); + } } - } - @Test - public void testAddMacToMacFlow_WhenNullSourceMac() throws Exception { - FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService); - flowWriterService.addMacToMacFlow(null, destMacAddress, destNodeConnectorRef); - verify(dataBrokerService, times(1)).beginTransaction(); - verify(dataModificationTransaction, times(1)).commit(); - } + @Test + public void testAddMacToMacFlow_WhenNullSourceMac() throws Exception { + FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService); + flowWriterService.addMacToMacFlow(null, destMacAddress, destNodeConnectorRef); + verify(dataBrokerService, times(1)).beginTransaction(); + verify(dataModificationTransaction, times(1)).commit(); + } - @Test - public void testAddMacToMacFlow_WhenSrcAndDestMacAreSame() throws Exception { - FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService); - flowWriterService.addMacToMacFlow(new MacAddress(destMacAddress.getValue()), destMacAddress, destNodeConnectorRef); - verify(dataBrokerService, never()).beginTransaction(); - verify(dataModificationTransaction, never()).commit(); + @Test + public void testAddMacToMacFlow_WhenSrcAndDestMacAreSame() throws Exception { + FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService); + flowWriterService.addMacToMacFlow(new MacAddress(destMacAddress.getValue()), destMacAddress, destNodeConnectorRef); + verify(dataBrokerService, never()).beginTransaction(); + verify(dataModificationTransaction, never()).commit(); - } + } - @Test - public void testAddMacToMacFlow_SunnyDay() throws Exception { - FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService); - flowWriterService.addMacToMacFlow(srcMacAddress, destMacAddress, destNodeConnectorRef); - verify(dataBrokerService, times(1)).beginTransaction(); - verify(dataModificationTransaction, times(1)).commit(); - } + @Test + public void testAddMacToMacFlow_SunnyDay() throws Exception { + FlowWriterService flowWriterService = new FlowWriterServiceImpl(dataBrokerService, networkGraphService); + flowWriterService.addMacToMacFlow(srcMacAddress, destMacAddress, destNodeConnectorRef); + verify(dataBrokerService, times(1)).beginTransaction(); + verify(dataModificationTransaction, times(1)).commit(); + } } diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java index ff950e95e9..c6974d4982 100644 --- a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java +++ b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/NetconfSSHServer.java @@ -27,7 +27,7 @@ public final class NetconfSSHServer implements Runnable { private static final AtomicLong sesssionId = new AtomicLong(); private final InetSocketAddress clientAddress; private final AuthProvider authProvider; - private boolean up = false; + private volatile boolean up = false; private NetconfSSHServer(int serverPort,InetSocketAddress clientAddress, AuthProvider authProvider) throws IllegalStateException, IOException { @@ -68,9 +68,17 @@ public final class NetconfSSHServer implements Runnable { while (up) { logger.trace("Starting new socket thread."); try { - SocketThread.start(ss.accept(), clientAddress, sesssionId.incrementAndGet(), authProvider); - } catch (IOException e) { - logger.error("Exception occurred during socket thread initialization {}", e); + SocketThread.start(ss.accept(), clientAddress, sesssionId.incrementAndGet(), authProvider); + } + catch (IOException e) { + if( up ) { + logger.error("Exception occurred during socket thread initialization", e); + } + else { + // We're shutting down so an exception is expected as the socket's been closed. + // Log to debug. + logger.debug("Shutting down - got expected exception: " + e); + } } } } diff --git a/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/Activator.java b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/Activator.java index c30f659032..f101538196 100644 --- a/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/Activator.java +++ b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/Activator.java @@ -22,6 +22,8 @@ import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD; import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD; import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD; import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityRuleCRUD; import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase; public class Activator extends ComponentActivatorAbstractBase { @@ -163,5 +165,37 @@ public class Activator extends ComponentActivatorAbstractBase { "setConfigurationContainerService", "unsetConfigurationContainerService").setRequired(true)); } + if (imp.equals(NeutronSecurityGroupInterface.class)) { + // export the service + c.setInterface( + new String[] { INeutronSecurityGroupCRUD.class.getName(), + IConfigurationContainerAware.class.getName()}, null); + Dictionary props = new Hashtable(); + props.put("salListenerName", "neutron"); + c.add(createContainerServiceDependency(containerName) + .setService(IClusterContainerServices.class) + .setCallbacks("setClusterContainerService", + "unsetClusterContainerService").setRequired(true)); + c.add(createContainerServiceDependency(containerName).setService( + IConfigurationContainerService.class).setCallbacks( + "setConfigurationContainerService", + "unsetConfigurationContainerService").setRequired(true)); + } + if (imp.equals(NeutronSecurityRuleInterface.class)) { + // export the service + c.setInterface( + new String[] { INeutronSecurityRuleCRUD.class.getName(), + IConfigurationContainerAware.class.getName()}, null); + Dictionary props = new Hashtable(); + props.put("salListenerName", "neutron"); + c.add(createContainerServiceDependency(containerName) + .setService(IClusterContainerServices.class) + .setCallbacks("setClusterContainerService", + "unsetClusterContainerService").setRequired(true)); + c.add(createContainerServiceDependency(containerName).setService( + IConfigurationContainerService.class).setCallbacks( + "setConfigurationContainerService", + "unsetConfigurationContainerService").setRequired(true)); + } } } diff --git a/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronSecurityGroupInterface.java b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronSecurityGroupInterface.java new file mode 100644 index 0000000000..a991f61fcb --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronSecurityGroupInterface.java @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + */ + +package org.opendaylight.controller.networkconfig.neutron.implementation; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Map.Entry; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentMap; +import org.apache.felix.dm.Component; +import org.opendaylight.controller.clustering.services.CacheConfigException; +import org.opendaylight.controller.clustering.services.CacheExistException; +import org.opendaylight.controller.clustering.services.IClusterContainerServices; +import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.configuration.ConfigurationObject; +import org.opendaylight.controller.configuration.IConfigurationContainerAware; +import org.opendaylight.controller.configuration.IConfigurationContainerService; +import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupCRUD; +import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup; +import org.opendaylight.controller.sal.utils.IObjectReader; +import org.opendaylight.controller.sal.utils.Status; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class NeutronSecurityGroupInterface implements INeutronSecurityGroupCRUD, IConfigurationContainerAware, IObjectReader { + private static final Logger logger = LoggerFactory.getLogger(NeutronSecurityGroupInterface.class); + private static final String FILE_NAME ="neutron.securitygroup.conf"; + private String containerName = null; + + private IClusterContainerServices clusterContainerService = null; + private IConfigurationContainerService configurationService; + private ConcurrentMap securityGroupDB; + + // methods needed for creating caches + void setClusterContainerService(IClusterContainerServices s) { + logger.debug("Cluster Service set"); + clusterContainerService = s; + } + + void unsetClusterContainerService(IClusterContainerServices s) { + if (clusterContainerService == s) { + logger.debug("Cluster Service removed!"); + clusterContainerService = null; + } + } + + public void setConfigurationContainerService(IConfigurationContainerService service) { + logger.trace("Configuration service set: {}", service); + configurationService = service; + } + + public void unsetConfigurationContainerService(IConfigurationContainerService service) { + logger.trace("Configuration service removed: {}", service); + configurationService = null; + } + + private void allocateCache() { + if (this.clusterContainerService == null) { + logger.error("un-initialized clusterContainerService, can't create cache"); + return; + } + logger.debug("Creating Cache for Neutron Security Groups"); + try { + // neutron caches + this.clusterContainerService.createCache("neutronSecurityGroups", + EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); + } catch (CacheConfigException cce) { + logger.error("Cache couldn't be created for Neutron Security Groups - check cache mode"); + } catch (CacheExistException cce) { + logger.error("Cache for Neutron Security Groups already exists, destroy and recreate"); + } + logger.debug("Cache successfully created for Neutron Security Groups"); + } + + @SuppressWarnings({ "unchecked" }) + private void retrieveCache() { + if (clusterContainerService == null) { + logger.error("un-initialized clusterContainerService, can't retrieve cache"); + return; + } + + logger.debug("Retrieving cache for Neutron Security Groups"); + securityGroupDB = (ConcurrentMap) clusterContainerService + .getCache("neutronSecurityGroups"); + if (securityGroupDB == null) { + logger.error("Cache couldn't be retrieved for Neutron Security Groups"); + } + logger.debug("Cache was successfully retrieved for Neutron Security Groups"); + } + + private void destroyCache() { + if (clusterContainerService == null) { + logger.error("un-initialized clusterMger, can't destroy cache"); + return; + } + logger.debug("Destroying Cache for Neutron Security Groups"); + clusterContainerService.destroyCache("neutronSecurityGroups"); + } + + private void startUp() { + allocateCache(); + retrieveCache(); + loadConfiguration(); + } + + /** + * Function called by the dependency manager when all the required + * dependencies are satisfied + * + */ + void init(Component c) { + Dictionary props = c.getServiceProperties(); + if (props != null) { + this.containerName = (String) props.get("containerName"); + logger.debug("Running containerName: {}", this.containerName); + } else { + // In the Global instance case the containerName is empty + this.containerName = ""; + } + startUp(); + } + + /** + * Function called by the dependency manager when at least one dependency + * become unsatisfied or when the component is shutting down because for + * example bundle is being stopped. + * + */ + void destroy() { + destroyCache(); + } + + /** + * Function called by dependency manager after "init ()" is called and after + * the services provided by the class are registered in the service registry + * + */ + void start() { + } + + /** + * Function called by the dependency manager before the services exported by + * the component are unregistered, this will be followed by a "destroy ()" + * calls + * + */ + void stop() { + } + + // this method uses reflection to update an object from it's delta. + + private boolean overwrite(Object target, Object delta) { + Method[] methods = target.getClass().getMethods(); + + for(Method toMethod: methods){ + if(toMethod.getDeclaringClass().equals(target.getClass()) + && toMethod.getName().startsWith("set")){ + + String toName = toMethod.getName(); + String fromName = toName.replace("set", "get"); + + try { + Method fromMethod = delta.getClass().getMethod(fromName); + Object value = fromMethod.invoke(delta, (Object[])null); + if(value != null){ + toMethod.invoke(target, value); + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + } + return true; + } + + @Override + public boolean neutronSecurityGroupExists(String uuid) { + return securityGroupDB.containsKey(uuid); + } + + @Override + public NeutronSecurityGroup getNeutronSecurityGroup(String uuid) { + if (!neutronSecurityGroupExists(uuid)) { + logger.debug("No Security Groups Have Been Defined"); + return null; + } + return securityGroupDB.get(uuid); + } + + @Override + public List getAllNeutronSecurityGroups() { + Set allSecurityGroups = new HashSet(); + for (Entry entry : securityGroupDB.entrySet()) { + NeutronSecurityGroup securityGroup = entry.getValue(); + allSecurityGroups.add(securityGroup); + } + logger.debug("Exiting getSecurityGroups, Found {} OpenStackSecurityGroup", allSecurityGroups.size()); + List ans = new ArrayList(); + ans.addAll(allSecurityGroups); + return ans; + } + + @Override + public boolean addNeutronSecurityGroup(NeutronSecurityGroup input) { + if (neutronSecurityGroupExists(input.getSecurityGroupUUID())) { + return false; + } + securityGroupDB.putIfAbsent(input.getSecurityGroupUUID(), input); + return true; + } + + @Override + public boolean removeNeutronSecurityGroup(String uuid) { + if (!neutronSecurityGroupExists(uuid)) { + return false; + } + securityGroupDB.remove(uuid); + return true; + } + + @Override + public boolean updateNeutronSecurityGroup(String uuid, NeutronSecurityGroup delta) { + if (!neutronSecurityGroupExists(uuid)) { + return false; + } + NeutronSecurityGroup target = securityGroupDB.get(uuid); + return overwrite(target, delta); + } + + @Override + public boolean neutronSecurityGroupInUse(String securityGroupUUID) { + return !neutronSecurityGroupExists(securityGroupUUID); + } + + private void loadConfiguration() { + for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) { + NeutronSecurityGroup nn = (NeutronSecurityGroup) conf; + securityGroupDB.put(nn.getSecurityGroupUUID(), nn); + } + } + + @Override + public Status saveConfiguration() { + return configurationService.persistConfiguration(new ArrayList(securityGroupDB.values()), + FILE_NAME); + } + + @Override + public Object readObject(ObjectInputStream ois) throws FileNotFoundException, IOException, ClassNotFoundException { + return ois.readObject(); + } + +} \ No newline at end of file diff --git a/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronSecurityRuleInterface.java b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronSecurityRuleInterface.java new file mode 100644 index 0000000000..5ca907b2b3 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronSecurityRuleInterface.java @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + */ + +package org.opendaylight.controller.networkconfig.neutron.implementation; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Map.Entry; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentMap; + +import org.apache.felix.dm.Component; +import org.opendaylight.controller.clustering.services.CacheConfigException; +import org.opendaylight.controller.clustering.services.CacheExistException; +import org.opendaylight.controller.clustering.services.IClusterContainerServices; +import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.configuration.ConfigurationObject; +import org.opendaylight.controller.configuration.IConfigurationContainerAware; +import org.opendaylight.controller.configuration.IConfigurationContainerService; +import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityRuleCRUD; +import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityRule; +import org.opendaylight.controller.sal.utils.IObjectReader; +import org.opendaylight.controller.sal.utils.Status; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class NeutronSecurityRuleInterface implements INeutronSecurityRuleCRUD, IConfigurationContainerAware, IObjectReader { + private static final Logger logger = LoggerFactory.getLogger(NeutronSecurityRuleInterface.class); + private static final String FILE_NAME = "neutron.securityrule.conf"; + private String containerName = null; + + private IClusterContainerServices clusterContainerService = null; + private IConfigurationContainerService configurationService; + private ConcurrentMap securityRuleDB; + + // methods needed for creating caches + void setClusterContainerService(IClusterContainerServices s) { + logger.debug("Cluster Service set"); + clusterContainerService = s; + } + + void unsetClusterContainerService(IClusterContainerServices s) { + if (clusterContainerService == s) { + logger.debug("Cluster Service removed!"); + clusterContainerService = null; + } + } + + public void setConfigurationContainerService(IConfigurationContainerService service) { + logger.trace("Configuration service set: {}", service); + configurationService = service; + } + + public void unsetConfigurationContainerService(IConfigurationContainerService service) { + logger.trace("Configuration service removed: {}", service); + configurationService = null; + } + + private void allocateCache() { + if (this.clusterContainerService == null) { + logger.error("un-initialized clusterContainerService, can't create cache"); + return; + } + logger.debug("Creating Cache for Neutron Security Rules"); + try { + // neutron caches + this.clusterContainerService.createCache("neutronSecurityRules", + EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); + } catch (CacheConfigException cce) { + logger.error("Cache couldn't be created for Neutron Security Rules - check cache mode"); + } catch (CacheExistException cce) { + logger.error("Cache for Neutron Security Rules already exists, destroy and recreate"); + } + logger.debug("Cache successfully created for Neutron Security Rules"); + } + + @SuppressWarnings({"unchecked"}) + private void retrieveCache() { + if (clusterContainerService == null) { + logger.error("un-initialized clusterContainerService, can't retrieve cache"); + return; + } + + logger.debug("Retrieving cache for Neutron Security Rules"); + securityRuleDB = (ConcurrentMap) clusterContainerService + .getCache("neutronSecurityRules"); + if (securityRuleDB == null) { + logger.error("Cache couldn't be retrieved for Neutron Security Rules"); + } + logger.debug("Cache was successfully retrieved for Neutron Security Rules"); + } + + private void destroyCache() { + if (clusterContainerService == null) { + logger.error("un-initialized clusterMger, can't destroy cache"); + return; + } + logger.debug("Destroying Cache for Neutron Security Rules"); + clusterContainerService.destroyCache("neutronSecurityRules"); + } + + private void startUp() { + allocateCache(); + retrieveCache(); + loadConfiguration(); + } + + /** + * Function called by the dependency manager when all the required + * dependencies are satisfied + */ + void init(Component c) { + Dictionary props = c.getServiceProperties(); + if (props != null) { + this.containerName = (String) props.get("containerName"); + logger.debug("Running containerName: {}", this.containerName); + } else { + // In the Global instance case the containerName is empty + this.containerName = ""; + } + startUp(); + } + + /** + * Function called by the dependency manager when at least one dependency + * become unsatisfied or when the component is shutting down because for + * example bundle is being stopped. + */ + void destroy() { + destroyCache(); + } + + /** + * Function called by dependency manager after "init ()" is called and after + * the services provided by the class are registered in the service registry + */ + void start() { + } + + /** + * Function called by the dependency manager before the services exported by + * the component are unregistered, this will be followed by a "destroy ()" + * calls + */ + void stop() { + } + + // this method uses reflection to update an object from it's delta. + private boolean overwrite(Object target, Object delta) { + Method[] methods = target.getClass().getMethods(); + + for (Method toMethod : methods) { + if (toMethod.getDeclaringClass().equals(target.getClass()) + && toMethod.getName().startsWith("set")) { + + String toName = toMethod.getName(); + String fromName = toName.replace("set", "get"); + + try { + Method fromMethod = delta.getClass().getMethod(fromName); + Object value = fromMethod.invoke(delta, (Object[]) null); + if (value != null) { + toMethod.invoke(target, value); + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + } + return true; + } + + @Override + public boolean neutronSecurityRuleExists(String uuid) { + return securityRuleDB.containsKey(uuid); + } + + @Override + public NeutronSecurityRule getNeutronSecurityRule(String uuid) { + if (!neutronSecurityRuleExists(uuid)) { + logger.debug("No Security Rules Have Been Defined"); + return null; + } + return securityRuleDB.get(uuid); + } + + @Override + public List getAllNeutronSecurityRules() { + Set allSecurityRules = new HashSet(); + for (Entry entry : securityRuleDB.entrySet()) { + NeutronSecurityRule securityRule = entry.getValue(); + allSecurityRules.add(securityRule); + } + logger.debug("Exiting getSecurityRule, Found {} OpenStackSecurityRule", allSecurityRules.size()); + List ans = new ArrayList(); + ans.addAll(allSecurityRules); + return ans; + } + + @Override + public boolean addNeutronSecurityRule(NeutronSecurityRule input) { + if (neutronSecurityRuleExists(input.getSecurityRuleUUID())) { + return false; + } + securityRuleDB.putIfAbsent(input.getSecurityRuleUUID(), input); + return true; + } + + @Override + public boolean removeNeutronSecurityRule(String uuid) { + if (!neutronSecurityRuleExists(uuid)) { + return false; + } + securityRuleDB.remove(uuid); + return true; + } + + @Override + public boolean updateNeutronSecurityRule(String uuid, NeutronSecurityRule delta) { + if (!neutronSecurityRuleExists(uuid)) { + return false; + } + NeutronSecurityRule target = securityRuleDB.get(uuid); + return overwrite(target, delta); + } + + @Override + public boolean neutronSecurityRuleInUse(String securityRuleUUID) { + return !neutronSecurityRuleExists(securityRuleUUID); + } + + private void loadConfiguration() { + for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) { + NeutronSecurityRule nn = (NeutronSecurityRule) conf; + securityRuleDB.put(nn.getSecurityRuleUUID(), nn); + } + } + + @Override + public Status saveConfiguration() { + return configurationService.persistConfiguration(new ArrayList(securityRuleDB.values()), + FILE_NAME); + } + + @Override + public Object readObject(ObjectInputStream ois) throws FileNotFoundException, IOException, ClassNotFoundException { + return ois.readObject(); + } + +} \ No newline at end of file diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityGroupAware.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityGroupAware.java new file mode 100644 index 0000000000..0fdf77f968 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityGroupAware.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + */ + +package org.opendaylight.controller.networkconfig.neutron; + +/** + * This interface defines the methods a service that wishes to be aware of Neutron Security Groups needs to implement + */ + +public interface INeutronSecurityGroupAware { + + /** + * Services provide this interface method to indicate if the specified security group can be created + * + * @param securityGroup instance of proposed new Neutron Security Group object + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the create operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canCreateNeutronSecurityGroup(NeutronSecurityGroup securityGroup); + + /** + * Services provide this interface method for taking action after a security group has been created + * + * @param securityGroup instance of new Neutron Security Group object + * @return void + */ + public void neutronSecurityGroupCreated(NeutronSecurityGroup securityGroup); + + /** + * Services provide this interface method to indicate if the specified security group can be changed using the specified + * delta + * + * @param delta updates to the security group object using patch semantics + * @param original instance of the Neutron Security Group object to be updated + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the update operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canUpdateNeutronSecurityGroup(NeutronSecurityGroup delta, NeutronSecurityGroup original); + + /** + * Services provide this interface method for taking action after a security group has been updated + * + * @param securityGroup instance of modified Neutron Security Group object + * @return void + */ + public void neutronSecurityGroupUpdated(NeutronSecurityGroup securityGroup); + + /** + * Services provide this interface method to indicate if the specified security group can be deleted + * + * @param securityGroup instance of the Neutron Security Group object to be deleted + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the delete operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canDeleteNeutronSecurityGroup(NeutronSecurityGroup securityGroup); + + /** + * Services provide this interface method for taking action after a security group has been deleted + * + * @param securityGroup instance of deleted Neutron Security Group object + * @return void + */ + public void neutronSecurityGroupDeleted(NeutronSecurityGroup securityGroup); +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityGroupCRUD.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityGroupCRUD.java new file mode 100644 index 0000000000..a408ef92a7 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityGroupCRUD.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import java.util.List; + +/** + * This interface defines the methods for CRUD of NB OpenStack Security Group objects + */ + +public interface INeutronSecurityGroupCRUD { + /** + * Applications call this interface method to determine if a particular + * Security Group object exists + * + * @param uuid UUID of the Security Group object + * @return boolean + */ + + public boolean neutronSecurityGroupExists(String uuid); + + /** + * Applications call this interface method to return if a particular + * Security Group object exists + * + * @param uuid UUID of the Security Group object + * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup.OpenStackSecurity Groups} + * OpenStack Security Group class + */ + + public NeutronSecurityGroup getNeutronSecurityGroup(String uuid); + + /** + * Applications call this interface method to return all Security Group objects + * + * @return List of OpenStackSecurity Groups objects + */ + + public List getAllNeutronSecurityGroups(); + + /** + * Applications call this interface method to add a Security Group object to the + * concurrent map + * + * @param input OpenStackSecurity Group object + * @return boolean on whether the object was added or not + */ + + public boolean addNeutronSecurityGroup(NeutronSecurityGroup input); + + /** + * Applications call this interface method to remove a Neutron Security Group object to the + * concurrent map + * + * @param uuid identifier for the security group object + * @return boolean on whether the object was removed or not + */ + + public boolean removeNeutronSecurityGroup(String uuid); + + /** + * Applications call this interface method to edit a Security Group object + * + * @param uuid identifier of the security group object + * @param delta OpenStackSecurity Group object containing changes to apply + * @return boolean on whether the object was updated or not + */ + + public boolean updateNeutronSecurityGroup(String uuid, NeutronSecurityGroup delta); + + /** + * Applications call this interface method to see if a MAC address is in use + * + * @param uuid identifier of the security group object + * @return boolean on whether the Security Groups is already in use + */ + + public boolean neutronSecurityGroupInUse(String uuid); + +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityRuleAware.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityRuleAware.java new file mode 100644 index 0000000000..ff2a1c4978 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityRuleAware.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + */ + +package org.opendaylight.controller.networkconfig.neutron; + +/** + * This interface defines the methods required to be aware of Neutron Security Rules + */ + +public interface INeutronSecurityRuleAware { + + /** + * Services provide this interface method to indicate if the specified security rule can be created + * + * @param securityRule instance of proposed new Neutron Security Rule object + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the create operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canCreateNeutronSecurityRule(NeutronSecurityRule securityRule); + + /** + * Services provide this interface method for taking action after a security rule has been created + * + * @param securityRule instance of new Neutron Security Rule object + * @return void + */ + public void neutronSecurityRuleCreated(NeutronSecurityRule securityRule); + + /** + * Services provide this interface method to indicate if the specified security rule can be changed using the specified + * delta + * + * @param delta updates to the security rule object using patch semantics + * @param original instance of the Neutron Security Rule object to be updated + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the update operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canUpdateNeutronSecurityRule(NeutronSecurityRule delta, NeutronSecurityRule original); + + /** + * Services provide this interface method for taking action after a security rule has been updated + * + * @param securityRule instance of modified Neutron Security Rule object + * @return void + */ + public void neutronSecurityRuleUpdated(NeutronSecurityRule securityRule); + + /** + * Services provide this interface method to indicate if the specified security rule can be deleted + * + * @param securityRule instance of the Neutron Security Rule object to be deleted + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the delete operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canDeleteNeutronSecurityRule(NeutronSecurityRule securityRule); + + /** + * Services provide this interface method for taking action after a security rule has been deleted + * + * @param securityRule instance of deleted Neutron Security Rule object + * @return void + */ + public void neutronSecurityRuleDeleted(NeutronSecurityRule securityRule); +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityRuleCRUD.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityRuleCRUD.java new file mode 100644 index 0000000000..73b41c71a4 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSecurityRuleCRUD.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import java.util.List; + +/** + * This interface defines the methods for CRUD of NB OpenStack Security Rule objects + */ + +public interface INeutronSecurityRuleCRUD { + /** + * Applications call this interface method to determine if a particular + * Security Rule object exists + * + * @param uuid UUID of theSecurity Rule object + * @return boolean + */ + + public boolean neutronSecurityRuleExists(String uuid); + + /** + * Applications call this interface method to return if a particular + * Security Rule object exists + * + * @param uuid UUID of the security rule object + * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronSecurityRule.OpenStackNetworks} + * OpenStackSecurity Rule class + */ + + public NeutronSecurityRule getNeutronSecurityRule(String uuid); + + /** + * Applications call this interface method to return all Security Rule objects + * + * @return List of OpenStack SecurityRules objects + */ + + public List getAllNeutronSecurityRules(); + + /** + * Applications call this interface method to add a Security Rule object to the + * concurrent map + * + * @param input OpenStack security rule object + * @return boolean on whether the object was added or not + */ + + public boolean addNeutronSecurityRule(NeutronSecurityRule input); + + /** + * Applications call this interface method to remove a Neutron Security Rule object to the + * concurrent map + * + * @param uuid identifier for the security rule object + * @return boolean on whether the object was removed or not + */ + + public boolean removeNeutronSecurityRule(String uuid); + + /** + * Applications call this interface method to edit aSecurity Rule object + * + * @param uuid identifier of the security rule object + * @param delta OpenStackSecurity Rule object containing changes to apply + * @return boolean on whether the object was updated or not + */ + + public boolean updateNeutronSecurityRule(String uuid, NeutronSecurityRule delta); + + /** + * Applications call this interface method to see if a MAC address is in use + * + * @param uuid identifier of the security rule object + * @return boolean on whether the macAddress is already associated with a + * port or not + */ + + public boolean neutronSecurityRuleInUse(String uuid); + +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronCRUDInterfaces.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronCRUDInterfaces.java index aebecfa93e..21cfdb1305 100644 --- a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronCRUDInterfaces.java +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronCRUDInterfaces.java @@ -36,4 +36,14 @@ public class NeutronCRUDInterfaces { INeutronFloatingIPCRUD answer = (INeutronFloatingIPCRUD) ServiceHelper.getGlobalInstance(INeutronFloatingIPCRUD.class, o); return answer; } -} + + public static INeutronSecurityGroupCRUD getINeutronSecurityGroupCRUD(Object o) { + INeutronSecurityGroupCRUD answer = (INeutronSecurityGroupCRUD) ServiceHelper.getGlobalInstance(INeutronSecurityGroupCRUD.class, o); + return answer; + } + + public static INeutronSecurityRuleCRUD getINeutronSecurityRuleCRUD(Object o) { + INeutronSecurityRuleCRUD answer = (INeutronSecurityRuleCRUD) ServiceHelper.getGlobalInstance(INeutronSecurityRuleCRUD.class, o); + return answer; + } +} \ No newline at end of file diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronPort.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronPort.java index c8ee4e8ccc..680a07453b 100644 --- a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronPort.java +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronPort.java @@ -61,9 +61,8 @@ public class NeutronPort extends ConfigurationObject implements Serializable { @XmlElement (name="tenant_id") String tenantID; - // TODO: add security groups - // @XmlElement (name="security_groups") - // List securityGroups; + @XmlElement (name="security_groups") + List securityGroups; /* this attribute stores the floating IP address assigned to * each fixed IP address @@ -162,6 +161,14 @@ public class NeutronPort extends ConfigurationObject implements Serializable { this.tenantID = tenantID; } + public List getSecurityGroups() { + return securityGroups; + } + + public void setSecurityGroups(List securityGroups) { + this.securityGroups = securityGroups; + } + public NeutronFloatingIP getFloatingIP(String key) { if (!floatingIPMap.containsKey(key)) { return null; @@ -259,6 +266,6 @@ public class NeutronPort extends ConfigurationObject implements Serializable { return "NeutronPort [portUUID=" + portUUID + ", networkUUID=" + networkUUID + ", name=" + name + ", adminStateUp=" + adminStateUp + ", status=" + status + ", macAddress=" + macAddress + ", fixedIPs=" + fixedIPs + ", deviceID=" + deviceID + ", deviceOwner=" + deviceOwner + ", tenantID=" - + tenantID + ", floatingIPMap=" + floatingIPMap + "]"; + + tenantID + ", floatingIPMap=" + floatingIPMap + ", securityGroups=" + securityGroups + "]"; } } diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSecurityGroup.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSecurityGroup.java new file mode 100644 index 0000000000..0f0a14ca58 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSecurityGroup.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import org.opendaylight.controller.configuration.ConfigurationObject; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * OpenStack Neutron v2.0 Security Group bindings. + * See OpenStack Network API v2.0 Reference for description of + * annotated attributes. The current fields are as follows: + *

    + * id uuid-str unique ID for the security group. + * name String name of the security group. + * description String name of the security group. + * tenant_id uuid-str Owner of security rule.. + * security_group_rules List nested RO in the sec group. + */ + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class NeutronSecurityGroup extends ConfigurationObject implements Serializable { + private static final long serialVersionUID = 1L; + + @XmlElement(name = "id") + String securityGroupUUID; + + @XmlElement(name = "name") + String securityGroupName; + + @XmlElement(name = "description") + String securityGroupDescription; + + @XmlElement(name = "tenant_id") + String securityGroupTenantID; + + @XmlElement(name = "security_group_rules") + List neutronSecurityRule; + + List neutronPorts; + + public NeutronSecurityGroup() { + neutronPorts = new ArrayList (); + List securityRules; + + } + + public String getSecurityGroupUUID() { + return securityGroupUUID; + } + + public void setSecurityGroupUUID(String securityGroupUUID) { + this.securityGroupUUID = securityGroupUUID; + } + + public String getSecurityGroupName() { + return securityGroupName; + } + + public void setSecurityGroupName(String securityGroupName) { + this.securityGroupName = securityGroupName; + } + + public String getSecurityGroupDescription() { + return securityGroupDescription; + } + + public void setSecurityGroupDescription(String securityGroupDescription) { + this.securityGroupDescription = securityGroupDescription; + } + + public String getSecurityGroupTenantID() { + return securityGroupTenantID; + } + + public void setSecurityGroupTenantID(String securityGroupTenantID) { + this.securityGroupTenantID = securityGroupTenantID; + } + + // Rules In Group + public List getSecurityRules() { + return neutronSecurityRule; + } + + public void setSecurityRules(NeutronSecurityRule neutronSecurityRule) { + this.neutronSecurityRule = (List) neutronSecurityRule; + } + + public NeutronSecurityGroup extractFields(List fields) { + NeutronSecurityGroup ans = new NeutronSecurityGroup (); + Iterator i = fields.iterator (); + while (i.hasNext ()) { + String s = i.next (); + if (s.equals ("id")) { + ans.setSecurityGroupUUID (this.getSecurityGroupUUID ()); + } + if (s.equals ("name")) { + ans.setSecurityGroupName (this.getSecurityGroupName ()); + } + if (s.equals ("description")) { + ans.setSecurityGroupDescription (this.getSecurityGroupDescription ()); + } + if (s.equals ("tenant_id")) { + ans.setSecurityGroupTenantID (this.getSecurityGroupTenantID ()); + } + if (s.equals ("security_group_rules")) { + ans.setSecurityRules ((NeutronSecurityRule) this.getSecurityRules ()); + } + } + return ans; + } + + @Override + public String toString() { + return "NeutronSecurityGroup{" + + "securityGroupUUID='" + securityGroupUUID + '\'' + + ", securityGroupName='" + securityGroupName + '\'' + + ", securityGroupDescription='" + securityGroupDescription + '\'' + + ", securityGroupTenantID='" + securityGroupTenantID + '\'' + + ", securityRules=" + neutronSecurityRule + "]"; + } + + public void initDefaults() { + //TODO verify no defaults values are nessecary required. + } +} \ No newline at end of file diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSecurityRule.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSecurityRule.java new file mode 100644 index 0000000000..3fad4fe626 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSecurityRule.java @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import org.opendaylight.controller.configuration.ConfigurationObject; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.Iterator; +import java.util.List; + +/** + * See OpenStack Network API v2.0 Reference for description of + * annotated attributes. The current fields are as follows: + *

    + * id uuid (String) UUID for the security group rule. + * security_rule_id uuid (String) The security group to associate rule. + * direction String Direction the VM traffic (ingress/egress). + * security_group_id The security group to associate rule with. + * protocol String IP Protocol (icmp, tcp, udp, etc). + * port_range_min Integer Port at start of range + * port_range_max Integer Port at end of range + * ethertype String ethertype in L2 packet (IPv4, IPv6, etc) + * remote_ip_prefix String (IP cidr) CIDR for address range. + * remote_group_id uuid-str Source security group to apply to rule. + * tenant_id uuid-str Owner of security rule. Admin only outside tenant. + */ + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class NeutronSecurityRule extends ConfigurationObject implements Serializable { + private static final long serialVersionUID = 1L; + + @XmlElement(name = "id") + String securityRuleUUID; + + @XmlElement(name = "direction") + String securityRuleDirection; + + @XmlElement(name = "protocol") + String securityRuleProtocol; + + @XmlElement(name = "port_range_min") + Integer securityRulePortMin; + + @XmlElement(name = " port_range_max") + Integer securityRulePortMax; + + @XmlElement(name = "ethertype") + String securityRuleEthertype; + + @XmlElement(name = "remote_ip_prefix") + String securityRuleRemoteIpPrefix; + + @XmlElement(name = "remote_group_id") + String securityRemoteGroupID; + + @XmlElement(name = "security_group_id") + String securityRuleGroupID; + + @XmlElement(name = "tenant_id") + String securityRuleTenantID; + + public NeutronSecurityRule() { + List securityRules; + } + + public String getSecurityRuleUUID() { + return securityRuleUUID; + } + + public void setSecurityRuleUUID(String securityRuleUUID) { + this.securityRuleUUID = securityRuleUUID; + } + + public String getSecurityRuleDirection() { + return securityRuleDirection; + } + + public void setSecurityRuleDirection(String securityRuleDirection) { + this.securityRuleDirection = securityRuleDirection; + } + + public String getSecurityRuleProtocol() { + return securityRuleProtocol; + } + + public void setSecurityRuleProtocol(String securityRuleProtocol) { + this.securityRuleProtocol = securityRuleProtocol; + } + + public Integer getSecurityRulePortMin() { + return securityRulePortMin; + } + + public void setSecurityRulePortMin(Integer securityRulePortMin) { + this.securityRulePortMin = securityRulePortMin; + } + + public Integer getSecurityRulePortMax() { + return securityRulePortMax; + } + + public void setSecurityRulePortMax(Integer securityRulePortMax) { + this.securityRulePortMax = securityRulePortMax; + } + + public String getSecurityRuleEthertype() { + return securityRuleEthertype; + } + + public void setSecurityRuleEthertype(String securityRuleEthertype) { + this.securityRuleEthertype = securityRuleEthertype; + } + + public String getSecurityRuleRemoteIpPrefix() { + return securityRuleRemoteIpPrefix; + } + + public void setSecurityRuleRemoteIpPrefix(String securityRuleRemoteIpPrefix) { + this.securityRuleRemoteIpPrefix = securityRuleRemoteIpPrefix; + } + + public String getSecurityRemoteGroupID() { + return securityRemoteGroupID; + } + + public void setSecurityRemoteGroupID(String securityRemoteGroupID) { + this.securityRemoteGroupID = securityRemoteGroupID; + } + + public String getSecurityRuleGroupID() { + return securityRuleGroupID; + } + + public void setSecurityRuleGroupID(String securityRuleGroupID) { + this.securityRuleGroupID = securityRuleGroupID; + } + + public String getSecurityRuleTenantID() { + return securityRuleTenantID; + } + + public void setSecurityRuleTenantID(String securityRuleTenantID) { + this.securityRuleTenantID = securityRuleTenantID; + } + + public NeutronSecurityRule extractFields(List fields) { + NeutronSecurityRule ans = new NeutronSecurityRule(); + Iterator i = fields.iterator(); + while (i.hasNext()) { + String s = i.next(); + if (s.equals("id")) { + ans.setSecurityRuleUUID(this.getSecurityRuleUUID()); + } + if (s.equals("direction")) { + ans.setSecurityRuleDirection(this.getSecurityRuleDirection()); + } + if (s.equals("protocol")) { + ans.setSecurityRuleProtocol(this.getSecurityRuleProtocol()); + } + if (s.equals("port_range_min")) { + ans.setSecurityRulePortMin(this.getSecurityRulePortMin()); + } + if (s.equals("port_range_max")) { + ans.setSecurityRulePortMax(this.getSecurityRulePortMax()); + } + if (s.equals("ethertype")) { + ans.setSecurityRuleEthertype(this.getSecurityRuleEthertype()); + } + if (s.equals("remote_ip_prefix")) { + ans.setSecurityRuleRemoteIpPrefix(this.getSecurityRuleRemoteIpPrefix()); + } + if (s.equals("remote_group_id")) { + ans.setSecurityRemoteGroupID(this.getSecurityRemoteGroupID()); + } + if (s.equals("security_group_id")) { + ans.setSecurityRuleGroupID(this.getSecurityRuleGroupID()); + } + if (s.equals("tenant_id")) { + ans.setSecurityRuleTenantID(this.getSecurityRuleTenantID()); + } + } + return ans; + } + + @Override + public String toString() { + return "NeutronSecurityRule{" + + "securityRuleUUID='" + securityRuleUUID + '\'' + + ", securityRuleDirection='" + securityRuleDirection + '\'' + + ", securityRuleProtocol='" + securityRuleProtocol + '\'' + + ", securityRulePortMin=" + securityRulePortMin + + ", securityRulePortMax=" + securityRulePortMax + + ", securityRuleEthertype='" + securityRuleEthertype + '\'' + + ", securityRuleRemoteIpPrefix='" + securityRuleRemoteIpPrefix + '\'' + + ", securityRemoteGroupID=" + securityRemoteGroupID + + ", securityRuleGroupID='" + securityRuleGroupID + '\'' + + ", securityRuleTenantID='" + securityRuleTenantID + '\'' + + '}'; + } + + public void initDefaults() { + //TODO verify no defaults values are nessecary required. + } +} \ No newline at end of file diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNorthboundRSApplication.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNorthboundRSApplication.java index 76c39e4294..3fe03a2dac 100644 --- a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNorthboundRSApplication.java +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNorthboundRSApplication.java @@ -32,6 +32,8 @@ public class NeutronNorthboundRSApplication extends Application { classes.add(NeutronPortsNorthbound.class); classes.add(NeutronRoutersNorthbound.class); classes.add(NeutronFloatingIPsNorthbound.class); + classes.add(NeutronSecurityGroupsNorthbound.class); + classes.add(NeutronSecurityRulesNorthbound.class); return classes; } diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityGroupRequest.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityGroupRequest.java new file mode 100644 index 0000000000..6e779d64e2 --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityGroupRequest.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + */ + +package org.opendaylight.controller.networkconfig.neutron.northbound; + +import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.List; + + +@XmlRootElement +@XmlAccessorType (XmlAccessType.NONE) + +public class NeutronSecurityGroupRequest { + /** + * See OpenStack Network API v2.0 Reference for a + * description of annotated attributes and operations + */ + + @XmlElement (name = "security_group") + NeutronSecurityGroup singletonSecurityGroup; + + @XmlElement (name = "security_groups") + List bulkRequest; + + NeutronSecurityGroupRequest() { + } + + NeutronSecurityGroupRequest(List bulk) { + bulkRequest = bulk; + singletonSecurityGroup = null; + } + + NeutronSecurityGroupRequest(NeutronSecurityGroup group) { + singletonSecurityGroup = group; + } + + public List getBulk() { + return bulkRequest; + } + + public NeutronSecurityGroup getSingleton() { + return singletonSecurityGroup; + } + + public boolean isSingleton() { + return (singletonSecurityGroup != null); + } +} \ No newline at end of file diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityGroupsNorthbound.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityGroupsNorthbound.java new file mode 100644 index 0000000000..5e9a3318b9 --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityGroupsNorthbound.java @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + */ + +package org.opendaylight.controller.networkconfig.neutron.northbound; + + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.codehaus.enunciate.jaxrs.ResponseCode; +import org.codehaus.enunciate.jaxrs.StatusCodes; +import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupAware; +import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupCRUD; +import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces; +import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup; +import org.opendaylight.controller.northbound.commons.RestMessages; +import org.opendaylight.controller.northbound.commons.exception.BadRequestException; +import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException; +import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException; +import org.opendaylight.controller.sal.utils.ServiceHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Neutron Northbound REST APIs for Security Group.
    + * This class provides REST APIs for managing neutron Security Group + *

    + *
    + *
    + * Authentication scheme : HTTP Basic
    + * Authentication realm : opendaylight
    + * Transport : HTTP and HTTPS
    + *
    + * HTTPS Authentication is disabled by default. Administrator can enable it in + * tomcat-server.xml after adding a proper keystore / SSL certificate from a + * trusted authority.
    + * More info : + * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration + */ +@Path ("/security-groups") +public class NeutronSecurityGroupsNorthbound { + static final Logger logger = LoggerFactory.getLogger(NeutronSecurityGroupsNorthbound.class); + + private NeutronSecurityGroup extractFields(NeutronSecurityGroup o, List fields) { + return o.extractFields(fields); + } + + /** + * Returns a list of all Security Groups + */ + @GET + @Produces ({MediaType.APPLICATION_JSON}) + @StatusCodes ({ + @ResponseCode (code = 200, condition = "Operation successful"), + @ResponseCode (code = 401, condition = "Unauthorized"), + @ResponseCode (code = 501, condition = "Not Implemented")}) + + public Response listGroups( + // return fields + @QueryParam ("fields") List fields, + // OpenStack security group attributes + @QueryParam ("id") String querySecurityGroupUUID, + @QueryParam ("name") String querySecurityGroupName, + @QueryParam ("description") String querySecurityDescription, + @QueryParam ("tenant_id") String querySecurityTenantID, + @QueryParam ("limit") String limit, + @QueryParam ("marker") String marker, + @QueryParam ("page_reverse") String pageReverse + ) { + INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this); + + if (securityGroupInterface == null) { + throw new ServiceUnavailableException("Security Group CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + List allSecurityGroups = securityGroupInterface.getAllNeutronSecurityGroups(); + List ans = new ArrayList(); + Iterator i = allSecurityGroups.iterator(); + while (i.hasNext()) { + NeutronSecurityGroup nsg = i.next(); + if ((querySecurityGroupUUID == null || + querySecurityGroupUUID.equals(nsg.getSecurityGroupUUID())) && + (querySecurityGroupName == null || + querySecurityGroupName.equals(nsg.getSecurityGroupName())) && + (querySecurityDescription == null || + querySecurityDescription.equals(nsg.getSecurityGroupDescription())) && + (querySecurityTenantID == null || + querySecurityTenantID.equals(nsg.getSecurityGroupTenantID()))) { + if (fields.size() > 0) { + ans.add(extractFields(nsg, fields)); + } else { + ans.add(nsg); + } + } + } + return Response.status(200).entity( + new NeutronSecurityGroupRequest(ans)).build(); + } + + /** + * Returns a specific Security Group + */ + + @Path ("{securityGroupUUID}") + @GET + @Produces ({MediaType.APPLICATION_JSON}) + @StatusCodes ({ + @ResponseCode (code = 200, condition = "Operation successful"), + @ResponseCode (code = 401, condition = "Unauthorized"), + @ResponseCode (code = 404, condition = "Not Found"), + @ResponseCode (code = 501, condition = "Not Implemented")}) + public Response showSecurityGroup(@PathParam ("securityGroupUUID") String securityGroupUUID, + // return fields + @QueryParam ("fields") List fields) { + INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this); + if (securityGroupInterface == null) { + throw new ServiceUnavailableException("Security Group CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + if (!securityGroupInterface.neutronSecurityGroupExists(securityGroupUUID)) { + throw new ResourceNotFoundException("Security Group UUID does not exist."); + } + if (!fields.isEmpty()) { + NeutronSecurityGroup ans = securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID); + return Response.status(200).entity( + new NeutronSecurityGroupRequest(extractFields(ans, fields))).build(); + } else { + return Response.status(200).entity(new NeutronSecurityGroupRequest(securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID))).build(); + } + } + + /** + * Creates new Security Group + */ + + @POST + @Produces ({MediaType.APPLICATION_JSON}) + @Consumes ({MediaType.APPLICATION_JSON}) + @StatusCodes ({ + @ResponseCode (code = 201, condition = "Created"), + @ResponseCode (code = 400, condition = "Bad Request"), + @ResponseCode (code = 401, condition = "Unauthorized"), + @ResponseCode (code = 403, condition = "Forbidden"), + @ResponseCode (code = 404, condition = "Not Found"), + @ResponseCode (code = 409, condition = "Conflict"), + @ResponseCode (code = 501, condition = "Not Implemented")}) + public Response createSecurityGroups(final NeutronSecurityGroupRequest input) { + INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this); + if (securityGroupInterface == null) { + throw new ServiceUnavailableException("Security Group CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + if (input.isSingleton()) { + NeutronSecurityGroup singleton = input.getSingleton(); + + /* + * Verify that the Security Group doesn't already exist. + */ + if (securityGroupInterface.neutronSecurityGroupExists(singleton.getSecurityGroupUUID())) { + throw new BadRequestException("Security Group UUID already exists"); + } + + Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityGroupAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance; + int status = service.canCreateNeutronSecurityGroup(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } + } + } + // Add to Neutron cache + securityGroupInterface.addNeutronSecurityGroup(singleton); + if (instances != null) { + for (Object instance : instances) { + INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance; + service.neutronSecurityGroupCreated(singleton); + } + } + } else { + List bulk = input.getBulk(); + Iterator i = bulk.iterator(); + HashMap testMap = new HashMap(); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityGroupAware.class, this, null); + while (i.hasNext()) { + NeutronSecurityGroup test = i.next(); + + /* + * Verify that the security group doesn't already exist + */ + + if (securityGroupInterface.neutronSecurityGroupExists(test.getSecurityGroupUUID())) { + throw new BadRequestException("Security Group UUID already is already created"); + } + if (instances != null) for (Object instance : instances) { + INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance; + int status = service.canCreateNeutronSecurityGroup(test); + if ((status < 200) || (status > 299)) return Response.status(status).build(); + } + } + + /* + * now, each element of the bulk request can be added to the cache + */ + i = bulk.iterator(); + while (i.hasNext()) { + NeutronSecurityGroup test = i.next(); + securityGroupInterface.addNeutronSecurityGroup(test); + if (instances != null) { + for (Object instance : instances) { + INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance; + service.neutronSecurityGroupCreated(test); + } + } + } + } + return Response.status(201).entity(input).build(); + } + + /** + * Updates a Security Group + */ + + @Path ("{securityGroupUUID}") + @PUT + @Produces ({MediaType.APPLICATION_JSON}) + @Consumes ({MediaType.APPLICATION_JSON}) + @StatusCodes ({ + @ResponseCode (code = 200, condition = "Operation successful"), + @ResponseCode (code = 400, condition = "Bad Request"), + @ResponseCode (code = 401, condition = "Unauthorized"), + @ResponseCode (code = 403, condition = "Forbidden"), + @ResponseCode (code = 404, condition = "Not Found"), + @ResponseCode (code = 501, condition = "Not Implemented")}) + public Response updateSecurityGroup( + @PathParam ("securityGroupUUID") String securityGroupUUID, final NeutronSecurityGroupRequest input) { + INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this); + if (securityGroupInterface == null) { + throw new ServiceUnavailableException("Security Group CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + /* + * verify the Security Group exists and there is only one delta provided + */ + if (!securityGroupInterface.neutronSecurityGroupExists(securityGroupUUID)) { + throw new ResourceNotFoundException("Security Group UUID does not exist."); + } + if (!input.isSingleton()) { + throw new BadRequestException("Only singleton edit supported"); + } + NeutronSecurityGroup delta = input.getSingleton(); + NeutronSecurityGroup original = securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID); + + if (delta.getSecurityGroupUUID() != null || + delta.getSecurityGroupTenantID() != null || + delta.getSecurityGroupName() != null || + delta.getSecurityGroupDescription() != null) { + throw new BadRequestException("Attribute edit blocked by Neutron"); + } + + Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityGroupAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance; + int status = service.canUpdateNeutronSecurityGroup(delta, original); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } + } + } + + /* + * update the object and return it + */ + securityGroupInterface.updateNeutronSecurityGroup(securityGroupUUID, delta); + NeutronSecurityGroup updatedSecurityGroup = securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID); + if (instances != null) { + for (Object instance : instances) { + INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance; + service.neutronSecurityGroupUpdated(updatedSecurityGroup); + } + } + return Response.status(200).entity(new NeutronSecurityGroupRequest(securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID))).build(); + } + + /** + * Deletes a Security Group + */ + + @Path ("{securityGroupUUID}") + @DELETE + @StatusCodes ({ + @ResponseCode (code = 204, condition = "No Content"), + @ResponseCode (code = 401, condition = "Unauthorized"), + @ResponseCode (code = 404, condition = "Not Found"), + @ResponseCode (code = 409, condition = "Conflict"), + @ResponseCode (code = 501, condition = "Not Implemented")}) + public Response deleteSecurityGroup( + @PathParam ("securityGroupUUID") String securityGroupUUID) { + INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this); + if (securityGroupInterface == null) { + throw new ServiceUnavailableException("Security Group CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + /* + * verify the Security Group exists and it isn't currently in use + */ + if (!securityGroupInterface.neutronSecurityGroupExists(securityGroupUUID)) { + throw new ResourceNotFoundException("Security Group UUID does not exist."); + } + if (securityGroupInterface.neutronSecurityGroupInUse(securityGroupUUID)) { + return Response.status(409).build(); + } + NeutronSecurityGroup singleton = securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityGroupAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance; + int status = service.canDeleteNeutronSecurityGroup(singleton); + if ((status < 200) || (status > 299)) { + return Response.status(status).build(); + } + } + } + + /* + * remove it and return 204 status + */ + securityGroupInterface.removeNeutronSecurityGroup(securityGroupUUID); + if (instances != null) { + for (Object instance : instances) { + INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance; + service.neutronSecurityGroupDeleted(singleton); + } + } + return Response.status(204).build(); + } +} \ No newline at end of file diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityRuleRequest.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityRuleRequest.java new file mode 100644 index 0000000000..b805bd63bc --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityRuleRequest.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + */ + +package org.opendaylight.controller.networkconfig.neutron.northbound; + +import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityRule; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.List; + + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class NeutronSecurityRuleRequest { + /** + * See OpenStack Network API v2.0 Reference for a + * description of annotated attributes and operations + */ + + @XmlElement(name="security_group_rule") + NeutronSecurityRule singletonSecurityRule; + + @XmlElement(name="security_group_rules") + List bulkRequest; + + NeutronSecurityRuleRequest() { + } + + NeutronSecurityRuleRequest(List bulk) { + bulkRequest = bulk; + singletonSecurityRule = null; + } + + NeutronSecurityRuleRequest(NeutronSecurityRule rule) { + singletonSecurityRule = rule; + } + + public NeutronSecurityRule getSingleton() { + return singletonSecurityRule; + } + + public boolean isSingleton() { + return (singletonSecurityRule != null); + } + public List getBulk() { + return bulkRequest; + } + +} \ No newline at end of file diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityRulesNorthbound.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityRulesNorthbound.java new file mode 100644 index 0000000000..b2c05e0071 --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityRulesNorthbound.java @@ -0,0 +1,411 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + */ + +package org.opendaylight.controller.networkconfig.neutron.northbound; + + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.codehaus.enunciate.jaxrs.ResponseCode; +import org.codehaus.enunciate.jaxrs.StatusCodes; +import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityGroupCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityRuleAware; +import org.opendaylight.controller.networkconfig.neutron.INeutronSecurityRuleCRUD; +import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces; +import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityRule; +import org.opendaylight.controller.northbound.commons.RestMessages; +import org.opendaylight.controller.northbound.commons.exception.BadRequestException; +import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException; +import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException; +import org.opendaylight.controller.sal.utils.ServiceHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Neutron Northbound REST APIs for Security Rule.
    + * This class provides REST APIs for managing neutron Security Rule + *

    + *
    + *
    + * Authentication scheme : HTTP Basic
    + * Authentication realm : opendaylight
    + * Transport : HTTP and HTTPS
    + *
    + * HTTPS Authentication is disabled by default. Administrator can enable it in + * tomcat-server.xml after adding a proper keystore / SSL certificate from a + * trusted authority.
    + * More info : + * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration + */ + +@Path ("/security-group-rules") +public class NeutronSecurityRulesNorthbound { + static final Logger logger = LoggerFactory.getLogger(NeutronSecurityRulesNorthbound.class); + + private NeutronSecurityRule extractFields(NeutronSecurityRule o, List fields) { + return o.extractFields(fields); + } + + /** + * Returns a list of all Security Rules + */ + @GET + @Produces ({MediaType.APPLICATION_JSON}) + @StatusCodes ({ + @ResponseCode (code = 200, condition = "Operation successful"), + @ResponseCode (code = 401, condition = "Unauthorized"), + @ResponseCode (code = 501, condition = "Not Implemented")}) + public Response listRules( + // return fields + @QueryParam ("fields") List fields, + // OpenStack security rule attributes + @QueryParam ("id") String querySecurityRuleUUID, + @QueryParam ("direction") String querySecurityRuleDirection, + @QueryParam ("protocol") String querySecurityRuleProtocol, + @QueryParam ("port_range_min") Integer querySecurityRulePortMin, + @QueryParam ("port_range_max") Integer querySecurityRulePortMax, + @QueryParam ("ethertype") String querySecurityRuleEthertype, + @QueryParam ("remote_ip_prefix") String querySecurityRuleIpPrefix, + @QueryParam ("remote_group_id") String querySecurityRemoteGroupID, + @QueryParam ("security_group_id") String querySecurityRuleGroupID, + @QueryParam ("tenant_id") String querySecurityRuleTenantID, + @QueryParam ("limit") String limit, + @QueryParam ("marker") String marker, + @QueryParam ("page_reverse") String pageReverse + ) { + INeutronSecurityRuleCRUD securityRuleInterface = NeutronCRUDInterfaces.getINeutronSecurityRuleCRUD(this); + if (securityRuleInterface == null) { + throw new ServiceUnavailableException("Security Rule CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + List allSecurityRules = securityRuleInterface.getAllNeutronSecurityRules(); + List ans = new ArrayList(); + Iterator i = allSecurityRules.iterator(); + while (i.hasNext()) { + NeutronSecurityRule nsr = i.next(); + if ((querySecurityRuleUUID == null || + querySecurityRuleUUID.equals(nsr.getSecurityRuleUUID())) && + (querySecurityRuleDirection == null || + querySecurityRuleDirection.equals(nsr.getSecurityRuleDirection())) && + (querySecurityRuleProtocol == null || + querySecurityRuleProtocol.equals(nsr.getSecurityRuleProtocol())) && + (querySecurityRulePortMin == null || + querySecurityRulePortMin.equals(nsr.getSecurityRulePortMin())) && + (querySecurityRulePortMax == null || + querySecurityRulePortMax.equals(nsr.getSecurityRulePortMax())) && + (querySecurityRuleEthertype == null || + querySecurityRuleEthertype.equals(nsr.getSecurityRuleEthertype())) && + (querySecurityRuleIpPrefix == null || + querySecurityRuleIpPrefix.equals(nsr.getSecurityRuleRemoteIpPrefix())) && + (querySecurityRuleGroupID == null || + querySecurityRuleGroupID.equals(nsr.getSecurityRuleGroupID())) && + (querySecurityRemoteGroupID == null || + querySecurityRemoteGroupID.equals(nsr.getSecurityRemoteGroupID())) && + (querySecurityRuleTenantID == null || + querySecurityRuleTenantID.equals(nsr.getSecurityRuleTenantID()))) { + if (fields.size() > 0) { + ans.add(extractFields(nsr, fields)); + } else { + ans.add(nsr); + } + } + } + return Response.status(200).entity( + new NeutronSecurityRuleRequest(ans)).build(); + } + + /** + * Returns a specific Security Rule + */ + + @Path ("{securityRuleUUID}") + @GET + @Produces ({MediaType.APPLICATION_JSON}) + @StatusCodes ({ + @ResponseCode (code = 200, condition = "Operation successful"), + @ResponseCode (code = 401, condition = "Unauthorized"), + @ResponseCode (code = 404, condition = "Not Found"), + @ResponseCode (code = 501, condition = "Not Implemented")}) + public Response showSecurityRule(@PathParam ("securityRuleUUID") String securityRuleUUID, + // return fields + @QueryParam ("fields") List fields) { + INeutronSecurityRuleCRUD securityRuleInterface = NeutronCRUDInterfaces.getINeutronSecurityRuleCRUD(this); + if (securityRuleInterface == null) { + throw new ServiceUnavailableException("Security Rule CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + if (!securityRuleInterface.neutronSecurityRuleExists(securityRuleUUID)) { + throw new ResourceNotFoundException("Security Rule UUID does not exist."); + } + if (!fields.isEmpty()) { + NeutronSecurityRule ans = securityRuleInterface.getNeutronSecurityRule(securityRuleUUID); + return Response.status(200).entity( + new NeutronSecurityRuleRequest(extractFields(ans, fields))).build(); + } else { + return Response.status(200).entity(new NeutronSecurityRuleRequest(securityRuleInterface.getNeutronSecurityRule(securityRuleUUID))).build(); + } + } + + /** + * Creates new Security Rule + */ + + @POST + @Produces ({MediaType.APPLICATION_JSON}) + @Consumes ({MediaType.APPLICATION_JSON}) + @StatusCodes ({ + @ResponseCode (code = 201, condition = "Created"), + @ResponseCode (code = 400, condition = "Bad Request"), + @ResponseCode (code = 401, condition = "Unauthorized"), + @ResponseCode (code = 403, condition = "Forbidden"), + @ResponseCode (code = 404, condition = "Not Found"), + @ResponseCode (code = 409, condition = "Conflict"), + @ResponseCode (code = 501, condition = "Not Implemented")}) + public Response createSecurityRules(final NeutronSecurityRuleRequest input) { + INeutronSecurityRuleCRUD securityRuleInterface = NeutronCRUDInterfaces.getINeutronSecurityRuleCRUD(this); + if (securityRuleInterface == null) { + throw new ServiceUnavailableException("Security Rule CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + INeutronSecurityGroupCRUD securityGroupInterface = NeutronCRUDInterfaces.getINeutronSecurityGroupCRUD(this); + if (securityGroupInterface == null) { + throw new ServiceUnavailableException("Security Group CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + /* + * Existing entry checks + */ + + if (input.isSingleton()) { + NeutronSecurityRule singleton = input.getSingleton(); + + if (securityRuleInterface.neutronSecurityRuleExists(singleton.getSecurityRuleUUID())) { + throw new BadRequestException("Security Rule UUID already exists"); + } + Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityRuleAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance; + int status = service.canCreateNeutronSecurityRule(singleton); + if ((status < 200) || (status > 299)) { + return Response.status(status).build(); + } + } + } + + // add rule to cache + singleton.initDefaults(); + securityRuleInterface.addNeutronSecurityRule(singleton); + if (instances != null) { + for (Object instance : instances) { + INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance; + service.neutronSecurityRuleCreated(singleton); + } + } + + securityRuleInterface.addNeutronSecurityRule(singleton); + if (instances != null) { + for (Object instance : instances) { + INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance; + service.neutronSecurityRuleCreated(singleton); + } + } + } else { + List bulk = input.getBulk(); + Iterator i = bulk.iterator(); + HashMap testMap = new HashMap(); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityRuleAware.class, this, null); + while (i.hasNext()) { + NeutronSecurityRule test = i.next(); + + /* + * Verify that the security rule doesn't already exist + */ + + if (securityRuleInterface.neutronSecurityRuleExists(test.getSecurityRuleUUID())) { + throw new BadRequestException("Security Rule UUID already exists"); + } + if (testMap.containsKey(test.getSecurityRuleUUID())) { + throw new BadRequestException("Security Rule UUID already exists"); + } + if (instances != null) { + for (Object instance : instances) { + INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance; + int status = service.canCreateNeutronSecurityRule(test); + if ((status < 200) || (status > 299)) { + return Response.status(status).build(); + } + } + } + } + + /* + * now, each element of the bulk request can be added to the cache + */ + i = bulk.iterator(); + while (i.hasNext()) { + NeutronSecurityRule test = i.next(); + securityRuleInterface.addNeutronSecurityRule(test); + if (instances != null) { + for (Object instance : instances) { + INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance; + service.neutronSecurityRuleCreated(test); + } + } + } + } + return Response.status(201).entity(input).build(); + } + + /** + * Updates a Security Rule + */ + + @Path ("{securityRuleUUID}") + @PUT + @Produces ({MediaType.APPLICATION_JSON}) + @Consumes ({MediaType.APPLICATION_JSON}) + @StatusCodes ({ + @ResponseCode (code = 200, condition = "Operation successful"), + @ResponseCode (code = 400, condition = "Bad Request"), + @ResponseCode (code = 401, condition = "Unauthorized"), + @ResponseCode (code = 403, condition = "Forbidden"), + @ResponseCode (code = 404, condition = "Not Found"), + @ResponseCode (code = 501, condition = "Not Implemented")}) + public Response updateSecurityRule( + @PathParam ("securityRuleUUID") String securityRuleUUID, final NeutronSecurityRuleRequest input) { + INeutronSecurityRuleCRUD securityRuleInterface = NeutronCRUDInterfaces.getINeutronSecurityRuleCRUD(this); + if (securityRuleInterface == null) { + throw new ServiceUnavailableException("Security Rule CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + /* + * verify the Security Rule exists and there is only one delta provided + */ + if (!securityRuleInterface.neutronSecurityRuleExists(securityRuleUUID)) { + throw new ResourceNotFoundException("Security Rule UUID does not exist."); + } + if (!input.isSingleton()) { + throw new BadRequestException("Only singleton edit supported"); + } + NeutronSecurityRule delta = input.getSingleton(); + NeutronSecurityRule original = securityRuleInterface.getNeutronSecurityRule(securityRuleUUID); + + /* + * updates restricted by Neutron + * + */ + if (delta.getSecurityRuleUUID() != null || + delta.getSecurityRuleDirection() != null || + delta.getSecurityRuleProtocol() != null || + delta.getSecurityRulePortMin() != null || + delta.getSecurityRulePortMax() != null || + delta.getSecurityRuleEthertype() != null || + delta.getSecurityRuleRemoteIpPrefix() != null || + delta.getSecurityRuleGroupID() != null || + delta.getSecurityRemoteGroupID() != null || + delta.getSecurityRuleTenantID() != null) { + throw new BadRequestException("Attribute edit blocked by Neutron"); + } + + Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityRuleAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance; + int status = service.canUpdateNeutronSecurityRule(delta, original); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } + } + } + + /* + * update the object and return it + */ + securityRuleInterface.updateNeutronSecurityRule(securityRuleUUID, delta); + NeutronSecurityRule updatedSecurityRule = securityRuleInterface.getNeutronSecurityRule(securityRuleUUID); + if (instances != null) { + for (Object instance : instances) { + INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance; + service.neutronSecurityRuleUpdated(updatedSecurityRule); + } + } + return Response.status(200).entity(new NeutronSecurityRuleRequest(securityRuleInterface.getNeutronSecurityRule(securityRuleUUID))).build(); + } + + /** + * Deletes a Security Rule + */ + + @Path ("{securityRuleUUID}") + @DELETE + @StatusCodes ({ + @ResponseCode (code = 204, condition = "No Content"), + @ResponseCode (code = 401, condition = "Unauthorized"), + @ResponseCode (code = 404, condition = "Not Found"), + @ResponseCode (code = 409, condition = "Conflict"), + @ResponseCode (code = 501, condition = "Not Implemented")}) + public Response deleteSecurityRule( + @PathParam ("securityRuleUUID") String securityRuleUUID) { + INeutronSecurityRuleCRUD securityRuleInterface = NeutronCRUDInterfaces.getINeutronSecurityRuleCRUD(this); + if (securityRuleInterface == null) { + throw new ServiceUnavailableException("Security Rule CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + /* + * verify the Security Rule exists and it isn't currently in use + */ + if (!securityRuleInterface.neutronSecurityRuleExists(securityRuleUUID)) { + throw new ResourceNotFoundException("Security Rule UUID does not exist."); + } + if (securityRuleInterface.neutronSecurityRuleInUse(securityRuleUUID)) { + return Response.status(409).build(); + } + NeutronSecurityRule singleton = securityRuleInterface.getNeutronSecurityRule(securityRuleUUID); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronSecurityRuleAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance; + int status = service.canDeleteNeutronSecurityRule(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } + } + } + + /* + * remove it and return 204 status + */ + securityRuleInterface.removeNeutronSecurityRule(securityRuleUUID); + if (instances != null) { + for (Object instance : instances) { + INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance; + service.neutronSecurityRuleDeleted(singleton); + } + } + return Response.status(204).build(); + } +} \ No newline at end of file