<groupId>org.opendaylight.controller</groupId>
<artifactId>mdsal-netconf-monitoring</artifactId>
</dependency>
-
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-mdsal-config</artifactId>
+ <version>${netconf.version}</version>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-netconf-connector</artifactId>
<version>${mdsal.version}</version>
</dependency>
+
<!-- toaster -->
<dependency>
<groupId>org.opendaylight.controller.samples</groupId>
</execution>
</executions>
</plugin>
- <plugin>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-maven-plugin</artifactId>
- <version>${yangtools.version}</version>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>maven-sal-api-gen-plugin</artifactId>
- <version>${yangtools.version}</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-binding</artifactId>
- <version>${yangtools.version}</version>
- <type>jar</type>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-rest-docgen-maven</artifactId>
- <version>${mdsal.version}</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- <executions>
- <execution>
- <goals>
- <goal>generate-sources</goal>
- </goals>
- <configuration>
- <yangFilesRootDir>src</yangFilesRootDir>
- <codeGenerators>
- <generator>
- <codeGeneratorClass>org.opendaylight.controller.sal.rest.doc.maven.StaticDocGenerator</codeGeneratorClass>
- <outputBaseDir>${project.build.directory}/generated-resources/swagger-api-documentation/explorer/static</outputBaseDir>
- </generator>
- </codeGenerators>
- <inspectDependencies>true</inspectDependencies>
- </configuration>
- </execution>
- </executions>
- </plugin>
</plugins>
</build>
<scm>
</feature>
<!-- TODO move to netconf features, however there are some weird dependencies on features-config-persister all over that cause cyclic dependencies-->
- <!-- TODO when installing this in pure karaf distro, many optimistic lock exceptions are thrown from config manager -->
<feature name='odl-netconf-mdsal' version='${project.version}' description="OpenDaylight :: Netconf :: Mdsal">
<feature version='${config.version}'>odl-config-all</feature>
<feature version='${netconf.version}'>odl-netconf-all</feature>
+ <!-- TODO remove dependency on sal netconf connector (odl-yangtools-models, sal-netconf-connector, model-inventory-->
+ <feature version='${yangtools.version}'>odl-yangtools-models</feature>
+ <bundle>mvn:org.opendaylight.controller/sal-netconf-connector/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller.model/model-inventory/${project.version}</bundle>
<bundle>mvn:org.opendaylight.controller/netconf-ssh/${netconf.version}</bundle>
<feature version='${mdsal.version}'>odl-mdsal-broker</feature>
<bundle>mvn:org.opendaylight.controller/mdsal-netconf-connector/${netconf.version}</bundle>
<bundle>mvn:org.opendaylight.controller.samples/clustering-it-provider/${project.version}</bundle>
<configfile finalname="${config.configfile.directory}/20-clustering-test-app.xml">mvn:org.opendaylight.controller.samples/clustering-it-config/${project.version}/xml/config</configfile>
</feature>
-
</features>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>
+
+
+ <!-- message-bus -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>messagebus-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>messagebus-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>messagebus-config</artifactId>
+ <version>${mdsal.version}</version>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>netconf-connector-config</artifactId>
<bundle>mvn:org.opendaylight.controller/netconf-tcp/${netconf.version}</bundle>
</feature>
+ <feature name='odl-message-bus' version='${project.version}'>
+ <feature version='${project.version}'>odl-netconf-connector</feature>
+ <feature version='${project.version}'>odl-mdsal-broker</feature>
+ <bundle>mvn:org.opendaylight.controller/messagebus-api/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.controller/messagebus-impl/${project.version}</bundle>
+ <configfile finalname="${config.configfile.directory}/05-message-bus.xml">mvn:org.opendaylight.controller/messagebus-config/${project.version}/xml/config</configfile>
+ </feature>
<!-- Optional TODO: Remove TODO Comments -->
</features>
<groupId>org.opendaylight.controller</groupId>
<artifactId>netconf-config</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>netconf-mdsal-config</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>netconf-auth</artifactId>
import org.opendaylight.controller.config.manager.impl.jmx.TransactionJMXRegistrator;
import org.opendaylight.controller.config.manager.impl.osgi.BeanToOsgiServiceManager;
import org.opendaylight.controller.config.manager.impl.osgi.BeanToOsgiServiceManager.OsgiRegistration;
+import org.opendaylight.controller.config.manager.impl.osgi.mapping.BindingContextProvider;
import org.opendaylight.controller.config.manager.impl.util.LookupBeansUtil;
import org.opendaylight.controller.config.manager.impl.util.ModuleQNameUtil;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
-import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final ModuleFactoriesResolver resolver;
private final MBeanServer configMBeanServer;
- private final CodecRegistry codecRegistry;
+ private final BindingContextProvider bindingContextProvider;
@GuardedBy("this")
private long version = 0;
// constructor
public ConfigRegistryImpl(ModuleFactoriesResolver resolver,
- MBeanServer configMBeanServer, CodecRegistry codecRegistry) {
+ MBeanServer configMBeanServer, BindingContextProvider bindingContextProvider) {
this(resolver, configMBeanServer,
- new BaseJMXRegistrator(configMBeanServer), codecRegistry);
+ new BaseJMXRegistrator(configMBeanServer), bindingContextProvider);
}
// constructor
public ConfigRegistryImpl(ModuleFactoriesResolver resolver,
MBeanServer configMBeanServer,
- BaseJMXRegistrator baseJMXRegistrator, CodecRegistry codecRegistry) {
+ BaseJMXRegistrator baseJMXRegistrator, BindingContextProvider bindingContextProvider) {
this.resolver = resolver;
this.beanToOsgiServiceManager = new BeanToOsgiServiceManager();
this.configMBeanServer = configMBeanServer;
this.baseJMXRegistrator = baseJMXRegistrator;
- this.codecRegistry = codecRegistry;
+ this.bindingContextProvider = bindingContextProvider;
this.registryMBeanServer = MBeanServerFactory
.createMBeanServer("ConfigRegistry" + configMBeanServer.getDefaultDomain());
this.transactionsMBeanServer = MBeanServerFactory
readableSRRegistry, txLookupRegistry, allCurrentFactories);
ConfigTransactionControllerInternal transactionController = new ConfigTransactionControllerImpl(
- txLookupRegistry, version, codecRegistry,
+ txLookupRegistry, version, bindingContextProvider,
versionCounter, allCurrentFactories, transactionsMBeanServer,
configMBeanServer, blankTransaction, writableRegistry);
try {
import org.opendaylight.controller.config.manager.impl.factoriesresolver.HierarchicalConfigMBeanFactoriesHolder;
import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator;
import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator.TransactionModuleJMXRegistration;
+import org.opendaylight.controller.config.manager.impl.osgi.mapping.BindingContextProvider;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.opendaylight.yangtools.concepts.Identifiable;
-import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final SearchableServiceReferenceWritableRegistry writableSRRegistry;
public ConfigTransactionControllerImpl(ConfigTransactionLookupRegistry txLookupRegistry,
- long parentVersion, CodecRegistry codecRegistry, long currentVersion,
+ long parentVersion, BindingContextProvider bindingContextProvider, long currentVersion,
Map<String, Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories,
MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer,
boolean blankTransaction, SearchableServiceReferenceWritableRegistry writableSRRegistry) {
this.factoriesHolder = new HierarchicalConfigMBeanFactoriesHolder(currentlyRegisteredFactories);
this.transactionStatus = new TransactionStatus();
this.dependencyResolverManager = new DependencyResolverManager(txLookupRegistry.getTransactionIdentifier(),
- transactionStatus, writableSRRegistry, codecRegistry, transactionsMBeanServer);
+ transactionStatus, writableSRRegistry, bindingContextProvider, transactionsMBeanServer);
this.transactionsMBeanServer = transactionsMBeanServer;
this.configMBeanServer = configMBeanServer;
this.blankTransaction = blankTransaction;
import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.config.manager.impl.TransactionStatus;
+import org.opendaylight.controller.config.manager.impl.osgi.mapping.BindingContextProvider;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.opendaylight.yangtools.yang.binding.BaseIdentity;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
-import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@GuardedBy("this")
private final Set<ModuleIdentifier> dependencies = new HashSet<>();
private final ServiceReferenceReadableRegistry readableRegistry;
- private final CodecRegistry codecRegistry;
+ private final BindingContextProvider bindingContextProvider;
private final String transactionName;
private final MBeanServer mBeanServer;
DependencyResolverImpl(ModuleIdentifier currentModule,
TransactionStatus transactionStatus, ModulesHolder modulesHolder,
- ServiceReferenceReadableRegistry readableRegistry, CodecRegistry codecRegistry,
+ ServiceReferenceReadableRegistry readableRegistry, BindingContextProvider bindingContextProvider,
String transactionName, MBeanServer mBeanServer) {
- this.codecRegistry = codecRegistry;
+ this.bindingContextProvider = bindingContextProvider;
this.name = currentModule;
this.transactionStatus = transactionStatus;
this.modulesHolder = modulesHolder;
@Override
public <T extends BaseIdentity> Class<? extends T> resolveIdentity(IdentityAttributeRef identityRef, Class<T> expectedBaseClass) {
final QName qName = QName.create(identityRef.getqNameOfIdentity());
- IdentityCodec<?> identityCodec = codecRegistry.getIdentityCodec();
- Class<? extends BaseIdentity> deserialized = identityCodec.deserialize(qName);
+ Class<?> deserialized = bindingContextProvider.getBindingContext().getIdentityClass(qName);
if (deserialized == null) {
throw new IllegalStateException("Unable to retrieve identity class for " + qName + ", null response from "
- + codecRegistry);
+ + bindingContextProvider.getBindingContext());
}
if (expectedBaseClass.isAssignableFrom(deserialized)) {
return (Class<T>) deserialized;
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
import static com.google.common.base.Preconditions.checkState;
+
import com.google.common.base.Preconditions;
import com.google.common.reflect.AbstractInvocationHandler;
import com.google.common.reflect.Reflection;
import org.opendaylight.controller.config.manager.impl.TransactionIdentifier;
import org.opendaylight.controller.config.manager.impl.TransactionStatus;
import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator.TransactionModuleJMXRegistration;
+import org.opendaylight.controller.config.manager.impl.osgi.mapping.BindingContextProvider;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
-import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
import org.osgi.framework.BundleContext;
/**
private final ModulesHolder modulesHolder;
private final TransactionStatus transactionStatus;
private final ServiceReferenceReadableRegistry readableRegistry;
- private final CodecRegistry codecRegistry;
+ private final BindingContextProvider bindingContextProvider;
private final DeadlockMonitor deadlockMonitor;
private final MBeanServer mBeanServer;
public DependencyResolverManager(final TransactionIdentifier transactionIdentifier,
final TransactionStatus transactionStatus,
- final ServiceReferenceReadableRegistry readableRegistry, final CodecRegistry codecRegistry,
+ final ServiceReferenceReadableRegistry readableRegistry, final BindingContextProvider bindingContextProvider,
final MBeanServer mBeanServer) {
this.transactionIdentifier = transactionIdentifier;
this.modulesHolder = new ModulesHolder(transactionIdentifier);
this.transactionStatus = transactionStatus;
this.readableRegistry = readableRegistry;
- this.codecRegistry = codecRegistry;
+ this.bindingContextProvider = bindingContextProvider;
this.deadlockMonitor = new DeadlockMonitor(transactionIdentifier);
this.mBeanServer = mBeanServer;
}
if (dependencyResolver == null) {
transactionStatus.checkNotCommitted();
dependencyResolver = new DependencyResolverImpl(name, transactionStatus, modulesHolder, readableRegistry,
- codecRegistry, transactionIdentifier.getName(), mBeanServer);
+ bindingContextProvider, transactionIdentifier.getName(), mBeanServer);
moduleIdentifiersToDependencyResolverMap.put(name, dependencyResolver);
}
return dependencyResolver;
import javax.management.MBeanServer;
import org.opendaylight.controller.config.manager.impl.ConfigRegistryImpl;
import org.opendaylight.controller.config.manager.impl.jmx.ConfigRegistryJMXRegistrator;
-import org.opendaylight.controller.config.manager.impl.osgi.mapping.CodecRegistryProvider;
+import org.opendaylight.controller.config.manager.impl.osgi.mapping.BindingContextProvider;
import org.opendaylight.controller.config.manager.impl.osgi.mapping.ModuleInfoBundleTracker;
import org.opendaylight.controller.config.manager.impl.osgi.mapping.RefreshingSCPModuleInfoRegistry;
import org.opendaylight.controller.config.manager.impl.util.OsgiRegistrationUtil;
ModuleInfoBackedContext moduleInfoBackedContext = ModuleInfoBackedContext.create();// the inner strategy is backed by thread context cl?
+ BindingContextProvider bindingContextProvider = new BindingContextProvider();
+
RefreshingSCPModuleInfoRegistry moduleInfoRegistryWrapper = new RefreshingSCPModuleInfoRegistry(
- moduleInfoBackedContext, moduleInfoBackedContext, context);
+ moduleInfoBackedContext, moduleInfoBackedContext, moduleInfoBackedContext, bindingContextProvider, context);
ModuleInfoBundleTracker moduleInfoBundleTracker = new ModuleInfoBundleTracker(moduleInfoRegistryWrapper);
- CodecRegistryProvider codecRegistryProvider = new CodecRegistryProvider(moduleInfoBackedContext, context);
// start config registry
BundleContextBackedModuleFactoriesResolver bundleContextBackedModuleFactoriesResolver = new BundleContextBackedModuleFactoriesResolver(
context);
ConfigRegistryImpl configRegistry = new ConfigRegistryImpl(bundleContextBackedModuleFactoriesResolver, configMBeanServer,
- codecRegistryProvider.getCodecRegistry());
+ bindingContextProvider);
// track bundles containing factories
BlankTransactionServiceTracker blankTransactionServiceTracker = new BlankTransactionServiceTracker(
serviceTracker.open();
List<AutoCloseable> list = Arrays.asList(
- codecRegistryProvider, clsReg,configRegistry, wrap(bundleTracker), configRegReg, configRegistryJMXRegistrator, wrap(serviceTracker));
+ bindingContextProvider, clsReg,configRegistry, wrap(bundleTracker), configRegReg, configRegistryJMXRegistrator, wrap(serviceTracker));
autoCloseable = OsgiRegistrationUtil.aggregate(list);
}
--- /dev/null
+/*
+ * 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.config.manager.impl.osgi.mapping;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
+
+/**
+ * Creates and initializes {@link BindingRuntimeContext}, which is used to resolve Identity classes from QName.
+ * An instance of {@link BindingRuntimeContext} is available only after first schema context was successfully built.
+ */
+// TODO move to yang runtime
+public class BindingContextProvider implements AutoCloseable {
+
+ private BindingRuntimeContext current;
+
+ public synchronized void update(final ClassLoadingStrategy classLoadingStrategy, final SchemaContextProvider ctxProvider) {
+ this.current = BindingRuntimeContext.create(classLoadingStrategy, ctxProvider.getSchemaContext());
+ }
+
+ public synchronized BindingRuntimeContext getBindingContext() {
+ Preconditions.checkState(current != null, "Binding context not yet initialized");
+ return this.current;
+ }
+
+ @Override
+ public synchronized void close() throws Exception {
+ current = null;
+ }
+}
+++ /dev/null
-/*
- * 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.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;
-import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
-import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
-import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
-import org.osgi.framework.BundleContext;
-
-/**
- * Creates and initializes {@link RuntimeGeneratedMappingServiceImpl}, which is used to get {@link CodecRegistry}.
- * Also maintains service registrations of {@link RuntimeGeneratedMappingServiceImpl}.
- */
-// TODO move to yang runtime
-public class CodecRegistryProvider implements AutoCloseable {
- private static final ClassPool CLASS_POOL = ClassPool.getDefault();
-
- private final RuntimeGeneratedMappingServiceImpl service;
- private final AutoCloseable registration;
-
- public CodecRegistryProvider(final ClassLoadingStrategy classLoadingStrategy, final BundleContext context) {
- service = new RuntimeGeneratedMappingServiceImpl(CLASS_POOL, classLoadingStrategy);
- registration = OsgiRegistrationUtil.registerService(context, service,
- SchemaContextListener.class, BindingIndependentMappingService.class);
- }
-
- public CodecRegistry getCodecRegistry() {
- return service.getCodecRegistry();
- }
-
- @Override
- public void close() throws Exception {
- registration.close();
- }
-}
import java.util.Hashtable;
import org.opendaylight.yangtools.concepts.ObjectRegistration;
+import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
import org.opendaylight.yangtools.sal.binding.generator.api.ModuleInfoRegistry;
import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
public class RefreshingSCPModuleInfoRegistry implements ModuleInfoRegistry, AutoCloseable {
private final ModuleInfoRegistry moduleInfoRegistry;
+ private final SchemaContextProvider schemaContextProvider;
+ private final BindingContextProvider bindingContextProvider;
+ private final ClassLoadingStrategy classLoadingStrat;
+
private final ServiceRegistration<SchemaContextProvider> osgiReg;
- public RefreshingSCPModuleInfoRegistry(ModuleInfoRegistry moduleInfoRegistry,
- SchemaContextProvider schemaContextProvider, BundleContext bundleContext) {
+ public RefreshingSCPModuleInfoRegistry(final ModuleInfoRegistry moduleInfoRegistry,
+ final SchemaContextProvider schemaContextProvider, final ClassLoadingStrategy classLoadingStrat, final BindingContextProvider bindingContextProvider, final BundleContext bundleContext) {
this.moduleInfoRegistry = moduleInfoRegistry;
+ this.schemaContextProvider = schemaContextProvider;
+ this.classLoadingStrat = classLoadingStrat;
+ this.bindingContextProvider = bindingContextProvider;
osgiReg = bundleContext.registerService(SchemaContextProvider.class, schemaContextProvider, new Hashtable<String, String>());
}
private void updateService() {
+ bindingContextProvider.update(classLoadingStrat, schemaContextProvider);
osgiReg.setProperties(null); // send modifiedService event
}
return wrapper;
}
-
@Override
- public void close() {
+ public void close() throws Exception {
osgiReg.unregister();
}
+
private class ObjectRegistrationWrapper implements ObjectRegistration<YangModuleInfo> {
private final ObjectRegistration<YangModuleInfo> inner;
import org.opendaylight.controller.config.manager.impl.jmx.BaseJMXRegistrator;
import org.opendaylight.controller.config.manager.impl.jmx.ConfigRegistryJMXRegistrator;
import org.opendaylight.controller.config.manager.impl.jmx.InternalJMXRegistrator;
+import org.opendaylight.controller.config.manager.impl.osgi.mapping.BindingContextProvider;
import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolImpl;
import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPool;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.util.ConfigRegistryJMXClient;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
-import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
internalJmxRegistrator = new InternalJMXRegistrator(platformMBeanServer);
baseJmxRegistrator = new BaseJMXRegistrator(internalJmxRegistrator);
- configRegistry = new ConfigRegistryImpl(resolver,
- platformMBeanServer, baseJmxRegistrator, getCodecRegistry());
+ configRegistry = new ConfigRegistryImpl(resolver, platformMBeanServer, baseJmxRegistrator, new BindingContextProvider() {
+ @Override
+ public synchronized void update(final ClassLoadingStrategy classLoadingStrategy, final SchemaContextProvider ctxProvider) {
+ // NOOP
+ }
+
+ @Override
+ public synchronized BindingRuntimeContext getBindingContext() {
+ return getBindingRuntimeContext();
+ }
+ });
try {
configRegistryJMXRegistrator.registerToJMX(configRegistry);
return new ClassBasedModuleFactory(implementationName, configBeanClass);
}
- protected CodecRegistry getCodecRegistry() {
- return mock(CodecRegistry.class);
+ protected BindingRuntimeContext getBindingRuntimeContext() {
+ return mock(BindingRuntimeContext.class);
}
public static interface BundleContextServiceRegistrationHandler {
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import java.util.Dictionary;
import org.junit.Test;
import org.mockito.Mockito;
+import org.opendaylight.controller.config.manager.impl.osgi.mapping.BindingContextProvider;
import org.opendaylight.controller.config.manager.impl.osgi.mapping.RefreshingSCPModuleInfoRegistry;
import org.opendaylight.yangtools.concepts.ObjectRegistration;
+import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
import org.opendaylight.yangtools.sal.binding.generator.api.ModuleInfoRegistry;
import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
ModuleInfoRegistry reg = mock(ModuleInfoRegistry.class);
SchemaContextProvider prov = mock(SchemaContextProvider.class);
doReturn("string").when(prov).toString();
-
BundleContext ctxt = mock(BundleContext.class);
ServiceRegistration<?> servReg = mock(ServiceRegistration.class);
doReturn(servReg).when(ctxt).registerService(Mockito.any(Class.class), Mockito.any(SchemaContextProvider.class), Mockito.any(Dictionary.class));
doReturn(servReg).when(ctxt).registerService(Mockito.anyString(), Mockito.any(Object.class), Mockito.any(Dictionary.class));
- RefreshingSCPModuleInfoRegistry scpreg = new RefreshingSCPModuleInfoRegistry(reg, prov, ctxt);
- YangModuleInfo modInfo = mock(YangModuleInfo.class);
+ final ClassLoadingStrategy classLoadingStrat = mock(ClassLoadingStrategy.class);
+ final BindingContextProvider codecRegistryProvider = mock(BindingContextProvider.class);
+ doNothing().when(codecRegistryProvider).update(classLoadingStrat, prov);
+
+ RefreshingSCPModuleInfoRegistry scpreg = new RefreshingSCPModuleInfoRegistry(reg, prov, classLoadingStrat, codecRegistryProvider, ctxt);
+
doNothing().when(servReg).setProperties(null);
doNothing().when(servReg).unregister();
+
+ YangModuleInfo modInfo = mock(YangModuleInfo.class);
doReturn("").when(modInfo).toString();
ObjectRegistration<YangModuleInfo> ymi = mock(ObjectRegistration.class);
doReturn(ymi).when(reg).registerModuleInfo(modInfo);
scpreg.registerModuleInfo(modInfo);
+
+ verify(codecRegistryProvider).update(classLoadingStrat, prov);
+
scpreg.close();
Mockito.verify(servReg, Mockito.times(1)).setProperties(null);
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity1;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity2;
-import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
-import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
public class NetconfTestImplModuleTest extends AbstractConfigTest {
}
@Override
- protected CodecRegistry getCodecRegistry() {
- final IdentityCodec<?> codec = mock(IdentityCodec.class);
- doReturn(TestIdentity1.class).when(codec).deserialize(TestIdentity1.QNAME);
- doReturn(TestIdentity2.class).when(codec).deserialize(TestIdentity2.QNAME);
-
- final CodecRegistry ret = super.getCodecRegistry();
- doReturn(codec).when(ret).getIdentityCodec();
+ protected BindingRuntimeContext getBindingRuntimeContext() {
+ final BindingRuntimeContext ret = super.getBindingRuntimeContext();
+ doReturn(TestIdentity1.class).when(ret).getIdentityClass(TestIdentity1.QNAME);
+ doReturn(TestIdentity2.class).when(ret).getIdentityClass(TestIdentity2.QNAME);
return ret;
}
<provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
</instance>
</service>
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-codec-tree-factory</type>
+ <instance>
+ <name>runtime-mapping-singleton</name>
+ <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
+ </instance>
+ </service>
<service>
<type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-new-notification-service</type>
<instance>
<!-- MessageBus -->
<dependency>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>message-bus-api</artifactId>
+ <artifactId>messagebus-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>message-bus-impl</artifactId>
+ <artifactId>messagebus-impl</artifactId>
<version>${project.version}</version>
</dependency>
<version>1.2.0-SNAPSHOT</version>
</parent>
- <artifactId>message-bus-api</artifactId>
+ <artifactId>messagebus-api</artifactId>
<name>${project.artifactId}</name>
<packaging>bundle</packaging>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.\r
+\r
+This program and the accompanying materials are made available under the\r
+terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+and is available at http://www.eclipse.org/legal/epl-v10.html\r
+-->\r
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
+\r
+ <modelVersion>4.0.0</modelVersion>\r
+\r
+ <parent>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>sal-parent</artifactId>\r
+ <version>1.2.0-SNAPSHOT</version>\r
+ </parent>\r
+\r
+ <artifactId>messagebus-config</artifactId>\r
+ <packaging>jar</packaging>\r
+ <description>Configuration files for message-bus</description>\r
+\r
+ <dependencies>\r
+ <dependency>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>config-api</artifactId>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>messagebus-api</artifactId>\r
+ <version>${project.version}</version>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>messagebus-impl</artifactId>\r
+ <version>${project.version}</version>\r
+ </dependency>\r
+ </dependencies>\r
+\r
+ <build>\r
+ <plugins>\r
+ <plugin>\r
+ <groupId>org.codehaus.mojo</groupId>\r
+ <artifactId>build-helper-maven-plugin</artifactId>\r
+ <executions>\r
+ <execution>\r
+ <id>attach-artifacts</id>\r
+ <goals>\r
+ <goal>attach-artifact</goal>\r
+ </goals>\r
+ <phase>package</phase>\r
+ <configuration>\r
+ <artifacts>\r
+ <artifact>\r
+ <file>${project.build.directory}/classes/initial/05-message-bus.xml</file>\r
+ <type>xml</type>\r
+ <classifier>config</classifier>\r
+ </artifact>\r
+ </artifacts>\r
+ </configuration>\r
+ </execution>\r
+ </executions>\r
+ </plugin>\r
+ </plugins>\r
+ </build>\r
+\r
+ <scm>\r
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>\r
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>\r
+ <tag>HEAD</tag>\r
+ <url>https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=summary</url>\r
+ </scm>\r
+</project>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2015 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
+-->
+<snapshot>
+ <configuration>
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <name>messagebus-app</name>
+ <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:messagebus:app:impl">binding-impl:messagebus-app-impl</type>
+ <binding-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:messagebus:app:impl">
+ <type xmlns:md-sal-binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">md-sal-binding:binding-broker-osgi-registry</type>
+ <name>binding-osgi-broker</name>
+ </binding-broker>
+ <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:messagebus:app:impl">
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+ <name>dom-broker</name>
+ </dom-broker>
+ <namespace-to-stream>
+ <urn-prefix>urn:ietf:params:xml:ns:yang:smiv2</urn-prefix>
+ <stream-name>SNMP</stream-name>
+ </namespace-to-stream>
+ <namespace-to-stream>
+ <urn-prefix>urn:ietf:params:xml:ns:yang:ietf-syslog-notification</urn-prefix>
+ <stream-name>SYSLOG</stream-name>
+ </namespace-to-stream>
+ </module>
+ </modules>
+ </data>
+ </configuration>
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:messagebus:app:impl?module=messagebus-app-impl&revision=2015-02-03</capability>
+ </required-capabilities>
+</snapshot>
<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.\r
+\r
+This program and the accompanying materials are made available under the\r
+terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+and is available at http://www.eclipse.org/legal/epl-v10.html\r
+-->\r
<project xmlns="http://maven.apache.org/POM/4.0.0"\r
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
<version>1.2.0-SNAPSHOT</version>\r
</parent>\r
\r
- <artifactId>message-bus-impl</artifactId>\r
+ <artifactId>messagebus-impl</artifactId>\r
<name>${project.artifactId}</name>\r
\r
<packaging>bundle</packaging>\r
<groupId>org.opendaylight.controller</groupId>\r
<artifactId>sal-binding-api</artifactId>\r
</dependency>\r
+ <dependency>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>sal-netconf-connector</artifactId>\r
+ </dependency>\r
<dependency>\r
<groupId>org.opendaylight.controller</groupId>\r
<artifactId>sal-core-api</artifactId>\r
</dependency>\r
<dependency>\r
<groupId>org.opendaylight.controller</groupId>\r
- <artifactId>message-bus-api</artifactId>\r
+ <artifactId>messagebus-api</artifactId>\r
+ <version>1.2.0-SNAPSHOT</version>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>sal-netconf-connector</artifactId>\r
</dependency>\r
<dependency>\r
<groupId>org.opendaylight.controller</groupId>\r
<artifactId>sal-binding-config</artifactId>\r
</dependency>\r
+\r
+ <!-- Testing Dependencies -->\r
+ <dependency>\r
+ <groupId>junit</groupId>\r
+ <artifactId>junit</artifactId>\r
+ <scope>test</scope>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>\r
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>\r
+ <scope>test</scope>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.mockito</groupId>\r
+ <artifactId>mockito-all</artifactId>\r
+ <scope>test</scope>\r
+ </dependency>\r
</dependencies>\r
\r
<build>\r
/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2015 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,
*/
package org.opendaylight.controller.config.yang.messagebus.app.impl;
+import java.util.List;
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.ModuleIdentifier;
-import org.opendaylight.controller.mdsal.InitializationContext;
-import org.opendaylight.controller.mdsal.Providers;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.MountPointService;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationPublishService;
+import org.opendaylight.controller.messagebus.app.impl.EventSourceTopology;
+import org.opendaylight.controller.messagebus.app.impl.NetconfEventSourceManager;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.List;
-
-public class MessageBusAppImplModule extends org.opendaylight.controller.config.yang.messagebus.app.impl.AbstractMessageBusAppImplModule {
+public class MessageBusAppImplModule extends
+ org.opendaylight.controller.config.yang.messagebus.app.impl.AbstractMessageBusAppImplModule {
private static final Logger LOGGER = LoggerFactory.getLogger(MessageBusAppImplModule.class);
private BundleContext bundleContext;
return bundleContext;
}
- public void setBundleContext(BundleContext bundleContext) {
+ public void setBundleContext(final BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
- public MessageBusAppImplModule( ModuleIdentifier identifier, DependencyResolver dependencyResolver) {
+ public MessageBusAppImplModule(final ModuleIdentifier identifier, final DependencyResolver dependencyResolver) {
super(identifier, dependencyResolver);
}
- public MessageBusAppImplModule( ModuleIdentifier identifier,
- DependencyResolver dependencyResolver,
- MessageBusAppImplModule oldModule,
- java.lang.AutoCloseable oldInstance) {
+ public MessageBusAppImplModule(final ModuleIdentifier identifier, final DependencyResolver dependencyResolver,
+ final MessageBusAppImplModule oldModule, final java.lang.AutoCloseable oldInstance) {
super(identifier, dependencyResolver, oldModule, oldInstance);
}
@Override
- protected void customValidation() {}
+ protected void customValidation() {
+ }
@Override
public java.lang.AutoCloseable createInstance() {
- List<NamespaceToStream> namespaceMapping = getNamespaceToStream();
- InitializationContext ic = new InitializationContext(namespaceMapping);
+ final List<NamespaceToStream> namespaceMapping = getNamespaceToStream();
+
+ final ProviderContext bindingCtx = getBindingBrokerDependency().registerProvider(new Providers.BindingAware());
+ final ProviderSession domCtx = getDomBrokerDependency().registerProvider(new Providers.BindingIndependent());
- final Providers.BindingAware bap = new Providers.BindingAware(ic);
- final Providers.BindingIndependent bip = new Providers.BindingIndependent(ic);
+ final DataBroker dataBroker = bindingCtx.getSALService(DataBroker.class);
+ final DOMNotificationPublishService domPublish = domCtx.getService(DOMNotificationPublishService.class);
+ final DOMMountPointService domMount = domCtx.getService(DOMMountPointService.class);
+ final MountPointService bindingMount = bindingCtx.getSALService(MountPointService.class);
+ final RpcProviderRegistry rpcRegistry = bindingCtx.getSALService(RpcProviderRegistry.class);
- getBindingBrokerDependency().registerProvider(bap, getBundleContext());
- getDomBrokerDependency().registerProvider(bip);
+ final EventSourceTopology eventSourceTopology = new EventSourceTopology(dataBroker, rpcRegistry);
+ final NetconfEventSourceManager eventSourceManager = new NetconfEventSourceManager(dataBroker, domPublish,
+ domMount, bindingMount, eventSourceTopology, getNamespaceToStream());
- AutoCloseable closer = new AutoCloseable() {
- @Override public void close() {
- closeProvider(bap);
- closeProvider(bip);
+ final AutoCloseable closer = new AutoCloseable() {
+ @Override
+ public void close() {
+ eventSourceTopology.close();
+ eventSourceManager.close();
}
};
return closer;
}
- private void closeProvider(AutoCloseable closable) {
+ private void closeProvider(final AutoCloseable closable) {
try {
closable.close();
- } catch (Exception e) {
+ } catch (final Exception e) {
LOGGER.error("Exception while closing: {}\n Exception: {}", closable, e);
}
}
/**
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2015 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.mdsal;
+package org.opendaylight.controller.config.yang.messagebus.app.impl;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
private static final Logger LOGGER = LoggerFactory.getLogger(Providers.class);
public static class BindingAware implements BindingAwareProvider, AutoCloseable {
- private final InitializationContext initializationContext;
- public BindingAware(InitializationContext ic) {
- this.initializationContext = ic;
- }
@Override
- public void onSessionInitiated(BindingAwareBroker.ProviderContext session) {
- initializationContext.set(session);
-
+ public void onSessionInitiated(final BindingAwareBroker.ProviderContext session) {
LOGGER.info("BindingAwareBroker.ProviderContext initialized");
}
}
public static class BindingIndependent extends AbstractProvider implements AutoCloseable {
- private final InitializationContext initializationContext;
-
- public BindingIndependent(InitializationContext ic) {
- this.initializationContext = ic;
- }
@Override
- public void onSessionInitiated(Broker.ProviderSession session) {
- initializationContext.set(session);
-
+ public void onSessionInitiated(final Broker.ProviderSession session) {
LOGGER.info("Broker.ProviderSession initialized");
}
+++ /dev/null
-/*
- * 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.mdsal;
-
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-public class DataStore {
- private static final FutureCallback<Void> DEFAULT_CALLBACK =
- new FutureCallback<Void>() {
- public void onSuccess(Void result) {
- // TODO: Implement default behaviour
- }
-
- public void onFailure(Throwable t) {
- // TODO: Implement default behaviour
- };
- };
-
- private final MdSAL mdSAL;
-
- public DataStore(MdSAL mdSAL) {
- this.mdSAL = mdSAL;
- }
-
- public ListenerRegistration<DataChangeListener> registerDataChangeListener(LogicalDatastoreType store,
- InstanceIdentifier<?> path,
- DataChangeListener listener,
- AsyncDataBroker.DataChangeScope triggeringScope) {
- return mdSAL.getDataBroker().registerDataChangeListener(store, path, listener, triggeringScope);
- }
-
- public <T extends DataObject> void asyncPUT(LogicalDatastoreType datastoreType,
- InstanceIdentifier<T> path,
- T data) {
- asyncPUT(datastoreType, path, data, DEFAULT_CALLBACK);
- }
-
- public <T extends DataObject> void asyncPUT(LogicalDatastoreType datastoreType,
- InstanceIdentifier<T> path,
- T data,
- FutureCallback<Void> callback) {
- WriteTransaction tx = mdSAL.getDataBroker().newWriteOnlyTransaction();
- tx.put(datastoreType, path, data, true);
- execPut(tx, callback);
- }
-
- public <T extends DataObject> T read(LogicalDatastoreType datastoreType,
- InstanceIdentifier<T> path) {
-
- ReadOnlyTransaction tx = mdSAL.getDataBroker().newReadOnlyTransaction();
- T result = null;
-
- try {
- result = tx.read(datastoreType, path).get().get();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
-
- return result;
- }
-
- private static void execPut(WriteTransaction tx, FutureCallback<Void> callback) {
- Futures.addCallback(tx.submit(), callback);
- }
-}
+++ /dev/null
-/**
- * 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.mdsal;
-
-import org.opendaylight.controller.config.yang.messagebus.app.impl.NamespaceToStream;
-import org.opendaylight.controller.messagebus.app.impl.EventAggregator;
-import org.opendaylight.controller.messagebus.app.impl.EventSourceManager;
-import org.opendaylight.controller.messagebus.app.impl.EventSourceTopology;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.controller.sal.core.api.Broker;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-
-public class InitializationContext {
- private static final Logger LOGGER = LoggerFactory.getLogger(InitializationContext.class);
-
- private final MdSAL mdSal;
- private final DataStore dataStore;
- private final EventSourceTopology eventSourceTopology;
- private final EventSourceManager eventSourceManager;
- private final EventAggregator eventAggregator;
-
- public InitializationContext(List<NamespaceToStream> namespaceMapping) {
- this.mdSal = new MdSAL();
- this.dataStore = new DataStore(mdSal);
- this.eventSourceTopology = new EventSourceTopology(dataStore);
- this.eventSourceManager = new EventSourceManager(dataStore, mdSal, eventSourceTopology, namespaceMapping);
- this.eventAggregator = new EventAggregator(mdSal, eventSourceTopology);
- }
-
- public synchronized void set(BindingAwareBroker.ProviderContext session) {
- mdSal.setBindingAwareContext(session);
-
- if (mdSal.isReady()) {
- initialize();
- }
- }
-
- public synchronized void set(Broker.ProviderSession session) {
- mdSal.setBindingIndependentContext(session);
-
- if (mdSal.isReady()) {
- initialize();
- }
- }
-
- private void initialize() {
- eventSourceTopology.mdsalReady();
- eventSourceManager.mdsalReady();
- eventAggregator.mdsalReady();
-
- LOGGER.info("InitializationContext started.");
- }
-}
+++ /dev/null
-/**
- * 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.mdsal;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
-import org.opendaylight.controller.sal.binding.api.BindingAwareService;
-import org.opendaylight.controller.sal.binding.api.mount.MountInstance;
-import org.opendaylight.controller.sal.binding.api.mount.MountProviderService;
-import org.opendaylight.controller.sal.core.api.Broker;
-import org.opendaylight.controller.sal.core.api.BrokerService;
-import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
-import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
-import org.opendaylight.controller.sal.core.api.notify.NotificationService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeContext;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.RpcService;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class MdSAL {
- private static final Logger LOGGER = LoggerFactory.getLogger(MdSAL.class);
-
- private BindingAwareBroker.ProviderContext bindingAwareContext;
- private Broker.ProviderSession bindingIndependentContext;
-
- // -----------------------------
- // ----- FRAMEWORK METHODS -----
- // -----------------------------
- public void setBindingAwareContext(BindingAwareBroker.ProviderContext bindingAwareContext) {
- this.bindingAwareContext = bindingAwareContext;
- }
-
- public void setBindingIndependentContext(Broker.ProviderSession bindingIndependentContext) {
- this.bindingIndependentContext = bindingIndependentContext;
- }
-
- //TODO: We should hide brokers and expose functionalities instead
- public DataBroker getDataBroker() {
- return getBaSalService(DataBroker.class);
- }
-
- public synchronized boolean isReady() {
- return (bindingAwareContext != null && bindingIndependentContext != null);
- }
-
- // -----------------------
- // ----- API METHODS -----
- // -----------------------
- // TODO: Factor out API methods to interface
- // method does not return registration object. Rather will hold references internally and manipulate using node id and API
- public <T extends RpcService> void addRpcImplementation(Class<T> serviceInterface,
- T implementation)
- throws IllegalStateException {
- bindingAwareContext.addRpcImplementation(serviceInterface, implementation);
- }
-
- // method does not return registration object. Rather will hold references internally and manipulate using node id and API
- public <T extends RpcService> void addRpcImplementation(Node node,
- Class<T> serviceInterface,
- T implementation)
- throws IllegalStateException {
- BindingAwareBroker.RoutedRpcRegistration<T> registration
- = addRoutedRpcImplementation(serviceInterface, implementation);
-
- NodeRef nodeRef = createNodeRef(node.getId());
- registration.registerPath(NodeContext.class, nodeRef.getValue());
- }
-
- public ListenerRegistration<NotificationListener> addNotificationListener(String nodeId,
- QName notification,
- NotificationListener listener) {
- YangInstanceIdentifier yii = inventoryNodeBIIdentifier(nodeId);
-
- NotificationService notificationService =
- getBiSalService(DOMMountPointService.class)
- .getMountPoint(yii)
- .get()
- .getService(NotificationPublishService.class)
- .get();
-
- ListenerRegistration<NotificationListener> registration =
- notificationService.addNotificationListener(notification, listener);
-
- LOGGER.info("Notification listener registered for {}, at node {}", notification, nodeId);
-
- return registration;
- }
-
- public ListenerRegistration<NotificationListener> addNotificationListener(QName notification,
- NotificationListener listener) {
- NotificationService notificationService =
- getBiSalService(NotificationPublishService.class);
-
- ListenerRegistration<NotificationListener> registration =
- notificationService.addNotificationListener(notification, listener);
-
- LOGGER.info("Notification listener registered for {}.", notification);
-
- return registration;
- }
-
- public <T extends RpcService> T getRpcService(Class<T> serviceInterface) {
- return bindingAwareContext.getRpcService(serviceInterface);
- }
-
- public <T extends RpcService> T getRpcService(String nodeId, Class<T> serviceInterface) {
- MountProviderService mountProviderService = getBaSalService(MountProviderService.class);
-
- InstanceIdentifier<Node> key = InstanceIdentifier.create(Nodes.class)
- .child(Node.class,
- new NodeKey(new NodeId(nodeId)));
-
- MountInstance mountPoint = mountProviderService.getMountPoint(key);
- return mountPoint.getRpcService(serviceInterface);
- }
-
- public void publishNotification(CompositeNode notification) {
- getBiSalService(NotificationPublishService.class).publish(notification);
- }
-
- public SchemaContext getSchemaContext(String nodeId) {
- YangInstanceIdentifier yii = inventoryNodeBIIdentifier(nodeId);
-
- SchemaContext schemaContext =
- getBiSalService(DOMMountPointService.class)
- .getMountPoint(yii)
- .get().getSchemaContext();
-
- return schemaContext;
- }
-
- // ---------------------------
- // ----- UTILITY METHODS -----
- // ---------------------------
- private <T extends BindingAwareService> T getBaSalService(Class<T> service) {
- return bindingAwareContext.getSALService(service);
- }
-
- private <T extends BrokerService> T getBiSalService(Class<T> service) {
- return bindingIndependentContext.getService(service);
- }
-
- private static final String NODE_ID_NAME = "id";
-
- public static YangInstanceIdentifier inventoryNodeBIIdentifier(String nodeId) {
- return YangInstanceIdentifier.builder()
- .node(Nodes.QNAME)
- .nodeWithKey(Node.QNAME,
- QName.create(Node.QNAME.getNamespace(),
- Node.QNAME.getRevision(),
- NODE_ID_NAME),
- nodeId)
- .build();
- }
-
- private <T extends RpcService> BindingAwareBroker.RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> serviceInterface,
- T implementation)
- throws IllegalStateException {
- return bindingAwareContext.addRoutedRpcImplementation(serviceInterface, implementation);
- }
-
- public static NodeRef createNodeRef(NodeId nodeId) {
- NodeKey nodeKey = new NodeKey(nodeId);
- InstanceIdentifier<Node> path = InstanceIdentifier
- .builder(Nodes.class)
- .child(Node.class, nodeKey)
- .build();
- return new NodeRef(path);
- }
-}
+++ /dev/null
-/*
- * 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.messagebus.app.impl;
-
-import java.util.List;
-import java.util.concurrent.Future;
-import org.opendaylight.controller.mdsal.MdSAL;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.CreateTopicInput;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.CreateTopicOutput;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.CreateTopicOutputBuilder;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.DestroyTopicInput;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.EventAggregatorService;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.NotificationPattern;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.Node1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-// TODO: implement topic created notification
-public class EventAggregator implements EventAggregatorService {
- private static final Logger LOGGER = LoggerFactory.getLogger(EventAggregator.class);
-
- private final MdSAL mdSAL;
- private final EventSourceTopology eventSourceTopology;
-
- public EventAggregator(final MdSAL mdSAL, final EventSourceTopology eventSourceTopology) {
- this.mdSAL = mdSAL;
- this.eventSourceTopology = eventSourceTopology;
- }
-
- public void mdsalReady() {
- mdSAL.addRpcImplementation(EventAggregatorService.class, this);
- }
-
- @Override
- public Future<RpcResult<CreateTopicOutput>> createTopic(final CreateTopicInput input) {
- LOGGER.info("Received Topic creation request: NotificationPattern -> {}, NodeIdPattern -> {}",
- input.getNotificationPattern(),
- input.getNodeIdPattern());
-
- Topic topic = new Topic(new NotificationPattern(input.getNotificationPattern()), input.getNodeIdPattern().getValue(), mdSAL);
-
- //# Make sure we capture all nodes from now on
- eventSourceTopology.registerDataChangeListener(topic);
-
- //# Notify existing nodes
- //# Code reader note: Context of Node type is NetworkTopology
- List<Node> nodes = eventSourceTopology.snapshot();
- for (Node node : nodes) {
- NodeId nodeIdToNotify = node.getAugmentation(Node1.class).getEventSourceNode();
- topic.notifyNode(nodeIdToNotify);
- }
-
- CreateTopicOutput cto = new CreateTopicOutputBuilder()
- .setTopicId(topic.getTopicId())
- .build();
-
- return Util.resultFor(cto);
- }
-
- @Override
- public Future<RpcResult<Void>> destroyTopic(final DestroyTopicInput input) {
- // 1. UNREGISTER DATA CHANGE LISTENER -> ?
- // 2. CLOSE TOPIC
- return null;
- }
-}
+++ /dev/null
-/*
- * 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.messagebus.app.impl;
-
-import org.opendaylight.controller.config.yang.messagebus.app.impl.NamespaceToStream;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.mdsal.DataStore;
-import org.opendaylight.controller.mdsal.MdSAL;
-import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.EventSourceService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.inventory.rev140108.NetconfNode;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public final class EventSourceManager implements DataChangeListener {
- private static final Logger LOGGER = LoggerFactory.getLogger(EventSourceManager.class);
- private static final InstanceIdentifier<Node> INVENTORY_PATH = InstanceIdentifier.create(Nodes.class)
- .child(Node.class);
- private final DataStore dataStore;
- private final MdSAL mdSal;
- private final EventSourceTopology eventSourceTopology;
- private final Map<String, String> streamMap;
-
- public EventSourceManager(DataStore dataStore,
- MdSAL mdSal,
- EventSourceTopology eventSourceTopology,
- List<NamespaceToStream> namespaceMapping) {
- this.dataStore = dataStore;
- this.mdSal = mdSal;
- this.eventSourceTopology = eventSourceTopology;
- this.streamMap = namespaceToStreamMapping(namespaceMapping);
- }
-
- private Map namespaceToStreamMapping(List<NamespaceToStream> namespaceMapping) {
- Map<String, String> streamMap = new HashMap<>(namespaceMapping.size());
-
- for (NamespaceToStream nToS : namespaceMapping) {
- streamMap.put(nToS.getUrnPrefix(), nToS.getStreamName());
- }
-
- return streamMap;
- }
-
- public void mdsalReady() {
- dataStore.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
- INVENTORY_PATH,
- this,
- DataBroker.DataChangeScope.SUBTREE);
-
- LOGGER.info("EventSourceManager initialized.");
- }
-
- @Override
- public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event) {
- //FIXME: Prevent creating new event source on subsequent changes in inventory, like disconnect.
- LOGGER.debug("[DataChangeEvent<InstanceIdentifier<?>, DataObject>: {}]", event);
-
- Node node = Util.getAffectedNode(event);
- // we listen on node tree, therefore we should rather throw IllegalStateException when node is null
- if ( node == null ) {
- LOGGER.debug("OnDataChanged Event. Node is null.");
- return;
- }
- if ( isNetconfNode(node) == false ) {
- LOGGER.debug("OnDataChanged Event. Not a Netconf node.");
- return;
- }
- if ( isEventSource(node) == false ) {
- LOGGER.debug("OnDataChanged Event. Node an EventSource node.");
- return;
- }
-
- NetconfEventSource netconfEventSource = new NetconfEventSource(mdSal,
- node.getKey().getId().getValue(),
- streamMap);
- mdSal.addRpcImplementation(node, EventSourceService.class, netconfEventSource);
-
- InstanceIdentifier<NetconfNode> nodeInstanceIdentifier =
- InstanceIdentifier.create(Nodes.class)
- .child(Node.class, node.getKey())
- .augmentation(NetconfNode.class);
-
- dataStore.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
- nodeInstanceIdentifier,
- netconfEventSource,
- DataBroker.DataChangeScope.SUBTREE);
-
- eventSourceTopology.insert(node);
- }
-
- private boolean isNetconfNode(Node node) {
- return node.getAugmentation(NetconfNode.class) != null ;
- }
-
- public boolean isEventSource(Node node) {
- NetconfNode netconfNode = node.getAugmentation(NetconfNode.class);
-
- return isEventSource(netconfNode);
- }
-
- private boolean isEventSource(NetconfNode node) {
- for (String capability : node.getInitialCapability()) {
- if(capability.startsWith("urn:ietf:params:xml:ns:netconf:notification")) {
- return true;
- }
- }
-
- return false;
- }
-}
\ No newline at end of file
/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2015 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,
package org.opendaylight.controller.messagebus.app.impl;
import com.google.common.base.Preconditions;
+import java.util.Map;
import java.util.regex.Pattern;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.mdsal.MdSAL;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.NotificationPattern;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.TopicId;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.EventSourceService;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.JoinTopicInput;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.JoinTopicInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.LoggerFactory;
-public class Topic implements DataChangeListener {
- private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(Topic.class);
+public class EventSourceTopic implements DataChangeListener {
+ private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(EventSourceTopic.class);
private final NotificationPattern notificationPattern;
+ private final EventSourceService sourceService;
private final Pattern nodeIdPattern;
private final TopicId topicId;
- private final MdSAL mdSal;
- public Topic(final NotificationPattern notificationPattern, final String nodeIdPattern, final MdSAL mdSal) {
+ public EventSourceTopic(final NotificationPattern notificationPattern, final String nodeIdPattern, final EventSourceService eventSource) {
this.notificationPattern = Preconditions.checkNotNull(notificationPattern);
+ this.sourceService = eventSource;
// FIXME: regex should be the language of nodeIdPattern
final String regex = Util.wildcardToRegex(nodeIdPattern);
this.nodeIdPattern = Pattern.compile(regex);
- this.mdSal = Preconditions.checkNotNull(mdSal);
+
// FIXME: We need to perform some salting in order to make
// the topic IDs less predictable.
@Override
public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event) {
- // TODO: affected must return topologyNode !!!
- final Node node = Util.getAffectedNode(event);
- if (nodeIdPattern.matcher(node.getId().getValue()).matches()) {
- notifyNode(node.getId());
- } else {
- LOG.debug("Skipping node {}", node.getId());
+ for (final Map.Entry<InstanceIdentifier<?>, DataObject> changeEntry : event.getUpdatedData().entrySet()) {
+ if (changeEntry.getValue() instanceof Node) {
+ final Node node = (Node) changeEntry.getValue();
+ if (nodeIdPattern.matcher(node.getId().getValue()).matches()) {
+ notifyNode(changeEntry.getKey());
+ }
+ }
}
}
- public void notifyNode(final NodeId nodeId) {
- JoinTopicInput jti = getJoinTopicInputArgument(nodeId);
- EventSourceService ess = mdSal.getRpcService(EventSourceService.class);
- Preconditions.checkState(ess != null, "EventSourceService is not registered");
-
- ess.joinTopic(jti);
+ public void notifyNode(final InstanceIdentifier<?> nodeId) {
+ try {
+ sourceService.joinTopic(getJoinTopicInputArgument(nodeId));
+ } catch (final Exception e) {
+ LOG.error("Could not invoke join topic for node {}", nodeId);
+ }
}
- private JoinTopicInput getJoinTopicInputArgument(final NodeId nodeId) {
- NodeRef nodeRef = MdSAL.createNodeRef(nodeId);
- JoinTopicInput jti =
+ private JoinTopicInput getJoinTopicInputArgument(final InstanceIdentifier<?> path) {
+ final NodeRef nodeRef = new NodeRef(path);
+ final JoinTopicInput jti =
new JoinTopicInputBuilder()
.setNode(nodeRef.getValue())
.setTopicId(topicId)
.build();
return jti;
}
+
+
}
/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2015 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,
package org.opendaylight.controller.messagebus.app.impl;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.mdsal.DataStore;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.CreateTopicInput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.CreateTopicOutput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.CreateTopicOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.DestroyTopicInput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.EventAggregatorService;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.NotificationPattern;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.EventSourceService;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.Node1;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.Node1Builder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.TopologyTypes1;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.TopologyTypes1Builder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.topology.event.source.type.TopologyEventSource;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.topology.event.source.type.TopologyEventSourceBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypes;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.regex.Pattern;
-public class EventSourceTopology {
- private static final Logger LOGGER = LoggerFactory.getLogger(EventSourceTopology.class);
+public class EventSourceTopology implements EventAggregatorService, AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(EventSourceTopology.class);
- private static final String topologyId = "EVENT-SOURCE-TOPOLOGY" ;
- private static final TopologyKey topologyKey = new TopologyKey(new TopologyId(topologyId));
- private static final LogicalDatastoreType datastoreType = LogicalDatastoreType.OPERATIONAL;
+ private static final String TOPOLOGY_ID = "EVENT-SOURCE-TOPOLOGY" ;
+ private static final TopologyKey EVENT_SOURCE_TOPOLOGY_KEY = new TopologyKey(new TopologyId(TOPOLOGY_ID));
+ private static final LogicalDatastoreType OPERATIONAL = LogicalDatastoreType.OPERATIONAL;
- private static final InstanceIdentifier<Topology> topologyInstanceIdentifier =
+ private static final InstanceIdentifier<Topology> EVENT_SOURCE_TOPOLOGY_PATH =
InstanceIdentifier.create(NetworkTopology.class)
- .child(Topology.class, topologyKey);
+ .child(Topology.class, EVENT_SOURCE_TOPOLOGY_KEY);
- private static final InstanceIdentifier<TopologyTypes1> topologyTypeInstanceIdentifier =
- topologyInstanceIdentifier
+ private static final InstanceIdentifier<TopologyTypes1> TOPOLOGY_TYPE_PATH =
+ EVENT_SOURCE_TOPOLOGY_PATH
.child(TopologyTypes.class)
.augmentation(TopologyTypes1.class);
- private static final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang
- .network.topology.rev131021.network.topology.topology.Node> eventSourceTopologyPath =
- InstanceIdentifier.create(NetworkTopology.class)
- .child(Topology.class)
- .child(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang
- .network.topology.rev131021.network.topology.topology.Node.class);
-
private final Map<DataChangeListener, ListenerRegistration<DataChangeListener>> registrations =
new ConcurrentHashMap<>();
- private final DataStore dataStore;
+ private final DataBroker dataBroker;
+ private final RpcRegistration<EventAggregatorService> aggregatorRpcReg;
+ private final EventSourceService eventSourceService;
+ private final RpcProviderRegistry rpcRegistry;
+ private final ExecutorService executorService;
+
+ public EventSourceTopology(final DataBroker dataBroker, final RpcProviderRegistry rpcRegistry) {
+ this.dataBroker = dataBroker;
+ this.executorService = Executors.newCachedThreadPool();
+ this.rpcRegistry = rpcRegistry;
+ aggregatorRpcReg = rpcRegistry.addRpcImplementation(EventAggregatorService.class, this);
+ eventSourceService = rpcRegistry.getRpcService(EventSourceService.class);
+
+ final TopologyEventSource topologySource = new TopologyEventSourceBuilder().build();
+ final TopologyTypes1 topologyTypeAugment = new TopologyTypes1Builder().setTopologyEventSource(topologySource).build();
+ putData(OPERATIONAL, TOPOLOGY_TYPE_PATH, topologyTypeAugment);
+ }
+
+ private <T extends DataObject> void putData(final LogicalDatastoreType store,
+ final InstanceIdentifier<T> path, final T data) {
- public EventSourceTopology(DataStore dataStore) {
- this.dataStore = dataStore;
+ final WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+ tx.put(store, path, data, true);
+ tx.submit();
}
- public void mdsalReady() {
- TopologyEventSource topologySource = new TopologyEventSourceBuilder().build();
- TopologyTypes1 topologyTypeAugment = new TopologyTypes1Builder().setTopologyEventSource(topologySource).build();
+ private void insert(final KeyedInstanceIdentifier<Node, NodeKey> sourcePath, final Node node) {
+ final NodeKey nodeKey = node.getKey();
+ final InstanceIdentifier<Node1> augmentPath = sourcePath.augmentation(Node1.class);
+ final Node1 nodeAgument = new Node1Builder().setEventSourceNode(new NodeId(nodeKey.getNodeId().getValue())).build();
+ putData(OPERATIONAL, augmentPath, nodeAgument);
+ }
- dataStore.asyncPUT(datastoreType, topologyTypeInstanceIdentifier, topologyTypeAugment);
+ private void notifyExistingNodes(final Pattern nodeIdPatternRegex, final EventSourceTopic eventSourceTopic){
+ executorService.execute(new NotifyAllNodeExecutor(dataBroker, nodeIdPatternRegex, eventSourceTopic));
}
- public void insert(Node node) {
- String nodeId = node.getKey().getId().getValue();
- NodeKey nodeKey = new NodeKey(new NodeId(nodeId));
- InstanceIdentifier<Node1> topologyNodeAugment
- = topologyInstanceIdentifier
- .child(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang
- .network.topology.rev131021.network.topology.topology.Node.class, nodeKey)
- .augmentation(Node1.class);
-
- Node1 nodeAgument = new Node1Builder().setEventSourceNode(node.getId()).build();
- dataStore.asyncPUT(datastoreType, topologyNodeAugment, nodeAgument);
+ @Override
+ public Future<RpcResult<CreateTopicOutput>> createTopic(final CreateTopicInput input) {
+ LOG.info("Received Topic creation request: NotificationPattern -> {}, NodeIdPattern -> {}",
+ input.getNotificationPattern(),
+ input.getNodeIdPattern());
+
+ final NotificationPattern notificationPattern = new NotificationPattern(input.getNotificationPattern());
+ final String nodeIdPattern = input.getNodeIdPattern().getValue();
+ final Pattern nodeIdPatternRegex = Pattern.compile(Util.wildcardToRegex(nodeIdPattern));
+ final EventSourceTopic eventSourceTopic = new EventSourceTopic(notificationPattern, input.getNodeIdPattern().getValue(), eventSourceService);
+
+ registerTopic(eventSourceTopic);
+
+ notifyExistingNodes(nodeIdPatternRegex, eventSourceTopic);
+
+ final CreateTopicOutput cto = new CreateTopicOutputBuilder()
+ .setTopicId(eventSourceTopic.getTopicId())
+ .build();
+
+ return Util.resultFor(cto);
+ }
+
+ @Override
+ public Future<RpcResult<Void>> destroyTopic(final DestroyTopicInput input) {
+ return Futures.immediateFailedFuture(new UnsupportedOperationException("Not Implemented"));
}
- // TODO: Should we expose this functioanlity over RPC?
- public List<org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang
- .network.topology.rev131021.network.topology.topology.Node> snapshot() {
- Topology topology = dataStore.read(datastoreType, topologyInstanceIdentifier);
- return topology.getNode();
+ @Override
+ public void close() {
+ aggregatorRpcReg.close();
}
- public void registerDataChangeListener(DataChangeListener listener) {
- ListenerRegistration<DataChangeListener> listenerRegistration = dataStore.registerDataChangeListener(datastoreType,
- eventSourceTopologyPath,
+ public void registerTopic(final EventSourceTopic listener) {
+ final ListenerRegistration<DataChangeListener> listenerRegistration = dataBroker.registerDataChangeListener(OPERATIONAL,
+ EVENT_SOURCE_TOPOLOGY_PATH,
listener,
DataBroker.DataChangeScope.SUBTREE);
registrations.put(listener, listenerRegistration);
}
+
+ public void register(final Node node, final NetconfEventSource netconfEventSource) {
+ final KeyedInstanceIdentifier<Node, NodeKey> sourcePath = EVENT_SOURCE_TOPOLOGY_PATH.child(Node.class, node.getKey());
+ rpcRegistry.addRoutedRpcImplementation(EventSourceService.class, netconfEventSource)
+ .registerPath(NodeContext.class, sourcePath);
+ insert(sourcePath,node);
+ // FIXME: Return registration object.
+ }
+
+ private class NotifyAllNodeExecutor implements Runnable {
+
+ private final EventSourceTopic topic;
+ private final DataBroker dataBroker;
+ private final Pattern nodeIdPatternRegex;
+
+ public NotifyAllNodeExecutor(final DataBroker dataBroker, final Pattern nodeIdPatternRegex, final EventSourceTopic topic) {
+ this.topic = topic;
+ this.dataBroker = dataBroker;
+ this.nodeIdPatternRegex = nodeIdPatternRegex;
+ }
+
+ @Override
+ public void run() {
+ //# Code reader note: Context of Node type is NetworkTopology
+ final List<Node> nodes = snapshot();
+ for (final Node node : nodes) {
+ if (nodeIdPatternRegex.matcher(node.getNodeId().getValue()).matches()) {
+ topic.notifyNode(EVENT_SOURCE_TOPOLOGY_PATH.child(Node.class, node.getKey()));
+ }
+ }
+ }
+
+ private List<Node> snapshot() {
+ try (ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction();) {
+
+ final Optional<Topology> data = tx.read(OPERATIONAL, EVENT_SOURCE_TOPOLOGY_PATH).checkedGet();
+
+ if(data.isPresent()) {
+ final List<Node> nodeList = data.get().getNode();
+ if(nodeList != null) {
+ return nodeList;
+ }
+ }
+ return Collections.emptyList();
+ } catch (final ReadFailedException e) {
+ LOG.error("Unable to retrieve node list.", e);
+ return Collections.emptyList();
+ }
+ }
+ }
}
/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2015 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,
package org.opendaylight.controller.messagebus.app.impl;
-import com.google.common.base.Preconditions;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.Future;
import java.util.regex.Pattern;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.MountPoint;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.mdsal.MdSAL;
-import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationListener;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationPublishService;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationService;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
+import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.NotificationPattern;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.TopicNotification;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.EventSourceService;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.JoinTopicInput;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.JoinTopicOutput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.JoinTopicOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.CreateSubscriptionInput;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.CreateSubscriptionInputBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.NotificationsService;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.StreamNameType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.inventory.rev140108.NetconfNode;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Throwables;
+
+public class NetconfEventSource implements EventSourceService, DOMNotificationListener, DataChangeListener {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NetconfEventSource.class);
+
+ private static final NodeIdentifier TOPIC_NOTIFICATION_ARG = new NodeIdentifier(TopicNotification.QNAME);
+ private static final NodeIdentifier EVENT_SOURCE_ARG = new NodeIdentifier(QName.create(TopicNotification.QNAME, "node-id"));
+ private static final NodeIdentifier PAYLOAD_ARG = new NodeIdentifier(QName.create(TopicNotification.QNAME, "payload"));
+
+ private static final NodeIdentifier STREAM_QNAME = new NodeIdentifier(QName.create(CreateSubscriptionInput.QNAME,"stream"));
+ private static final SchemaPath CREATE_SUBSCRIPTION = SchemaPath.create(true, QName.create(CreateSubscriptionInput.QNAME, "create-subscription"));
-public class NetconfEventSource implements EventSourceService, NotificationListener, DataChangeListener {
- private static final Logger LOGGER = LoggerFactory.getLogger(NetconfEventSource.class);
- private final MdSAL mdSal;
private final String nodeId;
- private final List<String> activeStreams = new ArrayList<>();
+
+ private final DOMMountPoint netconfMount;
+ private final DOMNotificationPublishService domPublish;
+ private final NotificationsService notificationRpcService;
+
+ private final Set<String> activeStreams = new ConcurrentSkipListSet<>();
private final Map<String, String> urnPrefixToStreamMap;
- public NetconfEventSource(final MdSAL mdSal, final String nodeId, final Map<String, String> streamMap) {
- Preconditions.checkNotNull(mdSal);
- Preconditions.checkNotNull(nodeId);
- this.mdSal = mdSal;
+ public NetconfEventSource(final String nodeId, final Map<String, String> streamMap, final DOMMountPoint netconfMount, final DOMNotificationPublishService publishService, final MountPoint bindingMount) {
+ this.netconfMount = netconfMount;
+ this.notificationRpcService = bindingMount.getService(RpcConsumerRegistry.class).get().getRpcService(NotificationsService.class);
this.nodeId = nodeId;
this.urnPrefixToStreamMap = streamMap;
-
- LOGGER.info("NetconfEventSource [{}] created.", nodeId);
+ this.domPublish = publishService;
+ LOG.info("NetconfEventSource [{}] created.", nodeId);
}
@Override
final String regex = Util.wildcardToRegex(notificationPattern.getValue());
final Pattern pattern = Pattern.compile(regex);
- List<QName> matchingNotifications = Util.expandQname(availableNotifications(), pattern);
+ final List<SchemaPath> matchingNotifications = Util.expandQname(availableNotifications(), pattern);
registerNotificationListener(matchingNotifications);
- return null;
+ final JoinTopicOutput output = new JoinTopicOutputBuilder().build();
+ return com.google.common.util.concurrent.Futures.immediateFuture(RpcResultBuilder.success(output).build());
}
- private List<QName> availableNotifications() {
+ private List<SchemaPath> availableNotifications() {
// FIXME: use SchemaContextListener to get changes asynchronously
- Set<NotificationDefinition> availableNotifications = mdSal.getSchemaContext(nodeId).getNotifications();
- List<QName> qNs = new ArrayList<>(availableNotifications.size());
- for (NotificationDefinition nd : availableNotifications) {
- qNs.add(nd.getQName());
+ final Set<NotificationDefinition> availableNotifications = netconfMount.getSchemaContext().getNotifications();
+ final List<SchemaPath> qNs = new ArrayList<>(availableNotifications.size());
+ for (final NotificationDefinition nd : availableNotifications) {
+ qNs.add(nd.getPath());
}
-
return qNs;
}
- private void registerNotificationListener(final List<QName> notificationsToSubscribe) {
- for (QName qName : notificationsToSubscribe) {
- startSubscription(qName);
- // FIXME: do not lose this registration
- final ListenerRegistration<NotificationListener> reg = mdSal.addNotificationListener(nodeId, qName, this);
+ private void registerNotificationListener(final List<SchemaPath> notificationsToSubscribe) {
+
+ final Optional<DOMNotificationService> notifyService = netconfMount.getService(DOMNotificationService.class);
+ if(notifyService.isPresent()) {
+ for (final SchemaPath qName : notificationsToSubscribe) {
+ startSubscription(qName);
+ }
+ // FIXME: Capture registration
+ notifyService.get().registerNotificationListener(this, notificationsToSubscribe);
}
}
- private synchronized void startSubscription(final QName qName) {
- String streamName = resolveStream(qName);
+ private void startSubscription(final SchemaPath path) {
+ final String streamName = resolveStream(path.getLastComponent());
if (streamIsActive(streamName) == false) {
- LOGGER.info("Stream {} is not active on node {}. Will subscribe.", streamName, nodeId);
+ LOG.info("Stream {} is not active on node {}. Will subscribe.", streamName, nodeId);
startSubscription(streamName);
}
}
- private synchronized void resubscribeToActiveStreams() {
- for (String streamName : activeStreams) {
+ private void resubscribeToActiveStreams() {
+ for (final String streamName : activeStreams) {
startSubscription(streamName);
}
}
private synchronized void startSubscription(final String streamName) {
- CreateSubscriptionInput subscriptionInput = getSubscriptionInput(streamName);
- mdSal.getRpcService(nodeId, NotificationsService.class).createSubscription(subscriptionInput);
+ final ContainerNode input = Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(CreateSubscriptionInput.QNAME))
+ .withChild(ImmutableNodes.leafNode(STREAM_QNAME, streamName))
+ .build();
+ netconfMount.getService(DOMRpcService.class).get().invokeRpc(CREATE_SUBSCRIPTION, input);
activeStreams.add(streamName);
}
- private static CreateSubscriptionInput getSubscriptionInput(final String streamName) {
- CreateSubscriptionInputBuilder csib = new CreateSubscriptionInputBuilder();
- csib.setStream(new StreamNameType(streamName));
- return csib.build();
- }
-
private String resolveStream(final QName qName) {
String streamName = null;
- for (Map.Entry<String, String> entry : urnPrefixToStreamMap.entrySet()) {
- String nameSpace = qName.getNamespace().toString();
- String urnPrefix = entry.getKey();
+ for (final Map.Entry<String, String> entry : urnPrefixToStreamMap.entrySet()) {
+ final String nameSpace = qName.getNamespace().toString();
+ final String urnPrefix = entry.getKey();
if( nameSpace.startsWith(urnPrefix) ) {
streamName = entry.getValue();
break;
return activeStreams.contains(streamName);
}
- // PASS
- @Override public Set<QName> getSupportedNotifications() {
- return null;
+ @Override
+ public void onNotification(final DOMNotification notification) {
+ final ContainerNode topicNotification = Builders.containerBuilder()
+ .withNodeIdentifier(TOPIC_NOTIFICATION_ARG)
+ .withChild(ImmutableNodes.leafNode(EVENT_SOURCE_ARG, nodeId))
+ .withChild(encapsulate(notification))
+ .build();
+ try {
+ domPublish.putNotification(new TopicDOMNotification(topicNotification));
+ } catch (final InterruptedException e) {
+ throw Throwables.propagate(e);
+ }
}
- @Override
- public void onNotification(final CompositeNode notification) {
- LOGGER.info("NetconfEventSource {} received notification {}. Will publish to MD-SAL.", nodeId, notification);
- ImmutableCompositeNode payload = ImmutableCompositeNode.builder()
- .setQName(QName.create(TopicNotification.QNAME, "payload"))
- .add(notification).toInstance();
- ImmutableCompositeNode icn = ImmutableCompositeNode.builder()
- .setQName(TopicNotification.QNAME)
- .add(payload)
- .addLeaf("event-source", nodeId)
- .toInstance();
-
- mdSal.publishNotification(icn);
+ private AnyXmlNode encapsulate(final DOMNotification body) {
+ // FIXME: Introduce something like AnyXmlWithNormalizedNodeData in Yangtools
+ final Document doc = XmlUtil.newDocument();
+ final Optional<String> namespace = Optional.of(PAYLOAD_ARG.getNodeType().getNamespace().toString());
+ final Element element = XmlUtil.createElement(doc , "payload", namespace);
+
+
+ final DOMResult result = new DOMResult(element);
+
+ final SchemaContext context = netconfMount.getSchemaContext();
+ final SchemaPath schemaPath = body.getType();
+ try {
+ NetconfMessageTransformUtil.writeNormalizedNode(body.getBody(), result, schemaPath, context);
+ return Builders.anyXmlBuilder().withNodeIdentifier(PAYLOAD_ARG)
+ .withValue(new DOMSource(element))
+ .build();
+ } catch (IOException | XMLStreamException e) {
+ LOG.error("Unable to encapsulate notification.",e);
+ throw Throwables.propagate(e);
+ }
}
@Override
boolean wasConnected = false;
boolean nowConnected = false;
- for (Map.Entry<InstanceIdentifier<?>, DataObject> changeEntry : change.getOriginalData().entrySet()) {
+ for (final Map.Entry<InstanceIdentifier<?>, DataObject> changeEntry : change.getOriginalData().entrySet()) {
if ( isNetconfNode(changeEntry) ) {
- NetconfNode nn = (NetconfNode)changeEntry.getValue();
+ final NetconfNode nn = (NetconfNode)changeEntry.getValue();
wasConnected = nn.isConnected();
}
}
- for (Map.Entry<InstanceIdentifier<?>, DataObject> changeEntry : change.getUpdatedData().entrySet()) {
+ for (final Map.Entry<InstanceIdentifier<?>, DataObject> changeEntry : change.getUpdatedData().entrySet()) {
if ( isNetconfNode(changeEntry) ) {
- NetconfNode nn = (NetconfNode)changeEntry.getValue();
+ final NetconfNode nn = (NetconfNode)changeEntry.getValue();
nowConnected = nn.isConnected();
}
}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.messagebus.app.impl;
+
+import com.google.common.base.Optional;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.opendaylight.controller.config.yang.messagebus.app.impl.NamespaceToStream;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.MountPoint;
+import org.opendaylight.controller.md.sal.binding.api.MountPointService;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationPublishService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeFields.ConnectionStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class NetconfEventSourceManager implements DataChangeListener, AutoCloseable {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(NetconfEventSourceManager.class);
+ private static final TopologyKey NETCONF_TOPOLOGY_KEY = new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName()));
+ private static final InstanceIdentifier<Node> NETCONF_DEVICE_PATH = InstanceIdentifier.create(NetworkTopology.class)
+ .child(Topology.class, NETCONF_TOPOLOGY_KEY)
+ .child(Node.class);
+
+ private static final YangInstanceIdentifier NETCONF_DEVICE_DOM_PATH = YangInstanceIdentifier.builder()
+ .node(NetworkTopology.QNAME)
+ .node(Topology.QNAME)
+ .nodeWithKey(Topology.QNAME, QName.create(Topology.QNAME, "topology-id"),TopologyNetconf.QNAME.getLocalName())
+ .node(Node.QNAME)
+ .build();
+ private static final QName NODE_ID_QNAME = QName.create(Node.QNAME,"node-id");
+
+
+ private final EventSourceTopology eventSourceTopology;
+ private final Map<String, String> streamMap;
+
+ private final ConcurrentHashMap<InstanceIdentifier<?>, NetconfEventSource> netconfSources = new ConcurrentHashMap<>();
+ private final ListenerRegistration<DataChangeListener> listenerReg;
+ private final DOMNotificationPublishService publishService;
+ private final DOMMountPointService domMounts;
+ private final MountPointService bindingMounts;
+
+ public NetconfEventSourceManager(final DataBroker dataStore,
+ final DOMNotificationPublishService domPublish,
+ final DOMMountPointService domMount,
+ final MountPointService bindingMount,
+ final EventSourceTopology eventSourceTopology,
+ final List<NamespaceToStream> namespaceMapping) {
+
+ listenerReg = dataStore.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, NETCONF_DEVICE_PATH, this, DataChangeScope.SUBTREE);
+ this.eventSourceTopology = eventSourceTopology;
+ this.streamMap = namespaceToStreamMapping(namespaceMapping);
+ this.domMounts = domMount;
+ this.bindingMounts = bindingMount;
+ this.publishService = domPublish;
+ LOGGER.info("EventSourceManager initialized.");
+ }
+
+ private Map<String,String> namespaceToStreamMapping(final List<NamespaceToStream> namespaceMapping) {
+ final Map<String, String> streamMap = new HashMap<>(namespaceMapping.size());
+
+ for (final NamespaceToStream nToS : namespaceMapping) {
+ streamMap.put(nToS.getUrnPrefix(), nToS.getStreamName());
+ }
+
+ return streamMap;
+ }
+
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event) {
+ //FIXME: Prevent creating new event source on subsequent changes in inventory, like disconnect.
+ LOGGER.debug("[DataChangeEvent<InstanceIdentifier<?>, DataObject>: {}]", event);
+ for (final Map.Entry<InstanceIdentifier<?>, DataObject> changeEntry : event.getCreatedData().entrySet()) {
+ if (changeEntry.getValue() instanceof Node) {
+ nodeUpdated(changeEntry.getKey(),(Node) changeEntry.getValue());
+ }
+ }
+
+
+ for (final Map.Entry<InstanceIdentifier<?>, DataObject> changeEntry : event.getUpdatedData().entrySet()) {
+ if (changeEntry.getValue() instanceof Node) {
+ nodeUpdated(changeEntry.getKey(),(Node) changeEntry.getValue());
+ }
+ }
+
+
+ }
+
+ private void nodeUpdated(final InstanceIdentifier<?> key, final Node node) {
+
+ // we listen on node tree, therefore we should rather throw IllegalStateException when node is null
+ if ( node == null ) {
+ LOGGER.debug("OnDataChanged Event. Node is null.");
+ return;
+ }
+ if ( isNetconfNode(node) == false ) {
+ LOGGER.debug("OnDataChanged Event. Not a Netconf node.");
+ return;
+ }
+ if ( isEventSource(node) == false ) {
+ LOGGER.debug("OnDataChanged Event. Node an EventSource node.");
+ return;
+ }
+ if(node.getAugmentation(NetconfNode.class).getConnectionStatus() != ConnectionStatus.Connected ) {
+ return;
+ }
+
+ if(!netconfSources.containsKey(key)) {
+ createEventSource(key,node);
+ }
+ }
+
+ private void createEventSource(final InstanceIdentifier<?> key, final Node node) {
+ final Optional<DOMMountPoint> netconfMount = domMounts.getMountPoint(domMountPath(node.getNodeId()));
+ final Optional<MountPoint> bindingMount = bindingMounts.getMountPoint(key);
+
+ if(netconfMount.isPresent() && bindingMount.isPresent()) {
+ final String nodeId = node.getNodeId().getValue();
+ final NetconfEventSource netconfEventSource = new NetconfEventSource(nodeId, streamMap, netconfMount.get(), publishService, bindingMount.get());
+ eventSourceTopology.register(node,netconfEventSource);
+ netconfSources.putIfAbsent(key, netconfEventSource);
+ }
+ }
+
+ private YangInstanceIdentifier domMountPath(final NodeId nodeId) {
+ return YangInstanceIdentifier.builder(NETCONF_DEVICE_DOM_PATH).nodeWithKey(Node.QNAME, NODE_ID_QNAME, nodeId.getValue()).build();
+ }
+
+ private boolean isNetconfNode(final Node node) {
+ return node.getAugmentation(NetconfNode.class) != null ;
+ }
+
+ public boolean isEventSource(final Node node) {
+ final NetconfNode netconfNode = node.getAugmentation(NetconfNode.class);
+
+ return isEventSource(netconfNode);
+ }
+
+ private boolean isEventSource(final NetconfNode node) {
+ for (final String capability : node.getAvailableCapabilities().getAvailableCapability()) {
+ if(capability.startsWith("(urn:ietf:params:xml:ns:netconf:notification")) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public void close() {
+ listenerReg.close();
+ }
+}
\ No newline at end of file
--- /dev/null
+
+/*
+ * Copyright (c) 2015 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.messagebus.app.impl;
+
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.TopicNotification;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+public class TopicDOMNotification implements DOMNotification {
+
+ private static final SchemaPath TOPIC_NOTIFICATION_ID = SchemaPath.create(true, TopicNotification.QNAME);
+ private final ContainerNode body;
+
+ public TopicDOMNotification(final ContainerNode body) {
+ this.body = body;
+ }
+
+ @Override
+ public SchemaPath getType() {
+ return TOPIC_NOTIFICATION_ID;
+ }
+
+ @Override
+ public ContainerNode getBody() {
+ return body;
+ }
+
+ @Override
+ public String toString() {
+ return "TopicDOMNotification [body=" + body + "]";
+ }
+}
/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2015 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,
package org.opendaylight.controller.messagebus.app.impl;
-import com.google.common.util.concurrent.Futures;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
-import java.util.Map;
import java.util.concurrent.Future;
import java.util.regex.Pattern;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.sal.common.util.Rpcs;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcError;
+
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+import com.google.common.util.concurrent.Futures;
public final class Util {
private static final MessageDigest messageDigestTemplate = getDigestInstance();
private static MessageDigest getDigestInstance() {
try {
return MessageDigest.getInstance("MD5");
- } catch (NoSuchAlgorithmException e) {
+ } catch (final NoSuchAlgorithmException e) {
throw new RuntimeException("Unable to get MD5 instance");
}
}
- public static String md5String(final String inputString) {
+ static String md5String(final String inputString) {
try {
- MessageDigest md = (MessageDigest)messageDigestTemplate.clone();
+ final MessageDigest md = (MessageDigest)messageDigestTemplate.clone();
md.update(inputString.getBytes("UTF-8"), 0, inputString.length());
return new BigInteger(1, md.digest()).toString(16);
- } catch (Exception e) {
+ } catch (final Exception e) {
throw new RuntimeException("Unable to get MD5 instance");
}
}
public static <T> Future<RpcResult<T>> resultFor(final T output) {
- RpcResult<T> result = Rpcs.getRpcResult(true, output, Collections.<RpcError>emptyList());
+ final RpcResult<T> result = RpcResultBuilder.success(output).build();
return Futures.immediateFuture(result);
}
- /**
- * Extracts affected node from data change event.
- * @param event
- * @return
- */
- public static Node getAffectedNode(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event) {
- // TODO: expect listener method to be called even when change impact node
- // TODO: test with change.getCreatedData()
- for (Map.Entry<InstanceIdentifier<?>, DataObject> changeEntry : event.getUpdatedData().entrySet()) {
- if (isNode(changeEntry)) {
- return (Node) changeEntry.getValue();
- }
- }
-
- return null;
- }
-
- private static boolean isNode(final Map.Entry<InstanceIdentifier<?>, DataObject> changeEntry ) {
- return Node.class.equals(changeEntry.getKey().getTargetType());
- }
-
/**
* Method filters qnames based on wildcard strings
*
- * @param availableQnames
+ * @param list
* @param patterh matching pattern
* @return list of filtered qnames
*/
- public static List<QName> expandQname(final List<QName> availableQnames, final Pattern pattern) {
- List<QName> matchingQnames = new ArrayList<>();
+ public static List<SchemaPath> expandQname(final List<SchemaPath> list, final Pattern pattern) {
+ final List<SchemaPath> matchingQnames = new ArrayList<>();
- for (QName qname : availableQnames) {
- String namespace = qname.getNamespace().toString();
+ for (final SchemaPath notification : list) {
+ final String namespace = notification.getLastComponent().getNamespace().toString();
if (pattern.matcher(namespace).matches()) {
- matchingQnames.add(qname);
+ matchingQnames.add(notification);
}
}
-
return matchingQnames;
}
* @return
*/
static String wildcardToRegex(final String wildcard){
- StringBuffer s = new StringBuffer(wildcard.length());
+ final StringBuffer s = new StringBuffer(wildcard.length());
s.append('^');
- for (char c : wildcard.toCharArray()) {
+ for (final char c : wildcard.toCharArray()) {
switch(c) {
case '*':
s.append(".*");
--- /dev/null
+/*
+ * Copyright (c) 2015 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.config.yang.messagebus.app.impl;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
+import org.osgi.framework.BundleContext;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+public class MessageBusAppImplModuleFactoryTest {
+
+ DependencyResolver dependencyResolverMock;
+ BundleContext bundleContextMock;
+ MessageBusAppImplModuleFactory messageBusAppImplModuleFactory;
+ DynamicMBeanWithInstance dynamicMBeanWithInstanceMock;
+
+ @BeforeClass
+ public static void initTestClass() throws IllegalAccessException, InstantiationException {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ dependencyResolverMock = mock(DependencyResolver.class);
+ bundleContextMock = mock(BundleContext.class);
+ dynamicMBeanWithInstanceMock = mock(DynamicMBeanWithInstance.class);
+ messageBusAppImplModuleFactory = new MessageBusAppImplModuleFactory();
+ }
+
+ @Test
+ public void createModuleTest() {
+ assertNotNull("Module has not been created correctly.", messageBusAppImplModuleFactory.createModule("instanceName1", dependencyResolverMock, bundleContextMock));
+ }
+
+ @Test
+ public void createModuleBTest() throws Exception{
+ MessageBusAppImplModule messageBusAppImplModuleMock = mock(MessageBusAppImplModule.class);
+ doReturn(messageBusAppImplModuleMock).when(dynamicMBeanWithInstanceMock).getModule();
+ assertNotNull("Module has not been created correctly.", messageBusAppImplModuleFactory.createModule("instanceName1", dependencyResolverMock, dynamicMBeanWithInstanceMock, bundleContextMock));
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.config.yang.messagebus.app.impl;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.messagebus.app.impl.EventSourceTopology;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.EventAggregatorService;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.EventSourceService;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.osgi.framework.BundleContext;
+
+import javax.management.ObjectName;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.notNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.doNothing;
+
+public class MessageBusAppImplModuleTest {
+
+ MessageBusAppImplModule messageBusAppImplModule;
+ ModuleIdentifier moduleIdentifier;
+ DependencyResolver dependencyResolverMock;
+
+ @BeforeClass
+ public static void initTestClass() throws IllegalAccessException, InstantiationException {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ moduleIdentifier = new ModuleIdentifier("factoryName1", "instanceName1");
+ dependencyResolverMock = mock(DependencyResolver.class);
+ messageBusAppImplModule = new MessageBusAppImplModule(moduleIdentifier, dependencyResolverMock);
+ }
+
+ @Test
+ public void constructorTest() {
+ assertNotNull("Instance has not been created correctly.", messageBusAppImplModule);
+ }
+
+ @Test
+ public void constructorBTest() {
+ MessageBusAppImplModule messageBusAppImplModuleOld = mock(MessageBusAppImplModule.class);
+ java.lang.AutoCloseable oldInstanceAutocloseableMock = mock(AutoCloseable.class);
+ MessageBusAppImplModule messageBusAppImplModule = new MessageBusAppImplModule(moduleIdentifier, dependencyResolverMock, messageBusAppImplModuleOld, oldInstanceAutocloseableMock);
+ assertNotNull("Instance has not been created correctly.", messageBusAppImplModule);
+ }
+
+ @Test
+ public void setGetBundleContextTest() {
+ BundleContext bundleContext = mock(BundleContext.class);
+ messageBusAppImplModule.setBundleContext(bundleContext);
+ assertEquals("Set and/or get method/s don't work correctly.", bundleContext, messageBusAppImplModule.getBundleContext());
+ }
+
+ @Test
+ public void createInstanceTest() {
+ createInstanceTestHelper();
+ messageBusAppImplModule.getInstance();
+ assertNotNull("AutoCloseable instance has not been created correctly.", messageBusAppImplModule.createInstance());
+ }
+
+ private void createInstanceTestHelper(){
+ NamespaceToStream namespaceToStream = mock(NamespaceToStream.class);
+ List<NamespaceToStream> listNamespaceToStreamMock = new ArrayList<>();
+ listNamespaceToStreamMock.add(namespaceToStream);
+ messageBusAppImplModule.setNamespaceToStream(listNamespaceToStreamMock);
+ ObjectName objectName = mock(ObjectName.class);
+ org.opendaylight.controller.sal.core.api.Broker domBrokerDependency = mock(Broker.class);
+ org.opendaylight.controller.sal.binding.api.BindingAwareBroker bindingBrokerDependency = mock(BindingAwareBroker.class);
+ when(dependencyResolverMock.resolveInstance((java.lang.Class) notNull(), (javax.management.ObjectName) notNull(), eq(AbstractMessageBusAppImplModule.domBrokerJmxAttribute))).thenReturn(domBrokerDependency);
+ when(dependencyResolverMock.resolveInstance((java.lang.Class) notNull(), (javax.management.ObjectName) notNull(), eq(AbstractMessageBusAppImplModule.bindingBrokerJmxAttribute))).thenReturn(bindingBrokerDependency);
+ messageBusAppImplModule.setBindingBroker(objectName);
+ messageBusAppImplModule.setDomBroker(objectName);
+ BindingAwareBroker.ProviderContext providerContextMock = mock(BindingAwareBroker.ProviderContext.class);
+ doReturn(providerContextMock).when(bindingBrokerDependency).registerProvider(any(BindingAwareProvider.class));
+ Broker.ProviderSession providerSessionMock = mock(Broker.ProviderSession.class);
+ doReturn(providerSessionMock).when(domBrokerDependency).registerProvider(any(Provider.class));
+
+ DataBroker dataBrokerMock = mock(DataBroker.class);
+ doReturn(dataBrokerMock).when(providerContextMock).getSALService(DataBroker.class);
+ RpcProviderRegistry rpcProviderRegistryMock = mock(RpcProviderRegistry.class);
+ doReturn(rpcProviderRegistryMock).when(providerContextMock).getSALService(RpcProviderRegistry.class);
+ BindingAwareBroker.RpcRegistration rpcRegistrationMock = mock(BindingAwareBroker.RpcRegistration.class);
+ doReturn(rpcRegistrationMock).when(rpcProviderRegistryMock).addRpcImplementation(eq(EventAggregatorService.class), any(EventSourceTopology.class));
+ EventSourceService eventSourceServiceMock = mock(EventSourceService.class);
+ doReturn(eventSourceServiceMock).when(rpcProviderRegistryMock).getRpcService(EventSourceService.class);
+
+ WriteTransaction writeTransactionMock = mock(WriteTransaction.class);
+ doReturn(writeTransactionMock).when(dataBrokerMock).newWriteOnlyTransaction();
+ doNothing().when(writeTransactionMock).put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(DataObject.class));
+ CheckedFuture checkedFutureMock = mock(CheckedFuture.class);
+ doReturn(checkedFutureMock).when(writeTransactionMock).submit();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.messagebus.app.impl;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.NotificationPattern;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.EventSourceService;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.JoinTopicInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.any;
+
+public class EventSourceTopicTest {
+
+ EventSourceTopic eventSourceTopic;
+ org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node dataObjectMock;
+ NodeId nodeIdMock;
+ EventSourceService eventSourceServiceMock;
+
+ @BeforeClass
+ public static void initTestClass() throws IllegalAccessException, InstantiationException {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ NotificationPattern notificationPattern = new NotificationPattern("value1");
+ eventSourceServiceMock = mock(EventSourceService.class);
+ eventSourceTopic = new EventSourceTopic(notificationPattern, "nodeIdPattern1", eventSourceServiceMock);
+ }
+
+ @Test
+ public void createModuleTest() {
+ assertNotNull("Instance has not been created correctly.", eventSourceTopic);
+ }
+
+ @Test
+ public void getTopicIdTest() {
+ assertNotNull("Topic has not been created correctly.", eventSourceTopic.getTopicId());
+ }
+
+ @Test
+ public void onDataChangedTest() {
+ AsyncDataChangeEvent asyncDataChangeEventMock = mock(AsyncDataChangeEvent.class);
+ onDataChangedTestHelper(asyncDataChangeEventMock);
+ eventSourceTopic.onDataChanged(asyncDataChangeEventMock);
+ verify(dataObjectMock, times(1)).getId();
+ verify(nodeIdMock, times(1)).getValue();
+ }
+
+ private void onDataChangedTestHelper(AsyncDataChangeEvent asyncDataChangeEventMock){
+ Map<InstanceIdentifier<?>, DataObject> map = new HashMap<>();
+ InstanceIdentifier instanceIdentifierMock = mock(InstanceIdentifier.class);
+ dataObjectMock = mock(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class);
+ map.put(instanceIdentifierMock, dataObjectMock);
+ doReturn(map).when(asyncDataChangeEventMock).getUpdatedData();
+
+ nodeIdMock = mock(NodeId.class);
+ doReturn(nodeIdMock).when(dataObjectMock).getId();
+ doReturn("0").when(nodeIdMock).getValue();
+ }
+
+ @Test
+ public void notifyNodeTest() {
+ InstanceIdentifier instanceIdentifierMock = mock(InstanceIdentifier.class);
+ eventSourceTopic.notifyNode(instanceIdentifierMock);
+ verify(eventSourceServiceMock, times(1)).joinTopic(any(JoinTopicInput.class));
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.messagebus.app.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.CreateTopicInput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.EventAggregatorService;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.DestroyTopicInput;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.NotificationPattern;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.Pattern;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.EventSourceService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeContext;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.eq;
+
+public class EventSourceTopologyTest {
+
+ EventSourceTopology eventSourceTopology;
+ DataBroker dataBrokerMock;
+ RpcProviderRegistry rpcProviderRegistryMock;
+ CreateTopicInput createTopicInputMock;
+ ListenerRegistration listenerRegistrationMock;
+ NodeKey nodeKey;
+
+ @BeforeClass
+ public static void initTestClass() throws IllegalAccessException, InstantiationException {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ dataBrokerMock = mock(DataBroker.class);
+ rpcProviderRegistryMock = mock(RpcProviderRegistry.class);
+
+ }
+
+ @Test
+ public void constructorTest() {
+ constructorTestHelper();
+ eventSourceTopology = new EventSourceTopology(dataBrokerMock, rpcProviderRegistryMock);
+ assertNotNull("Instance has not been created correctly.", eventSourceTopology);
+ }
+
+ private void constructorTestHelper(){
+ WriteTransaction writeTransactionMock = mock(WriteTransaction.class);
+ doReturn(writeTransactionMock).when(dataBrokerMock).newWriteOnlyTransaction();
+ doNothing().when(writeTransactionMock).put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(DataObject.class));
+ CheckedFuture checkedFutureMock = mock(CheckedFuture.class);
+ doReturn(checkedFutureMock).when(writeTransactionMock).submit();
+ }
+
+ @Test
+ public void createTopicTest() throws Exception{
+ createTopicTestHelper();
+ assertNotNull("Topic has not been created correctly.", eventSourceTopology.createTopic(createTopicInputMock));
+ }
+
+ private void createTopicTestHelper() throws Exception{
+ constructorTestHelper();
+ createTopicInputMock = mock(CreateTopicInput.class);
+ eventSourceTopology = new EventSourceTopology(dataBrokerMock, rpcProviderRegistryMock);
+
+ NotificationPattern notificationPattern = new NotificationPattern("value1");
+ doReturn(notificationPattern).when(createTopicInputMock).getNotificationPattern();
+ Pattern pattern = new Pattern("valuePattern1");
+ doReturn(pattern).when(createTopicInputMock).getNodeIdPattern();
+
+ listenerRegistrationMock = mock(ListenerRegistration.class);
+ doReturn(listenerRegistrationMock).when(dataBrokerMock).registerDataChangeListener(eq(LogicalDatastoreType.OPERATIONAL),
+ any(InstanceIdentifier.class),
+ any(EventSourceTopic.class),
+ eq(DataBroker.DataChangeScope.SUBTREE));
+
+ ReadOnlyTransaction readOnlyTransactionMock = mock(ReadOnlyTransaction.class);
+ doReturn(readOnlyTransactionMock).when(dataBrokerMock).newReadOnlyTransaction();
+
+ CheckedFuture checkedFutureMock = mock(CheckedFuture.class);
+ doReturn(checkedFutureMock).when(readOnlyTransactionMock).read(eq(LogicalDatastoreType.OPERATIONAL),
+ any(InstanceIdentifier.class));
+ Optional optionalMock = mock(Optional.class);
+ doReturn(optionalMock).when(checkedFutureMock).checkedGet();
+ doReturn(true).when(optionalMock).isPresent();
+
+ Topology topologyMock = mock(Topology.class);
+ doReturn(topologyMock).when(optionalMock).get();
+ Node nodeMock = mock(Node.class);
+ List<Node> nodeList = new ArrayList<>();
+ nodeList.add(nodeMock);
+ doReturn(nodeList).when(topologyMock).getNode();
+
+ NodeId nodeId = new NodeId("nodeIdValue1");
+ doReturn(nodeId).when(nodeMock).getNodeId();
+ }
+
+ @Test
+ public void destroyTopicTest() throws Exception{
+ createTopicTestHelper();
+ DestroyTopicInput destroyTopicInput = null;
+ assertNotNull("Instance has not been created correctly.", eventSourceTopology.destroyTopic(destroyTopicInput));
+ }
+
+ @Test
+ public void closeTest() throws Exception{
+ BindingAwareBroker.RpcRegistration rpcRegistrationMock = mock(BindingAwareBroker.RpcRegistration.class);
+ doReturn(rpcRegistrationMock).when(rpcProviderRegistryMock).addRpcImplementation(eq(EventAggregatorService.class), any(EventSourceTopology.class));
+ doNothing().when(rpcRegistrationMock).close();
+ createTopicTestHelper();
+ eventSourceTopology.createTopic(createTopicInputMock);
+ eventSourceTopology.close();
+ verify(rpcRegistrationMock, times(1)).close();
+ }
+
+ @Test
+ public void registerTest() throws Exception {
+ createTopicTestHelper();
+ Node nodeMock = mock(Node.class);
+ NetconfEventSource netconfEventSourceMock = mock(NetconfEventSource.class);
+
+ NodeId nodeId = new NodeId("nodeIdValue1");
+ nodeKey = new NodeKey(nodeId);
+ doReturn(nodeKey).when(nodeMock).getKey();
+
+ BindingAwareBroker.RoutedRpcRegistration routedRpcRegistrationMock = mock(BindingAwareBroker.RoutedRpcRegistration.class);
+ doReturn(routedRpcRegistrationMock).when(rpcProviderRegistryMock).addRoutedRpcImplementation(EventSourceService.class, netconfEventSourceMock);
+ eventSourceTopology.register(nodeMock, netconfEventSourceMock);
+ verify(routedRpcRegistrationMock, times(1)).registerPath(eq(NodeContext.class), any(KeyedInstanceIdentifier.class));
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.messagebus.app.impl;
+
+import com.google.common.base.Optional;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.config.yang.messagebus.app.impl.NamespaceToStream;
+import org.opendaylight.controller.md.sal.binding.api.BindingService;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.MountPoint;
+import org.opendaylight.controller.md.sal.binding.api.MountPointService;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationPublishService;
+import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.NotificationsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeFields;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.fields.AvailableCapabilities;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.notNull;
+
+public class NetconfEventSourceManagerTest {
+
+ NetconfEventSourceManager netconfEventSourceManager;
+ ListenerRegistration listenerRegistrationMock;
+ DOMMountPointService domMountPointServiceMock;
+ MountPointService mountPointServiceMock;
+ EventSourceTopology eventSourceTopologyMock;
+ AsyncDataChangeEvent asyncDataChangeEventMock;
+
+ @BeforeClass
+ public static void initTestClass() throws IllegalAccessException, InstantiationException {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ DataBroker dataBrokerMock = mock(DataBroker.class);
+ DOMNotificationPublishService domNotificationPublishServiceMock = mock(DOMNotificationPublishService.class);
+ domMountPointServiceMock = mock(DOMMountPointService.class);
+ mountPointServiceMock = mock(MountPointService.class);
+ eventSourceTopologyMock = mock(EventSourceTopology.class);
+ List<NamespaceToStream> namespaceToStreamList = new ArrayList<>();
+
+ listenerRegistrationMock = mock(ListenerRegistration.class);
+ doReturn(listenerRegistrationMock).when(dataBrokerMock).registerDataChangeListener(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class), any(NetconfEventSourceManager.class), eq(AsyncDataBroker.DataChangeScope.SUBTREE));
+
+ netconfEventSourceManager = new NetconfEventSourceManager(dataBrokerMock, domNotificationPublishServiceMock, domMountPointServiceMock,
+ mountPointServiceMock, eventSourceTopologyMock, namespaceToStreamList);
+ }
+
+ @Test
+ public void constructorTest() {
+ assertNotNull("Instance has not been created correctly.", netconfEventSourceManager);
+ }
+
+ @Test
+ public void onDataChangedTest() {
+ AsyncDataChangeEvent asyncDataChangeEventMock = mock(AsyncDataChangeEvent.class);
+ Map<InstanceIdentifier, DataObject> map = new HashMap<>();
+ InstanceIdentifier instanceIdentifierMock = mock(InstanceIdentifier.class);
+ Node dataObjectMock = mock(Node.class);
+ map.put(instanceIdentifierMock, dataObjectMock);
+ doReturn(map).when(asyncDataChangeEventMock).getCreatedData();
+ doReturn(map).when(asyncDataChangeEventMock).getUpdatedData();
+ netconfEventSourceManager.onDataChanged(asyncDataChangeEventMock);
+ verify(dataObjectMock, times(2)).getAugmentation(NetconfNode.class);
+ }
+
+ @Test
+ public void onDataChangedCreateEventSourceTest() {
+ onDataChangedCreateEventSourceTestHelper();
+ netconfEventSourceManager.onDataChanged(asyncDataChangeEventMock);
+ verify(eventSourceTopologyMock, times(1)).register(any(Node.class), any(NetconfEventSource.class));
+ }
+
+ private void onDataChangedCreateEventSourceTestHelper(){
+ asyncDataChangeEventMock = mock(AsyncDataChangeEvent.class);
+ Map<InstanceIdentifier, DataObject> map = new HashMap<>();
+ InstanceIdentifier instanceIdentifierMock = mock(InstanceIdentifier.class);
+ Node dataObjectMock = mock(Node.class);
+ map.put(instanceIdentifierMock, dataObjectMock);
+ doReturn(map).when(asyncDataChangeEventMock).getCreatedData();
+ doReturn(map).when(asyncDataChangeEventMock).getUpdatedData();
+
+ NetconfNode netconfNodeMock = mock(NetconfNode.class);
+ AvailableCapabilities availableCapabilitiesMock = mock(AvailableCapabilities.class);
+ doReturn(netconfNodeMock).when(dataObjectMock).getAugmentation(NetconfNode.class);
+ doReturn(availableCapabilitiesMock).when(netconfNodeMock).getAvailableCapabilities();
+ List<String> availableCapabilityList = new ArrayList<>();
+ availableCapabilityList.add("(urn:ietf:params:xml:ns:netconf:notification_availableCapabilityString1");
+ doReturn(availableCapabilityList).when(availableCapabilitiesMock).getAvailableCapability();
+
+ doReturn(NetconfNodeFields.ConnectionStatus.Connected).when(netconfNodeMock).getConnectionStatus();
+
+ Optional optionalMock = mock(Optional.class);
+ Optional optionalBindingMountMock = mock(Optional.class);
+ NodeId nodeId = new NodeId("nodeId1");
+ doReturn(nodeId).when(dataObjectMock).getNodeId();
+ doReturn(optionalMock).when(domMountPointServiceMock).getMountPoint((YangInstanceIdentifier)notNull());
+ doReturn(optionalBindingMountMock).when(mountPointServiceMock).getMountPoint(any(InstanceIdentifier.class));
+ doReturn(true).when(optionalMock).isPresent();
+ doReturn(true).when(optionalBindingMountMock).isPresent();
+
+ DOMMountPoint domMountPointMock = mock(DOMMountPoint.class);
+ MountPoint mountPointMock = mock(MountPoint.class);
+ doReturn(domMountPointMock).when(optionalMock).get();
+ doReturn(mountPointMock).when(optionalBindingMountMock).get();
+
+ RpcConsumerRegistry rpcConsumerRegistryMock = mock(RpcConsumerRegistry.class);
+ Optional<BindingService> onlyOptionalMock = (Optional<BindingService>) mock(Optional.class);
+ NotificationsService notificationsServiceMock = mock(NotificationsService.class);
+
+ doReturn(onlyOptionalMock).when(mountPointMock).getService(RpcConsumerRegistry.class);
+ doReturn(rpcConsumerRegistryMock).when(onlyOptionalMock).get();
+ doReturn(notificationsServiceMock).when(rpcConsumerRegistryMock).getRpcService(NotificationsService.class);
+ }
+
+ @Test
+ public void isEventSourceTest() {
+ Node nodeMock = mock(Node.class);
+ NetconfNode netconfNodeMock = mock(NetconfNode.class);
+ AvailableCapabilities availableCapabilitiesMock = mock(AvailableCapabilities.class);
+ doReturn(netconfNodeMock).when(nodeMock).getAugmentation(NetconfNode.class);
+ doReturn(availableCapabilitiesMock).when(netconfNodeMock).getAvailableCapabilities();
+ List<String> availableCapabilityList = new ArrayList<>();
+ availableCapabilityList.add("(urn:ietf:params:xml:ns:netconf:notification_availableCapabilityString1");
+ doReturn(availableCapabilityList).when(availableCapabilitiesMock).getAvailableCapability();
+ assertTrue("Method has not been run correctly.", netconfEventSourceManager.isEventSource(nodeMock));
+ }
+
+ @Test
+ public void isNotEventSourceTest() {
+ Node nodeMock = mock(Node.class);
+ NetconfNode netconfNodeMock = mock(NetconfNode.class);
+ AvailableCapabilities availableCapabilitiesMock = mock(AvailableCapabilities.class);
+ doReturn(netconfNodeMock).when(nodeMock).getAugmentation(NetconfNode.class);
+ doReturn(availableCapabilitiesMock).when(netconfNodeMock).getAvailableCapabilities();
+ List<String> availableCapabilityList = new ArrayList<>();
+ availableCapabilityList.add("availableCapabilityString1");
+ doReturn(availableCapabilityList).when(availableCapabilitiesMock).getAvailableCapability();
+ assertFalse("Method has not been run correctly.", netconfEventSourceManager.isEventSource(nodeMock));
+ }
+
+ @Test
+ public void closeTest() {
+ netconfEventSourceManager.close();
+ verify(listenerRegistrationMock, times(1)).close();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.messagebus.app.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.BindingService;
+import org.opendaylight.controller.md.sal.binding.api.MountPoint;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationPublishService;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationService;
+import org.opendaylight.controller.md.sal.dom.api.DOMService;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.NotificationPattern;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.JoinTopicInput;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.NotificationsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.inventory.rev140108.NetconfNode;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+import org.opendaylight.yangtools.yang.common.QName;
+
+import java.lang.reflect.Field;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.times;
+
+public class NetconfEventSourceTest {
+
+ NetconfEventSource netconfEventSource;
+ DOMMountPoint domMountPointMock;
+ JoinTopicInput joinTopicInputMock;
+
+ @BeforeClass
+ public static void initTestClass() throws IllegalAccessException, InstantiationException {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ Map<String, String> streamMap = new HashMap<>();
+ streamMap.put("string1", "string2");
+ domMountPointMock = mock(DOMMountPoint.class);
+ DOMNotificationPublishService domNotificationPublishServiceMock = mock(DOMNotificationPublishService.class);
+ MountPoint mountPointMock = mock(MountPoint.class);
+
+ RpcConsumerRegistry rpcConsumerRegistryMock = mock(RpcConsumerRegistry.class);
+ Optional<BindingService> onlyOptionalMock = (Optional<BindingService>) mock(Optional.class);
+ NotificationsService notificationsServiceMock = mock(NotificationsService.class);
+
+ doReturn(onlyOptionalMock).when(mountPointMock).getService(RpcConsumerRegistry.class);
+ doReturn(rpcConsumerRegistryMock).when(onlyOptionalMock).get();
+ doReturn(notificationsServiceMock).when(rpcConsumerRegistryMock).getRpcService(NotificationsService.class);
+ netconfEventSource = new NetconfEventSource("nodeId1", streamMap, domMountPointMock, domNotificationPublishServiceMock, mountPointMock);
+ }
+
+ @Test
+ public void constructorTest() {
+ assertNotNull("Instance has not been created correctly.", netconfEventSource);
+ }
+
+ @Test
+ public void joinTopicTest() throws Exception{
+ joinTopicTestHelper();
+ assertNotNull("JoinTopic return value has not been created correctly.", netconfEventSource.joinTopic(joinTopicInputMock));
+ }
+
+ private void joinTopicTestHelper() throws Exception{
+ joinTopicInputMock = mock(JoinTopicInput.class);
+ NotificationPattern notificationPatternMock = mock(NotificationPattern.class);
+ doReturn(notificationPatternMock).when(joinTopicInputMock).getNotificationPattern();
+ doReturn("regexString1").when(notificationPatternMock).getValue();
+
+ SchemaContext schemaContextMock = mock(SchemaContext.class);
+ doReturn(schemaContextMock).when(domMountPointMock).getSchemaContext();
+ Set<NotificationDefinition> notificationDefinitionSet = new HashSet<>();
+ NotificationDefinition notificationDefinitionMock = mock(NotificationDefinition.class);
+ notificationDefinitionSet.add(notificationDefinitionMock);
+
+ URI uri = new URI("uriStr1");
+ QName qName = new QName(uri, "localName1");
+ org.opendaylight.yangtools.yang.model.api.SchemaPath schemaPath = SchemaPath.create(true, qName);
+ doReturn(notificationDefinitionSet).when(schemaContextMock).getNotifications();
+ doReturn(schemaPath).when(notificationDefinitionMock).getPath();
+
+ Optional<DOMNotificationService> domNotificationServiceOptionalMock = (Optional<DOMNotificationService>) mock(Optional.class);
+ doReturn(domNotificationServiceOptionalMock).when(domMountPointMock).getService(DOMNotificationService.class);
+ doReturn(true).when(domNotificationServiceOptionalMock).isPresent();
+
+ DOMNotificationService domNotificationServiceMock = mock(DOMNotificationService.class);
+ doReturn(domNotificationServiceMock).when(domNotificationServiceOptionalMock).get();
+ ListenerRegistration listenerRegistrationMock = mock(ListenerRegistration.class);
+ doReturn(listenerRegistrationMock).when(domNotificationServiceMock).registerNotificationListener(any(NetconfEventSource.class), any(List.class));
+ }
+
+ @Test (expected=NullPointerException.class)
+ public void onNotificationTest() {
+ DOMNotification domNotificationMock = mock(DOMNotification.class);
+ ContainerNode containerNodeMock = mock(ContainerNode.class);
+ SchemaContext schemaContextMock = mock(SchemaContext.class);
+ SchemaPath schemaPathMock = mock(SchemaPath.class);
+ doReturn(schemaContextMock).when(domMountPointMock).getSchemaContext();
+ doReturn(schemaPathMock).when(domNotificationMock).getType();
+ doReturn(containerNodeMock).when(domNotificationMock).getBody();
+ netconfEventSource.onNotification(domNotificationMock);
+ }
+
+ @Test
+ public void onDataChangedTest() {
+ InstanceIdentifier brmIdent = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class, new NodeKey(new NodeId("brm"))).augmentation(NetconfNode.class);
+ AsyncDataChangeEvent asyncDataChangeEventMock = mock(AsyncDataChangeEvent.class);
+ NetconfNode dataObjectMock = mock(NetconfNode.class);
+ Map<InstanceIdentifier, DataObject> dataChangeMap = new HashMap<>();
+ dataChangeMap.put(brmIdent, dataObjectMock);
+ doReturn(dataChangeMap).when(asyncDataChangeEventMock).getOriginalData();
+ doReturn(dataChangeMap).when(asyncDataChangeEventMock).getUpdatedData();
+
+ netconfEventSource.onDataChanged(asyncDataChangeEventMock);
+ verify(dataObjectMock, times(2)).isConnected();
+ }
+
+ @Test
+ public void onDataChangedResubscribeTest() throws Exception{
+ InstanceIdentifier brmIdent = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class, new NodeKey(new NodeId("brm"))).augmentation(NetconfNode.class);
+ AsyncDataChangeEvent asyncDataChangeEventMock = mock(AsyncDataChangeEvent.class);
+ NetconfNode dataObjectMock = mock(NetconfNode.class);
+ Map<InstanceIdentifier, DataObject> dataChangeMap = new HashMap<>();
+ dataChangeMap.put(brmIdent, dataObjectMock);
+ doReturn(dataChangeMap).when(asyncDataChangeEventMock).getUpdatedData();
+ doReturn(true).when(dataObjectMock).isConnected();
+
+ Set<String> localSet = getActiveStreams();
+ localSet.add("activeStream1");
+
+ Optional<DOMService> optionalMock = (Optional<DOMService>) mock(Optional.class);
+ doReturn(optionalMock).when(domMountPointMock).getService(DOMRpcService.class);
+ DOMRpcService domRpcServiceMock = mock(DOMRpcService.class);
+ doReturn(domRpcServiceMock).when(optionalMock).get();
+ CheckedFuture checkedFutureMock = mock(CheckedFuture.class);
+ doReturn(checkedFutureMock).when(domRpcServiceMock).invokeRpc(any(SchemaPath.class), any(ContainerNode.class));
+
+ netconfEventSource.onDataChanged(asyncDataChangeEventMock);
+ verify(dataObjectMock, times(1)).isConnected();
+ assertEquals("Size of set has not been set correctly.", 1, getActiveStreams().size());
+ }
+
+ private Set getActiveStreams() throws Exception{
+ Field nesField = NetconfEventSource.class.getDeclaredField("activeStreams");
+ nesField.setAccessible(true);
+ return (Set) nesField.get(netconfEventSource);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.messagebus.app.impl;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.TopicNotification;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+
+public class TopicDOMNotificationTest {
+
+ ContainerNode containerNodeBodyMock;
+ TopicDOMNotification topicDOMNotification;
+
+ @BeforeClass
+ public static void initTestClass() throws IllegalAccessException, InstantiationException {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ containerNodeBodyMock = mock(ContainerNode.class);
+ topicDOMNotification = new TopicDOMNotification(containerNodeBodyMock);
+ }
+
+ @Test
+ public void constructorTest() {
+ assertNotNull("Instance has not been created correctly.", topicDOMNotification);
+ }
+
+ @Test
+ public void getTypeTest() {
+ SchemaPath TOPIC_NOTIFICATION_ID = SchemaPath.create(true, TopicNotification.QNAME);
+ assertEquals("Type has not been created correctly.", TOPIC_NOTIFICATION_ID, topicDOMNotification.getType());
+ }
+
+ @Test
+ public void getBodyTest() {
+ assertEquals("String has not been created correctly.", containerNodeBodyMock, topicDOMNotification.getBody());
+ }
+
+ @Test
+ public void getToStringTest() {
+ String bodyString = "TopicDOMNotification [body=" + containerNodeBodyMock + "]";
+ assertEquals("String has not been created correctly.", bodyString, topicDOMNotification.toString());
+ }
+}
--- /dev/null
+/*
+ * 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.messagebus.app.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+public class UtilTest {
+
+ @Test
+ public void testMD5Hash() throws Exception {
+ // empty string
+ createAndAssertHash("", "d41d8cd98f00b204e9800998ecf8427e");
+
+ // non-empty string
+ createAndAssertHash("The Guardian", "69b929ae473ed732d5fb8e0a55a8dc8d");
+
+ // the same hash for the same string
+ createAndAssertHash("The Independent", "db793706d70c37dcc16454fa8eb21b1c");
+ createAndAssertHash("The Independent", "db793706d70c37dcc16454fa8eb21b1c"); // one more time
+
+ // different strings must have different hashes
+ createAndAssertHash("orange", "fe01d67a002dfa0f3ac084298142eccd");
+ createAndAssertHash("yellow", "d487dd0b55dfcacdd920ccbdaeafa351");
+ }
+
+ //TODO: IllegalArgumentException would be better
+ @Test(expected = RuntimeException.class)
+ public void testMD5HashInvalidInput() throws Exception {
+ Util.md5String(null);
+ }
+
+ @Test
+ public void testWildcardToRegex() throws Exception {
+ // empty wildcard string
+ createAndAssertRegex("", "^$");
+
+ // wildcard string is a char to be replaced
+ createAndAssertRegex("*", "^.*$");
+ createAndAssertRegex("?", "^.$");
+ final String relevantChars = "()[]$^.{}|\\";
+ for (final char c : relevantChars.toCharArray()) {
+ final char oneChar[] = {c};
+ final String wildcardStr = new String(oneChar);
+ final String expectedRegex = "^\\" + c + "$";
+ createAndAssertRegex(wildcardStr, expectedRegex);
+ }
+
+ // wildcard string consists of more chars
+ createAndAssertRegex("a", "^a$");
+ createAndAssertRegex("aBc", "^aBc$");
+ createAndAssertRegex("a1b2C34", "^a1b2C34$");
+ createAndAssertRegex("*?()[]$^.{}|\\X", "^.*.\\(\\)\\[\\]\\$\\^\\.\\{\\}\\|\\\\X$");
+ createAndAssertRegex("a*BB?37|42$", "^a.*BB.37\\|42\\$$");
+ }
+
+ @Test
+ public void testResultFor() throws Exception {
+ {
+ final String expectedResult = "dummy string";
+ RpcResult<String> rpcResult = Util.resultFor(expectedResult).get();
+ assertEquals(expectedResult, rpcResult.getResult());
+ assertTrue(rpcResult.isSuccessful());
+ assertTrue(rpcResult.getErrors().isEmpty());
+ }
+ {
+ final Integer expectedResult = 42;
+ RpcResult<Integer> rpcResult = Util.resultFor(expectedResult).get();
+ assertEquals(expectedResult, rpcResult.getResult());
+ assertTrue(rpcResult.isSuccessful());
+ assertTrue(rpcResult.getErrors().isEmpty());
+ }
+ }
+
+ @Test
+ public void testExpandQname() throws Exception {
+ // match no path because the list of the allowed paths is empty
+ {
+ final List<SchemaPath> paths = new ArrayList<>();
+ final Pattern regexPattern = Pattern.compile(".*"); // match everything
+ final List<SchemaPath> matchingPaths = Util.expandQname(paths, regexPattern);
+ assertTrue(matchingPaths.isEmpty());
+ }
+
+ // match no path because of regex pattern
+ {
+ final List<SchemaPath> paths = createSchemaPathList();
+ final Pattern regexPattern = Pattern.compile("^@.*");
+ final List<SchemaPath> matchingPaths = Util.expandQname(paths, regexPattern);
+ assertTrue(matchingPaths.isEmpty());
+ }
+
+ // match all paths
+ {
+ final List<SchemaPath> paths = createSchemaPathList();
+ final Pattern regexPattern = Pattern.compile(".*");
+ final List<SchemaPath> matchingPaths = Util.expandQname(paths, regexPattern);
+ assertTrue(matchingPaths.contains(paths.get(0)));
+ assertTrue(matchingPaths.contains(paths.get(1)));
+ assertEquals(paths.size(), matchingPaths.size());
+ }
+
+ // match one path only
+ {
+ final List<SchemaPath> paths = createSchemaPathList();
+ final Pattern regexPattern = Pattern.compile(".*yyy$");
+ final List<SchemaPath> matchingPaths = Util.expandQname(paths, regexPattern);
+ assertTrue(matchingPaths.contains(paths.get(1)));
+ assertEquals(1, matchingPaths.size());
+ }
+ }
+
+ private static void createAndAssertHash(final String inString, final String expectedHash) {
+ assertEquals("Incorrect hash.", expectedHash, Util.md5String(inString));
+ }
+
+ private static void createAndAssertRegex(final String wildcardStr, final String expectedRegex) {
+ assertEquals("Incorrect regex string.", expectedRegex, Util.wildcardToRegex(wildcardStr));
+ }
+
+ private static List<SchemaPath> createSchemaPathList() {
+ final QName qname1 = QName.create("urn:odl:xxx", "2015-01-01", "localName");
+ final QName qname2 = QName.create("urn:odl:yyy", "2015-01-01", "localName");
+ final SchemaPath path1 = SchemaPath.create(true, qname1);
+ final SchemaPath path2 = SchemaPath.create(true, qname2);
+ return Arrays.asList(path1, path2);
+ }
+}
<!-- Message Bus -->
<module>messagebus-api</module>
<module>messagebus-impl</module>
+ <module>messagebus-config</module>
</modules>
<build>
</goals>
</pluginExecutionFilter>
<action>
- <execute></execute>
+ <execute/>
</action>
</pluginExecution>
</pluginExecutions>
</modules>
</profile>
</profiles>
-</project>
+</project>
\ No newline at end of file
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<configuration>
- <excludes>**/protobuff/**/*</excludes>
+ <excludes>**/protobuff/**/*,**/target/**/*</excludes>
</configuration>
</plugin>
LOG.info("{}: Persisting of snapshot done:{}", persistenceId(), sn.getLogMessage());
- long dataThreshold = Runtime.getRuntime().totalMemory() *
+ long dataThreshold = getTotalMemory() *
getRaftActorContext().getConfigParams().getSnapshotDataThresholdPercentage() / 100;
if (context.getReplicatedLog().dataSize() > dataThreshold) {
context.setSnapshotCaptureInitiated(false);
}
+ protected long getTotalMemory() {
+ return Runtime.getRuntime().totalMemory();
+ }
+
protected boolean hasFollowers(){
return getRaftActorContext().getPeerAddresses().keySet().size() > 0;
}
dataSizeForCheck = dataSizeSinceLastSnapshot / DATA_SIZE_DIVIDER;
}
- long dataThreshold = Runtime.getRuntime().totalMemory() *
+ long dataThreshold = getTotalMemory() *
getRaftActorContext().getConfigParams().getSnapshotDataThresholdPercentage() / 100;
// when a snaphsot is being taken, captureSnapshot != null
package org.opendaylight.controller.cluster.raft.base.messages;
public class CaptureSnapshot {
- private long lastAppliedIndex;
- private long lastAppliedTerm;
- private long lastIndex;
- private long lastTerm;
- private boolean installSnapshotInitiated;
- private long replicatedToAllIndex;
- private long replicatedToAllTerm;
+ private final long lastAppliedIndex;
+ private final long lastAppliedTerm;
+ private final long lastIndex;
+ private final long lastTerm;
+ private final boolean installSnapshotInitiated;
+ private final long replicatedToAllIndex;
+ private final long replicatedToAllTerm;
public CaptureSnapshot(long lastIndex, long lastTerm,
long lastAppliedIndex, long lastAppliedTerm, long replicatedToAllIndex, long replicatedToAllTerm) {
public long getReplicatedToAllTerm() {
return replicatedToAllTerm;
}
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("CaptureSnapshot [lastAppliedIndex=").append(lastAppliedIndex).append(", lastAppliedTerm=")
+ .append(lastAppliedTerm).append(", lastIndex=").append(lastIndex).append(", lastTerm=")
+ .append(lastTerm).append(", installSnapshotInitiated=").append(installSnapshotInitiated)
+ .append(", replicatedToAllIndex=").append(replicatedToAllIndex).append(", replicatedToAllTerm=")
+ .append(replicatedToAllTerm).append("]");
+ return builder.toString();
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2015 Brocade Communications 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.cluster.raft;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import akka.actor.ActorRef;
+import akka.actor.PoisonPill;
+import akka.actor.Props;
+import akka.actor.Terminated;
+import akka.dispatch.Dispatchers;
+import akka.testkit.JavaTestKit;
+import akka.testkit.TestActorRef;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMap;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import org.junit.After;
+import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload;
+import org.opendaylight.controller.cluster.raft.RaftActorTest.MockRaftActor;
+import org.opendaylight.controller.cluster.raft.base.messages.ApplyJournalEntries;
+import org.opendaylight.controller.cluster.raft.base.messages.ApplyState;
+import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshotReply;
+import org.opendaylight.controller.cluster.raft.base.messages.SendHeartBeat;
+import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior;
+import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
+import org.opendaylight.controller.cluster.raft.utils.InMemoryJournal;
+import org.opendaylight.controller.cluster.raft.utils.InMemorySnapshotStore;
+import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import scala.concurrent.duration.FiniteDuration;
+
+/**
+ * Abstract base for an integration test that tests end-to-end RaftActor and behavior functionality.
+ *
+ * @author Thomas Pantelis
+ */
+public abstract class AbstractRaftActorIntegrationTest extends AbstractActorTest {
+
+ public static class TestRaftActor extends MockRaftActor {
+
+ private final TestActorRef<MessageCollectorActor> collectorActor;
+ private final Map<Class<?>, Boolean> dropMessages = new ConcurrentHashMap<>();
+ private volatile byte[] snapshot;
+ private volatile long mockTotalMemory;
+
+ private TestRaftActor(String id, Map<String, String> peerAddresses, ConfigParams config,
+ TestActorRef<MessageCollectorActor> collectorActor) {
+ super(id, peerAddresses, Optional.of(config), null);
+ dataPersistenceProvider = new PersistentDataProvider();
+ this.collectorActor = collectorActor;
+ }
+
+ public static Props props(String id, Map<String, String> peerAddresses, ConfigParams config,
+ TestActorRef<MessageCollectorActor> collectorActor) {
+ return Props.create(TestRaftActor.class, id, peerAddresses, config, collectorActor).
+ withDispatcher(Dispatchers.DefaultDispatcherId());
+ }
+
+ void startDropMessages(Class<?> msgClass) {
+ dropMessages.put(msgClass, Boolean.TRUE);
+ }
+
+ void stopDropMessages(Class<?> msgClass) {
+ dropMessages.remove(msgClass);
+ }
+
+ void setMockTotalMemory(long mockTotalMemory) {
+ this.mockTotalMemory = mockTotalMemory;
+ }
+
+ @Override
+ protected long getTotalMemory() {
+ return mockTotalMemory > 0 ? mockTotalMemory : super.getTotalMemory();
+ }
+
+ @Override
+ public void handleCommand(Object message) {
+ if(message instanceof MockPayload) {
+ MockPayload payload = (MockPayload)message;
+ super.persistData(collectorActor, payload.toString(), payload);
+ return;
+ }
+
+ try {
+ if(!dropMessages.containsKey(message.getClass())) {
+ super.handleCommand(message);
+ }
+ } finally {
+ if(!(message instanceof SendHeartBeat)) {
+ try {
+ collectorActor.tell(message, ActorRef.noSender());
+ } catch (Exception e) {
+ LOG.error("MessageCollectorActor error", e);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void createSnapshot() {
+ if(snapshot != null) {
+ getSelf().tell(new CaptureSnapshotReply(snapshot), ActorRef.noSender());
+ }
+ }
+
+ @Override
+ protected void applyRecoverySnapshot(byte[] bytes) {
+ }
+
+ void setSnapshot(byte[] snapshot) {
+ this.snapshot = snapshot;
+ }
+
+ public ActorRef collectorActor() {
+ return collectorActor;
+ }
+ }
+
+ protected final Logger testLog = LoggerFactory.getLogger(getClass());
+
+ protected final TestActorFactory factory = new TestActorFactory(getSystem());
+
+ protected String leaderId = factory.generateActorId("leader");
+ protected DefaultConfigParamsImpl leaderConfigParams;
+ protected TestActorRef<TestRaftActor> leaderActor;
+ protected ActorRef leaderCollectorActor;
+ protected RaftActorContext leaderContext;
+ protected RaftActorBehavior leader;
+
+ protected String follower1Id = factory.generateActorId("follower");
+ protected TestActorRef<TestRaftActor> follower1Actor;
+ protected ActorRef follower1CollectorActor;
+ protected RaftActorBehavior follower1;
+ protected RaftActorContext follower1Context;
+
+ protected String follower2Id = factory.generateActorId("follower");
+ protected TestActorRef<TestRaftActor> follower2Actor;
+ protected ActorRef follower2CollectorActor;
+ protected RaftActorBehavior follower2;
+ protected RaftActorContext follower2Context;
+
+ protected ImmutableMap<String, String> peerAddresses;
+
+ protected long initialTerm = 5;
+ protected long currentTerm;
+
+ @After
+ public void tearDown() {
+ InMemoryJournal.clear();
+ InMemorySnapshotStore.clear();
+ factory.close();
+ }
+
+ protected DefaultConfigParamsImpl newLeaderConfigParams() {
+ DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
+ configParams.setHeartBeatInterval(new FiniteDuration(100, TimeUnit.MILLISECONDS));
+ configParams.setElectionTimeoutFactor(1);
+ configParams.setSnapshotBatchCount(4);
+ configParams.setSnapshotDataThresholdPercentage(70);
+ configParams.setIsolatedLeaderCheckInterval(new FiniteDuration(1, TimeUnit.DAYS));
+ return configParams;
+ }
+
+ protected DefaultConfigParamsImpl newFollowerConfigParams() {
+ DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
+ configParams.setHeartBeatInterval(new FiniteDuration(500, TimeUnit.MILLISECONDS));
+ configParams.setElectionTimeoutFactor(1000);
+ return configParams;
+ }
+
+ protected void waitUntilLeader(ActorRef actorRef) {
+ RaftActorTest.RaftActorTestKit.waitUntilLeader(actorRef);
+ }
+
+ protected TestActorRef<TestRaftActor> newTestRaftActor(String id, Map<String, String> peerAddresses,
+ ConfigParams configParams) {
+ TestActorRef<MessageCollectorActor> collectorActor = factory.createTestActor(
+ MessageCollectorActor.props().withDispatcher(Dispatchers.DefaultDispatcherId()),
+ factory.generateActorId(id + "-collector"));
+ return factory.createTestActor(TestRaftActor.props(id,
+ peerAddresses != null ? peerAddresses : Collections.<String, String>emptyMap(),
+ configParams, collectorActor), id);
+ }
+
+ protected void killActor(TestActorRef<TestRaftActor> leaderActor) {
+ JavaTestKit testkit = new JavaTestKit(getSystem());
+ testkit.watch(leaderActor);
+
+ leaderActor.tell(PoisonPill.getInstance(), null);
+ testkit.expectMsgClass(JavaTestKit.duration("5 seconds"), Terminated.class);
+
+ testkit.unwatch(leaderActor);
+ }
+
+ protected void verifyApplyJournalEntries(ActorRef actor, final long expIndex) {
+ MessageCollectorActor.expectFirstMatching(actor, ApplyJournalEntries.class, new Predicate<ApplyJournalEntries>() {
+ @Override
+ public boolean apply(ApplyJournalEntries msg) {
+ return msg.getToIndex() == expIndex;
+ }
+ });
+ }
+
+ protected void verifySnapshot(String prefix, Snapshot snapshot, long lastAppliedTerm,
+ int lastAppliedIndex, long lastTerm, long lastIndex, byte[] data) {
+ assertEquals(prefix + " Snapshot getLastAppliedTerm", lastAppliedTerm, snapshot.getLastAppliedTerm());
+ assertEquals(prefix + " Snapshot getLastAppliedIndex", lastAppliedIndex, snapshot.getLastAppliedIndex());
+ assertEquals(prefix + " Snapshot getLastTerm", lastTerm, snapshot.getLastTerm());
+ assertEquals(prefix + " Snapshot getLastIndex", lastIndex, snapshot.getLastIndex());
+ assertArrayEquals(prefix + " Snapshot getState", data, snapshot.getState());
+ }
+
+ protected void verifyPersistedJournal(String persistenceId, List<? extends ReplicatedLogEntry> expJournal) {
+ List<ReplicatedLogEntry> journal = InMemoryJournal.get(persistenceId, ReplicatedLogEntry.class);
+ assertEquals("Journal ReplicatedLogEntry count", expJournal.size(), journal.size());
+ for(int i = 0; i < expJournal.size(); i++) {
+ ReplicatedLogEntry expected = expJournal.get(i);
+ ReplicatedLogEntry actual = journal.get(i);
+ verifyReplicatedLogEntry(expected, actual.getTerm(), actual.getIndex(), actual.getData());
+ }
+ }
+
+ protected MockPayload sendPayloadData(ActorRef leaderActor, String data) {
+ return sendPayloadData(leaderActor, data, 0);
+ }
+
+ protected MockPayload sendPayloadData(ActorRef leaderActor, String data, int size) {
+ MockPayload payload;
+ if(size > 0) {
+ payload = new MockPayload(data, size);
+ } else {
+ payload = new MockPayload(data);
+ }
+
+ leaderActor.tell(payload, ActorRef.noSender());
+ return payload;
+ }
+
+ protected void verifyApplyState(ApplyState applyState, ActorRef expClientActor,
+ String expId, long expTerm, long expIndex, MockPayload payload) {
+ assertEquals("ApplyState getClientActor", expClientActor, applyState.getClientActor());
+ assertEquals("ApplyState getIdentifier", expId, applyState.getIdentifier());
+ ReplicatedLogEntry replicatedLogEntry = applyState.getReplicatedLogEntry();
+ verifyReplicatedLogEntry(replicatedLogEntry, expTerm, expIndex, payload);
+ }
+
+ protected void verifyReplicatedLogEntry(ReplicatedLogEntry replicatedLogEntry, long expTerm, long expIndex,
+ Payload payload) {
+ assertEquals("ReplicatedLogEntry getTerm", expTerm, replicatedLogEntry.getTerm());
+ assertEquals("ReplicatedLogEntry getIndex", expIndex, replicatedLogEntry.getIndex());
+ assertEquals("ReplicatedLogEntry getData", payload, replicatedLogEntry.getData());
+ }
+}
public static class MockPayload extends Payload implements Serializable {
private static final long serialVersionUID = 3121380393130864247L;
private String value = "";
+ private int size;
- public MockPayload(){
-
+ public MockPayload() {
}
public MockPayload(String s) {
this.value = s;
+ size = value.length();
+ }
+
+ public MockPayload(String s, int size) {
+ this(s);
+ this.size = size;
}
@Override public Map<GeneratedMessage.GeneratedExtension, String> encode() {
@Override
public int size() {
- return value.length();
+ return size;
}
@Override public String getClientPayloadClassName() {
import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
+import org.opendaylight.controller.cluster.raft.utils.InMemoryJournal;
+import org.opendaylight.controller.cluster.raft.utils.InMemorySnapshotStore;
import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
-import org.opendaylight.controller.cluster.raft.utils.MockAkkaJournal;
-import org.opendaylight.controller.cluster.raft.utils.MockSnapshotStore;
import scala.concurrent.Await;
import scala.concurrent.Future;
import scala.concurrent.duration.Duration;
@After
public void tearDown() throws Exception {
factory.close();
- MockAkkaJournal.clearJournal();
- MockSnapshotStore.setMockSnapshot(null);
+ InMemoryJournal.clear();
+ InMemorySnapshotStore.clear();
}
public static class MockRaftActor extends RaftActor {
- private final DataPersistenceProvider dataPersistenceProvider;
+ protected DataPersistenceProvider dataPersistenceProvider;
private final RaftActor delegate;
private final CountDownLatch recoveryComplete = new CountDownLatch(1);
private final List<Object> state;
@Override protected void applyState(ActorRef clientActor, String identifier, Object data) {
delegate.applyState(clientActor, identifier, data);
- LOG.info("applyState called");
+ LOG.info("{}: applyState called", persistenceId());
}
@Override
}
@Override protected void createSnapshot() {
+ LOG.info("{}: createSnapshot called", persistenceId());
delegate.createSnapshot();
}
@Override protected void applySnapshot(byte [] snapshot) {
+ LOG.info("{}: applySnapshot called", persistenceId());
delegate.applySnapshot(snapshot);
}
}
- private static class RaftActorTestKit extends JavaTestKit {
+ public static class RaftActorTestKit extends JavaTestKit {
private final ActorRef raftActor;
public RaftActorTestKit(ActorSystem actorSystem, String actorName) {
waitUntilLeader(raftActor);
}
- protected void waitUntilLeader(ActorRef actorRef) {
+ public static void waitUntilLeader(ActorRef actorRef) {
FiniteDuration duration = Duration.create(100, TimeUnit.MILLISECONDS);
for(int i = 0; i < 20 * 5; i++) {
Future<Object> future = Patterns.ask(actorRef, new FindLeader(), new Timeout(duration));
Snapshot snapshot = Snapshot.create(snapshotBytes.toByteArray(),
snapshotUnappliedEntries, lastIndexDuringSnapshotCapture, 1,
lastAppliedDuringSnapshotCapture, 1);
- MockSnapshotStore.setMockSnapshot(snapshot);
- MockSnapshotStore.setPersistenceId(persistenceId);
+ InMemorySnapshotStore.addSnapshot(persistenceId, snapshot);
// add more entries after snapshot is taken
List<ReplicatedLogEntry> entries = new ArrayList<>();
int lastAppliedToState = 5;
int lastIndex = 7;
- MockAkkaJournal.addToJournal(5, entry2);
+ InMemoryJournal.addEntry(persistenceId, 5, entry2);
// 2 entries are applied to state besides the 4 entries in snapshot
- MockAkkaJournal.addToJournal(6, new ApplyJournalEntries(lastAppliedToState));
- MockAkkaJournal.addToJournal(7, entry3);
- MockAkkaJournal.addToJournal(8, entry4);
-
+ InMemoryJournal.addEntry(persistenceId, 6, new ApplyJournalEntries(lastAppliedToState));
+ InMemoryJournal.addEntry(persistenceId, 7, entry3);
+ InMemoryJournal.addEntry(persistenceId, 8, entry4);
// kill the actor
followerActor.tell(PoisonPill.getInstance(), null);
new MockRaftActorContext.MockPayload("two"));
long seqNr = 1;
- MockAkkaJournal.addToJournal(seqNr++, entry0);
- MockAkkaJournal.addToJournal(seqNr++, entry1);
- MockAkkaJournal.addToJournal(seqNr++, new ApplyLogEntries(1));
- MockAkkaJournal.addToJournal(seqNr++, entry2);
+ InMemoryJournal.addEntry(persistenceId, seqNr++, entry0);
+ InMemoryJournal.addEntry(persistenceId, seqNr++, entry1);
+ InMemoryJournal.addEntry(persistenceId, seqNr++, new ApplyLogEntries(1));
+ InMemoryJournal.addEntry(persistenceId, seqNr++, entry2);
int lastAppliedToState = 1;
int lastIndex = 2;
--- /dev/null
+/*
+ * Copyright (c) 2015 Brocade Communications 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.cluster.raft;
+
+import static org.junit.Assert.assertEquals;
+import akka.persistence.SaveSnapshotSuccess;
+import com.google.common.collect.ImmutableMap;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload;
+import org.opendaylight.controller.cluster.raft.RaftActor.UpdateElectionTerm;
+import org.opendaylight.controller.cluster.raft.base.messages.ApplyLogEntries;
+import org.opendaylight.controller.cluster.raft.base.messages.ApplyState;
+import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot;
+import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshotReply;
+import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
+import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
+import org.opendaylight.controller.cluster.raft.utils.InMemoryJournal;
+import org.opendaylight.controller.cluster.raft.utils.InMemorySnapshotStore;
+import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
+
+/**
+ * Tests replication and snapshots end-to-end using real RaftActors and behavior communication.
+ *
+ * @author Thomas Pantelis
+ */
+public class ReplicationAndSnapshotsIntegrationTest extends AbstractRaftActorIntegrationTest {
+
+ private List<ReplicatedLogImplEntry> origLeaderJournal;
+
+ private MockPayload recoveredPayload0;
+ private MockPayload recoveredPayload1;
+ private MockPayload recoveredPayload2;
+ private MockPayload payload4;
+ private MockPayload payload5;
+ private MockPayload payload6;
+ private MockPayload payload7;
+
+ @Test
+ public void runTest() {
+ testLog.info("testReplicationAndSnapshots starting");
+
+ // Setup the persistent journal for the leader. We'll start up with 3 journal log entries (one less
+ // than the snapshotBatchCount).
+ long seqId = 1;
+ InMemoryJournal.addEntry(leaderId, seqId++, new UpdateElectionTerm(initialTerm, leaderId));
+ recoveredPayload0 = new MockPayload("zero");
+ InMemoryJournal.addEntry(leaderId, seqId++, new ReplicatedLogImplEntry(0, initialTerm, recoveredPayload0));
+ recoveredPayload1 = new MockPayload("one");
+ InMemoryJournal.addEntry(leaderId, seqId++, new ReplicatedLogImplEntry(1, initialTerm, recoveredPayload1));
+ recoveredPayload2 = new MockPayload("two");
+ InMemoryJournal.addEntry(leaderId, seqId++, new ReplicatedLogImplEntry(2, initialTerm, recoveredPayload2));
+ InMemoryJournal.addEntry(leaderId, seqId++, new ApplyLogEntries(2));
+
+ origLeaderJournal = InMemoryJournal.get(leaderId, ReplicatedLogImplEntry.class);
+
+ // Create the leader and 2 follower actors and verify initial syncing of the followers after leader
+ // persistence recovery.
+
+ follower1Actor = newTestRaftActor(follower1Id, null, newFollowerConfigParams());
+
+ follower2Actor = newTestRaftActor(follower2Id, null, newFollowerConfigParams());
+
+ peerAddresses = ImmutableMap.<String, String>builder().
+ put(follower1Id, follower1Actor.path().toString()).
+ put(follower2Id, follower2Actor.path().toString()).build();
+
+ leaderConfigParams = newLeaderConfigParams();
+ leaderActor = newTestRaftActor(leaderId, peerAddresses, leaderConfigParams);
+
+ follower1CollectorActor = follower1Actor.underlyingActor().collectorActor();
+ follower2CollectorActor = follower2Actor.underlyingActor().collectorActor();
+ leaderCollectorActor = leaderActor.underlyingActor().collectorActor();
+
+ leaderContext = leaderActor.underlyingActor().getRaftActorContext();
+
+ verifyLeaderRecoveryAndInitialization();
+
+ testFirstSnapshot();
+
+ testSubsequentReplications();
+
+ testSecondSnapshot();
+
+ testLeaderReinstatement();
+
+ testLog.info("testReplicationAndSnapshots ending");
+ }
+
+ /**
+ * Verify the expected leader is elected as the leader and verify initial syncing of the followers
+ * from the leader's persistence recovery.
+ */
+ void verifyLeaderRecoveryAndInitialization() {
+ testLog.info("verifyLeaderRecoveryAndInitialization starting");
+
+ waitUntilLeader(leaderActor);
+
+ currentTerm = leaderContext.getTermInformation().getCurrentTerm();
+ assertEquals("Current term > " + initialTerm, true, currentTerm > initialTerm);
+
+ leader = leaderActor.underlyingActor().getCurrentBehavior();
+
+ // The followers should receive AppendEntries for each leader log entry that was recovered from
+ // persistence and apply each one.
+ List<ApplyState> applyStates = MessageCollectorActor.expectMatching(
+ follower1CollectorActor, ApplyState.class, 3);
+ verifyApplyState(applyStates.get(0), null, null, initialTerm, 0, recoveredPayload0);
+ verifyApplyState(applyStates.get(1), null, null, initialTerm, 1, recoveredPayload1);
+ verifyApplyState(applyStates.get(2), null, null, initialTerm, 2, recoveredPayload2);
+
+ // Verify follower 1 applies a log entry for at least the last entry index.
+ verifyApplyJournalEntries(follower1CollectorActor, 2);
+
+ applyStates = MessageCollectorActor.expectMatching(follower2CollectorActor, ApplyState.class, 3);
+ verifyApplyState(applyStates.get(0), null, null, initialTerm, 0, recoveredPayload0);
+ verifyApplyState(applyStates.get(1), null, null, initialTerm, 1, recoveredPayload1);
+ verifyApplyState(applyStates.get(2), null, null, initialTerm, 2, recoveredPayload2);
+
+ // Verify follower 1]2 applies a log entry for at least the last entry index.
+ verifyApplyJournalEntries(follower2CollectorActor, 2);
+
+ MessageCollectorActor.clearMessages(leaderCollectorActor);
+ MessageCollectorActor.clearMessages(follower1CollectorActor);
+ MessageCollectorActor.clearMessages(follower2CollectorActor);
+
+ // The leader should have performed fake snapshots due to the follower's AppendEntriesReplies and
+ // trimmed the in-memory log so that only the last entry remains.
+ assertEquals("Leader snapshot term", initialTerm, leaderContext.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Leader snapshot index", 1, leaderContext.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Leader journal log size", 1, leaderContext.getReplicatedLog().size());
+ assertEquals("Leader journal last index", 2, leaderContext.getReplicatedLog().lastIndex());
+ assertEquals("Leader commit index", 2, leaderContext.getCommitIndex());
+ assertEquals("Leader last applied", 2, leaderContext.getLastApplied());
+ assertEquals("Leader replicatedToAllIndex", 1, leader.getReplicatedToAllIndex());
+
+ // Verify the follower's persisted journal log.
+ verifyPersistedJournal(follower1Id, origLeaderJournal);
+ verifyPersistedJournal(follower2Id, origLeaderJournal);
+
+ MessageCollectorActor.clearMessages(leaderCollectorActor);
+ MessageCollectorActor.clearMessages(follower1CollectorActor);
+ MessageCollectorActor.clearMessages(follower2CollectorActor);
+
+ testLog.info("verifyLeaderRecoveryAndInitialization ending");
+ }
+
+ /**
+ * Send a payload to the TestRaftActor to persist and replicate. Since snapshotBatchCount is set to
+ * 4 and we already have 3 entries in the journal log, this should initiate a snapshot. In this
+ * scenario, the follower consensus and application of state is delayed until after the snapshot
+ * completes.
+ */
+ private void testFirstSnapshot() {
+ testLog.info("testFirstSnapshot starting");
+
+ byte[] snapshot = new byte[] {1,2,3,4};
+ leaderActor.underlyingActor().setSnapshot(snapshot);
+
+ // Delay the consensus by temporarily dropping the AppendEntries to both followers.
+ follower1Actor.underlyingActor().startDropMessages(AppendEntries.class);
+ follower2Actor.underlyingActor().startDropMessages(AppendEntries.class);
+
+ // Send the payload.
+ MockPayload payload3 = sendPayloadData(leaderActor, "three");
+
+ // Wait for snapshot complete.
+ MessageCollectorActor.expectFirstMatching(leaderCollectorActor, SaveSnapshotSuccess.class);
+
+ // The snapshot index should not be advanced nor the log trimmed because replicatedToAllIndex
+ // is behind due the followers not being replicated yet via AppendEntries.
+ assertEquals("Leader snapshot term", initialTerm, leaderContext.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Leader snapshot index", 1, leaderContext.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Leader journal log size", 2, leaderContext.getReplicatedLog().size());
+ assertEquals("Leader journal last index", 3, leaderContext.getReplicatedLog().lastIndex());
+
+ // Verify the persisted snapshot in the leader. This should reflect the advanced snapshot index as
+ // the last applied log entry (2) even though the leader hasn't yet advanced its cached snapshot index.
+ List<Snapshot> persistedSnapshots = InMemorySnapshotStore.getSnapshots(leaderId, Snapshot.class);
+ assertEquals("Persisted snapshots size", 1, persistedSnapshots.size());
+ verifySnapshot("Persisted", persistedSnapshots.get(0), initialTerm, 2, currentTerm, 3, snapshot);
+ List<ReplicatedLogEntry> unAppliedEntry = persistedSnapshots.get(0).getUnAppliedEntries();
+ assertEquals("Persisted Snapshot getUnAppliedEntries size", 1, unAppliedEntry.size());
+ verifyReplicatedLogEntry(unAppliedEntry.get(0), currentTerm, 3, payload3);
+
+ // The leader's persisted journal log should be cleared since we snapshotted.
+ List<ReplicatedLogImplEntry> persistedLeaderJournal = InMemoryJournal.get(leaderId, ReplicatedLogImplEntry.class);
+ assertEquals("Persisted journal log size", 0, persistedLeaderJournal.size());
+
+ // Allow AppendEntries to both followers to proceed. This should catch up the followers and cause a
+ // "fake" snapshot in the leader to advance the snapshot index to 2. Also the state should be applied
+ // in all members (via ApplyState).
+ follower1Actor.underlyingActor().stopDropMessages(AppendEntries.class);
+ follower2Actor.underlyingActor().stopDropMessages(AppendEntries.class);
+
+ ApplyState applyState = MessageCollectorActor.expectFirstMatching(leaderCollectorActor, ApplyState.class);
+ verifyApplyState(applyState, leaderCollectorActor, payload3.toString(), currentTerm, 3, payload3);
+
+ verifyApplyJournalEntries(leaderCollectorActor, 3);
+
+ assertEquals("Leader commit index", 3, leaderContext.getCommitIndex());
+
+ applyState = MessageCollectorActor.expectFirstMatching(follower1CollectorActor, ApplyState.class);
+ verifyApplyState(applyState, null, null, currentTerm, 3, payload3);
+
+ verifyApplyJournalEntries(follower1CollectorActor, 3);
+
+ applyState = MessageCollectorActor.expectFirstMatching(follower2CollectorActor, ApplyState.class);
+ verifyApplyState(applyState, null, null, currentTerm, 3, payload3);
+
+ verifyApplyJournalEntries(follower2CollectorActor, 3);
+
+ assertEquals("Leader snapshot term", initialTerm, leaderContext.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Leader snapshot index", 2, leaderContext.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Leader journal log size", 1, leaderContext.getReplicatedLog().size());
+ assertEquals("Leader commit index", 3, leaderContext.getCommitIndex());
+ assertEquals("Leader last applied", 3, leaderContext.getLastApplied());
+ assertEquals("Leader replicatedToAllIndex", 2, leader.getReplicatedToAllIndex());
+
+ MessageCollectorActor.clearMessages(leaderCollectorActor);
+ MessageCollectorActor.clearMessages(follower1CollectorActor);
+ MessageCollectorActor.clearMessages(follower2CollectorActor);
+
+ testLog.info("testFirstSnapshot ending");
+ }
+
+ /**
+ * Send 3 more payload instances and verify they get applied by all members.
+ */
+ private void testSubsequentReplications() {
+ testLog.info("testSubsequentReplications starting");
+
+ payload4 = sendPayloadData(leaderActor, "four");
+ payload5 = sendPayloadData(leaderActor, "five");
+ payload6 = sendPayloadData(leaderActor, "six");
+
+ // Verify the leader applies the states.
+ List<ApplyState> applyStates = MessageCollectorActor.expectMatching(leaderCollectorActor, ApplyState.class, 3);
+ verifyApplyState(applyStates.get(0), leaderCollectorActor, payload4.toString(), currentTerm, 4, payload4);
+ verifyApplyState(applyStates.get(1), leaderCollectorActor, payload5.toString(), currentTerm, 5, payload5);
+ verifyApplyState(applyStates.get(2), leaderCollectorActor, payload6.toString(), currentTerm, 6, payload6);
+
+ // Verify the leader applies a log entry for at least the last entry index.
+ verifyApplyJournalEntries(leaderCollectorActor, 6);
+
+ // The leader should have performed fake snapshots due to the follower's AppendEntriesReplies and
+ // trimmed the in-memory log so that only the last entry remains.
+ assertEquals("Leader snapshot term", currentTerm, leaderContext.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Leader snapshot index", 5, leaderContext.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Leader journal log size", 1, leaderContext.getReplicatedLog().size());
+ assertEquals("Leader journal last index", 6, leaderContext.getReplicatedLog().lastIndex());
+ assertEquals("Leader commit index", 6, leaderContext.getCommitIndex());
+ assertEquals("Leader last applied", 6, leaderContext.getLastApplied());
+ assertEquals("Leader replicatedToAllIndex", 5, leader.getReplicatedToAllIndex());
+
+ // Verify follower 1 applies the states.
+ applyStates = MessageCollectorActor.expectMatching(follower1CollectorActor, ApplyState.class, 3);
+ verifyApplyState(applyStates.get(0), null, null, currentTerm, 4, payload4);
+ verifyApplyState(applyStates.get(1), null, null, currentTerm, 5, payload5);
+ verifyApplyState(applyStates.get(2), null, null, currentTerm, 6, payload6);
+
+ // Verify follower 1 applies a log entry for at least the last entry index.
+ verifyApplyJournalEntries(follower1CollectorActor, 6);
+
+ // Verify follower 2 applies the states.
+ applyStates = MessageCollectorActor.expectMatching(follower2CollectorActor, ApplyState.class, 3);
+ verifyApplyState(applyStates.get(0), null, null, currentTerm, 4, payload4);
+ verifyApplyState(applyStates.get(1), null, null, currentTerm, 5, payload5);
+ verifyApplyState(applyStates.get(2), null, null, currentTerm, 6, payload6);
+
+ // Verify follower 2 applies a log entry for at least the last entry index.
+ verifyApplyJournalEntries(follower2CollectorActor, 6);
+
+ MessageCollectorActor.clearMessages(leaderCollectorActor);
+
+ testLog.info("testSubsequentReplications ending");
+ }
+
+ /**
+ * Send one more payload to trigger another snapshot. In this scenario, we delay the snapshot until
+ * consensus occurs and the leader applies the state.
+ */
+ private void testSecondSnapshot() {
+ testLog.info("testSecondSnapshot starting");
+
+ byte[] snapshot = new byte[] {5,6,7,8};
+ leaderActor.underlyingActor().setSnapshot(snapshot);
+
+ // Delay the CaptureSnapshot message to the leader actor.
+ leaderActor.underlyingActor().startDropMessages(CaptureSnapshot.class);
+
+ // Send the payload.
+ payload7 = sendPayloadData(leaderActor, "seven");
+
+ // Capture the CaptureSnapshot message so we can send it later.
+ CaptureSnapshot captureSnapshot = MessageCollectorActor.expectFirstMatching(
+ leaderCollectorActor, CaptureSnapshot.class);
+
+ // Wait for the state to be applied in the leader.
+ ApplyState applyState = MessageCollectorActor.expectFirstMatching(leaderCollectorActor, ApplyState.class);
+ verifyApplyState(applyState, leaderCollectorActor, payload7.toString(), currentTerm, 7, payload7);
+
+ // At this point the leader has applied the new state but the cached snapshot index should not be
+ // advanced by a "fake" snapshot because we're in the middle of a snapshot. We'll wait for at least
+ // one more heartbeat AppendEntriesReply to ensure this does not occur.
+ MessageCollectorActor.clearMessages(leaderCollectorActor);
+ MessageCollectorActor.expectFirstMatching(leaderCollectorActor, AppendEntriesReply.class);
+
+ assertEquals("Leader snapshot term", currentTerm, leaderContext.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Leader snapshot index", 5, leaderContext.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Leader journal log size", 2, leaderContext.getReplicatedLog().size());
+ assertEquals("Leader journal last index", 7, leaderContext.getReplicatedLog().lastIndex());
+ assertEquals("Leader commit index", 7, leaderContext.getCommitIndex());
+ assertEquals("Leader last applied", 7, leaderContext.getLastApplied());
+ assertEquals("Leader replicatedToAllIndex", 5, leader.getReplicatedToAllIndex());
+
+ // Now deliver the CaptureSnapshot.
+ leaderActor.underlyingActor().stopDropMessages(CaptureSnapshot.class);
+ leaderActor.tell(captureSnapshot, leaderActor);
+
+ // Wait for CaptureSnapshotReply to complete.
+ MessageCollectorActor.expectFirstMatching(leaderCollectorActor, CaptureSnapshotReply.class);
+
+ // Wait for snapshot complete.
+ MessageCollectorActor.expectFirstMatching(leaderCollectorActor, SaveSnapshotSuccess.class);
+
+ // Wait for another heartbeat AppendEntriesReply. This should cause a "fake" snapshot to advance the
+ // snapshot index and trimmed the log since we're no longer in a snapshot.
+ MessageCollectorActor.clearMessages(leaderCollectorActor);
+ MessageCollectorActor.expectFirstMatching(leaderCollectorActor, AppendEntriesReply.class);
+ assertEquals("Leader snapshot term", currentTerm, leaderContext.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Leader snapshot index", 6, leaderContext.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Leader journal log size", 1, leaderContext.getReplicatedLog().size());
+ assertEquals("Leader journal last index", 7, leaderContext.getReplicatedLog().lastIndex());
+ assertEquals("Leader commit index", 7, leaderContext.getCommitIndex());
+
+ // Verify the persisted snapshot. This should reflect the advanced snapshot index as the last applied
+ // log entry (6).
+ List<Snapshot> persistedSnapshots = InMemorySnapshotStore.getSnapshots(leaderId, Snapshot.class);
+ assertEquals("Persisted snapshots size", 1, persistedSnapshots.size());
+ verifySnapshot("Persisted", persistedSnapshots.get(0), currentTerm, 6, currentTerm, 7, snapshot);
+ List<ReplicatedLogEntry> unAppliedEntry = persistedSnapshots.get(0).getUnAppliedEntries();
+ assertEquals("Persisted Snapshot getUnAppliedEntries size", 1, unAppliedEntry.size());
+ verifyReplicatedLogEntry(unAppliedEntry.get(0), currentTerm, 7, payload7);
+
+ // The leader's persisted journal log should be cleared since we did a snapshot.
+ List<ReplicatedLogImplEntry> persistedLeaderJournal = InMemoryJournal.get(
+ leaderId, ReplicatedLogImplEntry.class);
+ assertEquals("Persisted journal log size", 0, persistedLeaderJournal.size());
+
+ // Verify the followers apply all 4 new log entries.
+ List<ApplyState> applyStates = MessageCollectorActor.expectMatching(follower1CollectorActor, ApplyState.class, 4);
+ verifyApplyState(applyStates.get(0), null, null, currentTerm, 4, payload4);
+ verifyApplyState(applyStates.get(1), null, null, currentTerm, 5, payload5);
+ verifyApplyState(applyStates.get(2), null, null, currentTerm, 6, payload6);
+ verifyApplyState(applyStates.get(3), null, null, currentTerm, 7, payload7);
+
+ applyStates = MessageCollectorActor.expectMatching(follower2CollectorActor, ApplyState.class, 4);
+ verifyApplyState(applyStates.get(0), null, null, currentTerm, 4, payload4);
+ verifyApplyState(applyStates.get(1), null, null, currentTerm, 5, payload5);
+ verifyApplyState(applyStates.get(2), null, null, currentTerm, 6, payload6);
+ verifyApplyState(applyStates.get(3), null, null, currentTerm, 7, payload7);
+
+ // Verify the follower's snapshot index has also advanced. (after another AppendEntries heartbeat
+ // to be safe).
+
+ MessageCollectorActor.clearMessages(follower1CollectorActor);
+ MessageCollectorActor.expectFirstMatching(follower1CollectorActor, AppendEntries.class);
+ RaftActorContext follower1Context = follower1Actor.underlyingActor().getRaftActorContext();
+ assertEquals("Follower 1 snapshot term", currentTerm, follower1Context.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Follower 1 snapshot index", 6, follower1Context.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Follower 1 journal log size", 1, follower1Context.getReplicatedLog().size());
+ assertEquals("Follower 1 journal last index", 7, follower1Context.getReplicatedLog().lastIndex());
+ assertEquals("Follower 1 commit index", 7, follower1Context.getCommitIndex());
+
+ MessageCollectorActor.clearMessages(follower2CollectorActor);
+ MessageCollectorActor.expectFirstMatching(follower2CollectorActor, AppendEntries.class);
+ RaftActorContext follower2Context = follower2Actor.underlyingActor().getRaftActorContext();
+ assertEquals("Follower 2 snapshot term", currentTerm, follower2Context.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Follower 2 snapshot index", 6, follower2Context.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Follower 2 journal log size", 1, follower2Context.getReplicatedLog().size());
+ assertEquals("Follower 2 journal last index", 7, follower2Context.getReplicatedLog().lastIndex());
+ assertEquals("Follower 2 commit index", 7, follower2Context.getCommitIndex());
+
+ testLog.info("testSecondSnapshot ending");
+ }
+
+ /**
+ * Kill the leader actor, reinstate it and verify the recovered journal.
+ */
+ private void testLeaderReinstatement() {
+ testLog.info("testLeaderReinstatement starting");
+
+ killActor(leaderActor);
+
+ leaderActor = newTestRaftActor(leaderId, peerAddresses, leaderConfigParams);
+
+ leaderActor.underlyingActor().waitForRecoveryComplete();
+
+ assertEquals("Leader snapshot term", currentTerm, leaderContext.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Leader snapshot index", 6, leaderContext.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Leader journal log size", 1, leaderContext.getReplicatedLog().size());
+ assertEquals("Leader journal last index", 7, leaderContext.getReplicatedLog().lastIndex());
+ assertEquals("Leader commit index", 7, leaderContext.getCommitIndex());
+ assertEquals("Leader last applied", 7, leaderContext.getLastApplied());
+ verifyReplicatedLogEntry(leaderContext.getReplicatedLog().last(), currentTerm, 7, payload7);
+
+ testLog.info("testLeaderReinstatement ending");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Brocade Communications 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.cluster.raft;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import akka.persistence.SaveSnapshotSuccess;
+import com.google.common.collect.ImmutableMap;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload;
+import org.opendaylight.controller.cluster.raft.RaftActor.UpdateElectionTerm;
+import org.opendaylight.controller.cluster.raft.base.messages.ApplyJournalEntries;
+import org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot;
+import org.opendaylight.controller.cluster.raft.base.messages.ApplyState;
+import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot;
+import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
+import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
+import org.opendaylight.controller.cluster.raft.messages.InstallSnapshot;
+import org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply;
+import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
+import org.opendaylight.controller.cluster.raft.utils.InMemoryJournal;
+import org.opendaylight.controller.cluster.raft.utils.InMemorySnapshotStore;
+import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
+
+/**
+ * Tests replication and snapshots end-to-end using real RaftActors and behavior communication with a
+ * lagging follower.
+ *
+ * @author Thomas Pantelis
+ */
+public class ReplicationAndSnapshotsWithLaggingFollowerIntegrationTest extends AbstractRaftActorIntegrationTest {
+
+ private MockPayload payload9;
+ private MockPayload payload11;
+ private MockPayload payload12;
+ private MockPayload payload13;
+
+ @Test
+ public void runTest() throws Exception {
+ testLog.info("testReplicationAndSnapshotsWithLaggingFollower starting");
+
+ leaderId = factory.generateActorId("leader");
+ follower1Id = factory.generateActorId("follower");
+ follower2Id = factory.generateActorId("follower");
+
+ // Setup the persistent journal for the leader - just an election term and no journal/snapshots.
+ InMemoryJournal.addEntry(leaderId, 1, new UpdateElectionTerm(initialTerm, leaderId));
+
+ // Create the leader and 2 follower actors.
+
+ follower1Actor = newTestRaftActor(follower1Id, null, newFollowerConfigParams());
+
+ follower2Actor = newTestRaftActor(follower2Id, null, newFollowerConfigParams());
+
+ Map<String, String> peerAddresses = ImmutableMap.<String, String>builder().
+ put(follower1Id, follower1Actor.path().toString()).
+ put(follower2Id, follower2Actor.path().toString()).build();
+
+ leaderConfigParams = newLeaderConfigParams();
+ leaderActor = newTestRaftActor(leaderId, peerAddresses, leaderConfigParams);
+
+ waitUntilLeader(leaderActor);
+
+ leaderContext = leaderActor.underlyingActor().getRaftActorContext();
+ leader = leaderActor.underlyingActor().getCurrentBehavior();
+
+ follower1Context = follower1Actor.underlyingActor().getRaftActorContext();
+ follower1 = follower1Actor.underlyingActor().getCurrentBehavior();
+
+ follower2Context = follower2Actor.underlyingActor().getRaftActorContext();
+ follower2 = follower2Actor.underlyingActor().getCurrentBehavior();
+
+ currentTerm = leaderContext.getTermInformation().getCurrentTerm();
+ assertEquals("Current term > " + initialTerm, true, currentTerm > initialTerm);
+
+ leaderCollectorActor = leaderActor.underlyingActor().collectorActor();
+ follower1CollectorActor = follower1Actor.underlyingActor().collectorActor();
+ follower2CollectorActor = follower2Actor.underlyingActor().collectorActor();
+
+ testLog.info("Leader created and elected");
+
+ testInitialReplications();
+
+ testSubsequentReplicationsAndSnapshots();
+
+ testLeaderSnapshotTriggeredByMemoryThresholdExceeded();
+
+ testInstallSnapshotToLaggingFollower();
+
+ verifyNoSubsequentSnapshotAfterMemoryThresholdExceededSnapshot();
+
+ testFinalReplicationsAndSnapshot();
+
+ testLeaderReinstatement();
+
+ testLog.info("testReplicationAndSnapshotsWithLaggingFollower ending");
+ }
+
+ /**
+ * Send 3 payload instances with follower 2 temporarily lagging.
+ *
+ * @throws Exception
+ */
+ private void testInitialReplications() throws Exception {
+
+ testLog.info("testInitialReplications starting: sending 2 new payloads");
+
+ // Simulate lagging by dropping AppendEntries messages in follower 2.
+ follower2Actor.underlyingActor().startDropMessages(AppendEntries.class);
+
+ // Send the payloads.
+ MockPayload payload0 = sendPayloadData(leaderActor, "zero");
+ MockPayload payload1 = sendPayloadData(leaderActor, "one");
+ MockPayload payload2 = sendPayloadData(leaderActor, "two");
+
+ // Verify the leader got consensus and applies each log entry even though follower 2 didn't respond.
+ List<ApplyState> applyStates = MessageCollectorActor.expectMatching(leaderCollectorActor, ApplyState.class, 3);
+ verifyApplyState(applyStates.get(0), leaderCollectorActor, payload0.toString(), currentTerm, 0, payload0);
+ verifyApplyState(applyStates.get(1), leaderCollectorActor, payload1.toString(), currentTerm, 1, payload1);
+ verifyApplyState(applyStates.get(2), leaderCollectorActor, payload2.toString(), currentTerm, 2, payload2);
+
+ // Verify follower 1 applies each log entry.
+ applyStates = MessageCollectorActor.expectMatching(follower1CollectorActor, ApplyState.class, 3);
+ verifyApplyState(applyStates.get(0), null, null, currentTerm, 0, payload0);
+ verifyApplyState(applyStates.get(1), null, null, currentTerm, 1, payload1);
+ verifyApplyState(applyStates.get(2), null, null, currentTerm, 2, payload2);
+
+ // Ensure there's at least 1 more heartbeat.
+ MessageCollectorActor.clearMessages(leaderCollectorActor);
+ MessageCollectorActor.expectFirstMatching(leaderCollectorActor, AppendEntriesReply.class);
+
+ // The leader should not have performed fake snapshots to trim the log because the entries have not
+ // been replicated to follower 2.
+ assertEquals("Leader snapshot term", -1, leaderContext.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Leader snapshot index", -1, leaderContext.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Leader journal log size", 3, leaderContext.getReplicatedLog().size());
+ assertEquals("Leader journal last index", 2, leaderContext.getReplicatedLog().lastIndex());
+ assertEquals("Leader commit index", 2, leaderContext.getCommitIndex());
+ assertEquals("Leader last applied", 2, leaderContext.getLastApplied());
+ assertEquals("Leader replicatedToAllIndex", -1, leader.getReplicatedToAllIndex());
+
+ testLog.info("Step 3: new entries applied - re-enabling follower {}", follower2Id);
+
+ // Now stop dropping AppendEntries in follower 2.
+ follower2Actor.underlyingActor().stopDropMessages(AppendEntries.class);
+
+ // Verify follower 2 applies each log entry.
+ applyStates = MessageCollectorActor.expectMatching(follower2CollectorActor, ApplyState.class, 3);
+ verifyApplyState(applyStates.get(0), null, null, currentTerm, 0, payload0);
+ verifyApplyState(applyStates.get(1), null, null, currentTerm, 1, payload1);
+ verifyApplyState(applyStates.get(2), null, null, currentTerm, 2, payload2);
+
+ // Ensure there's at least 1 more heartbeat.
+ MessageCollectorActor.clearMessages(leaderCollectorActor);
+ MessageCollectorActor.expectFirstMatching(leaderCollectorActor, AppendEntriesReply.class);
+
+ // The leader should now have performed fake snapshots to trim the log.
+ assertEquals("Leader snapshot term", currentTerm, leaderContext.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Leader snapshot index", 1, leaderContext.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Leader journal log size", 1, leaderContext.getReplicatedLog().size());
+ assertEquals("Leader journal last index", 2, leaderContext.getReplicatedLog().lastIndex());
+ assertEquals("Leader commit index", 2, leaderContext.getCommitIndex());
+ assertEquals("Leader last applied", 2, leaderContext.getLastApplied());
+ // Note - replicatedToAllIndex always lags 1 behind last applied since it trims the log up to the
+ // last applied index. The next entry successfully replicated to followers woild advance it.
+ assertEquals("Leader replicatedToAllIndex", 1, leader.getReplicatedToAllIndex());
+
+ // Even though follower 2 lagged behind, the leader should not have tried to install a snapshot
+ // to catch it up because no snapshotting was done so the follower's next index was present in the log.
+ InstallSnapshot installSnapshot = MessageCollectorActor.getFirstMatching(follower2CollectorActor,
+ InstallSnapshot.class);
+ Assert.assertNull("Follower 2 received unexpected InstallSnapshot", installSnapshot);
+
+ MessageCollectorActor.clearMessages(leaderCollectorActor);
+ MessageCollectorActor.clearMessages(follower1CollectorActor);
+ MessageCollectorActor.clearMessages(follower2CollectorActor);
+
+ testLog.info("testInitialReplications complete");
+ }
+
+ /**
+ * Send 5 more payloads with follower 2 lagging. Since the snapshotBatch count is 4, this should cause
+ * 2 leader snapshots and follower 2's log will be behind by 5 entries.
+ *
+ * @throws Exception
+ */
+ private void testSubsequentReplicationsAndSnapshots() throws Exception {
+ testLog.info("testSubsequentReplicationsAndSnapshots starting: sending first payload, replicatedToAllIndex: {}",
+ leader.getReplicatedToAllIndex());
+
+ leaderActor.underlyingActor().setSnapshot(new byte[] {2});
+
+ follower2Actor.underlyingActor().startDropMessages(AppendEntries.class);
+
+ // Send the first payload - this should cause the first snapshot.
+ MockPayload payload3 = sendPayloadData(leaderActor, "three");
+
+ MessageCollectorActor.expectFirstMatching(leaderCollectorActor, SaveSnapshotSuccess.class);
+
+ byte[] snapshot = new byte[] {6};
+ leaderActor.underlyingActor().setSnapshot(snapshot);
+
+ testLog.info("testSubsequentReplicationsAndSnapshots: sending 4 more payloads");
+
+ // Send the next 4. The last one should cause the second snapshot.
+ MockPayload payload4 = sendPayloadData(leaderActor, "four");
+ MockPayload payload5 = sendPayloadData(leaderActor, "five");
+ MockPayload payload6 = sendPayloadData(leaderActor, "six");
+ MockPayload payload7 = sendPayloadData(leaderActor, "seven");
+
+ // Verify the leader got consensus and applies each log entry even though follower 2 didn't respond.
+ List<ApplyState> applyStates = MessageCollectorActor.expectMatching(leaderCollectorActor, ApplyState.class, 5);
+ verifyApplyState(applyStates.get(0), leaderCollectorActor, payload3.toString(), currentTerm, 3, payload3);
+ verifyApplyState(applyStates.get(1), leaderCollectorActor, payload4.toString(), currentTerm, 4, payload4);
+ verifyApplyState(applyStates.get(2), leaderCollectorActor, payload5.toString(), currentTerm, 5, payload5);
+ verifyApplyState(applyStates.get(3), leaderCollectorActor, payload6.toString(), currentTerm, 6, payload6);
+ verifyApplyState(applyStates.get(4), leaderCollectorActor, payload7.toString(), currentTerm, 7, payload7);
+
+ // Verify follower 1 applies each log entry.
+ applyStates = MessageCollectorActor.expectMatching(follower1CollectorActor, ApplyState.class, 5);
+ verifyApplyState(applyStates.get(0), null, null, currentTerm, 3, payload3);
+ verifyApplyState(applyStates.get(1), null, null, currentTerm, 4, payload4);
+ verifyApplyState(applyStates.get(2), null, null, currentTerm, 5, payload5);
+ verifyApplyState(applyStates.get(3), null, null, currentTerm, 6, payload6);
+ verifyApplyState(applyStates.get(4), null, null, currentTerm, 7, payload7);
+
+ // Wait for snapshot completion.
+ MessageCollectorActor.expectFirstMatching(leaderCollectorActor, SaveSnapshotSuccess.class);
+
+ // The first new entry applied should have caused the leader to advanced the snapshot index to the
+ // last previously applied index (2) that was replicated to all followers.
+ assertEquals("Leader snapshot term", currentTerm, leaderContext.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Leader snapshot index", 2, leaderContext.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Leader journal log size", 5, leaderContext.getReplicatedLog().size());
+ assertEquals("Leader journal last index", 7, leaderContext.getReplicatedLog().lastIndex());
+ assertEquals("Leader commit index", 7, leaderContext.getCommitIndex());
+ assertEquals("Leader last applied", 7, leaderContext.getLastApplied());
+ assertEquals("Leader replicatedToAllIndex", 2, leader.getReplicatedToAllIndex());
+
+ // Now stop dropping AppendEntries in follower 2.
+ follower2Actor.underlyingActor().stopDropMessages(AppendEntries.class);
+
+ // Verify follower 2 applies each log entry.
+ applyStates = MessageCollectorActor.expectMatching(follower2CollectorActor, ApplyState.class, 5);
+ verifyApplyState(applyStates.get(0), null, null, currentTerm, 3, payload3);
+ verifyApplyState(applyStates.get(1), null, null, currentTerm, 4, payload4);
+ verifyApplyState(applyStates.get(2), null, null, currentTerm, 5, payload5);
+ verifyApplyState(applyStates.get(3), null, null, currentTerm, 6, payload6);
+ verifyApplyState(applyStates.get(4), null, null, currentTerm, 7, payload7);
+
+ // Ensure there's at least 1 more heartbeat.
+ MessageCollectorActor.clearMessages(leaderCollectorActor);
+ MessageCollectorActor.expectFirstMatching(leaderCollectorActor, AppendEntriesReply.class);
+
+ // The leader should now have performed fake snapshots to advance the snapshot index and to trim
+ // the log. In addition replicatedToAllIndex should've advanced.
+ assertEquals("Leader snapshot term", currentTerm, leaderContext.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Leader snapshot index", 6, leaderContext.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Leader journal log size", 1, leaderContext.getReplicatedLog().size());
+ assertEquals("Leader journal last index", 7, leaderContext.getReplicatedLog().lastIndex());
+ assertEquals("Leader replicatedToAllIndex", 6, leader.getReplicatedToAllIndex());
+
+ // Verify the leader's persisted snapshot.
+ List<Snapshot> persistedSnapshots = InMemorySnapshotStore.getSnapshots(leaderId, Snapshot.class);
+ assertEquals("Persisted snapshots size", 1, persistedSnapshots.size());
+ verifySnapshot("Persisted", persistedSnapshots.get(0), currentTerm, 3, currentTerm, 7, snapshot);
+ List<ReplicatedLogEntry> unAppliedEntry = persistedSnapshots.get(0).getUnAppliedEntries();
+ assertEquals("Persisted Snapshot getUnAppliedEntries size", 4, unAppliedEntry.size());
+ verifyReplicatedLogEntry(unAppliedEntry.get(0), currentTerm, 4, payload4);
+ verifyReplicatedLogEntry(unAppliedEntry.get(1), currentTerm, 5, payload5);
+ verifyReplicatedLogEntry(unAppliedEntry.get(2), currentTerm, 6, payload6);
+ verifyReplicatedLogEntry(unAppliedEntry.get(3), currentTerm, 7, payload7);
+
+ // Even though follower 2's log was behind by 5 entries and 2 snapshots were done, the leader
+ // should not have tried to install a snapshot to catch it up because replicatedToAllIndex was also
+ // behind. Instead of installing a snapshot the leader would've sent AppendEntries with the log entries.
+ InstallSnapshot installSnapshot = MessageCollectorActor.getFirstMatching(follower2CollectorActor, InstallSnapshot.class);
+ Assert.assertNull("Follower 2 received unexpected InstallSnapshot", installSnapshot);
+
+ // Verify follower 1's log and snapshot indexes.
+ MessageCollectorActor.clearMessages(follower1CollectorActor);
+ MessageCollectorActor.expectFirstMatching(follower1CollectorActor, AppendEntries.class);
+ assertEquals("Follower 1 snapshot term", currentTerm, follower1Context.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Follower 1 snapshot index", 6, follower1Context.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Follower 1 journal log size", 1, follower1Context.getReplicatedLog().size());
+ assertEquals("Follower 1 journal last index", 7, follower1Context.getReplicatedLog().lastIndex());
+ assertEquals("Follower 1 commit index", 7, follower1Context.getCommitIndex());
+ assertEquals("Follower 1 last applied", 7, follower1Context.getLastApplied());
+ assertEquals("Follower 1 replicatedToAllIndex", 6, follower1.getReplicatedToAllIndex());
+
+ // Verify follower 2's log and snapshot indexes.
+ MessageCollectorActor.clearMessages(follower2CollectorActor);
+ MessageCollectorActor.expectFirstMatching(follower2CollectorActor, AppendEntries.class);
+ assertEquals("Follower 2 snapshot term", currentTerm, follower2Context.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Follower 2 snapshot index", 6, follower2Context.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Follower 2 journal log size", 1, follower2Context.getReplicatedLog().size());
+ assertEquals("Follower 2 journal last index", 7, follower2Context.getReplicatedLog().lastIndex());
+ assertEquals("Follower 2 commit index", 7, follower2Context.getCommitIndex());
+ assertEquals("Follower 2 last applied", 7, follower2Context.getLastApplied());
+ assertEquals("Follower 2 replicatedToAllIndex", 6, follower2.getReplicatedToAllIndex());
+
+ MessageCollectorActor.clearMessages(leaderCollectorActor);
+ MessageCollectorActor.clearMessages(follower1CollectorActor);
+ MessageCollectorActor.clearMessages(follower2CollectorActor);
+
+ testLog.info("testSubsequentReplicationsAndSnapshots complete");
+ }
+
+ /**
+ * Send a couple more payloads with follower 2 lagging. The last payload will have a large enough size
+ * to trigger a leader snapshot.
+ *
+ * @throws Exception
+ */
+ private void testLeaderSnapshotTriggeredByMemoryThresholdExceeded() throws Exception {
+ testLog.info("testLeaderSnapshotTriggeredByMemoryThresholdExceeded starting: sending 3 payloads, replicatedToAllIndex: {}",
+ leader.getReplicatedToAllIndex());
+
+ leaderActor.underlyingActor().setMockTotalMemory(1000);
+ byte[] snapshot = new byte[] {6};
+ leaderActor.underlyingActor().setSnapshot(snapshot);
+
+ // We'll expect a ReplicatedLogImplEntry message and an ApplyJournalEntries message added to the journal.
+ InMemoryJournal.addWriteMessagesCompleteLatch(leaderId, 2);
+
+ follower2Actor.underlyingActor().startDropMessages(AppendEntries.class);
+
+ // Send a payload with a large relative size but not enough to trigger a snapshot.
+ MockPayload payload8 = sendPayloadData(leaderActor, "eight", 500);
+
+ // Verify the leader got consensus and applies the first log entry even though follower 2 didn't respond.
+ List<ApplyState> applyStates = MessageCollectorActor.expectMatching(leaderCollectorActor, ApplyState.class, 1);
+ verifyApplyState(applyStates.get(0), leaderCollectorActor, payload8.toString(), currentTerm, 8, payload8);
+
+ // Wait for all the ReplicatedLogImplEntry and ApplyJournalEntries messages to be added to the journal
+ // before the snapshot so the snapshot sequence # will be higher to ensure the snapshot gets
+ // purged from the snapshot store after subsequent snapshots.
+ InMemoryJournal.waitForWriteMessagesComplete(leaderId);
+
+ // Verify a snapshot is not triggered.
+ CaptureSnapshot captureSnapshot = MessageCollectorActor.getFirstMatching(leaderCollectorActor, CaptureSnapshot.class);
+ Assert.assertNull("Leader received unexpected CaptureSnapshot", captureSnapshot);
+
+ // Send another payload with a large enough relative size in combination with the last payload
+ // that exceeds the memory threshold (70% * 1000 = 700) - this should do a snapshot.
+ payload9 = sendPayloadData(leaderActor, "nine", 201);
+
+ // Verify the leader applies the last log entry.
+ applyStates = MessageCollectorActor.expectMatching(leaderCollectorActor, ApplyState.class, 2);
+ verifyApplyState(applyStates.get(1), leaderCollectorActor, payload9.toString(), currentTerm, 9, payload9);
+
+ // Verify follower 1 applies each log entry.
+ applyStates = MessageCollectorActor.expectMatching(follower1CollectorActor, ApplyState.class, 2);
+ verifyApplyState(applyStates.get(0), null, null, currentTerm, 8, payload8);
+ verifyApplyState(applyStates.get(1), null, null, currentTerm, 9, payload9);
+
+ // A snapshot should've occurred - wait for it to complete.
+ MessageCollectorActor.expectFirstMatching(leaderCollectorActor, SaveSnapshotSuccess.class);
+
+ // Because the snapshot was triggered by exceeding the memory threshold the leader should've advanced
+ // the snapshot index to the last applied index and trimmed the log even though the entries weren't
+ // replicated to all followers.
+ assertEquals("Leader snapshot term", currentTerm, leaderContext.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Leader snapshot index", 8, leaderContext.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Leader journal log size", 1, leaderContext.getReplicatedLog().size());
+ assertEquals("Leader journal last index", 9, leaderContext.getReplicatedLog().lastIndex());
+ assertEquals("Leader commit index", 9, leaderContext.getCommitIndex());
+ assertEquals("Leader last applied", 9, leaderContext.getLastApplied());
+ // Note: replicatedToAllIndex should not be advanced since log entries 8 and 9 haven't yet been
+ // replicated to follower 2.
+ assertEquals("Leader replicatedToAllIndex", 7, leader.getReplicatedToAllIndex());
+
+ // Verify the leader's persisted snapshot.
+ List<Snapshot> persistedSnapshots = InMemorySnapshotStore.getSnapshots(leaderId, Snapshot.class);
+ assertEquals("Persisted snapshots size", 1, persistedSnapshots.size());
+ verifySnapshot("Persisted", persistedSnapshots.get(0), currentTerm, 8, currentTerm, 9, snapshot);
+ List<ReplicatedLogEntry> unAppliedEntry = persistedSnapshots.get(0).getUnAppliedEntries();
+ assertEquals("Persisted Snapshot getUnAppliedEntries size", 1, unAppliedEntry.size());
+ verifyReplicatedLogEntry(unAppliedEntry.get(0), currentTerm, 9, payload9);
+
+ testLog.info("testLeaderSnapshotTriggeredByMemoryThresholdExceeded ending");
+ }
+
+ /**
+ * Send another payload to verify another snapshot is not done since the last snapshot trimmed the
+ * first log entry so the memory threshold should not be exceeded.
+ *
+ * @throws Exception
+ */
+ private void verifyNoSubsequentSnapshotAfterMemoryThresholdExceededSnapshot() throws Exception {
+ ApplyState applyState;
+ CaptureSnapshot captureSnapshot;
+
+ MockPayload payload10 = sendPayloadData(leaderActor, "ten");
+
+ // Verify the leader applies the state.
+ applyState = MessageCollectorActor.expectFirstMatching(leaderCollectorActor, ApplyState.class);
+ verifyApplyState(applyState, leaderCollectorActor, payload10.toString(), currentTerm, 10, payload10);
+
+ captureSnapshot = MessageCollectorActor.getFirstMatching(leaderCollectorActor, CaptureSnapshot.class);
+ Assert.assertNull("Leader received unexpected CaptureSnapshot", captureSnapshot);
+
+ // Verify the follower 1 applies the state.
+ applyState = MessageCollectorActor.expectFirstMatching(follower1CollectorActor, ApplyState.class);
+ verifyApplyState(applyState, null, null, currentTerm, 10, payload10);
+
+ // Verify the follower 2 applies the state.
+ applyState = MessageCollectorActor.expectFirstMatching(follower2CollectorActor, ApplyState.class);
+ verifyApplyState(applyState, null, null, currentTerm, 10, payload10);
+
+ // Verify the leader's state.
+ assertEquals("Leader snapshot term", currentTerm, leaderContext.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Leader snapshot index", 9, leaderContext.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Leader journal log size", 1, leaderContext.getReplicatedLog().size());
+ assertEquals("Leader journal last index", 10, leaderContext.getReplicatedLog().lastIndex());
+ assertEquals("Leader commit index", 10, leaderContext.getCommitIndex());
+ assertEquals("Leader last applied", 10, leaderContext.getLastApplied());
+ assertEquals("Leader replicatedToAllIndex", 9, leader.getReplicatedToAllIndex());
+
+ // Verify follower 1's state.
+ assertEquals("Follower 1 snapshot term", currentTerm, follower1Context.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Follower 1 snapshot index", 9, follower1Context.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Follower 1 journal log size", 1, follower1Context.getReplicatedLog().size());
+ assertEquals("Follower 1 journal last index", 10, follower1Context.getReplicatedLog().lastIndex());
+ assertEquals("Follower 1 commit index", 10, follower1Context.getCommitIndex());
+ assertEquals("Follower 1 last applied", 10, follower1Context.getLastApplied());
+ assertEquals("Follower 1 replicatedToAllIndex", 9, follower1.getReplicatedToAllIndex());
+
+ // Verify follower 2's state.
+ assertEquals("Follower 2 snapshot term", currentTerm, follower2Context.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Follower 2 snapshot index", 9, follower2Context.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Follower 2 journal log size", 1, follower2Context.getReplicatedLog().size());
+ assertEquals("Follower 2 journal last index", 10, follower2Context.getReplicatedLog().lastIndex());
+ assertEquals("Follower 2 commit index", 10, follower2Context.getCommitIndex());
+ assertEquals("Follower 2 last applied", 10, follower2Context.getLastApplied());
+ assertEquals("Follower 2 replicatedToAllIndex", 9, follower2.getReplicatedToAllIndex());
+
+ // Revert back to JVM total memory.
+ leaderActor.underlyingActor().setMockTotalMemory(0);
+
+ MessageCollectorActor.clearMessages(leaderCollectorActor);
+ MessageCollectorActor.clearMessages(follower1CollectorActor);
+ MessageCollectorActor.clearMessages(follower2CollectorActor);
+ }
+
+ /**
+ * Following a snapshot due memory threshold exceeded, resume the lagging follower and verify it receives
+ * an install snapshot from the leader.
+ *
+ * @throws Exception
+ */
+ private void testInstallSnapshotToLaggingFollower() throws Exception {
+ List<Snapshot> persistedSnapshots;
+ List<ReplicatedLogEntry> unAppliedEntry;
+ ApplyState applyState;
+ ApplySnapshot applySnapshot;
+ InstallSnapshot installSnapshot;
+ InstallSnapshotReply installSnapshotReply;
+
+ byte[] snapshot = new byte[] {10};
+ leaderActor.underlyingActor().setSnapshot(snapshot);
+
+ // Now stop dropping AppendEntries in follower 2.
+ follower2Actor.underlyingActor().stopDropMessages(AppendEntries.class);
+
+ installSnapshot = MessageCollectorActor.expectFirstMatching(follower2CollectorActor, InstallSnapshot.class);
+ assertEquals("InstallSnapshot getTerm", currentTerm, installSnapshot.getTerm());
+ assertEquals("InstallSnapshot getLeaderId", leaderId, installSnapshot.getLeaderId());
+ assertEquals("InstallSnapshot getChunkIndex", 1, installSnapshot.getChunkIndex());
+ assertEquals("InstallSnapshot getTotalChunks", 1, installSnapshot.getTotalChunks());
+ assertEquals("InstallSnapshot getLastIncludedTerm", currentTerm, installSnapshot.getLastIncludedTerm());
+ assertEquals("InstallSnapshot getLastIncludedIndex", 8, installSnapshot.getLastIncludedIndex());
+ assertArrayEquals("InstallSnapshot getData", snapshot, installSnapshot.getData().toByteArray());
+
+ installSnapshotReply = MessageCollectorActor.expectFirstMatching(leaderCollectorActor, InstallSnapshotReply.class);
+ assertEquals("InstallSnapshotReply getTerm", currentTerm, installSnapshotReply.getTerm());
+ assertEquals("InstallSnapshotReply getChunkIndex", 1, installSnapshotReply.getChunkIndex());
+ assertEquals("InstallSnapshotReply getFollowerId", follower2Id, installSnapshotReply.getFollowerId());
+ assertEquals("InstallSnapshotReply isSuccess", true, installSnapshotReply.isSuccess());
+
+ // Verify follower 2 applies the snapshot.
+ applySnapshot = MessageCollectorActor.expectFirstMatching(follower2CollectorActor, ApplySnapshot.class);
+ verifySnapshot("Follower 2", applySnapshot.getSnapshot(), currentTerm, 8, currentTerm, 8, snapshot);
+ assertEquals("Persisted Snapshot getUnAppliedEntries size", 0, applySnapshot.getSnapshot().getUnAppliedEntries().size());
+
+ // Verify follower 2 only applies the second log entry (9) as the first one (8) was in the snapshot.
+ applyState = MessageCollectorActor.expectFirstMatching(follower2CollectorActor, ApplyState.class);
+ verifyApplyState(applyState, null, null, currentTerm, 9, payload9);
+
+ // Wait for the snapshot to complete.
+ MessageCollectorActor.expectFirstMatching(leaderCollectorActor, SaveSnapshotSuccess.class);
+
+ // Ensure there's at least 1 more heartbeat.
+ MessageCollectorActor.clearMessages(leaderCollectorActor);
+ MessageCollectorActor.expectFirstMatching(leaderCollectorActor, AppendEntriesReply.class);
+
+ // The leader should now have performed fake snapshots to advance the snapshot index and to trim
+ // the log. In addition replicatedToAllIndex should've advanced.
+ assertEquals("Leader snapshot term", currentTerm, leaderContext.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Leader snapshot index", 8, leaderContext.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Leader journal log size", 1, leaderContext.getReplicatedLog().size());
+ assertEquals("Leader commit index", 9, leaderContext.getCommitIndex());
+ assertEquals("Leader last applied", 9, leaderContext.getLastApplied());
+ assertEquals("Leader replicatedToAllIndex", 8, leader.getReplicatedToAllIndex());
+
+ // Verify the leader's persisted snapshot. The previous snapshot (currently) won't be deleted from
+ // the snapshot store because the second snapshot was initiated by the follower install snapshot and
+ // not because the batch count was reached so the persisted journal sequence number wasn't advanced
+ // far enough to cause the previous snapshot to be deleted. This is because
+ // RaftActor#trimPersistentData subtracts the snapshotBatchCount from the snapshot's sequence number.
+ // This is OK - the next snapshot should delete it. In production, even if the system restarted
+ // before another snapshot, they would both get applied which wouldn't hurt anything.
+ persistedSnapshots = InMemorySnapshotStore.getSnapshots(leaderId, Snapshot.class);
+ Assert.assertTrue("Expected at least 1 persisted snapshots", persistedSnapshots.size() > 0);
+ Snapshot persistedSnapshot = persistedSnapshots.get(persistedSnapshots.size() - 1);
+ verifySnapshot("Persisted", persistedSnapshot, currentTerm, 9, currentTerm, 9, snapshot);
+ unAppliedEntry = persistedSnapshot.getUnAppliedEntries();
+ assertEquals("Persisted Snapshot getUnAppliedEntries size", 0, unAppliedEntry.size());
+
+ MessageCollectorActor.clearMessages(leaderCollectorActor);
+ MessageCollectorActor.clearMessages(follower1CollectorActor);
+ MessageCollectorActor.clearMessages(follower2CollectorActor);
+ }
+
+ /**
+ * Do another round of payloads and snapshot to verify replicatedToAllIndex gets back on track and
+ * snapshots works as expected after doing a follower snapshot. In this step we don't lag a follower.
+ */
+ private void testFinalReplicationsAndSnapshot() {
+ List<ApplyState> applyStates;
+ ApplyState applyState;
+
+ testLog.info("testFinalReplicationsAndSnapshot starting: replicatedToAllIndex: {}", leader.getReplicatedToAllIndex());
+
+ byte[] snapshot = new byte[] {14};
+ leaderActor.underlyingActor().setSnapshot(snapshot);
+
+ // Send another payload - a snapshot should occur.
+ payload11 = sendPayloadData(leaderActor, "eleven");
+
+ // Wait for the snapshot to complete.
+ MessageCollectorActor.expectFirstMatching(leaderCollectorActor, SaveSnapshotSuccess.class);
+
+ applyState = MessageCollectorActor.expectFirstMatching(leaderCollectorActor, ApplyState.class);
+ verifyApplyState(applyState, leaderCollectorActor, payload11.toString(), currentTerm, 11, payload11);
+
+ // Verify the leader's last persisted snapshot (previous ones may not be purged yet).
+ List<Snapshot> persistedSnapshots = InMemorySnapshotStore.getSnapshots(leaderId, Snapshot.class);
+ Snapshot persistedSnapshot = persistedSnapshots.get(persistedSnapshots.size() - 1);
+ verifySnapshot("Persisted", persistedSnapshot, currentTerm, 10, currentTerm, 11, snapshot);
+ List<ReplicatedLogEntry> unAppliedEntry = persistedSnapshot.getUnAppliedEntries();
+ assertEquals("Persisted Snapshot getUnAppliedEntries size", 1, unAppliedEntry.size());
+ verifyReplicatedLogEntry(unAppliedEntry.get(0), currentTerm, 11, payload11);
+
+ // Send a couple more payloads.
+ payload12 = sendPayloadData(leaderActor, "twelve");
+ payload13 = sendPayloadData(leaderActor, "thirteen");
+
+ // Verify the leader applies the 2 log entries.
+ applyStates = MessageCollectorActor.expectMatching(leaderCollectorActor, ApplyState.class, 3);
+ verifyApplyState(applyStates.get(1), leaderCollectorActor, payload12.toString(), currentTerm, 12, payload12);
+ verifyApplyState(applyStates.get(2), leaderCollectorActor, payload13.toString(), currentTerm, 13, payload13);
+
+ // Verify the leader applies a log entry for at least the last entry index.
+ verifyApplyJournalEntries(leaderCollectorActor, 13);
+
+ // Ensure there's at least 1 more heartbeat to trim the log.
+ MessageCollectorActor.clearMessages(leaderCollectorActor);
+ MessageCollectorActor.expectFirstMatching(leaderCollectorActor, AppendEntriesReply.class);
+
+ // Verify the leader's final snapshot index et al.
+ assertEquals("Leader snapshot term", currentTerm, leaderContext.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Leader snapshot index", 12, leaderContext.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Leader journal log size", 1, leaderContext.getReplicatedLog().size());
+ assertEquals("Leader journal last index", 13, leaderContext.getReplicatedLog().lastIndex());
+ assertEquals("Leader commit index", 13, leaderContext.getCommitIndex());
+ assertEquals("Leader last applied", 13, leaderContext.getLastApplied());
+ assertEquals("Leader replicatedToAllIndex", 12, leader.getReplicatedToAllIndex());
+
+ InMemoryJournal.dumpJournal(leaderId);
+
+ // Verify the leaders's persisted journal log - should only contain the last 2 ReplicatedLogEntries
+ // added after the snapshot as the persisted journal should've been purged to the snapshot
+ // sequence number.
+ verifyPersistedJournal(leaderId, Arrays.asList(new ReplicatedLogImplEntry(12, currentTerm, payload12),
+ new ReplicatedLogImplEntry(13, currentTerm, payload13)));
+
+ // Verify the leaders's persisted journal contains an ApplyJournalEntries for at least the last entry index.
+ List<ApplyJournalEntries> persistedApplyJournalEntries = InMemoryJournal.get(leaderId, ApplyJournalEntries.class);
+ boolean found = false;
+ for(ApplyJournalEntries entry: persistedApplyJournalEntries) {
+ if(entry.getToIndex() == 13) {
+ found = true;
+ break;
+ }
+ }
+
+ Assert.assertTrue(String.format("ApplyJournalEntries with index %d not found in leader's persisted journal", 13), found);
+
+ // Verify follower 1 applies the 2 log entries.
+ applyStates = MessageCollectorActor.expectMatching(follower1CollectorActor, ApplyState.class, 3);
+ verifyApplyState(applyStates.get(0), null, null, currentTerm, 11, payload11);
+ verifyApplyState(applyStates.get(1), null, null, currentTerm, 12, payload12);
+ verifyApplyState(applyStates.get(2), null, null, currentTerm, 13, payload13);
+
+ // Verify follower 1's log state.
+ assertEquals("Follower 1 snapshot term", currentTerm, follower1Context.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Follower 1 snapshot index", 12, follower1Context.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Follower 1 journal log size", 1, follower1Context.getReplicatedLog().size());
+ assertEquals("Follower 1 journal last index", 13, follower1Context.getReplicatedLog().lastIndex());
+ assertEquals("Follower 1 commit index", 13, follower1Context.getCommitIndex());
+ assertEquals("Follower 1 last applied", 13, follower1Context.getLastApplied());
+ assertEquals("Follower 1 replicatedToAllIndex", 12, follower1.getReplicatedToAllIndex());
+
+ // Verify follower 2 applies the 2 log entries.
+ applyStates = MessageCollectorActor.expectMatching(follower2CollectorActor, ApplyState.class, 3);
+ verifyApplyState(applyStates.get(0), null, null, currentTerm, 11, payload11);
+ verifyApplyState(applyStates.get(1), null, null, currentTerm, 12, payload12);
+ verifyApplyState(applyStates.get(2), null, null, currentTerm, 13, payload13);
+
+ // Verify follower 2's log state.
+ assertEquals("Follower 2 snapshot term", currentTerm, follower2Context.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Follower 2 snapshot index", 12, follower2Context.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Follower 2 journal log size", 1, follower2Context.getReplicatedLog().size());
+ assertEquals("Follower 2 journal last index", 13, follower2Context.getReplicatedLog().lastIndex());
+ assertEquals("Follower 2 commit index", 13, follower2Context.getCommitIndex());
+ assertEquals("Follower 2 last applied", 13, follower2Context.getLastApplied());
+ assertEquals("Follower 2 replicatedToAllIndex", 12, follower2.getReplicatedToAllIndex());
+
+ testLog.info("testFinalReplicationsAndSnapshot ending");
+ }
+
+ /**
+ * Kill the leader actor, reinstate it and verify the recovered journal.
+ */
+ private void testLeaderReinstatement() {
+ testLog.info("testLeaderReinstatement starting");
+
+ killActor(leaderActor);
+
+ leaderActor = newTestRaftActor(leaderId, peerAddresses, leaderConfigParams);
+
+ leaderActor.underlyingActor().startDropMessages(RequestVoteReply.class);
+
+ leaderContext = leaderActor.underlyingActor().getRaftActorContext();
+
+ leaderActor.underlyingActor().waitForRecoveryComplete();
+
+ assertEquals("Leader snapshot term", currentTerm, leaderContext.getReplicatedLog().getSnapshotTerm());
+ assertEquals("Leader snapshot index", 10, leaderContext.getReplicatedLog().getSnapshotIndex());
+ assertEquals("Leader journal log size", 3, leaderContext.getReplicatedLog().size());
+ assertEquals("Leader journal last index", 13, leaderContext.getReplicatedLog().lastIndex());
+ assertEquals("Leader commit index", 13, leaderContext.getCommitIndex());
+ assertEquals("Leader last applied", 13, leaderContext.getLastApplied());
+ verifyReplicatedLogEntry(leaderContext.getReplicatedLog().get(11), currentTerm, 11, payload11);
+ verifyReplicatedLogEntry(leaderContext.getReplicatedLog().get(12), currentTerm, 12, payload12);
+ verifyReplicatedLogEntry(leaderContext.getReplicatedLog().get(13), currentTerm, 13, payload13);
+
+ testLog.info("testLeaderReinstatement ending");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Brocade Communications 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.cluster.raft.behaviors;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import akka.dispatch.Dispatchers;
+import akka.testkit.JavaTestKit;
+import akka.testkit.TestActorRef;
+import com.google.common.util.concurrent.Uninterruptibles;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import org.junit.After;
+import org.junit.Before;
+import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
+import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
+import org.opendaylight.controller.cluster.raft.RaftActorContext;
+import org.opendaylight.controller.cluster.raft.RaftState;
+import org.opendaylight.controller.cluster.raft.base.messages.SendHeartBeat;
+import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
+import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import scala.concurrent.duration.FiniteDuration;
+
+/**
+ * Abstract base for a leader election scenario test.
+ *
+ * @author Thomas Pantelis
+ */
+public class AbstractLeaderElectionScenarioTest {
+ static final int HEARTBEAT_INTERVAL = 50;
+
+ static class MemberActor extends MessageCollectorActor {
+
+ volatile RaftActorBehavior behavior;
+ Map<Class<?>, CountDownLatch> messagesReceivedLatches = new ConcurrentHashMap<>();
+ Map<Class<?>, Boolean> dropMessagesToBehavior = new ConcurrentHashMap<>();
+ CountDownLatch behaviorStateChangeLatch;
+
+ public static Props props() {
+ return Props.create(MemberActor.class).withDispatcher(Dispatchers.DefaultDispatcherId());
+ }
+
+ @Override
+ public void onReceive(Object message) throws Exception {
+ // Ignore scheduled SendHeartBeat messages.
+ if(message instanceof SendHeartBeat) {
+ return;
+ }
+
+ try {
+ if(behavior != null && !dropMessagesToBehavior.containsKey(message.getClass())) {
+ RaftActorBehavior oldBehavior = behavior;
+ behavior = behavior.handleMessage(getSender(), message);
+ if(behavior != oldBehavior && behaviorStateChangeLatch != null) {
+ behaviorStateChangeLatch.countDown();
+ }
+ }
+ } finally {
+ super.onReceive(message);
+
+ CountDownLatch latch = messagesReceivedLatches.get(message.getClass());
+ if(latch != null) {
+ latch.countDown();
+ }
+ }
+ }
+
+ void expectBehaviorStateChange() {
+ behaviorStateChangeLatch = new CountDownLatch(1);
+ }
+
+ void waitForBehaviorStateChange() {
+ assertTrue("Expected behavior state change",
+ Uninterruptibles.awaitUninterruptibly(behaviorStateChangeLatch, 5, TimeUnit.SECONDS));
+ }
+
+ void expectMessageClass(Class<?> expClass, int expCount) {
+ messagesReceivedLatches.put(expClass, new CountDownLatch(expCount));
+ }
+
+ void waitForExpectedMessages(Class<?> expClass) {
+ CountDownLatch latch = messagesReceivedLatches.get(expClass);
+ assertNotNull("No messages received for " + expClass, latch);
+ assertTrue("Missing messages of type " + expClass,
+ Uninterruptibles.awaitUninterruptibly(latch, 5, TimeUnit.SECONDS));
+ }
+
+ void dropMessagesToBehavior(Class<?> msgClass) {
+ dropMessagesToBehavior(msgClass, 1);
+ }
+
+ void dropMessagesToBehavior(Class<?> msgClass, int expCount) {
+ expectMessageClass(msgClass, expCount);
+ dropMessagesToBehavior.put(msgClass, Boolean.TRUE);
+ }
+
+ void clearDropMessagesToBehavior() {
+ dropMessagesToBehavior.clear();
+ }
+
+ @Override
+ public void clear() {
+ behaviorStateChangeLatch = null;
+ clearDropMessagesToBehavior();
+ messagesReceivedLatches.clear();
+ super.clear();
+ }
+
+ void forwardCapturedMessageToBehavior(Class<?> msgClass, ActorRef sender) throws Exception {
+ Object message = getFirstMatching(getSelf(), msgClass);
+ assertNotNull("Message of type " + msgClass + " not received", message);
+ getSelf().tell(message, sender);
+ }
+
+ void forwardCapturedMessagesToBehavior(Class<?> msgClass, ActorRef sender) throws Exception {
+ for(Object m: getAllMatching(getSelf(), msgClass)) {
+ getSelf().tell(m, sender);
+ }
+ }
+
+ <T> T getCapturedMessage(Class<T> msgClass) throws Exception {
+ Object message = getFirstMatching(getSelf(), msgClass);
+ assertNotNull("Message of type " + msgClass + " not received", message);
+ return (T) message;
+ }
+ }
+
+ protected final Logger testLog = LoggerFactory.getLogger(MockRaftActorContext.class);
+ protected final ActorSystem system = ActorSystem.create("test");
+ protected TestActorRef<MemberActor> member1ActorRef;
+ protected TestActorRef<MemberActor> member2ActorRef;
+ protected TestActorRef<MemberActor> member3ActorRef;
+ protected MemberActor member1Actor;
+ protected MemberActor member2Actor;
+ protected MemberActor member3Actor;
+ protected MockRaftActorContext member1Context;
+ protected MockRaftActorContext member2Context;
+ protected MockRaftActorContext member3Context;
+
+ @Before
+ public void setup() throws Exception {
+ member1ActorRef = newMemberActor("member1");
+ member2ActorRef = newMemberActor("member2");
+ member3ActorRef = newMemberActor("member3");
+
+ member1Actor = member1ActorRef.underlyingActor();
+ member2Actor = member2ActorRef.underlyingActor();
+ member3Actor = member3ActorRef.underlyingActor();
+ }
+
+ @After
+ public void tearDown() {
+ JavaTestKit.shutdownActorSystem(system);
+ }
+
+ DefaultConfigParamsImpl newConfigParams() {
+ DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
+ configParams.setHeartBeatInterval(new FiniteDuration(HEARTBEAT_INTERVAL, TimeUnit.MILLISECONDS));
+ configParams.setElectionTimeoutFactor(100000);
+ configParams.setIsolatedLeaderCheckInterval(new FiniteDuration(1, TimeUnit.DAYS));
+ return configParams;
+ }
+
+ MockRaftActorContext newRaftActorContext(String id, ActorRef actor,
+ Map<String, String> peerAddresses) {
+ MockRaftActorContext context = new MockRaftActorContext(id, system, actor);
+ context.setPeerAddresses(peerAddresses);
+ context.getTermInformation().updateAndPersist(1, "");
+ return context;
+ }
+
+ void verifyBehaviorState(String name, MemberActor actor, RaftState expState) {
+ assertEquals(name + " behavior state", expState, actor.behavior.state());
+ }
+
+ void initializeLeaderBehavior(MemberActor actor, RaftActorContext context,
+ int numActiveFollowers) throws Exception {
+ // Leader sends immediate heartbeats - we don't care about it so ignore it.
+
+ actor.expectMessageClass(AppendEntriesReply.class, numActiveFollowers);
+ Leader leader = new Leader(context);
+ actor.waitForExpectedMessages(AppendEntriesReply.class);
+ actor.behavior = leader;
+
+ actor.forwardCapturedMessagesToBehavior(AppendEntriesReply.class, ActorRef.noSender());
+ actor.clear();
+ }
+
+ TestActorRef<MemberActor> newMemberActor(String name) throws Exception {
+ TestActorRef<MemberActor> actor = TestActorRef.create(system, MemberActor.props(), name);
+ MessageCollectorActor.waitUntilReady(actor);
+ return actor;
+ }
+
+ void sendHeartbeat(TestActorRef<MemberActor> leaderActor) {
+ Uninterruptibles.sleepUninterruptibly(HEARTBEAT_INTERVAL, TimeUnit.MILLISECONDS);
+ leaderActor.underlyingActor().behavior.handleMessage(leaderActor, new SendHeartBeat());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Brocade Communications 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.cluster.raft.behaviors;
+
+import static org.junit.Assert.assertEquals;
+import akka.actor.ActorRef;
+import com.google.common.collect.ImmutableMap;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
+import org.opendaylight.controller.cluster.raft.RaftState;
+import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout;
+import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
+import org.opendaylight.controller.cluster.raft.messages.RequestVote;
+import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
+
+/**
+ * A leader election scenario test that delays various messages to behaviors to simulate network delays.
+ *
+ * @author Thomas Pantelis
+ */
+public class DelayedMessagesElectionScenarioTest extends AbstractLeaderElectionScenarioTest {
+
+ @Test
+ public void runTest() throws Exception {
+ testLog.info("DelayedMessagesElectionScenarioTest starting");
+
+ setupInitialMemberBehaviors();
+
+ sendInitialElectionTimeoutToFollowerMember2();
+
+ forwardDelayedRequestVotesToLeaderMember1AndFollowerMember3();
+
+ sendElectionTimeoutToFollowerMember3();
+
+ forwardDelayedRequestVoteReplyFromOriginalFollowerMember3ToMember2();
+
+ testLog.info("DelayedMessagesElectionScenarioTest ending");
+ }
+
+ private void forwardDelayedRequestVoteReplyFromOriginalFollowerMember3ToMember2() throws Exception {
+ testLog.info("forwardDelayedRequestVoteReplyFromOriginalFollowerMember3ToMember2 starting");
+
+ // Now forward the original delayed RequestVoteReply from member 3 to member 2 that granted
+ // the vote. Since member 2 is now a Follower, the RequestVoteReply should be ignored.
+
+ member2Actor.clearDropMessagesToBehavior();
+ member2Actor.forwardCapturedMessageToBehavior(RequestVoteReply.class, member3ActorRef);
+
+ member2Actor.waitForExpectedMessages(RequestVoteReply.class);
+
+ verifyBehaviorState("member 1", member1Actor, RaftState.Follower);
+ verifyBehaviorState("member 2", member2Actor, RaftState.Follower);
+ verifyBehaviorState("member 3", member3Actor, RaftState.Leader);
+
+ assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 3 election term", 3, member3Context.getTermInformation().getCurrentTerm());
+
+ testLog.info("forwardDelayedRequestVoteReplyFromOriginalFollowerMember3ToMember2 ending");
+ }
+
+ private void sendElectionTimeoutToFollowerMember3() throws Exception {
+ testLog.info("sendElectionTimeoutToFollowerMember3 starting");
+
+ // Send ElectionTimeout to member 3 to simulate missing heartbeat from a Leader. member 3
+ // should switch to Candidate and send out RequestVote messages. member 1 should grant the
+ // vote and send a reply. After receiving the RequestVoteReply, member 3 should switch to leader.
+
+ member2Actor.expectBehaviorStateChange();
+ member3Actor.clear();
+ member3Actor.expectMessageClass(RequestVoteReply.class, 1);
+ member3Actor.expectMessageClass(AppendEntriesReply.class, 2);
+
+ member3ActorRef.tell(new ElectionTimeout(), ActorRef.noSender());
+
+ member3Actor.waitForExpectedMessages(RequestVoteReply.class);
+
+ RequestVoteReply requestVoteReply = member3Actor.getCapturedMessage(RequestVoteReply.class);
+ assertEquals("getTerm", member3Context.getTermInformation().getCurrentTerm(), requestVoteReply.getTerm());
+ assertEquals("isVoteGranted", true, requestVoteReply.isVoteGranted());
+
+ verifyBehaviorState("member 3", member3Actor, RaftState.Leader);
+
+ // member 2 should've switched to Follower as member 3's RequestVote term (3) was greater
+ // than member 2's term (2).
+
+ member2Actor.waitForBehaviorStateChange();
+ verifyBehaviorState("member 2", member2Actor, RaftState.Follower);
+
+ // The switch to leader should cause an immediate AppendEntries heartbeat from member 3.
+
+ member3Actor.waitForExpectedMessages(AppendEntriesReply.class);
+
+ assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 3 election term", 3, member3Context.getTermInformation().getCurrentTerm());
+
+ testLog.info("sendElectionTimeoutToFollowerMember3 ending");
+ }
+
+ private void forwardDelayedRequestVotesToLeaderMember1AndFollowerMember3() throws Exception {
+ testLog.info("forwardDelayedRequestVotesToLeaderMember1AndFollowerMember3 starting");
+
+ // At this point member 1 and 3 actors have captured the RequestVote messages. First
+ // forward the RequestVote message to member 1's behavior. Since the RequestVote term
+ // is greater than member 1's term and member 1 is a Leader, member 1 should switch to Follower
+ // without replying to RequestVote and update its term to 2.
+
+ member1Actor.clearDropMessagesToBehavior();
+ member1Actor.expectBehaviorStateChange();
+ member1Actor.forwardCapturedMessageToBehavior(RequestVote.class, member2ActorRef);
+ member1Actor.waitForExpectedMessages(RequestVote.class);
+
+ member1Actor.waitForBehaviorStateChange();
+ verifyBehaviorState("member 1", member1Actor, RaftState.Follower);
+
+ // Now forward member 3's captured RequestVote message to its behavior. Since member 3 is
+ // already a Follower, it should update its term to 2 and send a RequestVoteReply back to
+ // member 2 granting the vote b/c the RequestVote's term, lastLogTerm, and lastLogIndex
+ // should satisfy the criteria for granting the vote. However, we'll delay sending the
+ // RequestVoteReply to member 2's behavior to simulate network latency.
+
+ member2Actor.dropMessagesToBehavior(RequestVoteReply.class);
+
+ member3Actor.clearDropMessagesToBehavior();
+ member3Actor.expectMessageClass(RequestVote.class, 1);
+ member3Actor.forwardCapturedMessageToBehavior(RequestVote.class, member2ActorRef);
+ member3Actor.waitForExpectedMessages(RequestVote.class);
+ verifyBehaviorState("member 3", member3Actor, RaftState.Follower);
+
+ assertEquals("member 1 election term", 2, member1Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 2 election term", 2, member2Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 3 election term", 2, member3Context.getTermInformation().getCurrentTerm());
+
+ testLog.info("forwardDelayedRequestVotesToLeaderMember1AndFollowerMember3 ending");
+ }
+
+ private void sendInitialElectionTimeoutToFollowerMember2() {
+ testLog.info("sendInitialElectionTimeoutToFollowerMember2 starting");
+
+ // Send ElectionTimeout to member 2 to simulate missing heartbeat from the Leader. member 2
+ // should switch to Candidate and send out RequestVote messages. Set member 1 and 3 actors
+ // to capture RequestVote but not to forward to the behavior just yet as we want to
+ // control the order of RequestVote messages to member 1 and 3.
+
+ member1Actor.dropMessagesToBehavior(RequestVote.class);
+
+ member2Actor.expectBehaviorStateChange();
+
+ member3Actor.dropMessagesToBehavior(RequestVote.class);
+
+ member2ActorRef.tell(new ElectionTimeout(), ActorRef.noSender());
+
+ member1Actor.waitForExpectedMessages(RequestVote.class);
+ member3Actor.waitForExpectedMessages(RequestVote.class);
+
+ member2Actor.waitForBehaviorStateChange();
+ verifyBehaviorState("member 2", member2Actor, RaftState.Candidate);
+
+ assertEquals("member 1 election term", 1, member1Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 2 election term", 2, member2Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 3 election term", 1, member3Context.getTermInformation().getCurrentTerm());
+
+ testLog.info("sendInitialElectionTimeoutToFollowerMember2 ending");
+ }
+
+ private void setupInitialMemberBehaviors() throws Exception {
+ testLog.info("setupInitialMemberBehaviors starting");
+
+ // Create member 2's behavior initially as Follower
+
+ member2Context = newRaftActorContext("member2", member2ActorRef,
+ ImmutableMap.<String,String>builder().
+ put("member1", member1ActorRef.path().toString()).
+ put("member3", member3ActorRef.path().toString()).build());
+
+ DefaultConfigParamsImpl member2ConfigParams = newConfigParams();
+ member2Context.setConfigParams(member2ConfigParams);
+
+ Follower member2Behavior = new Follower(member2Context);
+ member2Actor.behavior = member2Behavior;
+
+ // Create member 3's behavior initially as Follower
+
+ member3Context = newRaftActorContext("member3", member3ActorRef,
+ ImmutableMap.<String,String>builder().
+ put("member1", member1ActorRef.path().toString()).
+ put("member2", member2ActorRef.path().toString()).build());
+
+ DefaultConfigParamsImpl member3ConfigParams = newConfigParams();
+ member3Context.setConfigParams(member3ConfigParams);
+
+ Follower member3Behavior = new Follower(member3Context);
+ member3Actor.behavior = member3Behavior;
+
+ // Create member 1's behavior initially as Leader
+
+ member1Context = newRaftActorContext("member1", member1ActorRef,
+ ImmutableMap.<String,String>builder().
+ put("member2", member2ActorRef.path().toString()).
+ put("member3", member3ActorRef.path().toString()).build());
+
+ DefaultConfigParamsImpl member1ConfigParams = newConfigParams();
+ member1Context.setConfigParams(member1ConfigParams);
+
+ initializeLeaderBehavior(member1Actor, member1Context, 2);
+
+ member2Actor.clear();
+ member3Actor.clear();
+
+ testLog.info("setupInitialMemberBehaviors ending");
+ }
+}
+++ /dev/null
-/*
- * Copyright (c) 2015 Brocade Communications 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.cluster.raft.behaviors;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.actor.Props;
-import akka.dispatch.Dispatchers;
-import akka.testkit.JavaTestKit;
-import akka.testkit.TestActorRef;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.util.concurrent.Uninterruptibles;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import org.junit.After;
-import org.junit.Test;
-import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
-import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
-import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload;
-import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockReplicatedLogEntry;
-import org.opendaylight.controller.cluster.raft.MockRaftActorContext.SimpleReplicatedLog;
-import org.opendaylight.controller.cluster.raft.RaftActorContext;
-import org.opendaylight.controller.cluster.raft.RaftState;
-import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout;
-import org.opendaylight.controller.cluster.raft.base.messages.SendHeartBeat;
-import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
-import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
-import org.opendaylight.controller.cluster.raft.messages.RequestVote;
-import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
-import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.slf4j.impl.SimpleLogger;
-import scala.concurrent.duration.FiniteDuration;
-
-/**
- * Tests various leader election scenarios.
- *
- * @author Thomas Pantelis
- */
-public class LeaderElectionScenariosTest {
-
- private static final int HEARTBEAT_INTERVAL = 50;
-
- public static class MemberActor extends MessageCollectorActor {
-
- volatile RaftActorBehavior behavior;
- Map<Class<?>, CountDownLatch> messagesReceivedLatches = new ConcurrentHashMap<>();
- Map<Class<?>, Boolean> dropMessagesToBehavior = new ConcurrentHashMap<>();
- CountDownLatch behaviorStateChangeLatch;
-
- public static Props props() {
- return Props.create(MemberActor.class).withDispatcher(Dispatchers.DefaultDispatcherId());
- }
-
- @Override
- public void onReceive(Object message) throws Exception {
- // Ignore scheduled SendHeartBeat messages.
- if(message instanceof SendHeartBeat) {
- return;
- }
-
- try {
- if(behavior != null && !dropMessagesToBehavior.containsKey(message.getClass())) {
- RaftActorBehavior oldBehavior = behavior;
- behavior = behavior.handleMessage(getSender(), message);
- if(behavior != oldBehavior && behaviorStateChangeLatch != null) {
- behaviorStateChangeLatch.countDown();
- }
- }
- } finally {
- super.onReceive(message);
-
- CountDownLatch latch = messagesReceivedLatches.get(message.getClass());
- if(latch != null) {
- latch.countDown();
- }
- }
- }
-
- void expectBehaviorStateChange() {
- behaviorStateChangeLatch = new CountDownLatch(1);
- }
-
- void waitForBehaviorStateChange() {
- assertTrue("Expected behavior state change",
- Uninterruptibles.awaitUninterruptibly(behaviorStateChangeLatch, 5, TimeUnit.SECONDS));
- }
-
- void expectMessageClass(Class<?> expClass, int expCount) {
- messagesReceivedLatches.put(expClass, new CountDownLatch(expCount));
- }
-
- void waitForExpectedMessages(Class<?> expClass) {
- CountDownLatch latch = messagesReceivedLatches.get(expClass);
- assertNotNull("No messages received for " + expClass, latch);
- assertTrue("Missing messages of type " + expClass,
- Uninterruptibles.awaitUninterruptibly(latch, 5, TimeUnit.SECONDS));
- }
-
- void dropMessagesToBehavior(Class<?> msgClass) {
- dropMessagesToBehavior(msgClass, 1);
- }
-
- void dropMessagesToBehavior(Class<?> msgClass, int expCount) {
- expectMessageClass(msgClass, expCount);
- dropMessagesToBehavior.put(msgClass, Boolean.TRUE);
- }
-
- void clearDropMessagesToBehavior() {
- dropMessagesToBehavior.clear();
- }
-
- @Override
- public void clear() {
- behaviorStateChangeLatch = null;
- clearDropMessagesToBehavior();
- messagesReceivedLatches.clear();
- super.clear();
- }
-
- void forwardCapturedMessageToBehavior(Class<?> msgClass, ActorRef sender) throws Exception {
- Object message = getFirstMatching(getSelf(), msgClass);
- assertNotNull("Message of type " + msgClass + " not received", message);
- getSelf().tell(message, sender);
- }
-
- void forwardCapturedMessagesToBehavior(Class<?> msgClass, ActorRef sender) throws Exception {
- for(Object m: getAllMatching(getSelf(), msgClass)) {
- getSelf().tell(m, sender);
- }
- }
-
- <T> T getCapturedMessage(Class<T> msgClass) throws Exception {
- Object message = getFirstMatching(getSelf(), msgClass);
- assertNotNull("Message of type " + msgClass + " not received", message);
- return (T) message;
- }
- }
-
- static {
- System.setProperty(SimpleLogger.LOG_KEY_PREFIX + MockRaftActorContext.class.getName(), "trace");
- }
-
- private final Logger testLog = LoggerFactory.getLogger(MockRaftActorContext.class);
- private final ActorSystem system = ActorSystem.create("test");
-
- @After
- public void tearDown() {
- JavaTestKit.shutdownActorSystem(system);
- }
-
- private DefaultConfigParamsImpl newConfigParams() {
- DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
- configParams.setHeartBeatInterval(new FiniteDuration(HEARTBEAT_INTERVAL, TimeUnit.MILLISECONDS));
- configParams.setElectionTimeoutFactor(100000);
- configParams.setIsolatedLeaderCheckInterval(new FiniteDuration(1, TimeUnit.DAYS));
- return configParams;
- }
-
- private MockRaftActorContext newRaftActorContext(String id, ActorRef actor,
- Map<String, String> peerAddresses) {
- MockRaftActorContext context = new MockRaftActorContext(id, system, actor);
- context.setPeerAddresses(peerAddresses);
- context.getTermInformation().updateAndPersist(1, "");
- return context;
- }
-
- private void verifyBehaviorState(String name, TestActorRef<MemberActor> actor, RaftState expState) {
- assertEquals(name + " behavior state", expState, actor.underlyingActor().behavior.state());
- }
-
- private void initializeLeaderBehavior(TestActorRef<MemberActor> actor, RaftActorContext context,
- int numActiveFollowers) throws Exception {
- // Leader sends immediate heartbeats - we don't care about it so ignore it.
-
- actor.underlyingActor().expectMessageClass(AppendEntriesReply.class, numActiveFollowers);
- Leader leader = new Leader(context);
- actor.underlyingActor().waitForExpectedMessages(AppendEntriesReply.class);
- actor.underlyingActor().behavior = leader;
-
- actor.underlyingActor().forwardCapturedMessagesToBehavior(AppendEntriesReply.class, ActorRef.noSender());
- actor.underlyingActor().clear();
- }
-
- private TestActorRef<MemberActor> newMemberActor(String name) throws Exception {
- TestActorRef<MemberActor> actor = TestActorRef.create(system, MemberActor.props(), name);
- MessageCollectorActor.waitUntilReady(actor);
- return actor;
- }
-
- private void sendHeartbeat(TestActorRef<MemberActor> leaderActor) {
- Uninterruptibles.sleepUninterruptibly(HEARTBEAT_INTERVAL, TimeUnit.MILLISECONDS);
- leaderActor.underlyingActor().behavior.handleMessage(leaderActor, new SendHeartBeat());
- }
-
- @Test
- public void testDelayedMessagesScenario() throws Exception {
- testLog.info("Starting testDelayedMessagesScenario");
-
- TestActorRef<MemberActor> member1Actor = newMemberActor("member1");
- TestActorRef<MemberActor> member2Actor = newMemberActor("member2");
- TestActorRef<MemberActor> member3Actor = newMemberActor("member3");
-
- // Create member 2's behavior initially as Follower
-
- MockRaftActorContext member2Context = newRaftActorContext("member2", member2Actor,
- ImmutableMap.<String,String>builder().
- put("member1", member1Actor.path().toString()).
- put("member3", member3Actor.path().toString()).build());
-
- DefaultConfigParamsImpl member2ConfigParams = newConfigParams();
- member2Context.setConfigParams(member2ConfigParams);
-
- Follower member2Behavior = new Follower(member2Context);
- member2Actor.underlyingActor().behavior = member2Behavior;
-
- // Create member 3's behavior initially as Follower
-
- MockRaftActorContext member3Context = newRaftActorContext("member3", member3Actor,
- ImmutableMap.<String,String>builder().
- put("member1", member1Actor.path().toString()).
- put("member2", member2Actor.path().toString()).build());
-
- DefaultConfigParamsImpl member3ConfigParams = newConfigParams();
- member3Context.setConfigParams(member3ConfigParams);
-
- Follower member3Behavior = new Follower(member3Context);
- member3Actor.underlyingActor().behavior = member3Behavior;
-
- // Create member 1's behavior initially as Leader
-
- MockRaftActorContext member1Context = newRaftActorContext("member1", member1Actor,
- ImmutableMap.<String,String>builder().
- put("member2", member2Actor.path().toString()).
- put("member3", member3Actor.path().toString()).build());
-
- DefaultConfigParamsImpl member1ConfigParams = newConfigParams();
- member1Context.setConfigParams(member1ConfigParams);
-
- initializeLeaderBehavior(member1Actor, member1Context, 2);
-
- member2Actor.underlyingActor().clear();
- member3Actor.underlyingActor().clear();
-
- // Send ElectionTimeout to member 2 to simulate missing heartbeat from the Leader. member 2
- // should switch to Candidate and send out RequestVote messages. Set member 1 and 3 actors
- // to capture RequestVote but not to forward to the behavior just yet as we want to
- // control the order of RequestVote messages to member 1 and 3.
-
- member1Actor.underlyingActor().dropMessagesToBehavior(RequestVote.class);
-
- member2Actor.underlyingActor().expectBehaviorStateChange();
-
- member3Actor.underlyingActor().dropMessagesToBehavior(RequestVote.class);
-
- member2Actor.tell(new ElectionTimeout(), ActorRef.noSender());
-
- member1Actor.underlyingActor().waitForExpectedMessages(RequestVote.class);
- member3Actor.underlyingActor().waitForExpectedMessages(RequestVote.class);
-
- member2Actor.underlyingActor().waitForBehaviorStateChange();
- verifyBehaviorState("member 2", member2Actor, RaftState.Candidate);
-
- assertEquals("member 1 election term", 1, member1Context.getTermInformation().getCurrentTerm());
- assertEquals("member 2 election term", 2, member2Context.getTermInformation().getCurrentTerm());
- assertEquals("member 3 election term", 1, member3Context.getTermInformation().getCurrentTerm());
-
- // At this point member 1 and 3 actors have captured the RequestVote messages. First
- // forward the RequestVote message to member 1's behavior. Since the RequestVote term
- // is greater than member 1's term, member 1 should switch to Follower without replying
- // to RequestVote and update its term to 2.
-
- member1Actor.underlyingActor().clearDropMessagesToBehavior();
- member1Actor.underlyingActor().expectBehaviorStateChange();
- member1Actor.underlyingActor().forwardCapturedMessageToBehavior(RequestVote.class, member2Actor);
- member1Actor.underlyingActor().waitForExpectedMessages(RequestVote.class);
-
- member1Actor.underlyingActor().waitForBehaviorStateChange();
- verifyBehaviorState("member 1", member1Actor, RaftState.Follower);
-
- // Now forward member 3's captured RequestVote message to its behavior. Since member 3 is
- // already a Follower, it should update its term to 2 and send a RequestVoteReply back to
- // member 2 granting the vote b/c the RequestVote's term, lastLogTerm, and lastLogIndex
- // should satisfy the criteria for granting the vote. However, we'll delay sending the
- // RequestVoteReply to member 2's behavior to simulate network latency.
-
- member2Actor.underlyingActor().dropMessagesToBehavior(RequestVoteReply.class);
-
- member3Actor.underlyingActor().clearDropMessagesToBehavior();
- member3Actor.underlyingActor().expectMessageClass(RequestVote.class, 1);
- member3Actor.underlyingActor().forwardCapturedMessageToBehavior(RequestVote.class, member2Actor);
- member3Actor.underlyingActor().waitForExpectedMessages(RequestVote.class);
- verifyBehaviorState("member 3", member3Actor, RaftState.Follower);
-
- assertEquals("member 1 election term", 2, member1Context.getTermInformation().getCurrentTerm());
- assertEquals("member 2 election term", 2, member2Context.getTermInformation().getCurrentTerm());
- assertEquals("member 3 election term", 2, member3Context.getTermInformation().getCurrentTerm());
-
- // Send ElectionTimeout to member 3 to simulate missing heartbeat from a Leader. member 3
- // should switch to Candidate and send out RequestVote messages. member 1 should grant the
- // vote and send a reply. After receiving the RequestVoteReply, member 3 should switch to leader.
-
- member2Actor.underlyingActor().expectBehaviorStateChange();
- member3Actor.underlyingActor().clear();
- member3Actor.underlyingActor().expectMessageClass(RequestVoteReply.class, 1);
- member3Actor.underlyingActor().expectMessageClass(AppendEntriesReply.class, 2);
-
- member3Actor.tell(new ElectionTimeout(), ActorRef.noSender());
-
- member3Actor.underlyingActor().waitForExpectedMessages(RequestVoteReply.class);
-
- RequestVoteReply requestVoteReply = member3Actor.underlyingActor().getCapturedMessage(RequestVoteReply.class);
- assertEquals("getTerm", member3Context.getTermInformation().getCurrentTerm(), requestVoteReply.getTerm());
- assertEquals("isVoteGranted", true, requestVoteReply.isVoteGranted());
-
- verifyBehaviorState("member 3", member3Actor, RaftState.Leader);
-
- // member 2 should've switched to Follower as member 3's RequestVote term (3) was greater
- // than member 2's term (2).
-
- member2Actor.underlyingActor().waitForBehaviorStateChange();
- verifyBehaviorState("member 2", member2Actor, RaftState.Follower);
-
- // The switch to leader should cause an immediate AppendEntries heartbeat from member 3.
-
- member3Actor.underlyingActor().waitForExpectedMessages(AppendEntriesReply.class);
-
- assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm());
- assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm());
- assertEquals("member 3 election term", 3, member3Context.getTermInformation().getCurrentTerm());
-
- // Now forward the original delayed RequestVoteReply from member 3 to member 2 that granted
- // the vote. Since member 2 is now a Follower, the RequestVoteReply should be ignored.
-
- member2Actor.underlyingActor().clearDropMessagesToBehavior();
- member2Actor.underlyingActor().forwardCapturedMessageToBehavior(RequestVoteReply.class, member3Actor);
-
- member2Actor.underlyingActor().waitForExpectedMessages(RequestVoteReply.class);
-
- verifyBehaviorState("member 1", member1Actor, RaftState.Follower);
- verifyBehaviorState("member 2", member2Actor, RaftState.Follower);
- verifyBehaviorState("member 3", member3Actor, RaftState.Leader);
-
- assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm());
- assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm());
- assertEquals("member 3 election term", 3, member3Context.getTermInformation().getCurrentTerm());
-
- testLog.info("testDelayedMessagesScenario done");
- }
-
- @Test
- public void testPartitionedLeadersScenario() throws Exception {
- testLog.info("Starting testPartitionedLeadersScenario");
-
- TestActorRef<MemberActor> member1Actor = newMemberActor("member1");
- TestActorRef<MemberActor> member2Actor = newMemberActor("member2");
- TestActorRef<MemberActor> member3Actor = newMemberActor("member3");
-
- // Create member 2's behavior initially as Follower
-
- MockRaftActorContext member2Context = newRaftActorContext("member2", member2Actor,
- ImmutableMap.<String,String>builder().
- put("member1", member1Actor.path().toString()).
- put("member3", member3Actor.path().toString()).build());
-
- DefaultConfigParamsImpl member2ConfigParams = newConfigParams();
- member2Context.setConfigParams(member2ConfigParams);
-
- Follower member2Behavior = new Follower(member2Context);
- member2Actor.underlyingActor().behavior = member2Behavior;
-
- // Create member 3's behavior initially as Follower
-
- MockRaftActorContext member3Context = newRaftActorContext("member3", member3Actor,
- ImmutableMap.<String,String>builder().
- put("member1", member1Actor.path().toString()).
- put("member2", member2Actor.path().toString()).build());
-
- DefaultConfigParamsImpl member3ConfigParams = newConfigParams();
- member3Context.setConfigParams(member3ConfigParams);
-
- Follower member3Behavior = new Follower(member3Context);
- member3Actor.underlyingActor().behavior = member3Behavior;
-
- // Create member 1's behavior initially as Leader
-
- MockRaftActorContext member1Context = newRaftActorContext("member1", member1Actor,
- ImmutableMap.<String,String>builder().
- put("member2", member2Actor.path().toString()).
- put("member3", member3Actor.path().toString()).build());
-
- DefaultConfigParamsImpl member1ConfigParams = newConfigParams();
- member1Context.setConfigParams(member1ConfigParams);
-
- initializeLeaderBehavior(member1Actor, member1Context, 2);
-
- member2Actor.underlyingActor().clear();
- member3Actor.underlyingActor().clear();
-
- // Send ElectionTimeout to member 2 to simulate no heartbeat from the Leader (member 1).
- // member 2 should switch to Candidate, start new term 2 and send out RequestVote messages.
- // member 1 will switch to Follower b/c its term is less than the RequestVote term, also it
- // won't send back a reply. member 3 will drop the message (ie won't forward it to its behavior) to
- // simulate loss of network connectivity between member 2 and 3.
-
- member1Actor.underlyingActor().expectMessageClass(RequestVote.class, 1);
-
- member2Actor.underlyingActor().expectBehaviorStateChange();
-
- member3Actor.underlyingActor().dropMessagesToBehavior(RequestVote.class);
-
- member2Actor.tell(new ElectionTimeout(), ActorRef.noSender());
-
- member1Actor.underlyingActor().waitForExpectedMessages(RequestVote.class);
- member3Actor.underlyingActor().waitForExpectedMessages(RequestVote.class);
-
- // member 1 should switch to Follower as the RequestVote term is greater than its term. It
- // won't send back a RequestVoteReply in this case.
-
- verifyBehaviorState("member 1", member1Actor, RaftState.Follower);
-
- // member 2 should switch to Candidate since member 1 didn't reply.
-
- member2Actor.underlyingActor().waitForBehaviorStateChange();
- verifyBehaviorState("member 2", member2Actor, RaftState.Candidate);
-
- assertEquals("member 1 election term", 2, member1Context.getTermInformation().getCurrentTerm());
- assertEquals("member 2 election term", 2, member2Context.getTermInformation().getCurrentTerm());
- assertEquals("member 3 election term", 1, member3Context.getTermInformation().getCurrentTerm());
-
- // Send ElectionTimeout to member 3 to simulate no heartbeat from the Leader (member 1).
- // member 2 should switch to Candidate and send out RequestVote messages. member 1 will reply and
- // grant the vote but member 2 will drop the message to simulate loss of network connectivity.
-
- member1Actor.underlyingActor().clear();
- member1Actor.underlyingActor().expectMessageClass(RequestVote.class, 1);
- member1Actor.underlyingActor().expectMessageClass(AppendEntries.class, 1);
-
- member2Actor.underlyingActor().clear();
- member2Actor.underlyingActor().dropMessagesToBehavior(RequestVote.class);
- member2Actor.underlyingActor().dropMessagesToBehavior(AppendEntries.class);
-
- member3Actor.underlyingActor().clear();
- member3Actor.underlyingActor().expectMessageClass(RequestVoteReply.class, 1);
- member3Actor.underlyingActor().expectMessageClass(AppendEntriesReply.class, 1);
-
- member3Actor.tell(new ElectionTimeout(), ActorRef.noSender());
-
- member1Actor.underlyingActor().waitForExpectedMessages(RequestVote.class);
- member2Actor.underlyingActor().waitForExpectedMessages(RequestVote.class);
- member3Actor.underlyingActor().waitForExpectedMessages(RequestVoteReply.class);
-
- RequestVoteReply requestVoteReply = member3Actor.underlyingActor().getCapturedMessage(RequestVoteReply.class);
- assertEquals("getTerm", member3Context.getTermInformation().getCurrentTerm(), requestVoteReply.getTerm());
- assertEquals("isVoteGranted", true, requestVoteReply.isVoteGranted());
-
- // when member 3 switches to Leader it will immediately send out heartbeat AppendEntries to
- // the followers. Wait for AppendEntries to member 1 and its AppendEntriesReply. The
- // AppendEntries message to member 2 is dropped.
-
- member1Actor.underlyingActor().waitForExpectedMessages(AppendEntries.class);
- member2Actor.underlyingActor().waitForExpectedMessages(AppendEntries.class);
- member3Actor.underlyingActor().waitForExpectedMessages(AppendEntriesReply.class);
-
- verifyBehaviorState("member 1", member1Actor, RaftState.Follower);
- verifyBehaviorState("member 2", member2Actor, RaftState.Candidate);
- verifyBehaviorState("member 3", member3Actor, RaftState.Leader);
-
- assertEquals("member 1 election term", 2, member1Context.getTermInformation().getCurrentTerm());
- assertEquals("member 2 election term", 2, member2Context.getTermInformation().getCurrentTerm());
- assertEquals("member 3 election term", 2, member3Context.getTermInformation().getCurrentTerm());
-
- // member 2 is partitioned from the Leader (member 3) and hasn't received any messages. It
- // would get another ElectionTimeout so simulate that. member 1 should send back a reply
- // granting the vote. Messages (RequestVote and AppendEntries) from member 2 to member 3
- // are dropped to simulate loss of network connectivity. Note member 2 will increment its
- // election term to 3.
-
- member1Actor.underlyingActor().clear();
- member1Actor.underlyingActor().expectMessageClass(AppendEntries.class, 1);
-
- member2Actor.underlyingActor().clear();
- member2Actor.underlyingActor().expectMessageClass(RequestVoteReply.class, 1);
- member2Actor.underlyingActor().expectMessageClass(AppendEntriesReply.class, 1);
-
- member3Actor.underlyingActor().clear();
- member3Actor.underlyingActor().dropMessagesToBehavior(AppendEntries.class);
- member3Actor.underlyingActor().dropMessagesToBehavior(RequestVote.class);
-
- member2Actor.tell(new ElectionTimeout(), ActorRef.noSender());
-
- member2Actor.underlyingActor().waitForExpectedMessages(RequestVoteReply.class);
-
- requestVoteReply = member2Actor.underlyingActor().getCapturedMessage(RequestVoteReply.class);
- assertEquals("getTerm", member2Context.getTermInformation().getCurrentTerm(), requestVoteReply.getTerm());
- assertEquals("isVoteGranted", true, requestVoteReply.isVoteGranted());
-
- member3Actor.underlyingActor().waitForExpectedMessages(RequestVote.class);
-
- member1Actor.underlyingActor().waitForExpectedMessages(AppendEntries.class);
- member3Actor.underlyingActor().waitForExpectedMessages(AppendEntries.class);
- member2Actor.underlyingActor().waitForExpectedMessages(AppendEntriesReply.class);
-
- // We end up with 2 partitioned leaders both leading member 1. The term for member 1 and 3
- // is 3 and member 3's term is 2.
-
- verifyBehaviorState("member 1", member1Actor, RaftState.Follower);
- verifyBehaviorState("member 2", member2Actor, RaftState.Leader);
- verifyBehaviorState("member 3", member3Actor, RaftState.Leader);
-
- assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm());
- assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm());
- assertEquals("member 3 election term", 2, member3Context.getTermInformation().getCurrentTerm());
-
- // Re-establish connectivity between member 2 and 3, ie stop dropping messages between
- // the 2. Send heartbeats (AppendEntries) from member 3. Both member 1 and 2 should send back
- // an unsuccessful AppendEntriesReply b/c their term (3) is greater than member 3's term (2).
- // This should cause member 3 to switch to Follower.
-
- RaftActorBehavior savedMember1Behavior = member1Actor.underlyingActor().behavior;
- RaftActorBehavior savedMember2Behavior = member2Actor.underlyingActor().behavior;
- RaftActorBehavior savedMember3Behavior = member3Actor.underlyingActor().behavior;
- long savedMember3Term = member3Context.getTermInformation().getCurrentTerm();
- String savedMember3VoterFor = member3Context.getTermInformation().getVotedFor();
-
- member1Actor.underlyingActor().clear();
- member1Actor.underlyingActor().expectMessageClass(AppendEntries.class, 1);
-
- member2Actor.underlyingActor().clear();
- member2Actor.underlyingActor().expectMessageClass(AppendEntries.class, 1);
-
- member3Actor.underlyingActor().clear();
- member3Actor.underlyingActor().expectMessageClass(AppendEntriesReply.class, 1);
-
- sendHeartbeat(member3Actor);
-
- member3Actor.underlyingActor().waitForExpectedMessages(AppendEntriesReply.class);
-
- AppendEntriesReply appendEntriesReply = member3Actor.underlyingActor().
- getCapturedMessage(AppendEntriesReply.class);
- assertEquals("isSuccess", false, appendEntriesReply.isSuccess());
- assertEquals("getTerm", 3, appendEntriesReply.getTerm());
-
- verifyBehaviorState("member 1", member1Actor, RaftState.Follower);
- verifyBehaviorState("member 2", member2Actor, RaftState.Leader);
- verifyBehaviorState("member 3", member3Actor, RaftState.Follower);
-
- assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm());
- assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm());
- assertEquals("member 3 election term", 3, member3Context.getTermInformation().getCurrentTerm());
-
- // Revert back to the partitioned leaders state to test the other sequence where member 2
- // sends heartbeats first before member 3. member 1 should return a successful
- // AppendEntriesReply b/c his term matches member 2's. member 3 should switch to Follower
- // as his term is less than member 2's.
-
- member1Actor.underlyingActor().behavior = savedMember1Behavior;
- member2Actor.underlyingActor().behavior = savedMember2Behavior;
- member3Actor.underlyingActor().behavior = savedMember3Behavior;
-
- member3Context.getTermInformation().update(savedMember3Term, savedMember3VoterFor);
-
- member1Actor.underlyingActor().clear();
- member1Actor.underlyingActor().expectMessageClass(AppendEntries.class, 1);
-
- member2Actor.underlyingActor().clear();
- member2Actor.underlyingActor().expectMessageClass(AppendEntriesReply.class, 1);
-
- member3Actor.underlyingActor().clear();
- member3Actor.underlyingActor().expectMessageClass(AppendEntries.class, 1);
-
- sendHeartbeat(member2Actor);
-
- member1Actor.underlyingActor().waitForExpectedMessages(AppendEntries.class);
- member3Actor.underlyingActor().waitForExpectedMessages(AppendEntries.class);
-
- member2Actor.underlyingActor().waitForExpectedMessages(AppendEntriesReply.class);
-
- verifyBehaviorState("member 1", member1Actor, RaftState.Follower);
- verifyBehaviorState("member 2", member2Actor, RaftState.Leader);
- verifyBehaviorState("member 3", member3Actor, RaftState.Follower);
-
- assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm());
- assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm());
- assertEquals("member 3 election term", 3, member3Context.getTermInformation().getCurrentTerm());
-
- testLog.info("testPartitionedLeadersScenario done");
- }
-
- @Test
- public void testPartitionedCandidateOnStartupScenario() throws Exception {
- testLog.info("Starting testPartitionedCandidateOnStartupScenario");
-
- TestActorRef<MemberActor> member1Actor = newMemberActor("member1") ;
- TestActorRef<MemberActor> member2Actor = newMemberActor("member2");
- TestActorRef<MemberActor> member3Actor = newMemberActor("member3");
-
- // Create member 2's behavior as Follower.
-
- MockRaftActorContext member2Context = newRaftActorContext("member2", member2Actor,
- ImmutableMap.<String,String>builder().
- put("member1", member1Actor.path().toString()).
- put("member3", member3Actor.path().toString()).build());
-
- DefaultConfigParamsImpl member2ConfigParams = newConfigParams();
- member2Context.setConfigParams(member2ConfigParams);
-
- Follower member2Behavior = new Follower(member2Context);
- member2Actor.underlyingActor().behavior = member2Behavior;
-
- // Create member 1's behavior as Leader.
-
- MockRaftActorContext member1Context = newRaftActorContext("member1", member1Actor,
- ImmutableMap.<String,String>builder().
- put("member2", member2Actor.path().toString()).
- put("member3", member3Actor.path().toString()).build());
-
- DefaultConfigParamsImpl member1ConfigParams = newConfigParams();
- member1Context.setConfigParams(member1ConfigParams);
-
- initializeLeaderBehavior(member1Actor, member1Context, 1);
-
- member2Actor.underlyingActor().clear();
- member3Actor.underlyingActor().clear();
-
- // Initialize the ReplicatedLog and election term info for member 1 and 2. The current term
- // will be 3 and the last term will be 2.
-
- SimpleReplicatedLog replicatedLog = new SimpleReplicatedLog();
- replicatedLog.append(new MockReplicatedLogEntry(2, 1, new MockPayload("")));
- replicatedLog.append(new MockReplicatedLogEntry(3, 1, new MockPayload("")));
-
- member1Context.setReplicatedLog(replicatedLog);
- member1Context.getTermInformation().update(3, "");
-
- member2Context.setReplicatedLog(replicatedLog);
- member2Context.getTermInformation().update(3, member1Context.getId());
-
- // Create member 3's behavior initially as a Candidate.
-
- MockRaftActorContext member3Context = newRaftActorContext("member3", member3Actor,
- ImmutableMap.<String,String>builder().
- put("member1", member1Actor.path().toString()).
- put("member2", member2Actor.path().toString()).build());
-
- DefaultConfigParamsImpl member3ConfigParams = newConfigParams();
- member3Context.setConfigParams(member3ConfigParams);
-
- // Initialize the ReplicatedLog and election term info for Candidate member 3. The current term
- // will be 2 and the last term will be 1 so it is behind the leader's log.
-
- SimpleReplicatedLog candidateReplicatedLog = new SimpleReplicatedLog();
- candidateReplicatedLog.append(new MockReplicatedLogEntry(1, 1, new MockPayload("")));
- candidateReplicatedLog.append(new MockReplicatedLogEntry(2, 1, new MockPayload("")));
-
- member3Context.setReplicatedLog(candidateReplicatedLog);
- member3Context.getTermInformation().update(2, member1Context.getId());
-
- // The member 3 Candidate will start a new term and send RequestVotes. However it will be
- // partitioned from the cluster by having member 1 and 2 drop its RequestVote messages.
-
- int numCandidateElections = 5;
- long candidateElectionTerm = member3Context.getTermInformation().getCurrentTerm() + numCandidateElections;
-
- member1Actor.underlyingActor().dropMessagesToBehavior(RequestVote.class, numCandidateElections);
-
- member2Actor.underlyingActor().dropMessagesToBehavior(RequestVote.class, numCandidateElections);
-
- Candidate member3Behavior = new Candidate(member3Context);
- member3Actor.underlyingActor().behavior = member3Behavior;
-
- // Send several additional ElectionTimeouts to Candidate member 3. Each ElectionTimeout will
- // start a new term so Candidate member 3's current term will be greater than the leader's
- // current term.
-
- for(int i = 0; i < numCandidateElections - 1; i++) {
- member3Actor.tell(new ElectionTimeout(), ActorRef.noSender());
- }
-
- member1Actor.underlyingActor().waitForExpectedMessages(RequestVote.class);
- member2Actor.underlyingActor().waitForExpectedMessages(RequestVote.class);
-
- verifyBehaviorState("member 1", member1Actor, RaftState.Leader);
- verifyBehaviorState("member 2", member2Actor, RaftState.Follower);
- verifyBehaviorState("member 3", member3Actor, RaftState.Candidate);
-
- assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm());
- assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm());
- assertEquals("member 3 election term", candidateElectionTerm,
- member3Context.getTermInformation().getCurrentTerm());
-
- // Now send a couple more ElectionTimeouts to Candidate member 3 with the partition resolved.
- //
- // On the first RequestVote, Leader member 1 should switch to Follower as its term (s) is less than
- // the RequestVote's term (8) from member 3. No RequestVoteReply should be sent by member 1.
- // Follower member 2 should update its term since it less than the RequestVote's term and
- // should return a RequestVoteReply but should not grant the vote as its last term and index
- // is greater than the RequestVote's lastLogTerm and lastLogIndex, ie member 2's log is later
- // or more up to date than member 3's.
- //
- // On the second RequestVote, both member 1 and 2 are followers so they should update their
- // term and return a RequestVoteReply but should not grant the vote.
-
- candidateElectionTerm += 2;
- for(int i = 0; i < 2; i++) {
- member1Actor.underlyingActor().clear();
- member1Actor.underlyingActor().expectMessageClass(RequestVote.class, 1);
- member2Actor.underlyingActor().clear();
- member2Actor.underlyingActor().expectMessageClass(RequestVote.class, 1);
- member3Actor.underlyingActor().clear();
- member3Actor.underlyingActor().expectMessageClass(RequestVoteReply.class, 1);
-
- member3Actor.tell(new ElectionTimeout(), ActorRef.noSender());
-
- member1Actor.underlyingActor().waitForExpectedMessages(RequestVote.class);
- member2Actor.underlyingActor().waitForExpectedMessages(RequestVote.class);
-
- member3Actor.underlyingActor().waitForExpectedMessages(RequestVoteReply.class);
-
- RequestVoteReply requestVoteReply = member3Actor.underlyingActor().getCapturedMessage(RequestVoteReply.class);
- assertEquals("getTerm", member3Context.getTermInformation().getCurrentTerm(), requestVoteReply.getTerm());
- assertEquals("isVoteGranted", false, requestVoteReply.isVoteGranted());
- }
-
- verifyBehaviorState("member 1", member1Actor, RaftState.Follower);
- verifyBehaviorState("member 2", member2Actor, RaftState.Follower);
- verifyBehaviorState("member 3", member3Actor, RaftState.Candidate);
-
- // Even though member 3 didn't get voted for, member 1 and 2 should have updated their term
- // to member 3's.
-
- assertEquals("member 1 election term", candidateElectionTerm,
- member1Context.getTermInformation().getCurrentTerm());
- assertEquals("member 2 election term", candidateElectionTerm,
- member2Context.getTermInformation().getCurrentTerm());
- assertEquals("member 3 election term", candidateElectionTerm,
- member3Context.getTermInformation().getCurrentTerm());
-
- // At this point we have no leader. Candidate member 3 would continue to start new elections
- // but wouldn't be granted a vote. One of the 2 followers would eventually time out from
- // not having received a heartbeat from a leader and switch to candidate and start a new
- // election. We'll simulate that here by sending an ElectionTimeout to member 1.
-
- member1Actor.underlyingActor().clear();
- member1Actor.underlyingActor().expectMessageClass(RequestVoteReply.class, 1);
- member2Actor.underlyingActor().clear();
- member2Actor.underlyingActor().expectMessageClass(RequestVote.class, 1);
- member3Actor.underlyingActor().clear();
- member3Actor.underlyingActor().expectMessageClass(RequestVote.class, 1);
- member3Actor.underlyingActor().expectBehaviorStateChange();
-
- member1Actor.tell(new ElectionTimeout(), ActorRef.noSender());
-
- member2Actor.underlyingActor().waitForExpectedMessages(RequestVote.class);
- member3Actor.underlyingActor().waitForExpectedMessages(RequestVote.class);
-
- // The RequestVoteReply should come from Follower member 2 and the vote should be granted
- // since member 2's last term and index matches member 1's.
-
- member1Actor.underlyingActor().waitForExpectedMessages(RequestVoteReply.class);
-
- RequestVoteReply requestVoteReply = member1Actor.underlyingActor().getCapturedMessage(RequestVoteReply.class);
- assertEquals("getTerm", member1Context.getTermInformation().getCurrentTerm(), requestVoteReply.getTerm());
- assertEquals("isVoteGranted", true, requestVoteReply.isVoteGranted());
-
- // Candidate member 3 should change to follower as its term should be less than the
- // RequestVote term (member 1 started a new term higher than the other member's terms).
-
- member3Actor.underlyingActor().waitForBehaviorStateChange();
-
- verifyBehaviorState("member 1", member1Actor, RaftState.Leader);
- verifyBehaviorState("member 2", member2Actor, RaftState.Follower);
- verifyBehaviorState("member 3", member3Actor, RaftState.Follower);
-
- // newTerm should be 10.
-
- long newTerm = candidateElectionTerm + 1;
- assertEquals("member 1 election term", newTerm, member1Context.getTermInformation().getCurrentTerm());
- assertEquals("member 2 election term", newTerm, member2Context.getTermInformation().getCurrentTerm());
- assertEquals("member 3 election term", newTerm, member3Context.getTermInformation().getCurrentTerm());
-
- testLog.info("testPartitionedCandidateOnStartupScenario done");
- }
-}
import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
import org.opendaylight.controller.cluster.raft.utils.ForwardMessageToBehaviorActor;
import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
-import org.opendaylight.controller.protobuff.messages.cluster.raft.InstallSnapshotMessages;
import scala.concurrent.duration.FiniteDuration;
public class LeaderTest extends AbstractLeaderTest {
leader.handleMessage(leaderActor, new SendHeartBeat());
- InstallSnapshotMessages.InstallSnapshot isproto = MessageCollectorActor.expectFirstMatching(followerActor,
- InstallSnapshot.SERIALIZABLE_CLASS);
-
- InstallSnapshot is = (InstallSnapshot) SerializationUtils.fromSerializable(isproto);
+ InstallSnapshot is = MessageCollectorActor.expectFirstMatching(followerActor, InstallSnapshot.class);
assertEquals(snapshotIndex, is.getLastIncludedIndex());
}
// check if installsnapshot gets called with the correct values.
- InstallSnapshot installSnapshot = (InstallSnapshot) SerializationUtils.fromSerializable(
- MessageCollectorActor.expectFirstMatching(followerActor, InstallSnapshotMessages.InstallSnapshot.class));
+ InstallSnapshot installSnapshot = MessageCollectorActor.expectFirstMatching(followerActor, InstallSnapshot.class);
assertNotNull(installSnapshot.getData());
assertEquals(snapshotIndex, installSnapshot.getLastIncludedIndex());
leader.handleMessage(leaderActor, new SendInstallSnapshot(bs));
- InstallSnapshotMessages.InstallSnapshot installSnapshot = MessageCollectorActor.expectFirstMatching(
- followerActor, InstallSnapshotMessages.InstallSnapshot.class);
+ InstallSnapshot installSnapshot = MessageCollectorActor.expectFirstMatching(followerActor, InstallSnapshot.class);
assertEquals(1, installSnapshot.getChunkIndex());
assertEquals(3, installSnapshot.getTotalChunks());
leader.handleMessage(followerActor, new InstallSnapshotReply(actorContext.getTermInformation().getCurrentTerm(),
FOLLOWER_ID, installSnapshot.getChunkIndex(), true));
- installSnapshot = MessageCollectorActor.expectFirstMatching(
- followerActor, InstallSnapshotMessages.InstallSnapshot.class);
+ installSnapshot = MessageCollectorActor.expectFirstMatching(followerActor, InstallSnapshot.class);
assertEquals(2, installSnapshot.getChunkIndex());
assertEquals(3, installSnapshot.getTotalChunks());
leader.handleMessage(followerActor, new InstallSnapshotReply(actorContext.getTermInformation().getCurrentTerm(),
FOLLOWER_ID, installSnapshot.getChunkIndex(), true));
- installSnapshot = MessageCollectorActor.expectFirstMatching(
- followerActor, InstallSnapshotMessages.InstallSnapshot.class);
+ installSnapshot = MessageCollectorActor.expectFirstMatching(followerActor, InstallSnapshot.class);
// Send snapshot reply one more time and make sure that a new snapshot message should not be sent to follower
followerActor.underlyingActor().clear();
leader.handleMessage(followerActor, new InstallSnapshotReply(actorContext.getTermInformation().getCurrentTerm(),
FOLLOWER_ID, installSnapshot.getChunkIndex(), true));
- installSnapshot = MessageCollectorActor.getFirstMatching(
- followerActor, InstallSnapshotMessages.InstallSnapshot.class);
+ installSnapshot = MessageCollectorActor.getFirstMatching(followerActor, InstallSnapshot.class);
Assert.assertNull(installSnapshot);
}
ByteString bs = toByteString(leadersSnapshot);
leader.setSnapshot(Optional.of(bs));
+ Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
leader.handleMessage(leaderActor, new SendInstallSnapshot(bs));
- InstallSnapshotMessages.InstallSnapshot installSnapshot = MessageCollectorActor.expectFirstMatching(
- followerActor, InstallSnapshotMessages.InstallSnapshot.class);
+ InstallSnapshot installSnapshot = MessageCollectorActor.expectFirstMatching(followerActor, InstallSnapshot.class);
assertEquals(1, installSnapshot.getChunkIndex());
assertEquals(3, installSnapshot.getTotalChunks());
leader.handleMessage(leaderActor, new SendHeartBeat());
- installSnapshot = MessageCollectorActor.expectFirstMatching(
- followerActor, InstallSnapshotMessages.InstallSnapshot.class);
+ installSnapshot = MessageCollectorActor.expectFirstMatching(followerActor, InstallSnapshot.class);
assertEquals(1, installSnapshot.getChunkIndex());
assertEquals(3, installSnapshot.getTotalChunks());
leader.handleMessage(leaderActor, new SendInstallSnapshot(bs));
- InstallSnapshotMessages.InstallSnapshot installSnapshot = MessageCollectorActor.expectFirstMatching(
- followerActor, InstallSnapshotMessages.InstallSnapshot.class);
+ InstallSnapshot installSnapshot = MessageCollectorActor.expectFirstMatching(followerActor, InstallSnapshot.class);
assertEquals(1, installSnapshot.getChunkIndex());
assertEquals(3, installSnapshot.getTotalChunks());
- assertEquals(AbstractLeader.INITIAL_LAST_CHUNK_HASH_CODE, installSnapshot.getLastChunkHashCode());
+ assertEquals(AbstractLeader.INITIAL_LAST_CHUNK_HASH_CODE, installSnapshot.getLastChunkHashCode().get().intValue());
int hashCode = installSnapshot.getData().hashCode();
leader.handleMessage(followerActor, new InstallSnapshotReply(installSnapshot.getTerm(),
FOLLOWER_ID, 1, true));
- installSnapshot = MessageCollectorActor.expectFirstMatching(
- followerActor, InstallSnapshotMessages.InstallSnapshot.class);
+ installSnapshot = MessageCollectorActor.expectFirstMatching(followerActor, InstallSnapshot.class);
assertEquals(2, installSnapshot.getChunkIndex());
assertEquals(3, installSnapshot.getTotalChunks());
- assertEquals(hashCode, installSnapshot.getLastChunkHashCode());
+ assertEquals(hashCode, installSnapshot.getLastChunkHashCode().get().intValue());
}
@Test
--- /dev/null
+/*
+ * Copyright (c) 2015 Brocade Communications 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.cluster.raft.behaviors;
+
+import static org.junit.Assert.assertEquals;
+import akka.actor.ActorRef;
+import com.google.common.collect.ImmutableMap;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
+import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload;
+import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockReplicatedLogEntry;
+import org.opendaylight.controller.cluster.raft.MockRaftActorContext.SimpleReplicatedLog;
+import org.opendaylight.controller.cluster.raft.RaftState;
+import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout;
+import org.opendaylight.controller.cluster.raft.messages.RequestVote;
+import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
+
+/**
+ * A leader election scenario test that partitions a candidate when trying to join a cluster on startup.
+ *
+ * @author Thomas Pantelis
+ */
+public class PartitionedCandidateOnStartupElectionScenarioTest extends AbstractLeaderElectionScenarioTest {
+
+ private final int numCandidateElections = 5;
+ private long candidateElectionTerm;
+
+ @Test
+ public void runTest() throws Exception {
+ testLog.info("PartitionedCandidateOnStartupElectionScenarioTest starting");
+
+ setupInitialMember1AndMember2Behaviors();
+
+ setupPartitionedCandidateMember3AndSendElectionTimeouts();
+
+ resolvePartitionAndSendElectionTimeoutsToCandidateMember3();
+
+ sendElectionTimeoutToFollowerMember1();
+
+ testLog.info("PartitionedCandidateOnStartupElectionScenarioTest ending");
+ }
+
+ private void sendElectionTimeoutToFollowerMember1() throws Exception {
+ testLog.info("sendElectionTimeoutToFollowerMember1 starting");
+
+ // At this point we have no leader. Candidate member 3 would continue to start new elections
+ // but wouldn't be granted a vote. One of the 2 followers would eventually time out from
+ // not having received a heartbeat from a leader and switch to candidate and start a new
+ // election. We'll simulate that here by sending an ElectionTimeout to member 1.
+
+ member1Actor.clear();
+ member1Actor.expectMessageClass(RequestVoteReply.class, 1);
+ member2Actor.clear();
+ member2Actor.expectMessageClass(RequestVote.class, 1);
+ member3Actor.clear();
+ member3Actor.expectMessageClass(RequestVote.class, 1);
+ member3Actor.expectBehaviorStateChange();
+
+ member1ActorRef.tell(new ElectionTimeout(), ActorRef.noSender());
+
+ member2Actor.waitForExpectedMessages(RequestVote.class);
+ member3Actor.waitForExpectedMessages(RequestVote.class);
+
+ // The RequestVoteReply should come from Follower member 2 and the vote should be granted
+ // since member 2's last term and index matches member 1's.
+
+ member1Actor.waitForExpectedMessages(RequestVoteReply.class);
+
+ RequestVoteReply requestVoteReply = member1Actor.getCapturedMessage(RequestVoteReply.class);
+ assertEquals("getTerm", member1Context.getTermInformation().getCurrentTerm(), requestVoteReply.getTerm());
+ assertEquals("isVoteGranted", true, requestVoteReply.isVoteGranted());
+
+ // Candidate member 3 should change to follower as its term should be less than the
+ // RequestVote term (member 1 started a new term higher than the other member's terms).
+
+ member3Actor.waitForBehaviorStateChange();
+
+ verifyBehaviorState("member 1", member1Actor, RaftState.Leader);
+ verifyBehaviorState("member 2", member2Actor, RaftState.Follower);
+ verifyBehaviorState("member 3", member3Actor, RaftState.Follower);
+
+ // newTerm should be 10.
+
+ long newTerm = candidateElectionTerm + 1;
+ assertEquals("member 1 election term", newTerm, member1Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 2 election term", newTerm, member2Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 3 election term", newTerm, member3Context.getTermInformation().getCurrentTerm());
+
+ testLog.info("sendElectionTimeoutToFollowerMember1 ending");
+ }
+
+ private void resolvePartitionAndSendElectionTimeoutsToCandidateMember3() throws Exception {
+ testLog.info("resolvePartitionAndSendElectionTimeoutsToCandidateMember3 starting");
+
+ // Now send a couple more ElectionTimeouts to Candidate member 3 with the partition resolved.
+ //
+ // On the first RequestVote, Leader member 1 should switch to Follower as its term (s) is less than
+ // the RequestVote's term (8) from member 3. No RequestVoteReply should be sent by member 1.
+ // Follower member 2 should update its term since it less than the RequestVote's term and
+ // should return a RequestVoteReply but should not grant the vote as its last term and index
+ // is greater than the RequestVote's lastLogTerm and lastLogIndex, ie member 2's log is later
+ // or more up to date than member 3's.
+ //
+ // On the second RequestVote, both member 1 and 2 are followers so they should update their
+ // term and return a RequestVoteReply but should not grant the vote.
+
+ candidateElectionTerm += 2;
+ for(int i = 0; i < 2; i++) {
+ member1Actor.clear();
+ member1Actor.expectMessageClass(RequestVote.class, 1);
+ member2Actor.clear();
+ member2Actor.expectMessageClass(RequestVote.class, 1);
+ member3Actor.clear();
+ member3Actor.expectMessageClass(RequestVoteReply.class, 1);
+
+ member3ActorRef.tell(new ElectionTimeout(), ActorRef.noSender());
+
+ member1Actor.waitForExpectedMessages(RequestVote.class);
+ member2Actor.waitForExpectedMessages(RequestVote.class);
+
+ member3Actor.waitForExpectedMessages(RequestVoteReply.class);
+
+ RequestVoteReply requestVoteReply = member3Actor.getCapturedMessage(RequestVoteReply.class);
+ assertEquals("getTerm", member3Context.getTermInformation().getCurrentTerm(), requestVoteReply.getTerm());
+ assertEquals("isVoteGranted", false, requestVoteReply.isVoteGranted());
+ }
+
+ verifyBehaviorState("member 1", member1Actor, RaftState.Follower);
+ verifyBehaviorState("member 2", member2Actor, RaftState.Follower);
+ verifyBehaviorState("member 3", member3Actor, RaftState.Candidate);
+
+ // Even though member 3 didn't get voted for, member 1 and 2 should have updated their term
+ // to member 3's.
+
+ assertEquals("member 1 election term", candidateElectionTerm,
+ member1Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 2 election term", candidateElectionTerm,
+ member2Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 3 election term", candidateElectionTerm,
+ member3Context.getTermInformation().getCurrentTerm());
+
+ testLog.info("resolvePartitionAndSendElectionTimeoutsToCandidateMember3 ending");
+ }
+
+ private void setupPartitionedCandidateMember3AndSendElectionTimeouts() {
+ testLog.info("setupPartitionedCandidateMember3AndSendElectionTimeouts starting");
+
+ // Create member 3's behavior initially as a Candidate.
+
+ member3Context = newRaftActorContext("member3", member3ActorRef,
+ ImmutableMap.<String,String>builder().
+ put("member1", member1ActorRef.path().toString()).
+ put("member2", member2ActorRef.path().toString()).build());
+
+ DefaultConfigParamsImpl member3ConfigParams = newConfigParams();
+ member3Context.setConfigParams(member3ConfigParams);
+
+ // Initialize the ReplicatedLog and election term info for Candidate member 3. The current term
+ // will be 2 and the last term will be 1 so it is behind the leader's log.
+
+ SimpleReplicatedLog candidateReplicatedLog = new SimpleReplicatedLog();
+ candidateReplicatedLog.append(new MockReplicatedLogEntry(1, 1, new MockPayload("")));
+ candidateReplicatedLog.append(new MockReplicatedLogEntry(2, 1, new MockPayload("")));
+
+ member3Context.setReplicatedLog(candidateReplicatedLog);
+ member3Context.getTermInformation().update(2, member1Context.getId());
+
+ // The member 3 Candidate will start a new term and send RequestVotes. However it will be
+ // partitioned from the cluster by having member 1 and 2 drop its RequestVote messages.
+
+ candidateElectionTerm = member3Context.getTermInformation().getCurrentTerm() + numCandidateElections;
+
+ member1Actor.dropMessagesToBehavior(RequestVote.class, numCandidateElections);
+
+ member2Actor.dropMessagesToBehavior(RequestVote.class, numCandidateElections);
+
+ Candidate member3Behavior = new Candidate(member3Context);
+ member3Actor.behavior = member3Behavior;
+
+ // Send several additional ElectionTimeouts to Candidate member 3. Each ElectionTimeout will
+ // start a new term so Candidate member 3's current term will be greater than the leader's
+ // current term.
+
+ for(int i = 0; i < numCandidateElections - 1; i++) {
+ member3ActorRef.tell(new ElectionTimeout(), ActorRef.noSender());
+ }
+
+ member1Actor.waitForExpectedMessages(RequestVote.class);
+ member2Actor.waitForExpectedMessages(RequestVote.class);
+
+ verifyBehaviorState("member 1", member1Actor, RaftState.Leader);
+ verifyBehaviorState("member 2", member2Actor, RaftState.Follower);
+ verifyBehaviorState("member 3", member3Actor, RaftState.Candidate);
+
+ assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 3 election term", candidateElectionTerm,
+ member3Context.getTermInformation().getCurrentTerm());
+
+ testLog.info("setupPartitionedCandidateMember3AndSendElectionTimeouts ending");
+ }
+
+ private void setupInitialMember1AndMember2Behaviors() throws Exception {
+ testLog.info("setupInitialMember1AndMember2Behaviors starting");
+
+ // Create member 2's behavior as Follower.
+
+ member2Context = newRaftActorContext("member2", member2ActorRef,
+ ImmutableMap.<String,String>builder().
+ put("member1", member1ActorRef.path().toString()).
+ put("member3", member3ActorRef.path().toString()).build());
+
+ DefaultConfigParamsImpl member2ConfigParams = newConfigParams();
+ member2Context.setConfigParams(member2ConfigParams);
+
+ Follower member2Behavior = new Follower(member2Context);
+ member2Actor.behavior = member2Behavior;
+
+ // Create member 1's behavior as Leader.
+
+ member1Context = newRaftActorContext("member1", member1ActorRef,
+ ImmutableMap.<String,String>builder().
+ put("member2", member2ActorRef.path().toString()).
+ put("member3", member3ActorRef.path().toString()).build());
+
+ DefaultConfigParamsImpl member1ConfigParams = newConfigParams();
+ member1Context.setConfigParams(member1ConfigParams);
+
+ initializeLeaderBehavior(member1Actor, member1Context, 1);
+
+ member2Actor.clear();
+ member3Actor.clear();
+
+ // Initialize the ReplicatedLog and election term info for member 1 and 2. The current term
+ // will be 3 and the last term will be 2.
+
+ SimpleReplicatedLog replicatedLog = new SimpleReplicatedLog();
+ replicatedLog.append(new MockReplicatedLogEntry(2, 1, new MockPayload("")));
+ replicatedLog.append(new MockReplicatedLogEntry(3, 1, new MockPayload("")));
+
+ member1Context.setReplicatedLog(replicatedLog);
+ member1Context.getTermInformation().update(3, "");
+
+ member2Context.setReplicatedLog(replicatedLog);
+ member2Context.getTermInformation().update(3, member1Context.getId());
+
+ testLog.info("setupInitialMember1AndMember2Behaviors ending");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Brocade Communications 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.cluster.raft.behaviors;
+
+import static org.junit.Assert.assertEquals;
+import akka.actor.ActorRef;
+import com.google.common.collect.ImmutableMap;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
+import org.opendaylight.controller.cluster.raft.RaftState;
+import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout;
+import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
+import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
+import org.opendaylight.controller.cluster.raft.messages.RequestVote;
+import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
+
+/**
+ * A leader election scenario test that causes partitioned leaders by dropping messages between 2 members.
+ *
+ * @author Thomas Pantelis
+ */
+public class PartitionedLeadersElectionScenarioTest extends AbstractLeaderElectionScenarioTest {
+
+ /**
+ * This test sets up a scenario with partitioned leaders member 2 and 3 where partitioned leader 3
+ * sends a heartbeat first when connectivity is re-established.
+ */
+ @Test
+ public void runTest1() throws Exception {
+ testLog.info("PartitionedLeadersElectionScenarioTest 1 starting");
+
+ setupInitialMemberBehaviors();
+
+ sendInitialElectionTimeoutToFollowerMember2();
+
+ sendInitialElectionTimeoutToFollowerMember3();
+
+ sendElectionTimeoutToNowCandidateMember2();
+
+ resolvePartitionedLeadersWithLeaderMember3SendingHeartbeatFirst();
+
+ testLog.info("PartitionedLeadersElectionScenarioTest 1 ending");
+ }
+
+ /**
+ * This test sets up a scenario with partitioned leaders member 2 and 3 where partitioned leader 2
+ * sends a heartbeat first when connectivity is re-established.
+ */
+ @Test
+ public void runTest2() throws Exception {
+ testLog.info("PartitionedLeadersElectionScenarioTest 2 starting");
+
+ setupInitialMemberBehaviors();
+
+ sendInitialElectionTimeoutToFollowerMember2();
+
+ sendInitialElectionTimeoutToFollowerMember3();
+
+ sendElectionTimeoutToNowCandidateMember2();
+
+ resolvePartitionedLeadersWithLeaderMember2SendingHeartbeatFirst();
+
+ testLog.info("PartitionedLeadersElectionScenarioTest 2 ending");
+ }
+
+ private void resolvePartitionedLeadersWithLeaderMember2SendingHeartbeatFirst() {
+ testLog.info("resolvePartitionedLeadersWithLeaderMember2SendingHeartbeatFirst starting");
+
+ // Re-establish connectivity between member 2 and 3, ie stop dropping messages between
+ // the 2. Send heartbeats (AppendEntries) from partitioned leader member 2. Follower member 1 should
+ // return a successful AppendEntriesReply b/c its term matches member 2's. member 3 should switch to
+ // Follower as its term is less than member 2's.
+
+ member1Actor.clear();
+ member1Actor.expectMessageClass(AppendEntries.class, 1);
+
+ member2Actor.clear();
+ member2Actor.expectMessageClass(AppendEntriesReply.class, 1);
+
+ member3Actor.clear();
+ member3Actor.expectMessageClass(AppendEntries.class, 1);
+
+ sendHeartbeat(member2ActorRef);
+
+ member1Actor.waitForExpectedMessages(AppendEntries.class);
+ member3Actor.waitForExpectedMessages(AppendEntries.class);
+
+ member2Actor.waitForExpectedMessages(AppendEntriesReply.class);
+
+ verifyBehaviorState("member 1", member1Actor, RaftState.Follower);
+ verifyBehaviorState("member 2", member2Actor, RaftState.Leader);
+ verifyBehaviorState("member 3", member3Actor, RaftState.Follower);
+
+ assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 3 election term", 3, member3Context.getTermInformation().getCurrentTerm());
+
+ testLog.info("resolvePartitionedLeadersWithLeaderMember2SendingHeartbeatFirst ending");
+ }
+
+ private void resolvePartitionedLeadersWithLeaderMember3SendingHeartbeatFirst() throws Exception {
+ testLog.info("resolvePartitionedLeadersWithLeaderMember3SendingHeartbeatFirst starting");
+
+ // Re-establish connectivity between member 2 and 3, ie stop dropping messages between
+ // the 2. Send heartbeats (AppendEntries) from now leader member 3. Both member 1 and 2 should send
+ // back an unsuccessful AppendEntriesReply b/c their term (3) is greater than member 3's term (2).
+ // This should cause member 3 to switch to Follower.
+
+ member1Actor.clear();
+ member1Actor.expectMessageClass(AppendEntries.class, 1);
+
+ member2Actor.clear();
+ member2Actor.expectMessageClass(AppendEntries.class, 1);
+
+ member3Actor.clear();
+ member3Actor.expectMessageClass(AppendEntriesReply.class, 1);
+
+ sendHeartbeat(member3ActorRef);
+
+ member3Actor.waitForExpectedMessages(AppendEntriesReply.class);
+
+ AppendEntriesReply appendEntriesReply = member3Actor.getCapturedMessage(AppendEntriesReply.class);
+ assertEquals("isSuccess", false, appendEntriesReply.isSuccess());
+ assertEquals("getTerm", 3, appendEntriesReply.getTerm());
+
+ verifyBehaviorState("member 1", member1Actor, RaftState.Follower);
+ verifyBehaviorState("member 2", member2Actor, RaftState.Leader);
+ verifyBehaviorState("member 3", member3Actor, RaftState.Follower);
+
+ assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 3 election term", 3, member3Context.getTermInformation().getCurrentTerm());
+
+ testLog.info("resolvePartitionedLeadersWithLeaderMember3SendingHeartbeatFirst ending");
+ }
+
+ private void sendElectionTimeoutToNowCandidateMember2() throws Exception {
+ testLog.info("sendElectionTimeoutToNowCandidateMember2 starting");
+
+ // member 2, now a candidate, is partitioned from the Leader (now member 3) and hasn't received any
+ // messages. It would get another ElectionTimeout so simulate that. member 1 should send back a reply
+ // granting the vote. Messages (RequestVote and AppendEntries) from member 2 to member 3
+ // are dropped to simulate loss of network connectivity. Note member 2 will increment its
+ // election term to 3.
+
+ member1Actor.clear();
+ member1Actor.expectMessageClass(AppendEntries.class, 1);
+
+ member2Actor.clear();
+ member2Actor.expectMessageClass(RequestVoteReply.class, 1);
+ member2Actor.expectMessageClass(AppendEntriesReply.class, 1);
+
+ member3Actor.clear();
+ member3Actor.dropMessagesToBehavior(AppendEntries.class);
+ member3Actor.dropMessagesToBehavior(RequestVote.class);
+
+ member2ActorRef.tell(new ElectionTimeout(), ActorRef.noSender());
+
+ member2Actor.waitForExpectedMessages(RequestVoteReply.class);
+
+ RequestVoteReply requestVoteReply = member2Actor.getCapturedMessage(RequestVoteReply.class);
+ assertEquals("getTerm", member2Context.getTermInformation().getCurrentTerm(), requestVoteReply.getTerm());
+ assertEquals("isVoteGranted", true, requestVoteReply.isVoteGranted());
+
+ member3Actor.waitForExpectedMessages(RequestVote.class);
+
+ member1Actor.waitForExpectedMessages(AppendEntries.class);
+ member3Actor.waitForExpectedMessages(AppendEntries.class);
+ member2Actor.waitForExpectedMessages(AppendEntriesReply.class);
+
+ // We end up with 2 partitioned leaders both leading member 1. The term for member 1 and 3
+ // is 3 and member 3's term is 2.
+
+ verifyBehaviorState("member 1", member1Actor, RaftState.Follower);
+ verifyBehaviorState("member 2", member2Actor, RaftState.Leader);
+ verifyBehaviorState("member 3", member3Actor, RaftState.Leader);
+
+ assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 3 election term", 2, member3Context.getTermInformation().getCurrentTerm());
+
+ testLog.info("sendElectionTimeoutToNowCandidateMember2 ending");
+ }
+
+ private void sendInitialElectionTimeoutToFollowerMember3() throws Exception {
+ testLog.info("sendInitialElectionTimeoutToFollowerMember3 starting");
+
+ // Send ElectionTimeout to member 3 to simulate no heartbeat from a Leader (originally member 1).
+ // member 3 should switch to Candidate and send out RequestVote messages. member 1, now a follower,
+ // should reply and grant the vote but member 2 will drop the message to simulate loss of network
+ // connectivity between members 2 and 3. member 3 should switch to leader.
+
+ member1Actor.clear();
+ member1Actor.expectMessageClass(RequestVote.class, 1);
+ member1Actor.expectMessageClass(AppendEntries.class, 1);
+
+ member2Actor.clear();
+ member2Actor.dropMessagesToBehavior(RequestVote.class);
+ member2Actor.dropMessagesToBehavior(AppendEntries.class);
+
+ member3Actor.clear();
+ member3Actor.expectMessageClass(RequestVoteReply.class, 1);
+ member3Actor.expectMessageClass(AppendEntriesReply.class, 1);
+
+ member3ActorRef.tell(new ElectionTimeout(), ActorRef.noSender());
+
+ member1Actor.waitForExpectedMessages(RequestVote.class);
+ member2Actor.waitForExpectedMessages(RequestVote.class);
+ member3Actor.waitForExpectedMessages(RequestVoteReply.class);
+
+ RequestVoteReply requestVoteReply = member3Actor.getCapturedMessage(RequestVoteReply.class);
+ assertEquals("getTerm", member3Context.getTermInformation().getCurrentTerm(), requestVoteReply.getTerm());
+ assertEquals("isVoteGranted", true, requestVoteReply.isVoteGranted());
+
+ // when member 3 switches to Leader it will immediately send out heartbeat AppendEntries to
+ // the followers. Wait for AppendEntries to member 1 and its AppendEntriesReply. The
+ // AppendEntries message to member 2 is dropped.
+
+ member1Actor.waitForExpectedMessages(AppendEntries.class);
+ member2Actor.waitForExpectedMessages(AppendEntries.class);
+ member3Actor.waitForExpectedMessages(AppendEntriesReply.class);
+
+ verifyBehaviorState("member 1", member1Actor, RaftState.Follower);
+ verifyBehaviorState("member 2", member2Actor, RaftState.Candidate);
+ verifyBehaviorState("member 3", member3Actor, RaftState.Leader);
+
+ assertEquals("member 1 election term", 2, member1Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 2 election term", 2, member2Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 3 election term", 2, member3Context.getTermInformation().getCurrentTerm());
+
+ testLog.info("sendInitialElectionTimeoutToFollowerMember3 ending");
+ }
+
+ private void sendInitialElectionTimeoutToFollowerMember2() {
+ testLog.info("sendInitialElectionTimeoutToFollowerMember2 starting");
+
+ // Send ElectionTimeout to member 2 to simulate no heartbeat from the Leader (member 1).
+ // member 2 should switch to Candidate, start new term 2 and send out RequestVote messages.
+ // member 1 will switch to Follower b/c its term is less than the member 2's RequestVote term, also it
+ // won't send back a reply. member 3 will drop the message (ie won't forward it to its behavior) to
+ // simulate loss of network connectivity between members 2 and 3.
+
+ member1Actor.expectMessageClass(RequestVote.class, 1);
+
+ member2Actor.expectBehaviorStateChange();
+
+ member3Actor.dropMessagesToBehavior(RequestVote.class);
+
+ member2ActorRef.tell(new ElectionTimeout(), ActorRef.noSender());
+
+ member1Actor.waitForExpectedMessages(RequestVote.class);
+ member3Actor.waitForExpectedMessages(RequestVote.class);
+
+ // Original leader member 1 should switch to Follower as the RequestVote term is greater than its
+ // term. It won't send back a RequestVoteReply in this case.
+
+ verifyBehaviorState("member 1", member1Actor, RaftState.Follower);
+
+ // member 2 should switch to Candidate since it didn't get a RequestVoteReply from the other 2 members.
+
+ member2Actor.waitForBehaviorStateChange();
+ verifyBehaviorState("member 2", member2Actor, RaftState.Candidate);
+
+ assertEquals("member 1 election term", 2, member1Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 2 election term", 2, member2Context.getTermInformation().getCurrentTerm());
+ assertEquals("member 3 election term", 1, member3Context.getTermInformation().getCurrentTerm());
+
+ testLog.info("sendInitialElectionTimeoutToFollowerMember2 ending");
+ }
+
+ private void setupInitialMemberBehaviors() throws Exception {
+ testLog.info("setupInitialMemberBehaviors starting");
+
+ // Create member 2's behavior initially as Follower
+
+ member2Context = newRaftActorContext("member2", member2ActorRef,
+ ImmutableMap.<String,String>builder().
+ put("member1", member1ActorRef.path().toString()).
+ put("member3", member3ActorRef.path().toString()).build());
+
+ DefaultConfigParamsImpl member2ConfigParams = newConfigParams();
+ member2Context.setConfigParams(member2ConfigParams);
+
+ Follower member2Behavior = new Follower(member2Context);
+ member2Actor.behavior = member2Behavior;
+
+ // Create member 3's behavior initially as Follower
+
+ member3Context = newRaftActorContext("member3", member3ActorRef,
+ ImmutableMap.<String,String>builder().
+ put("member1", member1ActorRef.path().toString()).
+ put("member2", member2ActorRef.path().toString()).build());
+
+ DefaultConfigParamsImpl member3ConfigParams = newConfigParams();
+ member3Context.setConfigParams(member3ConfigParams);
+
+ Follower member3Behavior = new Follower(member3Context);
+ member3Actor.behavior = member3Behavior;
+
+ // Create member 1's behavior initially as Leader
+
+ member1Context = newRaftActorContext("member1", member1ActorRef,
+ ImmutableMap.<String,String>builder().
+ put("member2", member2ActorRef.path().toString()).
+ put("member3", member3ActorRef.path().toString()).build());
+
+ DefaultConfigParamsImpl member1ConfigParams = newConfigParams();
+ member1Context.setConfigParams(member1ConfigParams);
+
+ initializeLeaderBehavior(member1Actor, member1Context, 2);
+
+ member2Actor.clear();
+ member3Actor.clear();
+
+ testLog.info("setupInitialMemberBehaviors ending");
+ }
+}
/*
- * Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2015 Brocade Communications 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.cluster.datastore.utils;
+package org.opendaylight.controller.cluster.raft.utils;
-import static org.junit.Assert.assertEquals;
+import akka.dispatch.Futures;
+import akka.japi.Procedure;
+import akka.persistence.PersistentConfirmation;
+import akka.persistence.PersistentId;
+import akka.persistence.PersistentImpl;
+import akka.persistence.PersistentRepr;
+import akka.persistence.journal.japi.AsyncWriteJournal;
+import com.google.common.collect.Maps;
+import com.google.common.util.concurrent.Uninterruptibles;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import com.google.common.collect.Maps;
-import com.google.common.util.concurrent.Uninterruptibles;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import scala.concurrent.Future;
-import akka.dispatch.Futures;
-import akka.japi.Procedure;
-import akka.persistence.PersistentConfirmation;
-import akka.persistence.PersistentId;
-import akka.persistence.PersistentImpl;
-import akka.persistence.PersistentRepr;
-import akka.persistence.journal.japi.AsyncWriteJournal;
+/**
+ * An akka AsyncWriteJournal implementation that stores data in memory. This is intended for testing.
+ *
+ * @author Thomas Pantelis
+ */
public class InMemoryJournal extends AsyncWriteJournal {
+ static final Logger LOG = LoggerFactory.getLogger(InMemoryJournal.class);
+
private static final Map<String, Map<Long, Object>> journals = new ConcurrentHashMap<>();
private static final Map<String, CountDownLatch> deleteMessagesCompleteLatches = new ConcurrentHashMap<>();
+ private static final Map<String, CountDownLatch> writeMessagesCompleteLatches = new ConcurrentHashMap<>();
+
private static final Map<String, CountDownLatch> blockReadMessagesLatches = new ConcurrentHashMap<>();
public static void addEntry(String persistenceId, long sequenceNr, Object data) {
journals.clear();
}
+ @SuppressWarnings("unchecked")
+ public static <T> List<T> get(String persistenceId, Class<T> type) {
+ Map<Long, Object> journalMap = journals.get(persistenceId);
+ if(journalMap == null) {
+ return Collections.<T>emptyList();
+ }
+
+ synchronized (journalMap) {
+ List<T> journal = new ArrayList<>(journalMap.size());
+ for(Object entry: journalMap.values()) {
+ if(type.isInstance(entry)) {
+ journal.add((T) entry);
+ }
+ }
+
+ return journal;
+ }
+ }
+
public static Map<Long, Object> get(String persistenceId) {
- Map<Long, Object> journal = journals.get(persistenceId);
- return journal != null ? journal : Collections.<Long, Object>emptyMap();
+ Map<Long, Object> journalMap = journals.get(persistenceId);
+ return journalMap != null ? journalMap : Collections.<Long, Object>emptyMap();
+ }
+
+ public static void dumpJournal(String persistenceId) {
+ StringBuilder builder = new StringBuilder(String.format("Journal log for %s:", persistenceId));
+ Map<Long, Object> journalMap = journals.get(persistenceId);
+ if(journalMap != null) {
+ synchronized (journalMap) {
+ for(Map.Entry<Long, Object> e: journalMap.entrySet()) {
+ builder.append("\n ").append(e.getKey()).append(" = ").append(e.getValue());
+ }
+ }
+ }
+
+ LOG.info(builder.toString());
}
public static void waitForDeleteMessagesComplete(String persistenceId) {
- assertEquals("Recovery complete", true, Uninterruptibles.awaitUninterruptibly(
- deleteMessagesCompleteLatches.get(persistenceId), 5, TimeUnit.SECONDS));
+ if(!Uninterruptibles.awaitUninterruptibly(deleteMessagesCompleteLatches.get(persistenceId), 5, TimeUnit.SECONDS)) {
+ throw new AssertionError("Delete messages did not complete");
+ }
+ }
+
+ public static void waitForWriteMessagesComplete(String persistenceId) {
+ if(!Uninterruptibles.awaitUninterruptibly(writeMessagesCompleteLatches.get(persistenceId), 5, TimeUnit.SECONDS)) {
+ throw new AssertionError("Journal write messages did not complete");
+ }
}
public static void addDeleteMessagesCompleteLatch(String persistenceId) {
deleteMessagesCompleteLatches.put(persistenceId, new CountDownLatch(1));
}
+ public static void addWriteMessagesCompleteLatch(String persistenceId, int count) {
+ writeMessagesCompleteLatches.put(persistenceId, new CountDownLatch(count));
+ }
+
public static void addBlockReadMessagesLatch(String persistenceId, CountDownLatch latch) {
blockReadMessagesLatches.put(persistenceId, latch);
}
@Override
public Future<Long> doAsyncReadHighestSequenceNr(String persistenceId, long fromSequenceNr) {
- return Futures.successful(-1L);
+ // Akka calls this during recovery.
+
+ Map<Long, Object> journal = journals.get(persistenceId);
+ if(journal == null) {
+ return Futures.successful(-1L);
+ }
+
+ synchronized (journal) {
+ long highest = -1;
+ for (Long seqNr : journal.keySet()) {
+ if(seqNr.longValue() >= fromSequenceNr && seqNr.longValue() > highest) {
+ highest = seqNr.longValue();
+ }
+ }
+
+ return Futures.successful(highest);
+ }
}
@Override
}
synchronized (journal) {
+ LOG.trace("doAsyncWriteMessages: id: {}: seqNr: {}, payload: {}", repr.persistenceId(),
+ repr.sequenceNr(), repr.payload());
journal.put(repr.sequenceNr(), repr.payload());
}
+
+ CountDownLatch latch = writeMessagesCompleteLatches.get(repr.persistenceId());
+ if(latch != null) {
+ latch.countDown();
+ }
}
+
return null;
}
}, context().dispatcher());
/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2015 Brocade Communications 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.cluster.datastore.utils;
+package org.opendaylight.controller.cluster.raft.utils;
import akka.dispatch.Futures;
import akka.japi.Option;
import akka.persistence.SnapshotSelectionCriteria;
import akka.persistence.snapshot.japi.SnapshotStore;
import com.google.common.collect.Iterables;
-import scala.concurrent.Future;
+import com.google.common.collect.Lists;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import org.opendaylight.controller.cluster.raft.Snapshot;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import scala.concurrent.Future;
+/**
+ * An akka SnapshotStore implementation that stores data in memory. This is intended for testing.
+ *
+ * @author Thomas Pantelis
+ */
public class InMemorySnapshotStore extends SnapshotStore {
+ static final Logger LOG = LoggerFactory.getLogger(InMemorySnapshotStore.class);
+
private static Map<String, List<StoredSnapshot>> snapshots = new ConcurrentHashMap<>();
- public static void addSnapshot(String persistentId, Snapshot snapshot) {
+ public static void addSnapshot(String persistentId, Object snapshot) {
List<StoredSnapshot> snapshotList = snapshots.get(persistentId);
if(snapshotList == null) {
snapshots.put(persistentId, snapshotList);
}
- snapshotList.add(new StoredSnapshot(new SnapshotMetadata(persistentId, snapshotList.size(),
- System.currentTimeMillis()), snapshot));
+ synchronized (snapshotList) {
+ snapshotList.add(new StoredSnapshot(new SnapshotMetadata(persistentId, snapshotList.size(),
+ System.currentTimeMillis()), snapshot));
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <T> List<T> getSnapshots(String persistentId, Class<T> type) {
+ List<StoredSnapshot> stored = snapshots.get(persistentId);
+ if(stored == null) {
+ return Collections.emptyList();
+ }
+
+ List<T> retList;
+ synchronized (stored) {
+ retList = Lists.newArrayListWithCapacity(stored.size());
+ for(StoredSnapshot s: stored) {
+ if(type.isInstance(s.getData())) {
+ retList.add((T) s.getData());
+ }
+ }
+ }
+
+ return retList;
}
public static void clear() {
snapshotList = new ArrayList<>();
snapshots.put(snapshotMetadata.persistenceId(), snapshotList);
}
- snapshotList.add(new StoredSnapshot(snapshotMetadata, o));
+ synchronized (snapshotList) {
+ snapshotList.add(new StoredSnapshot(snapshotMetadata, o));
+ }
return Futures.successful(null);
}
int deleteIndex = -1;
- for(int i=0;i<snapshotList.size(); i++){
- StoredSnapshot snapshot = snapshotList.get(i);
- if(snapshotMetadata.equals(snapshot.getMetadata())){
- deleteIndex = i;
- break;
+ synchronized (snapshotList) {
+ for(int i=0;i<snapshotList.size(); i++){
+ StoredSnapshot snapshot = snapshotList.get(i);
+ if(snapshotMetadata.equals(snapshot.getMetadata())){
+ deleteIndex = i;
+ break;
+ }
}
- }
- if(deleteIndex != -1){
- snapshotList.remove(deleteIndex);
+ if(deleteIndex != -1){
+ snapshotList.remove(deleteIndex);
+ }
}
-
}
@Override
- public void doDelete(String s, SnapshotSelectionCriteria snapshotSelectionCriteria)
+ public void doDelete(String persistentId, SnapshotSelectionCriteria snapshotSelectionCriteria)
throws Exception {
- List<StoredSnapshot> snapshotList = snapshots.get(s);
+ List<StoredSnapshot> snapshotList = snapshots.get(persistentId);
if(snapshotList == null){
return;
}
- // TODO : This is a quick and dirty implementation. Do actual match later.
- snapshotList.clear();
- snapshots.remove(s);
+ synchronized (snapshotList) {
+ Iterator<StoredSnapshot> iter = snapshotList.iterator();
+ while(iter.hasNext()) {
+ StoredSnapshot s = iter.next();
+ LOG.trace("doDelete: sequenceNr: {}, maxSequenceNr: {}", s.getMetadata().sequenceNr(),
+ snapshotSelectionCriteria.maxSequenceNr());
+
+ if(s.getMetadata().sequenceNr() <= snapshotSelectionCriteria.maxSequenceNr()) {
+ iter.remove();
+ }
+ }
+ }
}
private static class StoredSnapshot {
import akka.actor.UntypedActor;
import akka.pattern.Patterns;
import akka.util.Timeout;
+import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Uninterruptibles;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.Assert;
+import org.opendaylight.controller.cluster.raft.SerializationUtils;
import scala.concurrent.Await;
import scala.concurrent.Future;
import scala.concurrent.duration.Duration;
public class MessageCollectorActor extends UntypedActor {
private static final String ARE_YOU_READY = "ARE_YOU_READY";
+ private static final String GET_ALL_MESSAGES = "get-all-messages";
+ private static final String CLEAR_MESSAGES = "clear-messages";
private final List<Object> messages = new ArrayList<>();
return;
}
- if(message instanceof String){
- if("get-all-messages".equals(message)){
- getSender().tell(new ArrayList<>(messages), getSelf());
- }
+ if(GET_ALL_MESSAGES.equals(message)) {
+ getSender().tell(new ArrayList<>(messages), getSelf());
+ } else if(CLEAR_MESSAGES.equals(message)) {
+ messages.clear();
} else if(message != null) {
- messages.add(message);
+ messages.add(SerializationUtils.fromSerializable(message));
}
}
public static List<Object> getAllMessages(ActorRef actor) throws Exception {
FiniteDuration operationDuration = Duration.create(5, TimeUnit.SECONDS);
Timeout operationTimeout = new Timeout(operationDuration);
- Future<Object> future = Patterns.ask(actor, "get-all-messages", operationTimeout);
+ Future<Object> future = Patterns.ask(actor, GET_ALL_MESSAGES, operationTimeout);
return (List<Object>) Await.result(future, operationDuration);
}
+ public static void clearMessages(ActorRef actor) {
+ actor.tell(CLEAR_MESSAGES, ActorRef.noSender());
+ }
+
/**
* Get the first message that matches the specified class
* @param actor
return null;
}
+ public static <T> List<T> expectMatching(ActorRef actor, Class<T> clazz, int count) {
+ int timeout = 5000;
+ List<T> messages = Collections.emptyList();
+ for(int i = 0; i < timeout / 50; i++) {
+ try {
+ messages = getAllMatching(actor, clazz);
+ if(messages.size() >= count) {
+ return messages;
+ }
+ } catch (Exception e) {}
+
+ Uninterruptibles.sleepUninterruptibly(50, TimeUnit.MILLISECONDS);
+ }
+
+ Assert.fail(String.format("Expected %d messages of type %s. Actual received was %d: %s", count, clazz,
+ messages.size(), messages));
+ return null;
+ }
+
public static <T> T expectFirstMatching(ActorRef actor, Class<T> clazz) {
return expectFirstMatching(actor, clazz, 5000);
}
return null;
}
+ public static <T> T expectFirstMatching(ActorRef actor, Class<T> clazz, Predicate<T> matcher) {
+ int timeout = 5000;
+ T lastMessage = null;
+ for(int i = 0; i < timeout / 50; i++) {
+ try {
+ List<T> messages = getAllMatching(actor, clazz);
+ for(T msg: messages) {
+ if(matcher.apply(msg)) {
+ return msg;
+ }
+
+ lastMessage = msg;
+ }
+ } catch (Exception e) {}
+
+ Uninterruptibles.sleepUninterruptibly(50, TimeUnit.MILLISECONDS);
+ }
+
+ Assert.fail(String.format("Expected specific message of type %s. Last message received was: %s", clazz, lastMessage));
+ return null;
+ }
+
public static <T> List<T> getAllMatching(ActorRef actor, Class<T> clazz) throws Exception {
List<Object> allMessages = getAllMessages(actor);
+++ /dev/null
-/*
- * 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.cluster.raft.utils;
-
-import akka.dispatch.Futures;
-import akka.japi.Procedure;
-import akka.persistence.PersistentConfirmation;
-import akka.persistence.PersistentId;
-import akka.persistence.PersistentImpl;
-import akka.persistence.PersistentRepr;
-import akka.persistence.journal.japi.AsyncWriteJournal;
-import com.google.common.collect.Maps;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import scala.concurrent.Future;
-
-public class MockAkkaJournal extends AsyncWriteJournal {
-
- private static Map<Long, Object> journal = Maps.newLinkedHashMap();
-
- public static void addToJournal(long sequenceNr, Object message) {
- journal.put(sequenceNr, message);
- }
-
- public static void clearJournal() {
- journal.clear();
- }
-
- @Override
- public Future<Void> doAsyncReplayMessages(final String persistenceId, long fromSequenceNr,
- long toSequenceNr, long max, final Procedure<PersistentRepr> replayCallback) {
-
- return Futures.future(new Callable<Void>() {
- @Override
- public Void call() throws Exception {
- for (Map.Entry<Long,Object> entry : journal.entrySet()) {
- PersistentRepr persistentMessage =
- new PersistentImpl(entry.getValue(), entry.getKey(), persistenceId, false, null, null);
- replayCallback.apply(persistentMessage);
- }
- return null;
- }
- }, context().dispatcher());
- }
-
- @Override
- public Future<Long> doAsyncReadHighestSequenceNr(String s, long l) {
- return Futures.successful(new Long(0));
- }
-
- @Override
- public Future<Void> doAsyncWriteMessages(Iterable<PersistentRepr> persistentReprs) {
- return Futures.successful(null);
- }
-
- @Override
- public Future<Void> doAsyncWriteConfirmations(Iterable<PersistentConfirmation> persistentConfirmations) {
- return Futures.successful(null);
- }
-
- @Override
- public Future<Void> doAsyncDeleteMessages(Iterable<PersistentId> persistentIds, boolean b) {
- return Futures.successful(null);
- }
-
- @Override
- public Future<Void> doAsyncDeleteMessagesTo(String s, long l, boolean b) {
- return Futures.successful(null);
- }
-}
+++ /dev/null
-/*
- * 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.cluster.raft.utils;
-
-import akka.dispatch.Futures;
-import akka.japi.Option;
-import akka.persistence.SelectedSnapshot;
-import akka.persistence.SnapshotMetadata;
-import akka.persistence.SnapshotSelectionCriteria;
-import akka.persistence.snapshot.japi.SnapshotStore;
-import org.opendaylight.controller.cluster.raft.Snapshot;
-import scala.concurrent.Future;
-
-
-public class MockSnapshotStore extends SnapshotStore {
-
- private static Snapshot mockSnapshot;
- private static String persistenceId;
-
- public static void setMockSnapshot(Snapshot s) {
- mockSnapshot = s;
- }
-
- public static void setPersistenceId(String pId) {
- persistenceId = pId;
- }
-
- @Override
- public Future<Option<SelectedSnapshot>> doLoadAsync(String s, SnapshotSelectionCriteria snapshotSelectionCriteria) {
- if (mockSnapshot == null) {
- return Futures.successful(Option.<SelectedSnapshot>none());
- }
-
- SnapshotMetadata smd = new SnapshotMetadata(persistenceId, 1, 12345);
- SelectedSnapshot selectedSnapshot =
- new SelectedSnapshot(smd, mockSnapshot);
- return Futures.successful(Option.some(selectedSnapshot));
- }
-
- @Override
- public Future<Void> doSaveAsync(SnapshotMetadata snapshotMetadata, Object o) {
- return null;
- }
-
- @Override
- public void onSaved(SnapshotMetadata snapshotMetadata) throws Exception {
-
- }
-
- @Override
- public void doDelete(SnapshotMetadata snapshotMetadata) throws Exception {
-
- }
-
- @Override
- public void doDelete(String s, SnapshotSelectionCriteria snapshotSelectionCriteria) throws Exception {
-
- }
-}
mock-snapshot-store {
# Class name of the plugin.
- class = "org.opendaylight.controller.cluster.raft.utils.MockSnapshotStore"
+ class = "org.opendaylight.controller.cluster.raft.utils.InMemorySnapshotStore"
# Dispatcher for the plugin actor.
plugin-dispatcher = "akka.persistence.dispatchers.default-plugin-dispatcher"
}
mock-journal {
# Class name of the plugin.
- class = "org.opendaylight.controller.cluster.raft.utils.MockAkkaJournal"
+ class = "org.opendaylight.controller.cluster.raft.utils.InMemoryJournal"
# Dispatcher for the plugin actor.
plugin-dispatcher = "akka.persistence.dispatchers.default-plugin-dispatcher"
}
package org.opendaylight.controller.config.yang.md.sal.binding.impl;
import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
-import org.opendaylight.controller.md.sal.binding.impl.ForwardedBindingDataBroker;
+import org.opendaylight.controller.md.sal.binding.impl.BindingDOMDataBrokerAdapter;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
public class BindingAsyncDataBrokerImplModule extends
public java.lang.AutoCloseable createInstance() {
final BindingToNormalizedNodeCodec mappingService = getBindingMappingServiceDependency();
final DOMDataBroker domDataBroker = getDomAsyncBrokerDependency();
- return new ForwardedBindingDataBroker(domDataBroker, mappingService);
+ return new BindingDOMDataBrokerAdapter(domDataBroker, mappingService);
}
}
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
-import org.opendaylight.controller.md.sal.binding.impl.ForwardedNotificationService;
+import org.opendaylight.controller.md.sal.binding.impl.BindingDOMNotificationServiceAdapter;
import org.opendaylight.controller.md.sal.dom.api.DOMNotificationService;
import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
import org.opendaylight.controller.sal.core.api.Broker;
final BindingToNormalizedNodeCodec codec = getBindingMappingServiceDependency();
final Broker.ProviderSession session = getDomAsyncBrokerDependency().registerProvider(new DummyDOMProvider());
final DOMNotificationService notifService = session.getService(DOMNotificationService.class);
- return new ForwardedNotificationService(codec.getCodecRegistry(), notifService, SingletonHolder.INVOKER_FACTORY);
+ return new BindingDOMNotificationServiceAdapter(codec.getCodecRegistry(), notifService, SingletonHolder.INVOKER_FACTORY);
}
}
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
-import org.opendaylight.controller.md.sal.binding.impl.ForwardedNotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.impl.BindingDOMNotificationPublishServiceAdapter;
import org.opendaylight.controller.md.sal.dom.api.DOMNotificationPublishService;
import org.opendaylight.controller.sal.core.api.Broker;
final BindingToNormalizedNodeCodec codec = getBindingMappingServiceDependency();
final Broker.ProviderSession session = getDomAsyncBrokerDependency().registerProvider(new DummyDOMProvider());
final DOMNotificationPublishService publishService = session.getService(DOMNotificationPublishService.class);
- return new ForwardedNotificationPublishService(codec.getCodecRegistry(), publishService);
+ return new BindingDOMNotificationPublishServiceAdapter(codec.getCodecRegistry(), publishService);
}
}
import com.google.common.base.Preconditions;
import java.util.Hashtable;
-import javassist.ClassPool;
import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
-import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
-import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
/**
-*
-*/
+ *
+**/
public final class RuntimeMappingModule extends AbstractRuntimeMappingModule {
private BundleContext bundleContext;
@Override
public java.lang.AutoCloseable createInstance() {
final GeneratedClassLoadingStrategy classLoading = getGlobalClassLoadingStrategy();
- final BindingIndependentMappingService legacyMapping = getGlobalLegacyMappingService(classLoading);
BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(SingletonHolder.JAVASSIST));
- BindingToNormalizedNodeCodec instance = new BindingToNormalizedNodeCodec(classLoading, legacyMapping, codecRegistry);
+ BindingToNormalizedNodeCodec instance = new BindingToNormalizedNodeCodec(classLoading, codecRegistry);
bundleContext.registerService(SchemaContextListener.class, instance, new Hashtable<String,String>());
return instance;
}
- private BindingIndependentMappingService getGlobalLegacyMappingService(final GeneratedClassLoadingStrategy classLoading) {
- BindingIndependentMappingService potential = tryToReuseGlobalMappingServiceInstance();
- if(potential == null) {
- potential = new RuntimeGeneratedMappingServiceImpl(ClassPool.getDefault(),classLoading);
- bundleContext.registerService(SchemaContextListener.class, (SchemaContextListener) potential, new Hashtable<String,String>());
- }
- return potential;
- }
-
private GeneratedClassLoadingStrategy getGlobalClassLoadingStrategy() {
ServiceReference<GeneratedClassLoadingStrategy> ref = bundleContext.getServiceReference(GeneratedClassLoadingStrategy.class);
return bundleContext.getService(ref);
}
- private BindingIndependentMappingService tryToReuseGlobalMappingServiceInstance() {
- ServiceReference<BindingIndependentMappingService> serviceRef = getBundleContext().getServiceReference(BindingIndependentMappingService.class);
- if(serviceRef == null) {
- return null;
- }
- return bundleContext.getService(serviceRef);
-
- }
-
- private BundleContext getBundleContext() {
- return bundleContext;
- }
-
public void setBundleContext(final BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
private static final Map<Class<?>,BindingDOMAdapterBuilder.Factory<?>> FACTORIES = ImmutableMap.<Class<?>,BindingDOMAdapterBuilder.Factory<?>>builder()
- .put(NotificationService.class,ForwardedNotificationService.BUILDER_FACTORY)
- .put(NotificationPublishService.class,ForwardedNotificationPublishService.BUILDER_FACTORY)
- .put(DataBroker.class,ForwardedBindingDataBroker.BUILDER_FACTORY)
+ .put(NotificationService.class,BindingDOMNotificationServiceAdapter.BUILDER_FACTORY)
+ .put(NotificationPublishService.class,BindingDOMNotificationPublishServiceAdapter.BUILDER_FACTORY)
+ .put(DataBroker.class,BindingDOMDataBrokerAdapter.BUILDER_FACTORY)
.put(RpcConsumerRegistry.class,BindingDOMRpcServiceAdapter.BUILDER_FACTORY)
.build();
*
*/
-public class ForwardedBindingDataBroker extends AbstractForwardedDataBroker implements DataBroker {
+public class BindingDOMDataBrokerAdapter extends AbstractForwardedDataBroker implements DataBroker {
static final Factory<DataBroker> BUILDER_FACTORY = new BindingDOMAdapterBuilder.Factory<DataBroker>() {
};
- public ForwardedBindingDataBroker(final DOMDataBroker domDataBroker, final BindingToNormalizedNodeCodec codec) {
+ public BindingDOMDataBrokerAdapter(final DOMDataBroker domDataBroker, final BindingToNormalizedNodeCodec codec) {
super(domDataBroker, codec);
}
@Deprecated
- public ForwardedBindingDataBroker(final DOMDataBroker domDataBroker, final BindingToNormalizedNodeCodec codec, final SchemaService schemaService) {
+ public BindingDOMDataBrokerAdapter(final DOMDataBroker domDataBroker, final BindingToNormalizedNodeCodec codec, final SchemaService schemaService) {
super(domDataBroker, codec,schemaService);
}
@Override
public ReadOnlyTransaction newReadOnlyTransaction() {
- return new BindingDataReadTransactionImpl(getDelegate().newReadOnlyTransaction(),getCodec());
+ return new BindingDOMReadTransactionAdapter(getDelegate().newReadOnlyTransaction(),getCodec());
}
@Override
public ReadWriteTransaction newReadWriteTransaction() {
- return new BindingDataReadWriteTransactionImpl(getDelegate().newReadWriteTransaction(),getCodec());
+ return new BindingDOMReadWriteTransactionAdapter(getDelegate().newReadWriteTransaction(),getCodec());
}
@Override
public WriteTransaction newWriteOnlyTransaction() {
- return new BindingDataWriteTransactionImpl<>(getDelegate().newWriteOnlyTransaction(),getCodec());
+ return new BindingDOMWriteTransactionAdapter<>(getDelegate().newWriteOnlyTransaction(),getCodec());
}
@Override
public BindingTransactionChain createTransactionChain(final TransactionChainListener listener) {
- return new BindingTranslatedTransactionChain(getDelegate(), getCodec(), listener);
+ return new BindingDOMTransactionChainAdapter(getDelegate(), getCodec(), listener);
}
private static class Builder extends BindingDOMAdapterBuilder<DataBroker> {
protected DataBroker createInstance(BindingToNormalizedNodeCodec codec,
ClassToInstanceMap<DOMService> delegates) {
DOMDataBroker domDataBroker = delegates.getInstance(DOMDataBroker.class);
- return new ForwardedBindingDataBroker(domDataBroker, codec);
+ return new BindingDOMDataBrokerAdapter(domDataBroker, codec);
}
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-public class ForwardedNotificationPublishService implements NotificationPublishService, AutoCloseable {
+public class BindingDOMNotificationPublishServiceAdapter implements NotificationPublishService, AutoCloseable {
static final Factory<NotificationPublishService> BUILDER_FACTORY = new BindingDOMAdapterBuilder.Factory<NotificationPublishService>() {
private final BindingNormalizedNodeSerializer codecRegistry;
private final DOMNotificationPublishService domPublishService;
- public ForwardedNotificationPublishService(BindingNormalizedNodeSerializer codecRegistry, DOMNotificationPublishService domPublishService) {
+ public BindingDOMNotificationPublishServiceAdapter(BindingNormalizedNodeSerializer codecRegistry, DOMNotificationPublishService domPublishService) {
this.codecRegistry = codecRegistry;
this.domPublishService = domPublishService;
}
ClassToInstanceMap<DOMService> delegates) {
BindingNormalizedNodeSerializer codecReg = codec.getCodecRegistry();
DOMNotificationPublishService domPublish = delegates.getInstance(DOMNotificationPublishService.class);
- return new ForwardedNotificationPublishService(codecReg, domPublish);
+ return new BindingDOMNotificationPublishServiceAdapter(codecReg, domPublish);
}
}
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-public class ForwardedNotificationService implements NotificationService, AutoCloseable {
+public class BindingDOMNotificationServiceAdapter implements NotificationService, AutoCloseable {
public static final Factory<NotificationService> BUILDER_FACTORY = new Factory<NotificationService>() {
private final DOMNotificationService domNotifService;
private final NotificationInvokerFactory notificationInvokerFactory;
- public ForwardedNotificationService(BindingNormalizedNodeSerializer codec, DOMNotificationService domNotifService, NotificationInvokerFactory notificationInvokerFactory) {
+ public BindingDOMNotificationServiceAdapter(BindingNormalizedNodeSerializer codec, DOMNotificationService domNotifService, NotificationInvokerFactory notificationInvokerFactory) {
this.codec = codec;
this.domNotifService = domNotifService;
this.notificationInvokerFactory = notificationInvokerFactory;
ClassToInstanceMap<DOMService> delegates) {
DOMNotificationService domNotification = delegates.getInstance(DOMNotificationService.class);
NotificationInvokerFactory invokerFactory = SingletonHolder.INVOKER_FACTORY;
- return new ForwardedNotificationService(codec.getCodecFactory(), domNotification, invokerFactory);
+ return new BindingDOMNotificationServiceAdapter(codec.getCodecRegistry(), domNotification, invokerFactory);
}
@Override
import com.google.common.base.Optional;
import com.google.common.util.concurrent.CheckedFuture;
-class BindingDataReadTransactionImpl extends AbstractForwardedTransaction<DOMDataReadOnlyTransaction> implements
+class BindingDOMReadTransactionAdapter extends AbstractForwardedTransaction<DOMDataReadOnlyTransaction> implements
ReadOnlyTransaction {
- protected BindingDataReadTransactionImpl(final DOMDataReadOnlyTransaction delegate,
+ protected BindingDOMReadTransactionAdapter(final DOMDataReadOnlyTransaction delegate,
final BindingToNormalizedNodeCodec codec) {
super(delegate, codec);
}
import com.google.common.base.Optional;
import com.google.common.util.concurrent.CheckedFuture;
-class BindingDataReadWriteTransactionImpl extends
- BindingDataWriteTransactionImpl<DOMDataReadWriteTransaction> implements ReadWriteTransaction {
+class BindingDOMReadWriteTransactionAdapter extends
+ BindingDOMWriteTransactionAdapter<DOMDataReadWriteTransaction> implements ReadWriteTransaction {
- protected BindingDataReadWriteTransactionImpl(final DOMDataReadWriteTransaction delegate,
+ protected BindingDOMReadWriteTransactionAdapter(final DOMDataReadWriteTransaction delegate,
final BindingToNormalizedNodeCodec codec) {
super(delegate, codec);
}
}
private <S extends RpcService, T extends S> ObjectRegistration<T> register(final Class<S> type, final T implementation, final Set<DOMRpcIdentifier> domRpcs) {
- final BindingRpcImplementationAdapter adapter = new BindingRpcImplementationAdapter(codec.getCodecFactory(), type, implementation);
+ final BindingRpcImplementationAdapter adapter = new BindingRpcImplementationAdapter(codec.getCodecRegistry(), type, implementation);
final DOMRpcImplementationRegistration<?> domReg = domRpcRegistry.registerRpcImplementation(adapter, domRpcs);
@Override
public ListenableFuture<RpcResult<?>> invoke(final SchemaPath rpc, final DataObject input) {
final CheckedFuture<DOMRpcResult, DOMRpcException> domFuture = domService.invokeRpc(rpc, serialize(rpc,input));
- return transformFuture(rpc,domFuture,codec.getCodecFactory());
+ return transformFuture(rpc,domFuture,codec.getCodecRegistry());
}
private RpcServiceAdapter createProxy(final Class<? extends RpcService> key) {
return null;
}
final QName rpcInputIdentifier = QName.create(rpc.getLastComponent(),"input");
- return new LazySerializedContainerNode(rpcInputIdentifier, input, codec.getCodecFactory());
+ return new LazySerializedContainerNode(rpcInputIdentifier, input, codec.getCodecRegistry());
}
private static ListenableFuture<RpcResult<?>> transformFuture(final SchemaPath rpc,final ListenableFuture<DOMRpcResult> domFuture, final BindingNormalizedNodeCodecRegistry codec) {
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-final class BindingTranslatedTransactionChain implements BindingTransactionChain, Delegator<DOMTransactionChain> {
+final class BindingDOMTransactionChainAdapter implements BindingTransactionChain, Delegator<DOMTransactionChain> {
- private static final Logger LOG = LoggerFactory.getLogger(BindingTranslatedTransactionChain.class);
+ private static final Logger LOG = LoggerFactory.getLogger(BindingDOMTransactionChainAdapter.class);
private final DOMTransactionChain delegate;
private final BindingToNormalizedNodeCodec codec;
private final DelegateChainListener domListener;
private final TransactionChainListener bindingListener;
- public BindingTranslatedTransactionChain(final DOMDataBroker chainFactory,
+ public BindingDOMTransactionChainAdapter(final DOMDataBroker chainFactory,
final BindingToNormalizedNodeCodec codec, final TransactionChainListener listener) {
Preconditions.checkNotNull(chainFactory, "DOM Transaction chain factory must not be null");
this.domListener = new DelegateChainListener();
@Override
public ReadOnlyTransaction newReadOnlyTransaction() {
DOMDataReadOnlyTransaction delegateTx = delegate.newReadOnlyTransaction();
- ReadOnlyTransaction bindingTx = new BindingDataReadTransactionImpl(delegateTx, codec);
+ ReadOnlyTransaction bindingTx = new BindingDOMReadTransactionAdapter(delegateTx, codec);
return bindingTx;
}
@Override
public ReadWriteTransaction newReadWriteTransaction() {
DOMDataReadWriteTransaction delegateTx = delegate.newReadWriteTransaction();
- ReadWriteTransaction bindingTx = new BindingDataReadWriteTransactionImpl(delegateTx, codec) {
+ ReadWriteTransaction bindingTx = new BindingDOMReadWriteTransactionAdapter(delegateTx, codec) {
@Override
public CheckedFuture<Void, TransactionCommitFailedException> submit() {
@Override
public WriteTransaction newWriteOnlyTransaction() {
final DOMDataWriteTransaction delegateTx = delegate.newWriteOnlyTransaction();
- WriteTransaction bindingTx = new BindingDataWriteTransactionImpl<DOMDataWriteTransaction>(delegateTx, codec) {
+ WriteTransaction bindingTx = new BindingDOMWriteTransactionAdapter<DOMDataWriteTransaction>(delegateTx, codec) {
@Override
public CheckedFuture<Void,TransactionCommitFailedException> submit() {
public void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
Preconditions.checkState(delegate.equals(chain),
"Illegal state - listener for %s was invoked for incorrect chain %s.", delegate, chain);
- bindingListener.onTransactionChainSuccessful(BindingTranslatedTransactionChain.this);
+ bindingListener.onTransactionChainSuccessful(BindingDOMTransactionChainAdapter.this);
}
}
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.ListenableFuture;
-class BindingDataWriteTransactionImpl<T extends DOMDataWriteTransaction> extends
+class BindingDOMWriteTransactionAdapter<T extends DOMDataWriteTransaction> extends
AbstractWriteTransaction<T> implements WriteTransaction {
- protected BindingDataWriteTransactionImpl(final T delegateTx, final BindingToNormalizedNodeCodec codec) {
+ protected BindingDOMWriteTransactionAdapter(final T delegateTx, final BindingToNormalizedNodeCodec codec) {
super(delegateTx, codec);
}
import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTree;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeFactory;
import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-public class BindingToNormalizedNodeCodec implements SchemaContextListener,AutoCloseable {
+public class BindingToNormalizedNodeCodec implements BindingCodecTreeFactory, SchemaContextListener, AutoCloseable {
- private final BindingIndependentMappingService bindingToLegacy;
private final BindingNormalizedNodeCodecRegistry codecRegistry;
private DataNormalizer legacyToNormalized;
private final GeneratedClassLoadingStrategy classLoadingStrategy;
private BindingRuntimeContext runtimeContext;
- public BindingToNormalizedNodeCodec(final GeneratedClassLoadingStrategy classLoadingStrategy, final BindingIndependentMappingService mappingService, final BindingNormalizedNodeCodecRegistry codecRegistry) {
- super();
- this.bindingToLegacy = mappingService;
+ public BindingToNormalizedNodeCodec(final GeneratedClassLoadingStrategy classLoadingStrategy,
+ final BindingNormalizedNodeCodecRegistry codecRegistry) {
this.classLoadingStrategy = classLoadingStrategy;
this.codecRegistry = codecRegistry;
return currentOp.createDefault(path.getLastPathArgument());
}
- public BindingIndependentMappingService getLegacy() {
- return bindingToLegacy;
- }
-
public BindingNormalizedNodeCodecRegistry getCodecRegistry() {
return codecRegistry;
}
}
return key.getMethod(methodName);
}
+
+ @Override
+ public BindingCodecTree create(BindingRuntimeContext context) {
+ return codecRegistry.create(context);
+ }
+
+ @Override
+ public BindingCodecTree create(SchemaContext context, Class<?>... bindingClasses) {
+ return codecRegistry.create(context, bindingClasses);
+ }
+
}
identity runtime-generated-mapping {
base config:module-type;
config:provided-service binding-dom-mapping-service;
+ config:provided-service sal:binding-codec-tree-factory;
config:java-name-prefix RuntimeMapping;
}
package org.opendaylight.controller.md.sal.binding.impl.test;
import static org.junit.Assert.assertTrue;
-import javassist.ClassPool;
+import javassist.ClassPool;
import org.junit.Test;
import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
import org.opendaylight.controller.md.sal.binding.test.AbstractSchemaAwareTest;
import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
-import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.QName;
private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
- private RuntimeGeneratedMappingServiceImpl mappingService;
- private BindingToNormalizedNodeCodec codec;
+ private BindingToNormalizedNodeCodec codec;
@Override
protected void setupWithSchema(final SchemaContext context) {
- mappingService = new RuntimeGeneratedMappingServiceImpl(ClassPool.getDefault());
DataObjectSerializerGenerator streamWriter = StreamWriterGenerator.create(JavassistUtils.forClassPool(ClassPool.getDefault()));
BindingNormalizedNodeCodecRegistry registry = new BindingNormalizedNodeCodecRegistry(streamWriter);
- codec = new BindingToNormalizedNodeCodec(GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy(), mappingService, registry);
- mappingService.onGlobalContextUpdated(context);
+ codec = new BindingToNormalizedNodeCodec(GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy(), registry);
codec.onGlobalContextUpdated(context);
};
import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.path;
-import org.opendaylight.controller.md.sal.binding.compat.HeliumRpcProviderRegistry;
-
import com.google.common.base.Throwables;
import java.util.Arrays;
import javassist.ClassPool;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.binding.compat.HeliumRpcProviderRegistry;
import org.opendaylight.controller.md.sal.binding.impl.BindingDOMRpcProviderServiceAdapter;
import org.opendaylight.controller.md.sal.binding.impl.BindingDOMRpcServiceAdapter;
import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
final DataObjectSerializerGenerator generator = StreamWriterGenerator.create(JavassistUtils.forClassPool(ClassPool.getDefault()));
final BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(generator);
final GeneratedClassLoadingStrategy classLoadingStrategy = GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy();
- final BindingToNormalizedNodeCodec codec = new BindingToNormalizedNodeCodec(classLoadingStrategy, null, codecRegistry);
+ final BindingToNormalizedNodeCodec codec = new BindingToNormalizedNodeCodec(classLoadingStrategy, codecRegistry);
final DOMRpcRouter domRpcRegistry = new DOMRpcRouter();
domRpcRegistry.onGlobalContextUpdated(context);
codec.onGlobalContextUpdated(context);
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
import org.opendaylight.controller.md.sal.binding.api.NotificationService;
+import org.opendaylight.controller.md.sal.binding.impl.BindingDOMDataBrokerAdapter;
+import org.opendaylight.controller.md.sal.binding.impl.BindingDOMNotificationPublishServiceAdapter;
+import org.opendaylight.controller.md.sal.binding.impl.BindingDOMNotificationServiceAdapter;
import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
-import org.opendaylight.controller.md.sal.binding.impl.ForwardedBindingDataBroker;
-import org.opendaylight.controller.md.sal.binding.impl.ForwardedNotificationPublishService;
-import org.opendaylight.controller.md.sal.binding.impl.ForwardedNotificationService;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
import org.opendaylight.controller.md.sal.dom.broker.impl.DOMNotificationRouter;
import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
-import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
private DOMDataBroker domDataBroker;
private final DOMNotificationRouter domNotificationRouter;
- private final RuntimeGeneratedMappingServiceImpl mappingService;
private final MockSchemaService schemaService;
private ImmutableMap<LogicalDatastoreType, DOMStore> datastores;
private final BindingToNormalizedNodeCodec bindingToNormalized;
public DataBrokerTestCustomizer() {
schemaService = new MockSchemaService();
final ClassPool pool = ClassPool.getDefault();
- mappingService = new RuntimeGeneratedMappingServiceImpl(pool);
final DataObjectSerializerGenerator generator = StreamWriterGenerator.create(JavassistUtils.forClassPool(pool));
final BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(generator);
final GeneratedClassLoadingStrategy loading = GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy();
- bindingToNormalized = new BindingToNormalizedNodeCodec(loading, mappingService, codecRegistry);
+ bindingToNormalized = new BindingToNormalizedNodeCodec(loading, codecRegistry);
schemaService.registerSchemaContextListener(bindingToNormalized);
domNotificationRouter = DOMNotificationRouter.create(16);
}
}
public NotificationService createNotificationService() {
- return new ForwardedNotificationService(bindingToNormalized.getCodecRegistry(), domNotificationRouter,
+ return new BindingDOMNotificationServiceAdapter(bindingToNormalized.getCodecRegistry(), domNotificationRouter,
SingletonHolder.INVOKER_FACTORY);
}
public NotificationPublishService createNotificationPublishService() {
- return new ForwardedNotificationPublishService(bindingToNormalized.getCodecRegistry(), domNotificationRouter);
+ return new BindingDOMNotificationPublishServiceAdapter(bindingToNormalized.getCodecRegistry(), domNotificationRouter);
}
}
public DataBroker createDataBroker() {
- return new ForwardedBindingDataBroker(getDOMDataBroker(), bindingToNormalized);
+ return new BindingDOMDataBrokerAdapter(getDOMDataBroker(), bindingToNormalized);
}
public BindingToNormalizedNodeCodec getBindingToNormalized() {
public void updateSchema(final SchemaContext ctx) {
schemaService.changeSchema(ctx);
- mappingService.onGlobalContextUpdated(ctx);
}
public DOMNotificationRouter getDomNotificationRouter() {
*/
package org.opendaylight.controller.sal.binding.test;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
import org.junit.Before;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactory;
import org.opendaylight.controller.sal.binding.test.util.BindingTestContext;
-import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
-
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
@SuppressWarnings("deprecation")
public abstract class AbstractDataServiceTest {
- protected org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService;
protected DataProviderService baDataService;
- protected BindingIndependentMappingService mappingService;
+
protected BindingTestContext testContext;
@Before
testContext.start();
baDataService = testContext.getBindingDataBroker();
- biDataService = testContext.getDomDataBroker();
- mappingService = testContext.getBindingToDomMappingService();
}
protected boolean getStartWithSchema() {
+++ /dev/null
-/*
- * 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.sal.binding.test.compat;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
-import org.opendaylight.controller.sal.binding.test.AugmentationVerifier;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyAugment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyAugmentBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ContainerWithUsesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUses;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
-import org.opendaylight.yangtools.yang.binding.Augmentation;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-@Deprecated
-public class MultipleAugmentationPutsTest extends AbstractDataServiceTest implements DataChangeListener {
-
- private static final QName NODE_ID_QNAME = QName.create(TopLevelList.QNAME, "name");
- private static final String NODE_ID = "openflow:1";
-
- private static final TopLevelListKey NODE_KEY = new TopLevelListKey(NODE_ID);
-
- private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
- NODE_ID);
-
- private static final InstanceIdentifier<Top> NODES_INSTANCE_ID_BA = InstanceIdentifier.builder(Top.class) //
- .toInstance();
-
- private static final InstanceIdentifier<TopLevelList> NODE_INSTANCE_ID_BA =
- NODES_INSTANCE_ID_BA.child(TopLevelList.class, NODE_KEY);
-
- private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier NODE_INSTANCE_ID_BI = //
- org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.builder() //
- .node(Top.QNAME) //
- .nodeWithKey(TopLevelList.QNAME, NODE_KEY_BI) //
- .toInstance();
- private DataChangeEvent<InstanceIdentifier<?>, DataObject> receivedChangeEvent;
-
- /**
- * Test for Bug 148
- *
- * @throws Exception
- */
- @Test()
- public void testAugmentSerialization() throws Exception {
-
- baDataService.registerDataChangeListener(NODES_INSTANCE_ID_BA, this);
-
- TopLevelList flowCapableNode = createTestNode(TreeLeafOnlyAugment.class, createTreeLeafOnlyAugmentation());
- commitNodeAndVerifyTransaction(flowCapableNode);
-
- assertNotNull(receivedChangeEvent);
- verifyNode((Top) receivedChangeEvent.getUpdatedOperationalSubtree(), flowCapableNode);
-
- Top nodes = checkForNodes();
- verifyNode(nodes, flowCapableNode).assertHasAugmentation(TreeLeafOnlyAugment.class);
- assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
- TopLevelList meterStatsNode = createTestNode(TreeComplexUsesAugment.class, createTreeComplexUsesAugment());
- commitNodeAndVerifyTransaction(meterStatsNode);
-
- assertNotNull(receivedChangeEvent);
- verifyNode((Top) receivedChangeEvent.getUpdatedOperationalSubtree(), meterStatsNode);
-
- assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
-
- TopLevelList mergedNode = (TopLevelList) baDataService.readOperationalData(NODE_INSTANCE_ID_BA);
-
- AugmentationVerifier.from(mergedNode) //
- .assertHasAugmentation(TreeLeafOnlyAugment.class) //
- .assertHasAugmentation(TreeComplexUsesAugment.class);
-
- assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
-
- TopLevelList meterStatsNodeWithDuration = createTestNode(TreeComplexUsesAugment.class, createTreeComplexUsesAugment(5));
- commitNodeAndVerifyTransaction(meterStatsNodeWithDuration);
-
-
- TopLevelList nodeWithUpdatedList = (TopLevelList) baDataService.readOperationalData(NODE_INSTANCE_ID_BA);
- AugmentationVerifier.from(nodeWithUpdatedList) //
- .assertHasAugmentation(TreeLeafOnlyAugment.class) //
- .assertHasAugmentation(TreeComplexUsesAugment.class);
-
- List<ListViaUses> meterStats = nodeWithUpdatedList.getAugmentation(TreeComplexUsesAugment.class).getListViaUses();
- assertNotNull(meterStats);
- Assert.assertFalse(meterStats.isEmpty());
- assertBindingIndependentVersion(NODE_INSTANCE_ID_BI);
- testNodeRemove();
- }
-
- private static <T extends Augmentation<TopLevelList>> TopLevelList createTestNode(final Class<T> augmentationClass, final T augmentation) {
- TopLevelListBuilder nodeBuilder = new TopLevelListBuilder();
- nodeBuilder.setKey(NODE_KEY);
- nodeBuilder.setName(NODE_KEY.getName());
- nodeBuilder.addAugmentation(augmentationClass, augmentation);
- return nodeBuilder.build();
- }
-
- private DataModificationTransaction commitNodeAndVerifyTransaction(final TopLevelList original) throws Exception {
- DataModificationTransaction transaction = baDataService.beginTransaction();
- transaction.putOperationalData(NODE_INSTANCE_ID_BA, original);
- RpcResult<TransactionStatus> result = transaction.commit().get();
- assertEquals(TransactionStatus.COMMITED, result.getResult());
- return transaction;
- }
-
- private void testNodeRemove() throws Exception {
- DataModificationTransaction transaction = baDataService.beginTransaction();
- transaction.removeOperationalData(NODE_INSTANCE_ID_BA);
- RpcResult<TransactionStatus> result = transaction.commit().get();
- assertEquals(TransactionStatus.COMMITED, result.getResult());
-
- TopLevelList node = (TopLevelList) baDataService.readOperationalData(NODE_INSTANCE_ID_BA);
- assertNull(node);
- }
-
- private static AugmentationVerifier<TopLevelList> verifyNode(final Top nodes, final TopLevelList original) {
- assertNotNull(nodes);
- assertNotNull(nodes.getTopLevelList());
- assertEquals(1, nodes.getTopLevelList().size());
- TopLevelList readedNode = nodes.getTopLevelList().get(0);
- assertEquals(original.getName(), readedNode.getName());
- assertEquals(original.getKey(), readedNode.getKey());
- return new AugmentationVerifier<>(readedNode);
- }
-
- private void assertBindingIndependentVersion(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier nodeId) {
- CompositeNode node = biDataService.readOperationalData(nodeId);
- assertNotNull(node);
- }
-
- private Top checkForNodes() {
- return (Top) baDataService.readOperationalData(NODES_INSTANCE_ID_BA);
- }
-
- private static TreeComplexUsesAugment createTreeComplexUsesAugment() {
- return createTreeComplexUsesAugment(10);
- }
-
- private static TreeComplexUsesAugment createTreeComplexUsesAugment(final int count) {
- TreeComplexUsesAugmentBuilder tcuaBld = new TreeComplexUsesAugmentBuilder();
- ContainerWithUsesBuilder cwuBld = new ContainerWithUsesBuilder();
- cwuBld.setLeafFromGrouping("lfg1");
-
- List<ListViaUses> lvuBag = new ArrayList<>(count);
- for (int i = 0; i <= count; i++) {
- ListViaUsesBuilder statistic = new ListViaUsesBuilder();
- String name = String.valueOf(i);
- statistic.setKey(new ListViaUsesKey(name));
- statistic.setName(name);
- lvuBag.add(statistic.build());
- }
- tcuaBld.setContainerWithUses(cwuBld.build());
- tcuaBld.setListViaUses(lvuBag);
- return tcuaBld.build();
- }
-
- private static TreeLeafOnlyAugment createTreeLeafOnlyAugmentation() {
- TreeLeafOnlyAugmentBuilder fnub = new TreeLeafOnlyAugmentBuilder();
- fnub.setSimpleValue("meVerySimpleIs");
- TreeLeafOnlyAugment fnu = fnub.build();
- return fnu;
- }
-
- @Override
- public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
- receivedChangeEvent = change;
- }
-
-}
+++ /dev/null
-/*
- * 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.sal.binding.test.compat;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import org.junit.Test;
-import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.node.attributes.igp.node.attributes.Prefix;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.node.attributes.igp.node.attributes.PrefixBuilder;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-public class UnionSerializationTest extends AbstractDataServiceTest {
-
- public static final String PREFIX_STRING = "192.168.0.1/32";
-
-
- @Test
- public void testPrefixSerialization() throws Exception {
-
- Ipv4Prefix ipv4prefix = new Ipv4Prefix(PREFIX_STRING);
- IpPrefix ipPrefix = new IpPrefix(ipv4prefix);
- Prefix prefix = new PrefixBuilder().setPrefix(ipPrefix).build();
-
- CompositeNode serialized = testContext.getBindingToDomMappingService().toDataDom(prefix);
- assertNotNull(serialized);
- assertNotNull(serialized.getFirstSimpleByName(Prefix.QNAME));
- assertEquals(PREFIX_STRING, serialized.getFirstSimpleByName(Prefix.QNAME).getValue());
-
- Prefix deserialized = (Prefix) testContext.getBindingToDomMappingService().dataObjectFromDataDom(Prefix.class, serialized);
- assertNotNull(deserialized);
- assertNotNull(deserialized.getPrefix());
- assertNotNull(deserialized.getPrefix().getIpv4Prefix());
- assertEquals(PREFIX_STRING, deserialized.getPrefix().getIpv4Prefix().getValue());
- }
-
-}
+++ /dev/null
-/*
- * 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
- */
-/**
- *
- * Test suite targeting legacy Data APIs
- *
- */
-package org.opendaylight.controller.sal.binding.test.compat;
\ No newline at end of file
import com.google.common.collect.MutableClassToInstanceMap;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
-import java.util.Set;
-import java.util.concurrent.Future;
import javassist.ClassPool;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.MountPointService;
import org.opendaylight.controller.md.sal.binding.compat.HeliumRpcProviderRegistry;
import org.opendaylight.controller.md.sal.binding.compat.HydrogenDataBrokerAdapter;
import org.opendaylight.controller.md.sal.binding.compat.HydrogenMountProvisionServiceAdapter;
+import org.opendaylight.controller.md.sal.binding.impl.BindingDOMDataBrokerAdapter;
import org.opendaylight.controller.md.sal.binding.impl.BindingDOMMountPointServiceAdapter;
import org.opendaylight.controller.md.sal.binding.impl.BindingDOMRpcProviderServiceAdapter;
import org.opendaylight.controller.md.sal.binding.impl.BindingDOMRpcServiceAdapter;
import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
-import org.opendaylight.controller.md.sal.binding.impl.ForwardedBindingDataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
import org.opendaylight.controller.md.sal.dom.broker.impl.DOMRpcRouter;
import org.opendaylight.controller.md.sal.dom.broker.impl.SerializedDOMDataBroker;
-import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker;
import org.opendaylight.controller.md.sal.dom.broker.impl.mount.DOMMountPointServiceImpl;
import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
import org.opendaylight.controller.sal.binding.impl.NotificationBrokerImpl;
import org.opendaylight.controller.sal.binding.impl.RootBindingAwareBroker;
import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
import org.opendaylight.controller.sal.core.api.BrokerService;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
import org.opendaylight.controller.sal.core.spi.data.DOMStore;
import org.opendaylight.controller.sal.dom.broker.BrokerImpl;
-import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker;
import org.opendaylight.yangtools.binding.data.codec.gen.impl.DataObjectSerializerGenerator;
import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
-import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@Beta
public class BindingTestContext implements AutoCloseable {
- private RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
private BindingToNormalizedNodeCodec codec;
private RootBindingAwareBroker baBrokerImpl;
private NotificationBrokerImpl baNotifyImpl;
- @Deprecated
- private org.opendaylight.controller.sal.core.api.data.DataProviderService biDataLegacyBroker;
private BrokerImpl biBrokerImpl;
private final ListeningExecutorService executor;
private ImmutableMap<LogicalDatastoreType, DOMStore> newDatastores;
- @Deprecated
- private BackwardsCompatibleDataBroker biCompatibleBroker;
-
@Deprecated
private DataProviderService baData;
public void startNewDataBroker() {
checkState(executor != null, "Executor needs to be set");
checkState(newDOMDataBroker != null, "DOM Data Broker must be set");
- dataBroker = new ForwardedBindingDataBroker(newDOMDataBroker, codec);
+ dataBroker = new BindingDOMDataBrokerAdapter(newDOMDataBroker, codec);
}
public void startNewDomDataBroker() {
newDOMDataBroker = new SerializedDOMDataBroker(newDatastores, executor);
- biCompatibleBroker = new BackwardsCompatibleDataBroker(newDOMDataBroker,mockSchemaService);
-
mockSchemaService.registerSchemaContextListener(configStore);
mockSchemaService.registerSchemaContextListener(operStore);
- biDataLegacyBroker = biCompatibleBroker;
}
public void startBindingDataBroker() {
final MountPointService mountService = new BindingDOMMountPointServiceAdapter(biMountImpl, codec);
baBrokerImpl.setMountService(mountService);
baBrokerImpl.setLegacyMountManager(new HydrogenMountProvisionServiceAdapter(mountService));
- baBrokerImpl.setRpcBroker(new HeliumRpcProviderRegistry(baConsumerRpc,baProviderRpc));
+ baBrokerImpl.setRpcBroker(new HeliumRpcProviderRegistry(baConsumerRpc, baProviderRpc));
baBrokerImpl.setLegacyDataBroker(baData);
baBrokerImpl.setNotificationBroker(baNotifyImpl);
baBrokerImpl.start();
final ClassToInstanceMap<BrokerService> domBrokerServices = ImmutableClassToInstanceMap
.<BrokerService> builder()
//
- .put(org.opendaylight.controller.sal.core.api.data.DataProviderService.class, biDataLegacyBroker) //
- .put(RpcProvisionRegistry.class, biBrokerImpl.getRouter()) //
+ .put(DOMRpcRouter.class, biBrokerImpl.getRouter()) //
.put(DOMMountPointService.class, biMountImpl)
.build();
return new ProviderSession() {
- @Override
- public Future<RpcResult<CompositeNode>> rpc(final QName rpc, final CompositeNode input) {
- throw new UnsupportedOperationException();
- }
-
@Override
public <T extends BrokerService> T getService(final Class<T> service) {
return domBrokerServices.getInstance(service);
return false;
}
- @Override
- public Set<QName> getSupportedRpcs() {
- return null;
- }
-
@Override
public void close() {
}
-
- @Override
- public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(
- final RpcRegistrationListener listener) {
- return null;
- }
-
- @Override
- public RpcRegistration addRpcImplementation(final QName rpcType, final RpcImplementation implementation)
- throws IllegalArgumentException {
- return null;
- }
-
- @Override
- public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
- return null;
- }
-
- @Override
- public RoutedRpcRegistration addMountedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
- return null;
- }
};
}
public void startBindingToDomMappingService() {
checkState(classPool != null, "ClassPool needs to be present");
- mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl(classPool);
- mockSchemaService.registerSchemaContextListener(mappingServiceImpl);
final DataObjectSerializerGenerator generator = StreamWriterGenerator.create(JavassistUtils.forClassPool(classPool));
final BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(generator);
final GeneratedClassLoadingStrategy loading = GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy();
- codec = new BindingToNormalizedNodeCodec(loading, mappingServiceImpl, codecRegistry);
+ codec = new BindingToNormalizedNodeCodec(loading, codecRegistry);
mockSchemaService.registerSchemaContextListener(codec);
}
private void startDomBroker() {
checkState(executor != null);
- final SchemaAwareRpcBroker router = new SchemaAwareRpcBroker("/", mockSchemaService);
-
domRouter = new DOMRpcRouter();
mockSchemaService.registerSchemaContextListener(domRouter);
final ClassToInstanceMap<BrokerService> services = MutableClassToInstanceMap.create();
services.put(DOMRpcService.class, domRouter);
- biBrokerImpl = new BrokerImpl(router,services);
+ biBrokerImpl = new BrokerImpl(domRouter,services);
}
return baData;
}
- @Deprecated
- public org.opendaylight.controller.sal.core.api.data.DataProviderService getDomDataBroker() {
- return biDataLegacyBroker;
- }
-
- public BindingIndependentMappingService getBindingToDomMappingService() {
- return mappingServiceImpl;
- }
-
public RpcProviderRegistry getBindingRpcRegistry() {
return baBrokerImpl.getRoot();
}
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>binding-data-codec</artifactId>
+ </dependency>
</dependencies>
<build>
config:java-class "org.opendaylight.controller.sal.binding.api.NotificationProviderService";
}
+ identity binding-codec-tree-factory {
+ base "config:service-type";
+ config:java-class "org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeFactory";
+ }
+
identity binding-notification-subscription-service {
base "config:service-type";
config:java-class "org.opendaylight.controller.sal.binding.api.NotificationService";
+++ /dev/null
-/*
- * 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.binding.data;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-
-import org.junit.Test;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.Lists;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.OrderedContainer;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.UnkeyedContainer;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.UnkeyedContainerBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.UnorderedContainer;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.ordered.container.OrderedList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.ordered.container.OrderedListBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.ordered.container.OrderedListKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.unkeyed.container.UnkeyedList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.unkeyed.container.UnkeyedListBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.unordered.container.UnorderedList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.unordered.container.UnorderedListBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.store.rev140422.lists.unordered.container.UnorderedListKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-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.OrderedMapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
-
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableList;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/*
- * FIXME: THis test should be moved to sal-binding-broker and rewriten
- * to use new DataBroker API
- */
-@SuppressWarnings("deprecation")
-public class ListProcessingAndOrderingTest extends AbstractDataServiceTest {
-
- private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier DOM_UNORDERED_LIST_PATH = org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier
- .builder().node(Lists.QNAME).node(UnorderedContainer.QNAME).node(UnorderedList.QNAME).build();
-
- private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier DOM_ORDERED_LIST_PATH = org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier
- .builder().node(Lists.QNAME).node(OrderedContainer.QNAME).node(OrderedList.QNAME).build();
-
-
- private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier DOM_UNKEYED_LIST_PATH = org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier
- .builder().node(Lists.QNAME).node(UnkeyedContainer.QNAME).node(UnkeyedList.QNAME).build();
-
- private static final InstanceIdentifier<UnorderedContainer> UNORDERED_CONTAINER_PATH = InstanceIdentifier.builder(Lists.class).child(UnorderedContainer.class).build();
- private static final InstanceIdentifier<OrderedContainer> ORDERED_CONTAINER_PATH = InstanceIdentifier.builder(Lists.class).child(OrderedContainer.class).build();
- private static final InstanceIdentifier<UnkeyedContainer> UNKEYED_CONTAINER_PATH = InstanceIdentifier.builder(Lists.class).child(UnkeyedContainer.class).build();
-
- private static final UnorderedListKey UNORDERED_FOO_KEY = new UnorderedListKey("foo");
- private static final UnorderedListKey UNORDERED_BAR_KEY = new UnorderedListKey("bar");
-
- private static final InstanceIdentifier<UnorderedList> UNORDERED_FOO_PATH = UNORDERED_CONTAINER_PATH.child(UnorderedList.class,UNORDERED_FOO_KEY);
- private static final InstanceIdentifier<UnorderedList> UNORDERED_BAR_PATH = UNORDERED_CONTAINER_PATH.child(UnorderedList.class,UNORDERED_BAR_KEY);
-
- private static final OrderedListKey ORDERED_FOO_KEY = new OrderedListKey("foo");
- private static final OrderedListKey ORDERED_BAR_KEY = new OrderedListKey("bar");
- private static final InstanceIdentifier<OrderedList> ORDERED_FOO_PATH = ORDERED_CONTAINER_PATH.child(OrderedList.class,ORDERED_FOO_KEY);
- private static final InstanceIdentifier<OrderedList> ORDERED_BAR_PATH = ORDERED_CONTAINER_PATH.child(OrderedList.class,ORDERED_BAR_KEY);
-
-
- @Test
- public void unorderedListReadWriteTest() throws InterruptedException, ExecutionException {
- DataModificationTransaction tx = baDataService.beginTransaction();
-
- tx.putOperationalData(UNORDERED_FOO_PATH, createUnordered("foo"));
- tx.putOperationalData(UNORDERED_BAR_PATH, createUnordered("bar"));
- assertedCommit(tx);
-
- NormalizedNode<?, ?> data = resolveDataAsserted(DOM_UNORDERED_LIST_PATH);
- assertTrue(data instanceof MapNode);
- assertFalse(data instanceof OrderedMapNode);
-
- assertXmlRepresentation(UNORDERED_CONTAINER_PATH, "foo","bar");
- }
-
-
-
- @Test
- public void orderedListReadWriteTest() throws InterruptedException, ExecutionException {
- DataModificationTransaction tx = baDataService.beginTransaction();
-
- tx.putOperationalData(ORDERED_FOO_PATH, createOrdered("foo"));
- tx.putOperationalData(ORDERED_BAR_PATH, createOrdered("bar"));
- assertedCommit(tx);
- NormalizedNode<?, ?> data = resolveDataAsserted(DOM_ORDERED_LIST_PATH);
- assertTrue(data instanceof MapNode);
- assertTrue(data instanceof OrderedMapNode);
-
- assertXmlRepresentation(ORDERED_CONTAINER_PATH, "foo","bar");
-
- }
-
-
-
- @Test
- public void unkeyedListReadWriteTest() throws InterruptedException, ExecutionException {
- DataModificationTransaction tx = baDataService.beginTransaction();
-
- ImmutableList<UnkeyedList> unkeyedItems= ImmutableList.<UnkeyedList>builder()
- .add(createUnkeyed("foo"))
- .add(createUnkeyed("bar"))
- .build();
-
- tx.putOperationalData(UNKEYED_CONTAINER_PATH, new UnkeyedContainerBuilder().setUnkeyedList(unkeyedItems).build());
- assertedCommit(tx);
- NormalizedNode<?, ?> data = resolveDataAsserted(DOM_UNKEYED_LIST_PATH);
- assertFalse(data instanceof MapNode);
- assertTrue(data instanceof UnkeyedListNode);
-
- assertXmlRepresentation(UNKEYED_CONTAINER_PATH, "foo","bar");
- }
-
- private NormalizedNode<?, ?> resolveDataAsserted(
- final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier domPath) {
-
- try (DOMDataReadOnlyTransaction readTx = testContext.getDomAsyncDataBroker().newReadOnlyTransaction()){
- ListenableFuture<Optional<NormalizedNode<?, ?>>> data = readTx.read(LogicalDatastoreType.OPERATIONAL, domPath);
- Optional<NormalizedNode<?, ?>> potential = data.get();
- assertTrue(potential.isPresent());
- return potential.get();
- } catch (InterruptedException | ExecutionException e) {
- throw new RuntimeException(e);
- }
- }
-
- private static UnorderedList createUnordered(final String name) {
- return new UnorderedListBuilder().setName(name).setValue(createValue(name)).build();
- }
-
- private static OrderedList createOrdered(final String name) {
- return new OrderedListBuilder().setName(name).setValue(createValue(name)).build();
- }
-
- private static UnkeyedList createUnkeyed(final String name) {
- return new UnkeyedListBuilder().setName(name).setValue(createValue(name)).build();
- }
-
- private static String createValue(final String name) {
- return name + "-" + name.hashCode();
- }
-
- private static void assertedCommit(final DataModificationTransaction tx) throws InterruptedException, ExecutionException {
- RpcResult<TransactionStatus> result = tx.commit().get();
- assertTrue(result.isSuccessful());
- assertEquals(TransactionStatus.COMMITED,result.getResult());
- }
-
- private void assertXmlRepresentation(final InstanceIdentifier<?> containerPath, final String... childNameValues) {
-
- org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier domPath = testContext.getBindingToDomMappingService().toDataDom(containerPath);
- CompositeNode compositeNode = testContext.getDomDataBroker().readOperationalData(domPath);
- assertNotNull(compositeNode);
-
- Set<String> childValues = new HashSet<>();
- Collections.addAll(childValues, childNameValues);
-
- for(Node<?> child : compositeNode.getChildren()) {
- assertTrue(child instanceof CompositeNode);
- CompositeNode compChild = (CompositeNode) child;
- String nameLeafValue = (String) compChild.getSimpleNodesByName("name").get(0).getValue();
- String valueLeafValue = (String) compChild.getSimpleNodesByName("value").get(0).getValue();
-
- assertEquals(createValue(nameLeafValue), valueLeafValue);
- childValues.remove(nameLeafValue);
- }
- assertTrue(childValues.isEmpty());
- }
-
-}
+++ /dev/null
-/*
- * 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.sal.binding.test.bugfix;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import java.util.Collections;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
-import org.junit.Test;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
-import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactory;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.TopBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-
-@SuppressWarnings("deprecation")
-public class DOMCodecBug02Test extends AbstractDataServiceTest {
-
- private static final InstanceIdentifier<Top> TOP_INSTANCE_ID_BA = InstanceIdentifier.builder(Top.class) //
- .toInstance();
-
- /**
- * This test is ignored, till found out better way to test generation of
- * classes without leaking of instances from previous run
- *
- * @throws Exception
- */
-
- @Override
- public void setUp() {
- ListeningExecutorService executor = MoreExecutors.sameThreadExecutor();
- BindingBrokerTestFactory factory = new BindingBrokerTestFactory();
- factory.setExecutor(executor);
- factory.setStartWithParsedSchema(getStartWithSchema());
- testContext = factory.getTestContext();
- testContext.start();
-
- baDataService = testContext.getBindingDataBroker();
- biDataService = testContext.getDomDataBroker();
- mappingService = testContext.getBindingToDomMappingService();
- };
-
- @Test
- public void testSchemaContextNotAvailable() throws Exception {
-
- ExecutorService testExecutor = Executors.newFixedThreadPool(1);
- testContext.loadYangSchemaFromClasspath();
- Future<Future<RpcResult<TransactionStatus>>> future = testExecutor
- .submit(new Callable<Future<RpcResult<TransactionStatus>>>() {
- @Override
- public Future<RpcResult<TransactionStatus>> call() throws Exception {
- TopBuilder topBuilder = new TopBuilder();
- topBuilder.setTopLevelList(Collections.<TopLevelList> emptyList());
- DataModificationTransaction transaction = baDataService.beginTransaction();
- transaction.putOperationalData(TOP_INSTANCE_ID_BA, topBuilder.build());
- return transaction.commit();
- }
- });
-
- RpcResult<TransactionStatus> result = future.get().get();
- assertEquals(TransactionStatus.COMMITED, result.getResult());
-
- Top top = checkForTop();
- assertNotNull(top);
-
- }
-
- private Top checkForTop() {
- return (Top) baDataService.readOperationalData(TOP_INSTANCE_ID_BA);
-
- }
-
- @Override
- protected boolean getStartWithSchema() {
- return false;
- }
-
-}
+++ /dev/null
-/*
- * 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.sal.binding.test.bugfix;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-import org.junit.Test;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.CustomEnum;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.TllComplexAugment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.TllComplexAugmentBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.Cont2;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.Cont2Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.cont2.Contlist1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.cont2.Contlist1Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.top.level.list.NestedList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.top.level.list.NestedListBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.top.level.list.NestedListKey;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-import com.google.common.util.concurrent.SettableFuture;
-
-@SuppressWarnings("deprecation")
-public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataChangeListener {
-
- private static final QName TOP_LEVEL_LIST_NAME_QNAME = QName.create(TopLevelList.QNAME, "name");
- private static final String TOP_LEVEL_LIST_NAME = "tll:foo";
-
- private static final TopLevelListKey TLL_KEY = new TopLevelListKey(TOP_LEVEL_LIST_NAME);
-
- private static final Map<QName, Object> TLL_KEY_BI = Collections.<QName, Object> singletonMap(TOP_LEVEL_LIST_NAME_QNAME,
- TOP_LEVEL_LIST_NAME);
-
- private static final InstanceIdentifier<Top> TOP_INSTANCE_ID_BA = InstanceIdentifier.builder(Top.class) //
- .toInstance();
-
-
- private static final InstanceIdentifier<TopLevelList> TLL_INSTANCE_ID_BA = TOP_INSTANCE_ID_BA.child(TopLevelList.class, TLL_KEY);
-
-
- private static final InstanceIdentifier<Cont2> CONT2_INSTANCE_ID_BA = //
- TOP_INSTANCE_ID_BA.builder() //
- .child(TopLevelList.class, TLL_KEY) //
- .augmentation(TllComplexAugment.class) //
- .child(Cont2.class)
- .toInstance();
-
-
- private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier TLL_INSTANCE_ID_BI = //
- org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.builder() //
- .node(Top.QNAME) //
- .nodeWithKey(TopLevelList.QNAME, TLL_KEY_BI) //
- .toInstance();
- private static final QName CONT2_QNAME = QName.create(TllComplexAugment.QNAME, Cont2.QNAME.getLocalName());
-
-
- private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier CONT2_INSTANCE_ID_BI = //
- org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.builder() //
- .node(Top.QNAME) //
- .nodeWithKey(TopLevelList.QNAME, TLL_KEY_BI) //
- .node(CONT2_QNAME) //
- .toInstance();
-
- private final SettableFuture<DataChangeEvent<InstanceIdentifier<?>, DataObject>> receivedChangeEvent = SettableFuture.create();
-
-
-
- /**
- * Test for Bug 148
- *
- * @throws Exception
- */
- @Test
- public void testAugmentSerialization() throws Exception {
-
-
- baDataService.registerDataChangeListener(TOP_INSTANCE_ID_BA, this);
-
- TopLevelListBuilder tllBuilder = new TopLevelListBuilder();
- tllBuilder.setKey(TLL_KEY);
- DataModificationTransaction transaction = baDataService.beginTransaction();
-
-
- TllComplexAugmentBuilder tllcab = new TllComplexAugmentBuilder();
- tllcab.setAttrStr1("Hardware Foo");
- tllcab.setAttrStr2("Manufacturer Foo");
- tllcab.setAttrStr3("Serial Foo");
- tllcab.setAttrStr4("Description Foo");
- TllComplexAugment tlca = tllcab.build();
- tllBuilder.addAugmentation(TllComplexAugment.class, tlca);
- TopLevelList original = tllBuilder.build();
- transaction.putOperationalData(TLL_INSTANCE_ID_BA, original);
-
- RpcResult<TransactionStatus> result = transaction.commit().get();
- assertEquals(TransactionStatus.COMMITED, result.getResult());
-
- DataChangeEvent<InstanceIdentifier<?>, DataObject> potential = receivedChangeEvent.get(1000,TimeUnit.MILLISECONDS);
- assertNotNull(potential);
-
- verifyTll((Top) potential.getUpdatedOperationalSubtree(),original);
- assertBindingIndependentVersion(TLL_INSTANCE_ID_BI);
- Top top = checkForTop();
- verifyTll(top,original);
-
- testAddingNodeConnector();
- testTllRemove();
-
- }
-
- @Test
- public void testAugmentNestedSerialization() throws Exception {
- DataModificationTransaction transaction = baDataService.beginTransaction();
-
- Cont2Builder cont2b = new Cont2Builder();
- Contlist1Builder cl1b = new Contlist1Builder();
- cl1b.setAttrStr("foo-action");
- cl1b.setAttrEnum(CustomEnum.Type1);
- List<Contlist1> contlists = Collections.singletonList(cl1b.build());
- cont2b.setContlist1(contlists);
-
- transaction.putOperationalData(CONT2_INSTANCE_ID_BA, cont2b.build());
- RpcResult<TransactionStatus> putResult = transaction.commit().get();
- assertNotNull(putResult);
- assertEquals(TransactionStatus.COMMITED, putResult.getResult());
- Cont2 readedTable = (Cont2) baDataService.readOperationalData(CONT2_INSTANCE_ID_BA);
- assertNotNull(readedTable);
-
- CompositeNode biSupportedActions = biDataService.readOperationalData(CONT2_INSTANCE_ID_BI);
- assertNotNull(biSupportedActions);
-
- }
-
- private void testAddingNodeConnector() throws Exception {
- NestedListKey nlKey = new NestedListKey("test:0:0");
- InstanceIdentifier<NestedList> ncInstanceId = TLL_INSTANCE_ID_BA.child(NestedList.class, nlKey);
- NestedListBuilder nlBuilder = new NestedListBuilder();
- nlBuilder.setKey(nlKey);
- NestedList nestedList = nlBuilder.build();
- DataModificationTransaction transaction = baDataService.beginTransaction();
- transaction.putOperationalData(ncInstanceId, nestedList);
- RpcResult<TransactionStatus> result = transaction.commit().get();
- assertEquals(TransactionStatus.COMMITED, result.getResult());
- TopLevelList tll = (TopLevelList) baDataService.readOperationalData(TLL_INSTANCE_ID_BA);
- assertNotNull(tll);
- assertNotNull(tll.getNestedList());
- assertFalse(tll.getNestedList().isEmpty());
- NestedList readedNl = tll.getNestedList().get(0);
- assertNotNull(readedNl);
- }
-
- private void testTllRemove() throws Exception {
- DataModificationTransaction transaction = baDataService.beginTransaction();
- transaction.removeOperationalData(TLL_INSTANCE_ID_BA);
- RpcResult<TransactionStatus> result = transaction.commit().get();
- assertEquals(TransactionStatus.COMMITED, result.getResult());
-
- TopLevelList tll = (TopLevelList) baDataService.readOperationalData(TLL_INSTANCE_ID_BA);
- assertNull(tll);
- }
-
- private void verifyTll(final Top top,final TopLevelList original) {
- assertNotNull(top);
- assertNotNull(top.getTopLevelList());
- assertEquals(1, top.getTopLevelList().size());
- TopLevelList readedNode = top.getTopLevelList().get(0);
- assertEquals(original.getName(), readedNode.getName());
- assertEquals(original.getKey(), readedNode.getKey());
-
- TllComplexAugment fnu = original.getAugmentation(TllComplexAugment.class);
- TllComplexAugment readedAugment = readedNode.getAugmentation(TllComplexAugment.class);
- assertNotNull(fnu);
- assertEquals(fnu.getAttrStr2(), readedAugment.getAttrStr2());
- assertEquals(fnu.getAttrStr3(), readedAugment.getAttrStr3());
-
- }
-
- private void assertBindingIndependentVersion(
- final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier nodeId) {
- CompositeNode node = biDataService.readOperationalData(nodeId);
- assertNotNull(node);
- }
-
- private Top checkForTop() {
- return (Top) baDataService.readOperationalData(TOP_INSTANCE_ID_BA);
- }
-
- @Override
- public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
- receivedChangeEvent.set(change);
- }
-
-}
+++ /dev/null
-/*
- * 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.sal.binding.test.bugfix;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import org.junit.Test;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.BitFlags;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.TllComplexAugment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.List1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.List1Key;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11Key;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-import com.google.common.collect.ImmutableSet;
-
-@SuppressWarnings("deprecation")
-public class FlagsSerializationTest extends AbstractDataServiceTest {
- private static final TopLevelListKey TLL_KEY = new TopLevelListKey("foo");
- private static final List11Key LIST11_KEY = new List11Key(1234);
- private static final List1Key LIST1_KEY = new List1Key("1");
-
- private static final InstanceIdentifier<TopLevelList> TLL_INSTANCE_ID_BA = InstanceIdentifier.builder(Top.class) //
- .child(TopLevelList.class, TLL_KEY).toInstance();
-
- private static final InstanceIdentifier<? extends DataObject> LIST11_INSTANCE_ID_BA = //
- TLL_INSTANCE_ID_BA.builder() //
- .augmentation(TllComplexAugment.class)
- .child(List1.class,LIST1_KEY)
- .child(List11.class, LIST11_KEY) //
- .toInstance();
- private static final QName LIST11_FLAGS_QNAME = QName.create(List11.QNAME, "flags");
-
- @Test
- public void testIndirectGeneration() throws Exception {
-
- BitFlags checkOverlapFlags = new BitFlags(true,false,false,false,false);
- ImmutableSet<String> domCheckOverlapFlags = ImmutableSet.<String>of("FLAG_FIVE");
- testFlags(checkOverlapFlags,domCheckOverlapFlags);
-
-
-
- BitFlags allFalseFlags = new BitFlags(false,false,false,false,false);
- ImmutableSet<String> domAllFalseFlags = ImmutableSet.<String>of();
- testFlags(allFalseFlags,domAllFalseFlags);
-
- BitFlags allTrueFlags = new BitFlags(true,true,true,true,true);
- ImmutableSet<String> domAllTrueFlags = ImmutableSet.<String>of("FLAG_ONE","FLAG_TWO","FLAG_THREE","FLAG_FOUR","FLAG_FIVE");
- testFlags(allTrueFlags,domAllTrueFlags);
-
- testFlags(null,null);
-
-
-
- }
-
- private void testFlags(final BitFlags flagsToTest, final ImmutableSet<String> domFlags) throws Exception {
- List11 list11 = createList11(flagsToTest);
- assertNotNull(list11);
-
- CompositeNode domList11 = biDataService.readConfigurationData(mappingService.toDataDom(LIST11_INSTANCE_ID_BA));
-
- assertNotNull(domList11);
- org.opendaylight.yangtools.yang.data.api.Node<?> readedFlags = domList11.getFirstSimpleByName(LIST11_FLAGS_QNAME);
-
- if(domFlags != null) {
- assertNotNull(readedFlags);
- assertEquals(domFlags,readedFlags.getValue());
- } else {
- assertNull(readedFlags);
- }
- assertEquals(flagsToTest, list11.getFlags());
-
- DataModificationTransaction transaction = baDataService.beginTransaction();
- transaction.removeConfigurationData(LIST11_INSTANCE_ID_BA);
- RpcResult<TransactionStatus> result = transaction.commit().get();
- assertEquals(TransactionStatus.COMMITED, result.getResult());
-
- }
-
- private List11 createList11(final BitFlags flagsToTest) throws Exception {
-
- DataModificationTransaction modification = baDataService.beginTransaction();
-
- List11Builder list11b = new List11Builder();
-
- list11b.setKey(LIST11_KEY);
- list11b.setAttrStr("list:1:1");
-
- list11b.setFlags(flagsToTest);
-
- modification.putConfigurationData(LIST11_INSTANCE_ID_BA, list11b.build());
- RpcResult<TransactionStatus> ret = modification.commit().get();
- assertNotNull(ret);
- assertEquals(TransactionStatus.COMMITED, ret.getResult());
- return (List11) baDataService.readConfigurationData(LIST11_INSTANCE_ID_BA);
- }
-}
+++ /dev/null
-/*
- * 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.sal.binding.test.bugfix;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Collections;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-import org.junit.Ignore;
-import org.junit.Test;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.NestedListSimpleAugment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.NestedListSimpleAugmentBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.TllComplexAugment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.TllComplexAugmentBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.top.level.list.NestedList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.top.level.list.NestedListBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.top.level.list.NestedListKey;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-import com.google.common.util.concurrent.SettableFuture;
-
-@SuppressWarnings("deprecation")
-public class PutAugmentationTest extends AbstractDataServiceTest implements DataChangeListener {
-
- private static final QName TLL_NAME_QNAME = QName.create(TopLevelList.QNAME, "name");
- private static final String TLL_NAME = "foo";
-
- private static final TopLevelListKey TLL_KEY = new TopLevelListKey(TLL_NAME);
-
- private static final Map<QName, Object> TLL_KEY_BI = Collections.<QName, Object> singletonMap(TLL_NAME_QNAME,
- TLL_NAME);
-
- private static final InstanceIdentifier<Top> TOP_INSTANCE_ID_BA = InstanceIdentifier.builder(Top.class) //
- .toInstance();
-
- private static final InstanceIdentifier<TopLevelList> TLL_INSTANCE_ID_BA = //
- TOP_INSTANCE_ID_BA.builder() //
- .child(TopLevelList.class, TLL_KEY).toInstance();
-
- private static final InstanceIdentifier<TllComplexAugment> ALL_TCA = //
- TOP_INSTANCE_ID_BA.builder() //
- .child(TopLevelList.class) //
- .augmentation(TllComplexAugment.class) //
- .build();
-
- private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier TLL_INSTANCE_ID_BI = //
- org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.builder() //
- .node(Top.QNAME) //
- .nodeWithKey(TopLevelList.QNAME, TLL_KEY_BI) //
- .toInstance();
- private static final InstanceIdentifier<TllComplexAugment> TCA_AUGMENTATION_PATH =
- TLL_INSTANCE_ID_BA.builder() //
- .augmentation(TllComplexAugment.class) //
- .build();
-
- private SettableFuture<DataChangeEvent<InstanceIdentifier<?>, DataObject>> lastReceivedChangeEvent;
-
- /**
- * Test for Bug 148
- *
- * @throws Exception
- */
- @Test
- @Ignore
- public void putNodeAndAugmentation() throws Exception {
- lastReceivedChangeEvent = SettableFuture.create();
- baDataService.registerDataChangeListener(ALL_TCA, this);
-
-
- TopLevelListBuilder nodeBuilder = new TopLevelListBuilder();
- nodeBuilder.setKey(TLL_KEY);
- DataModificationTransaction baseTransaction = baDataService.beginTransaction();
- baseTransaction.putOperationalData(TLL_INSTANCE_ID_BA, nodeBuilder.build());
- RpcResult<TransactionStatus> result = baseTransaction.commit().get();
- assertEquals(TransactionStatus.COMMITED, result.getResult());
-
- TopLevelList tll = (TopLevelList) baDataService.readOperationalData(TLL_INSTANCE_ID_BA);
- assertNotNull(tll);
- assertEquals(TLL_KEY, tll.getKey());
-
- TllComplexAugmentBuilder tcab = new TllComplexAugmentBuilder();
- tcab.setAttrStr1("FooFoo");
- tcab.setAttrStr2("BarBar");
- TllComplexAugment tca = tcab.build();
- InstanceIdentifier<TreeComplexUsesAugment> augmentIdentifier = TLL_INSTANCE_ID_BA
- .augmentation(TreeComplexUsesAugment.class);
- DataModificationTransaction augmentedTransaction = baDataService.beginTransaction();
- augmentedTransaction.putOperationalData(augmentIdentifier, tca);
-
-
- lastReceivedChangeEvent = SettableFuture.create();
- result = augmentedTransaction.commit().get();
- assertEquals(TransactionStatus.COMMITED, result.getResult());
-
- DataChangeEvent<InstanceIdentifier<?>, DataObject> potential = lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS);
- assertNotNull(potential);
- assertTrue(potential.getCreatedOperationalData().containsKey(TCA_AUGMENTATION_PATH));
-
- lastReceivedChangeEvent = SettableFuture.create();
-
- TopLevelList augmentedTll = (TopLevelList) baDataService.readOperationalData(TLL_INSTANCE_ID_BA);
- assertNotNull(tll);
- assertEquals(TLL_KEY, augmentedTll.getKey());
- System.out.println("Before assertion");
- assertNotNull(augmentedTll.getAugmentation(TllComplexAugment.class));
- TllComplexAugment readedAugmentation = augmentedTll.getAugmentation(TllComplexAugment.class);
- assertEquals(tca.getAttrStr2(), readedAugmentation.getAttrStr2());
- assertBindingIndependentVersion(TLL_INSTANCE_ID_BI);
- testTllRemove();
- assertTrue(lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS).getRemovedOperationalData().contains(TCA_AUGMENTATION_PATH));
- }
-
- @Test
- @Ignore
- public void putNodeWithAugmentation() throws Exception {
- lastReceivedChangeEvent = SettableFuture.create();
- baDataService.registerDataChangeListener(ALL_TCA, this);
-
- TopLevelListBuilder nodeBuilder = new TopLevelListBuilder();
- nodeBuilder.setKey(TLL_KEY);
- TllComplexAugmentBuilder tcab = new TllComplexAugmentBuilder();
- tcab.setAttrStr1("FooFoo");
- tcab.setAttrStr2("BarBar");
- TllComplexAugment tca = tcab.build();
-
- nodeBuilder.addAugmentation(TreeComplexUsesAugment.class, tca);
- DataModificationTransaction baseTransaction = baDataService.beginTransaction();
- baseTransaction.putOperationalData(TLL_INSTANCE_ID_BA, nodeBuilder.build());
- RpcResult<TransactionStatus> result = baseTransaction.commit().get();
-
-
- DataChangeEvent<InstanceIdentifier<?>, DataObject> potential = lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS);
- assertNotNull(potential);
- assertTrue(potential.getCreatedOperationalData().containsKey(TCA_AUGMENTATION_PATH));
- lastReceivedChangeEvent = SettableFuture.create();
- assertEquals(TransactionStatus.COMMITED, result.getResult());
-
- TllComplexAugment readedAugmentation = (TllComplexAugment) baDataService.readOperationalData(
- TLL_INSTANCE_ID_BA.augmentation(TllComplexAugment.class));
- assertNotNull(readedAugmentation);
-
- assertEquals(tca.getAttrStr1(), readedAugmentation.getAttrStr1());
-
- testPutNodeConnectorWithAugmentation();
- lastReceivedChangeEvent = SettableFuture.create();
- testTllRemove();
-
- assertTrue(lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS).getRemovedOperationalData().contains(TCA_AUGMENTATION_PATH));
- }
-
- private void testPutNodeConnectorWithAugmentation() throws Exception {
- NestedListKey ncKey = new NestedListKey("test:0:0");
- InstanceIdentifier<NestedList> ncPath = TLL_INSTANCE_ID_BA
- .child(NestedList.class, ncKey);
- InstanceIdentifier<NestedListSimpleAugment> ncAugmentPath = ncPath
- .augmentation(NestedListSimpleAugment.class);
-
- NestedListBuilder nc = new NestedListBuilder();
- nc.setKey(ncKey);
-
- NestedListSimpleAugmentBuilder fncb = new NestedListSimpleAugmentBuilder();
- fncb.setType("Baz");
- nc.addAugmentation(NestedListSimpleAugment.class, fncb.build());
-
- DataModificationTransaction baseTransaction = baDataService.beginTransaction();
- baseTransaction.putOperationalData(ncPath, nc.build());
- RpcResult<TransactionStatus> result = baseTransaction.commit().get();
- assertEquals(TransactionStatus.COMMITED, result.getResult());
-
- NestedListSimpleAugment readedAugmentation = (NestedListSimpleAugment) baDataService
- .readOperationalData(ncAugmentPath);
- assertNotNull(readedAugmentation);
- assertEquals(fncb.getType(), readedAugmentation.getType());
- }
-
- private void testTllRemove() throws Exception {
- DataModificationTransaction transaction = baDataService.beginTransaction();
- transaction.removeOperationalData(TLL_INSTANCE_ID_BA);
- RpcResult<TransactionStatus> result = transaction.commit().get();
- assertEquals(TransactionStatus.COMMITED, result.getResult());
-
- TopLevelList tll = (TopLevelList) baDataService.readOperationalData(TLL_INSTANCE_ID_BA);
- assertNull(tll);
- }
-
- private void assertBindingIndependentVersion(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier tllId) {
- CompositeNode tll = biDataService.readOperationalData(tllId);
- assertNotNull(tll);
- }
-
- @Override
- public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
- lastReceivedChangeEvent.set(change);
- }
-
-}
+++ /dev/null
-/*
- * 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.sal.binding.test.connect.dom;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import java.util.Collections;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-import org.junit.Test;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
-import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
-import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.TllComplexAugment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.List1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.List1Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.List1Key;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11Key;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List12Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List12Key;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.util.concurrent.SettableFuture;
-
-/**
- * FIXME: Migrate to use new Data Broker APIs
- */
-@SuppressWarnings("deprecation")
-public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest {
-
- protected static final Logger LOG = LoggerFactory.getLogger(ChangeOriginatedInDomBrokerTest.class);
-
- private static final QName TLL_NAME_QNAME = QName.create(TopLevelList.QNAME, "name");
- private static final QName LIST1_ATTR_STR_QNAME = QName.create(List1.QNAME, "attr-str");
-
- private static final String TLL_NAME = "1";
- private static final int LIST11_ATTR_INT = 1234;
- private static final String LIST1_ATTR_STR = "foo:foo";
-
- private static final TopLevelListKey TLL_KEY = new TopLevelListKey(TLL_NAME);
- private static final List1Key LIST1_KEY = new List1Key(LIST1_ATTR_STR);
- private static final List11Key LIST11_KEY = new List11Key(LIST11_ATTR_INT);
-
- protected final SettableFuture<DataChangeEvent<InstanceIdentifier<?>, DataObject>> modificationCapture = SettableFuture.create();
-
- private static final Map<QName, Object> TLL_KEY_BI = Collections.<QName, Object> singletonMap(TLL_NAME_QNAME,
- TLL_NAME);
-
- private static final InstanceIdentifier<TopLevelList> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder(Top.class) //
- .child(TopLevelList.class, TLL_KEY).toInstance();
-
- private static final Map<QName, Object> LIST1_KEY_BI = //
- ImmutableMap.<QName, Object> of(LIST1_ATTR_STR_QNAME, LIST1_ATTR_STR);;
-
- private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier LIST1_INSTANCE_ID_BI = //
- org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.builder() //
- .node(Top.QNAME) //
- .nodeWithKey(TopLevelList.QNAME, TLL_KEY_BI) //
- .nodeWithKey(List1.QNAME, LIST1_KEY_BI) //
- .toInstance();
-
- private static final InstanceIdentifier<List1> LIST1_PATH_BA = //
- NODE_INSTANCE_ID_BA.builder() //
- .augmentation(TllComplexAugment.class) //
- .child(List1.class, LIST1_KEY) //
- .toInstance();
-
- @Test
- public void simpleModifyOperation() throws Exception {
-
- assertNull(biDataService.readConfigurationData(LIST1_INSTANCE_ID_BI));
-
- registerChangeListener();
-
- CompositeNode domflow = createTestList1();
- DataModificationTransaction biTransaction = biDataService.beginTransaction();
- biTransaction.putConfigurationData(LIST1_INSTANCE_ID_BI, domflow);
- RpcResult<TransactionStatus> biResult = biTransaction.commit().get();
- assertEquals(TransactionStatus.COMMITED, biResult.getResult());
- DataChangeEvent<InstanceIdentifier<?>, DataObject> event = modificationCapture.get(1000,TimeUnit.MILLISECONDS);
- assertNotNull(event);
- LOG.info("Created Configuration :{}",event.getCreatedConfigurationData());
- List1 list1 = (List1) event.getCreatedConfigurationData().get(LIST1_PATH_BA);
- assertNotNull(list1);
- assertNotNull(list1.getAttrStr());
- assertNotNull(list1.getList11());
- assertNotNull(list1.getList12());
- assertEquals(TransactionStatus.COMMITED, biResult.getResult());
-
- }
-
- private void registerChangeListener() {
- baDataService.registerDataChangeListener(LIST1_PATH_BA, new DataChangeListener() {
-
- @Override
- public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
- LOG.info("Data Change listener invoked.");
- modificationCapture.set(change);
- }
- });
- }
-
- private CompositeNode createTestList1() {
- List1Builder l1b = new List1Builder();
- List11Builder l11b = new List11Builder();
- List12Builder l12b = new List12Builder();
- l11b.setKey(LIST11_KEY);
- l11b.setAttrStr("foo:foo:foo");
- l12b.setKey(new List12Key(321));
- l12b.setAttrStr("foo:foo:bar");
- l1b.setKey(LIST1_KEY);
- l1b.setList11(ImmutableList.of(l11b.build()));
- l1b.setList12(ImmutableList.of(l12b.build()));
- CompositeNode domList1 = mappingService.toDataDom(l1b.build());
- return domList1;
- }
-}
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-
import com.google.common.base.Optional;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.Futures;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBrokerExtension;
import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
public DOMTransactionChain createTransactionChain(final TransactionChainListener listener) {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public Map<Class<? extends DOMDataBrokerExtension>, DOMDataBrokerExtension> getSupportedExtensions() {
+ return Collections.emptyMap();
+ }
}).register();
*/
package org.opendaylight.controller.xml.codec;
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableList;
+import java.net.URI;
+import java.util.Collection;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.ModifyAction;
-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.codec.TypeDefinitionAwareCodec;
import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-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.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
-import org.opendaylight.yangtools.yang.model.util.InstanceIdentifierType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-
-import javax.activation.UnsupportedDataTypeException;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.stream.XMLOutputFactory;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamWriter;
-import javax.xml.transform.dom.DOMResult;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import static com.google.common.base.Preconditions.checkState;
public class XmlDocumentUtils {
- private static class ElementWithSchemaContext {
- Element element;
- SchemaContext schemaContext;
-
- ElementWithSchemaContext(final Element element,final SchemaContext schemaContext) {
- this.schemaContext = schemaContext;
- this.element = element;
- }
-
- Element getElement() {
- return element;
- }
-
- SchemaContext getSchemaContext() {
- return schemaContext;
- }
- }
-
public static final QName OPERATION_ATTRIBUTE_QNAME = QName.create(URI.create("urn:ietf:params:xml:ns:netconf:base:1.0"), null, "operation");
- private static final Logger LOG = LoggerFactory.getLogger(XmlDocumentUtils.class);
- private static final XMLOutputFactory FACTORY = XMLOutputFactory.newFactory();
-
- /**
- * Converts Data DOM structure to XML Document for specified XML Codec Provider and corresponding
- * Data Node Container schema. The CompositeNode data parameter enters as root of Data DOM tree and will
- * be transformed to root in XML Document. Each element of Data DOM tree is compared against specified Data
- * Node Container Schema and transformed accordingly.
- *
- * @param data Data DOM root element
- * @param schema Data Node Container Schema
- * @param codecProvider XML Codec Provider
- * @return new instance of XML Document
- * @throws javax.activation.UnsupportedDataTypeException
- */
- public static Document toDocument(final CompositeNode data, final DataNodeContainer schema, final XmlCodecProvider codecProvider)
- throws UnsupportedDataTypeException {
- Preconditions.checkNotNull(data);
- Preconditions.checkNotNull(schema);
-
- if (!(schema instanceof ContainerSchemaNode || schema instanceof ListSchemaNode)) {
- throw new UnsupportedDataTypeException("Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet.");
- }
-
- final DOMResult result = new DOMResult(getDocument());
- try {
- final XMLStreamWriter writer = FACTORY.createXMLStreamWriter(result);
- XmlStreamUtils.create(codecProvider).writeDocument(writer, data, (SchemaNode)schema);
- writer.close();
- return (Document)result.getNode();
- } catch (XMLStreamException e) {
- LOG.error("Failed to serialize data {}", data, e);
- return null;
- }
- }
public static Document getDocument() {
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
Document doc = null;
try {
- DocumentBuilder bob = dbf.newDocumentBuilder();
+ final DocumentBuilder bob = dbf.newDocumentBuilder();
doc = bob.newDocument();
- } catch (ParserConfigurationException e) {
+ } catch (final ParserConfigurationException e) {
throw new RuntimeException(e);
}
return doc;
public static QName qNameFromElement(final Element xmlElement) {
- String namespace = xmlElement.getNamespaceURI();
- String localName = xmlElement.getLocalName();
+ final String namespace = xmlElement.getNamespaceURI();
+ final String localName = xmlElement.getLocalName();
return QName.create(namespace != null ? URI.create(namespace) : null, null, localName);
}
- private static Node<?> toNodeWithSchema(final Element xmlElement, final DataSchemaNode schema, final XmlCodecProvider codecProvider,final SchemaContext schemaCtx) {
- checkQName(xmlElement, schema.getQName());
- if (schema instanceof DataNodeContainer) {
- return toCompositeNodeWithSchema(xmlElement, schema.getQName(), (DataNodeContainer) schema, schemaCtx);
- } else if (schema instanceof LeafSchemaNode) {
- return toSimpleNodeWithType(xmlElement, (LeafSchemaNode) schema, codecProvider,schemaCtx);
- } else if (schema instanceof LeafListSchemaNode) {
- return toSimpleNodeWithType(xmlElement, (LeafListSchemaNode) schema, codecProvider,schemaCtx);
- }
- return null;
- }
-
-
-
- private static Node<?> toSimpleNodeWithType(final Element xmlElement, final LeafSchemaNode schema,
- final XmlCodecProvider codecProvider,final SchemaContext schemaCtx) {
- TypeDefinitionAwareCodec<? extends Object, ? extends TypeDefinition<?>> codec = codecProvider.codecFor(schema.getType());
- String text = xmlElement.getTextContent();
- Object value = null;
- if (codec != null) {
- LOG.debug("toSimpleNodeWithType: found codec, deserializing text {}", text);
- value = codec.deserialize(text);
- }
-
- final TypeDefinition<?> baseType = XmlUtils.resolveBaseTypeFrom(schema.getType());
- if (baseType instanceof InstanceIdentifierType) {
- LOG.debug("toSimpleNodeWithType: base type of node is instance identifier, deserializing element", xmlElement);
- value = InstanceIdentifierForXmlCodec.deserialize(xmlElement,schemaCtx);
-
- } else if(baseType instanceof IdentityrefTypeDefinition){
- LOG.debug("toSimpleNodeWithType: base type of node is IdentityrefTypeDefinition, deserializing element", xmlElement);
- value = InstanceIdentifierForXmlCodec.toIdentity(xmlElement.getTextContent(), xmlElement, schemaCtx);
-
- }
-
- if (value == null) {
- LOG.debug("toSimpleNodeWithType: no type found for element, returning just the text string value of element {}", xmlElement);
- value = xmlElement.getTextContent();
- }
-
- Optional<ModifyAction> modifyAction = getModifyOperationFromAttributes(xmlElement);
- return new SimpleNodeTOImpl<>(schema.getQName(), null, value, modifyAction.orNull());
- }
-
- private static Node<?> toSimpleNodeWithType(final Element xmlElement, final LeafListSchemaNode schema,
- final XmlCodecProvider codecProvider,final SchemaContext schemaCtx) {
- TypeDefinitionAwareCodec<? extends Object, ? extends TypeDefinition<?>> codec = codecProvider.codecFor(schema.getType());
- String text = xmlElement.getTextContent();
- Object value = null;
- if (codec != null) {
- LOG.debug("toSimpleNodeWithType: found codec, deserializing text {}", text);
- value = codec.deserialize(text);
- }
-
- final TypeDefinition<?> baseType = XmlUtils.resolveBaseTypeFrom(schema.getType());
- if (baseType instanceof InstanceIdentifierType) {
- LOG.debug("toSimpleNodeWithType: base type of node is instance identifier, deserializing element", xmlElement);
- value = InstanceIdentifierForXmlCodec.deserialize(xmlElement,schemaCtx);
- }
-
- if (value == null) {
- LOG.debug("toSimpleNodeWithType: no type found for element, returning just the text string value of element {}", xmlElement);
- value = xmlElement.getTextContent();
- }
-
- Optional<ModifyAction> modifyAction = getModifyOperationFromAttributes(xmlElement);
- return new SimpleNodeTOImpl<>(schema.getQName(), null, value, modifyAction.orNull());
- }
-
- private static Node<?> toCompositeNodeWithSchema(final Element xmlElement, final QName qName, final DataNodeContainer schema,
- final SchemaContext schemaCtx) {
- List<Node<?>> values = toDomNodes(xmlElement, Optional.fromNullable(schema.getChildNodes()),schemaCtx);
- Optional<ModifyAction> modifyAction = getModifyOperationFromAttributes(xmlElement);
- return ImmutableCompositeNode.create(qName, values, modifyAction.orNull());
- }
-
- private static Optional<ModifyAction> getModifyOperationFromAttributes(final Element xmlElement) {
- Attr attributeNodeNS = xmlElement.getAttributeNodeNS(OPERATION_ATTRIBUTE_QNAME.getNamespace().toString(), OPERATION_ATTRIBUTE_QNAME.getLocalName());
- if(attributeNodeNS == null) {
- return Optional.absent();
- }
-
- ModifyAction action = ModifyAction.fromXmlValue(attributeNodeNS.getValue());
- Preconditions.checkArgument(action.isOnElementPermitted(), "Unexpected operation %s on %s", action, xmlElement);
-
- return Optional.of(action);
- }
-
- private static void checkQName(final Element xmlElement, final QName qName) {
- checkState(Objects.equal(xmlElement.getNamespaceURI(), qName.getNamespace().toString()));
- checkState(qName.getLocalName().equals(xmlElement.getLocalName()));
- }
-
public static final Optional<DataSchemaNode> findFirstSchema(final QName qname, final Collection<DataSchemaNode> dataSchemaNode) {
if (dataSchemaNode != null && !dataSchemaNode.isEmpty() && qname != null) {
- for (DataSchemaNode dsn : dataSchemaNode) {
+ for (final DataSchemaNode dsn : dataSchemaNode) {
if (qname.isEqualWithoutRevision(dsn.getQName())) {
return Optional.<DataSchemaNode> of(dsn);
} else if (dsn instanceof ChoiceSchemaNode) {
- for (ChoiceCaseNode choiceCase : ((ChoiceSchemaNode) dsn).getCases()) {
- Optional<DataSchemaNode> foundDsn = findFirstSchema(qname, choiceCase.getChildNodes());
+ for (final ChoiceCaseNode choiceCase : ((ChoiceSchemaNode) dsn).getCases()) {
+ final Optional<DataSchemaNode> foundDsn = findFirstSchema(qname, choiceCase.getChildNodes());
if (foundDsn != null && foundDsn.isPresent()) {
return foundDsn;
}
return Optional.absent();
}
- private static Node<?> toDomNode(Element element) {
- QName qname = qNameFromElement(element);
-
- ImmutableList.Builder<Node<?>> values = ImmutableList.<Node<?>> builder();
- NodeList nodes = element.getChildNodes();
- boolean isSimpleObject = true;
- String value = null;
- for (int i = 0; i < nodes.getLength(); i++) {
- org.w3c.dom.Node child = nodes.item(i);
- if (child instanceof Element) {
- isSimpleObject = false;
- values.add(toDomNode((Element) child));
- }
- if (isSimpleObject && child instanceof org.w3c.dom.Text) {
- value = element.getTextContent();
- if (!Strings.isNullOrEmpty(value)) {
- isSimpleObject = true;
- }
- }
- }
- if (isSimpleObject) {
- return new SimpleNodeTOImpl<>(qname, null, value);
- }
- return ImmutableCompositeNode.create(qname, values.build());
- }
-
- public static List<Node<?>> toDomNodes(final Element element, final Optional<Collection<DataSchemaNode>> context,SchemaContext schemaCtx) {
- return forEachChild(element.getChildNodes(),schemaCtx, new Function<ElementWithSchemaContext, Optional<Node<?>>>() {
-
- @Override
- public Optional<Node<?>> apply(ElementWithSchemaContext input) {
- if (context.isPresent()) {
- QName partialQName = qNameFromElement(input.getElement());
- Optional<DataSchemaNode> schemaNode = XmlDocumentUtils.findFirstSchema(partialQName, context.get());
- if (schemaNode.isPresent()) {
- return Optional.<Node<?>> fromNullable(//
- toNodeWithSchema(input.getElement(), schemaNode.get(), XmlDocumentUtils.defaultValueCodecProvider(),input.getSchemaContext()));
- }
- }
- return Optional.<Node<?>> fromNullable(toDomNode(input.getElement()));
- }
-
- });
-
- }
-
- private static final <T> List<T> forEachChild(final NodeList nodes, final SchemaContext schemaContext, final Function<ElementWithSchemaContext, Optional<T>> forBody) {
- final int l = nodes.getLength();
- if (l == 0) {
- return ImmutableList.of();
- }
-
- final List<T> list = new ArrayList<>(l);
- for (int i = 0; i < l; i++) {
- org.w3c.dom.Node child = nodes.item(i);
- if (child instanceof Element) {
- Optional<T> result = forBody.apply(new ElementWithSchemaContext((Element) child,schemaContext));
- if (result.isPresent()) {
- list.add(result.get());
- }
- }
- }
- return ImmutableList.copyOf(list);
- }
-
public static final XmlCodecProvider defaultValueCodecProvider() {
return XmlUtils.DEFAULT_XML_CODEC_PROVIDER;
}
import java.net.URI;
import java.util.Map.Entry;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
-import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-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.SchemaNode;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
return new XmlStreamUtils(codecProvider);
}
- /**
- * Check if a particular data element can be emitted as an empty element, bypassing value encoding. This
- * functionality is optional, as valid XML stream is produced even if start/end element is produced unconditionally.
- *
- * @param data Data node
- * @return True if the data node will result in empty element body.
- */
- public static boolean isEmptyElement(final Node<?> data) {
- if (data == null) {
- return true;
- }
-
- if (data instanceof CompositeNode) {
- return ((CompositeNode) data).getValue().isEmpty();
- }
- if (data instanceof SimpleNode) {
- return data.getValue() == null;
- }
-
- // Safe default
- return false;
- }
-
/**
* Write an InstanceIdentifier into the output stream. Calling corresponding {@link javax.xml.stream.XMLStreamWriter#writeStartElement(String)}
* and {@link javax.xml.stream.XMLStreamWriter#writeEndElement()} is the responsibility of the caller.
final RandomPrefix prefixes = new RandomPrefix();
final String str = XmlUtils.encodeIdentifier(prefixes, id);
- for (Entry<URI, String> e: prefixes.getPrefixes()) {
+ for (final Entry<URI, String> e: prefixes.getPrefixes()) {
writer.writeNamespace(e.getValue(), e.getKey().toString());
}
if(LOG.isDebugEnabled()) {
writer.writeCharacters(str);
}
- /**
- * Write a full XML document corresponding to a CompositeNode into an XML stream writer.
- *
- * @param writer XML Stream writer
- * @param data data node
- * @param schema corresponding schema node, may be null
- * @throws javax.xml.stream.XMLStreamException if an encoding problem occurs
- */
- public void writeDocument(final @Nonnull XMLStreamWriter writer, final @Nonnull CompositeNode data, final @Nullable SchemaNode schema) throws XMLStreamException {
- // final Boolean repairing = (Boolean) writer.getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES);
- // Preconditions.checkArgument(repairing == true, "XML Stream Writer has to be repairing namespaces");
-
- writer.writeStartDocument();
- writeElement(writer, data, schema);
- writer.writeEndDocument();
- writer.flush();
- }
-
-
- /**
- * Write an element into a XML stream writer. This includes the element start/end tags and
- * the value of the element.
- *
- * @param writer XML Stream writer
- * @param data data node
- * @param schema Schema node
- * @throws javax.xml.stream.XMLStreamException if an encoding problem occurs
- */
- public void writeElement(final XMLStreamWriter writer, final @Nonnull Node<?> data, final SchemaNode schema) throws XMLStreamException {
- final QName qname = data.getNodeType();
- final String ns = qname.getNamespace() != null ? qname.getNamespace().toString() : "";
-
- if (isEmptyElement(data)) {
- writer.writeEmptyElement("", qname.getLocalName(), ns);
- return;
- }
-
- writer.writeStartElement("", qname.getLocalName(), ns);
- if (data instanceof AttributesContainer && ((AttributesContainer) data).getAttributes() != null) {
- for (Entry<QName, String> attribute : ((AttributesContainer) data).getAttributes().entrySet()) {
- writer.writeAttribute(attribute.getKey().getNamespace().toString(), attribute.getKey().getLocalName(), attribute.getValue());
- }
- }
-
- if (data instanceof SimpleNode<?>) {
- LOG.debug("writeElement : node is of type SimpleNode");
- // Simple node
- if (schema instanceof LeafListSchemaNode) {
- writeValue(writer, ((LeafListSchemaNode) schema).getType(), data.getValue());
- } else if (schema instanceof LeafSchemaNode) {
- writeValue(writer, ((LeafSchemaNode) schema).getType(), data.getValue());
- } else {
- Object value = data.getValue();
- if (value != null) {
- writer.writeCharacters(String.valueOf(value));
- }
- }
- } else {
- LOG.debug("writeElement : node is of type CompositeNode");
- // CompositeNode
- for (Node<?> child : ((CompositeNode) data).getValue()) {
- DataSchemaNode childSchema = null;
- if (schema instanceof DataNodeContainer) {
- childSchema = SchemaUtils.findFirstSchema(child.getNodeType(), ((DataNodeContainer) schema).getChildNodes()).orNull();
- if (childSchema == null && LOG.isDebugEnabled()) {
- LOG.debug("Probably the data node \"{}\" does not conform to schema", child == null ? "" : child.getNodeType().getLocalName());
- }
- }
-
- writeElement(writer, child, childSchema);
- }
- }
-
- writer.writeEndElement();
- }
-
/**
* Write a value into a XML stream writer. This method assumes the start and end of element is
* emitted by the caller.
if (codec != null) {
try {
text = codec.serialize(value);
- } catch (ClassCastException e) {
+ } catch (final ClassCastException e) {
LOG.error("Provided node value {} did not have type {} required by mapping. Using stream instead.", value, baseType, e);
text = String.valueOf(value);
}
*/
package org.opendaylight.controller.xml.codec;
-import com.google.common.base.Optional;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import java.util.Map;
+import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
-import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
-import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-import org.xml.sax.SAXException;
-
-import javax.activation.UnsupportedDataTypeException;
-import javax.annotation.Nonnull;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
/**
* Common XML-related utility methods, which are not specific to a particular
private XmlUtils() {
}
- private static final String BLANK = "";
- private static final Logger LOG = LoggerFactory.getLogger(XmlUtils.class);
-
- /**
- * Converts the composite node to xml using rpc input schema node
- * @param cNode
- * @param schemaContext
- * @return xml String
- */
- public static String inputCompositeNodeToXml(CompositeNode cNode, SchemaContext schemaContext){
- if(LOG.isDebugEnabled()) {
- LOG.debug("Converting input composite node to xml {}", cNode);
- }
- if (cNode == null) {
- return BLANK;
- }
-
- if(schemaContext == null) {
- return BLANK;
- }
-
- Document domTree = null;
- try {
- Set<RpcDefinition> rpcs = schemaContext.getOperations();
- for(RpcDefinition rpc : rpcs) {
- if(rpc.getQName().equals(cNode.getNodeType())){
- if(LOG.isDebugEnabled()) {
- LOG.debug("Found the rpc definition from schema context matching with input composite node {}", rpc.getQName());
- }
- CompositeNode inputContainer = cNode.getFirstCompositeByName(QName.create(cNode.getNodeType(), "input"));
- domTree = XmlDocumentUtils.toDocument(inputContainer, rpc.getInput(), XmlDocumentUtils.defaultValueCodecProvider());
- if(LOG.isDebugEnabled()) {
- LOG.debug("input composite node to document conversion complete, document is {}", domTree);
- }
- break;
- }
- }
-
- } catch (UnsupportedDataTypeException e) {
- LOG.error("Error during translation of CompositeNode to Document", e);
- }
- return domTransformer(domTree);
- }
-
- /**
- * Converts the composite node to xml String using rpc output schema node
- * @param cNode
- * @param schemaContext
- * @return xml string
- */
- public static String outputCompositeNodeToXml(CompositeNode cNode, SchemaContext schemaContext){
- if(LOG.isDebugEnabled()) {
- LOG.debug("Converting output composite node to xml {}", cNode);
- }
- if (cNode == null) {
- return BLANK;
- }
-
- if(schemaContext == null) {
- return BLANK;
- }
-
- Document domTree = null;
- try {
- Set<RpcDefinition> rpcs = schemaContext.getOperations();
- for(RpcDefinition rpc : rpcs) {
- if(rpc.getQName().equals(cNode.getNodeType())){
- if(LOG.isDebugEnabled()) {
- LOG.debug("Found the rpc definition from schema context matching with output composite node {}", rpc.getQName());
- }
- CompositeNode outputContainer = cNode.getFirstCompositeByName(QName.create(cNode.getNodeType(), "output"));
- domTree = XmlDocumentUtils.toDocument(outputContainer, rpc.getOutput(), XmlDocumentUtils.defaultValueCodecProvider());
- if(LOG.isDebugEnabled()) {
- LOG.debug("output composite node to document conversion complete, document is {}", domTree);
- }
- break;
- }
- }
-
- } catch (UnsupportedDataTypeException e) {
- LOG.error("Error during translation of CompositeNode to Document", e);
- }
- return domTransformer(domTree);
- }
-
- private static String domTransformer(Document domTree) {
- StringWriter writer = new StringWriter();
- try {
- TransformerFactory tf = TransformerFactory.newInstance();
- Transformer transformer = tf.newTransformer();
- transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
- transformer.transform(new DOMSource(domTree), new StreamResult(writer));
- } catch (TransformerException e) {
-
- LOG.error("Error during translation of Document to OutputStream", e);
- }
- if(LOG.isDebugEnabled()) {
- LOG.debug("Document to string conversion complete, xml string is {} ", writer.toString());
- }
- return writer.toString();
- }
-
- public static CompositeNode xmlToCompositeNode(String xml){
- if (xml==null || xml.length()==0) {
- return null;
- }
-
- Node<?> dataTree;
- try {
- dataTree = XmlTreeBuilder.buildDataTree(new ByteArrayInputStream(xml.getBytes()));
- } catch (XMLStreamException e) {
- LOG.error("Error during building data tree from XML", e);
- return null;
- }
- if (dataTree == null) {
- LOG.error("data tree is null");
- return null;
- }
- if (dataTree instanceof SimpleNode) {
- LOG.error("RPC XML was resolved as SimpleNode");
- return null;
- }
- return (CompositeNode) dataTree;
- }
-
- /**
- * Converts the xml to composite node using rpc input schema node
- * @param rpc
- * @param xml
- * @param schemaContext
- * @return CompositeNode object based on the input, if any of the input parameter is null, a null object is returned
- */
- public static CompositeNode inputXmlToCompositeNode(QName rpc, String xml, SchemaContext schemaContext){
- if(LOG.isDebugEnabled()) {
- LOG.debug("Converting input xml to composite node {}", xml);
- }
- if (xml==null || xml.length()==0) {
- return null;
- }
-
- if(rpc == null) {
- return null;
- }
-
- if(schemaContext == null) {
- return null;
- }
-
- CompositeNode compositeNode = null;
- try {
-
- Document doc = XmlUtil.readXmlToDocument(xml);
- Set<RpcDefinition> rpcs = schemaContext.getOperations();
- for(RpcDefinition rpcDef : rpcs) {
- if(rpcDef.getQName().equals(rpc)){
- if(LOG.isDebugEnabled()) {
- LOG.debug("found the rpc definition from schema context matching rpc {}", rpc);
- }
- if(rpcDef.getInput() == null) {
- LOG.warn("found rpc definition's input is null");
- return null;
- }
-
- QName input = rpcDef.getInput().getQName();
- NodeList nodeList = doc.getElementsByTagNameNS(input.getNamespace().toString(), "input");
- if(nodeList == null || nodeList.getLength() < 1) {
- LOG.warn("xml does not have input entry. {}", xml);
- return null;
- }
- Element xmlData = (Element)nodeList.item(0);
-
- List<Node<?>> dataNodes = XmlDocumentUtils.toDomNodes(xmlData,
- Optional.of(rpcDef.getInput().getChildNodes()), schemaContext);
- if(LOG.isDebugEnabled()) {
- LOG.debug("Converted xml input to list of nodes {}", dataNodes);
- }
- final CompositeNodeBuilder<ImmutableCompositeNode> it = ImmutableCompositeNode.builder();
- it.setQName(rpc);
- it.add(ImmutableCompositeNode.create(input, dataNodes));
- compositeNode = it.toInstance();
- break;
- }
- }
- } catch (SAXException e) {
- LOG.error("Error during building data tree from XML", e);
- } catch (IOException e) {
- LOG.error("Error during building data tree from XML", e);
- }
- if(LOG.isDebugEnabled()) {
- LOG.debug("Xml to composite node conversion complete {} ", compositeNode);
- }
- return compositeNode;
- }
-
public static TypeDefinition<?> resolveBaseTypeFrom(final @Nonnull TypeDefinition<?> type) {
TypeDefinition<?> superType = type;
while (superType.getBaseType() != null) {
*/
public static String encodeIdentifier(final RandomPrefix prefixes, final YangInstanceIdentifier id) {
- StringBuilder textContent = new StringBuilder();
- for (PathArgument pathArgument : id.getPathArguments()) {
+ final StringBuilder textContent = new StringBuilder();
+ for (final PathArgument pathArgument : id.getPathArguments()) {
textContent.append('/');
textContent.append(prefixes.encodeQName(pathArgument.getNodeType()));
if (pathArgument instanceof NodeIdentifierWithPredicates) {
- Map<QName, Object> predicates = ((NodeIdentifierWithPredicates) pathArgument).getKeyValues();
+ final Map<QName, Object> predicates = ((NodeIdentifierWithPredicates) pathArgument).getKeyValues();
- for (QName keyValue : predicates.keySet()) {
- Object value = predicates.get(keyValue);
- String type = value.getClass().getName();
- String predicateValue = String.valueOf(value);
+ for (final QName keyValue : predicates.keySet()) {
+ final Object value = predicates.get(keyValue);
+ final String type = value.getClass().getName();
+ final String predicateValue = String.valueOf(value);
textContent.append('[');
textContent.append(prefixes.encodeQName(keyValue));
textContent.append("='");
package org.opendaylight.controller.xml.codec;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.io.ByteSource;
import java.io.IOException;
import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
import javax.xml.parsers.DocumentBuilderFactory;
-import org.junit.Assert;
import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.ModifyAction;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+// FIXME : CompositeNode is not avaliable anymore so fix the test to use NormalizedNodeContainer ASAP
public class XmlUtilsTest {
private static final DocumentBuilderFactory BUILDERFACTORY;
testRpc = rpcTestModule.getRpcs().iterator().next();
}
- @Test
- public void testNullInputXmlToComposite() {
- CompositeNode node = XmlUtils.inputXmlToCompositeNode(testRpc.getQName(), null, schema);
- Assert.assertNull(node);
- }
-
- @Test
- public void testNullRpcXmlToComposite() {
- CompositeNode node = XmlUtils.inputXmlToCompositeNode(null, XML_CONTENT, schema);
- Assert.assertNull(node);
- }
-
- @Test
- public void testInputXmlToCompositeNode() {
- CompositeNode node = XmlUtils.inputXmlToCompositeNode(testRpc.getQName(), XML_CONTENT, schema);
- ImmutableList<SimpleNode<?>> input = (ImmutableList<SimpleNode<?>>)node.getValue().get(0).getValue();
- SimpleNode<?> firstNode = input.get(0);
-
- Assert.assertEquals("id", firstNode.getNodeType().getLocalName());
- Assert.assertEquals("flowid", firstNode.getValue());
-
- SimpleNode<?> secondNode = input.get(1);
- Assert.assertEquals("flow", secondNode.getNodeType().getLocalName());
-
- YangInstanceIdentifier instance = (YangInstanceIdentifier) secondNode.getValue();
- Iterable<YangInstanceIdentifier.PathArgument> iterable = instance.getPathArguments();
- Iterator<YangInstanceIdentifier.PathArgument> it = iterable.iterator();
- YangInstanceIdentifier.NodeIdentifier firstPath = (YangInstanceIdentifier.NodeIdentifier) it.next();
- Assert.assertEquals("node", firstPath.getNodeType().getLocalName());
- YangInstanceIdentifier.NodeIdentifierWithPredicates secondPath = (YangInstanceIdentifier.NodeIdentifierWithPredicates)it.next();
- Short value = (Short)secondPath.getKeyValues().values().iterator().next();
- Short expected = 3;
- Assert.assertEquals(expected, value);
- }
-
- @Test
- public void testInputCompositeNodeToXML() {
- CompositeNode input = XmlUtils.inputXmlToCompositeNode(testRpc.getQName(), XML_CONTENT, schema);
- List<Node<?>> childNodes = new ArrayList<>();
- childNodes.add(input);
- QName rpcQName = schema.getOperations().iterator().next().getQName();
- CompositeNode node = new ImmutableCompositeNode(rpcQName, input.getValue(), ModifyAction.REPLACE);
- String xml = XmlUtils.inputCompositeNodeToXml(node, schema);
- Assert.assertNotNull(xml);
- Assert.assertTrue(xml.contains("3@java.lang.Short"));
- }
-
- @Test
- public void testNullCompositeNodeToXml(){
- String xml = XmlUtils.inputCompositeNodeToXml(null, schema);
- Assert.assertTrue(xml.isEmpty());
- }
-
- @Test
- public void testNullSchemaCompositeNodeToXml(){
- String xml = XmlUtils.inputCompositeNodeToXml(new ImmutableCompositeNode(QName.create("ns", "2013-12-09", "child1"), new ArrayList<Node<?>>(), ModifyAction.REPLACE), null);
- Assert.assertTrue(xml.isEmpty());
- }
-
-
}
*/
package org.opendaylight.controller.md.sal.common.impl.util.compat;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-
+import com.google.common.base.Optional;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
-
-import javax.xml.transform.dom.DOMSource;
import org.opendaylight.yangtools.concepts.Identifiable;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
-import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-import com.google.common.base.Optional;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-
-/**
- * @deprecated This class provides compatibility between {@link CompositeNode} and {@link NormalizedNode}.
- * Users of this class should use {@link NormalizedNode}s directly.
- */
@Deprecated
public abstract class DataNormalizationOperation<T extends PathArgument> implements Identifiable<T> {
public abstract DataNormalizationOperation<?> getChild(QName child) throws DataNormalizationException;
- public abstract NormalizedNode<?, ?> normalize(Node<?> legacyData);
public abstract boolean isLeaf();
super(identifier,potential);
}
- @Override
- public NormalizedNode<?, ?> normalize(final Node<?> legacyData) {
- checkArgument(legacyData != null);
- checkArgument(legacyData instanceof SimpleNode<?>);
- return normalizeImpl((SimpleNode<?>) legacyData);
- }
-
- protected abstract NormalizedNode<?, ?> normalizeImpl(SimpleNode<?> node);
-
@Override
public DataNormalizationOperation<?> getChild(final PathArgument child) {
return null;
super(new NodeIdentifier(potential.getQName()),potential);
}
- @Override
- protected NormalizedNode<?, ?> normalizeImpl(final SimpleNode<?> node) {
- return ImmutableNodes.leafNode(node.getNodeType(), node.getValue());
- }
-
}
private static final class LeafListEntryNormalization extends SimpleTypeNormalization<NodeWithValue> {
super(new NodeWithValue(potential.getQName(), null),potential);
}
- @Override
- protected NormalizedNode<?, ?> normalizeImpl(final SimpleNode<?> node) {
- NodeWithValue nodeId = new NodeWithValue(node.getNodeType(), node.getValue());
- return Builders.leafSetEntryBuilder().withNodeIdentifier(nodeId).withValue(node.getValue()).build();
- }
-
-
@Override
public boolean isKeyedEntry() {
return true;
super(identifier,schema);
}
- @SuppressWarnings({ "rawtypes", "unchecked" })
- @Override
- public final NormalizedNode<?, ?> normalize(final Node<?> legacyData) {
- checkArgument(legacyData != null);
- if (!isMixin() && getIdentifier().getNodeType() != null) {
- checkArgument(getIdentifier().getNodeType().equals(legacyData.getNodeType()),
- "Node QName must be %s was %s", getIdentifier().getNodeType(), legacyData.getNodeType());
- }
- checkArgument(legacyData instanceof CompositeNode, "Node %s should be composite", legacyData);
- CompositeNode compositeNode = (CompositeNode) legacyData;
- NormalizedNodeContainerBuilder builder = createBuilder(compositeNode);
-
- Set<DataNormalizationOperation<?>> usedMixins = new HashSet<>();
- for (Node<?> childLegacy : compositeNode.getValue()) {
- final DataNormalizationOperation childOp;
-
- try {
- childOp = getChild(childLegacy.getNodeType());
- } catch (DataNormalizationException e) {
- throw new IllegalArgumentException(String.format("Failed to normalize data %s", compositeNode.getValue()), e);
- }
-
- // We skip unknown nodes if this node is mixin since
- // it's nodes and parent nodes are interleaved
- if (childOp == null && isMixin()) {
- continue;
- }
-
- checkArgument(childOp != null, "Node %s is not allowed inside %s", childLegacy.getNodeType(),
- getIdentifier());
- if (childOp.isMixin()) {
- if (usedMixins.contains(childOp)) {
- // We already run / processed that mixin, so to avoid
- // duplicity we are skipping next nodes.
- continue;
- }
- builder.addChild(childOp.normalize(compositeNode));
- usedMixins.add(childOp);
- } else {
- builder.addChild(childOp.normalize(childLegacy));
- }
- }
- return builder.build();
- }
-
@Override
public boolean isLeaf() {
return false;
}
- @SuppressWarnings("rawtypes")
- protected abstract NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode);
}
keyDefinition = schema.getKeyDefinition();
}
- @Override
- protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
- ImmutableMap.Builder<QName, Object> keys = ImmutableMap.builder();
- for (QName key : keyDefinition) {
-
- SimpleNode<?> valueNode = checkNotNull(compositeNode.getFirstSimpleByName(key),
- "List node %s MUST contain leaf %s with value.", getIdentifier().getNodeType(), key);
- keys.put(key, valueNode.getValue());
- }
-
- return Builders.mapEntryBuilder().withNodeIdentifier(
- new NodeIdentifierWithPredicates(getIdentifier().getNodeType(), keys.build()));
- }
-
@Override
public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> builder = Builders
super(new NodeIdentifier(schema.getQName()), schema,schema);
}
- @Override
- protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
- return Builders.unkeyedListEntryBuilder().withNodeIdentifier(getIdentifier());
- }
-
@Override
public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
return Builders.unkeyedListEntryBuilder().withNodeIdentifier((NodeIdentifier) currentArg).build();
super(new NodeIdentifier(schema.getQName()),schema, schema);
}
- @Override
- protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
- return Builders.containerBuilder().withNodeIdentifier(getIdentifier());
- }
-
@Override
public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
return Builders.containerBuilder().withNodeIdentifier((NodeIdentifier) currentArg).build();
super(potential);
}
- @Override
- protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
- return Builders.orderedLeafSetBuilder().withNodeIdentifier(getIdentifier());
- }
-
@Override
public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
return Builders.orderedLeafSetBuilder().withNodeIdentifier(getIdentifier()).build();
super(new NodeIdentifier(potential.getQName()),potential);
innerOp = new LeafListEntryNormalization(potential);
}
-
- @Override
- protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
- return Builders.leafSetBuilder().withNodeIdentifier(getIdentifier());
- }
-
@Override
public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
return Builders.leafSetBuilder().withNodeIdentifier(getIdentifier()).build();
return getIdentifier().getPossibleChildNames();
}
- @SuppressWarnings("rawtypes")
- @Override
- protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
- return Builders.augmentationBuilder().withNodeIdentifier(getIdentifier());
- }
-
@Override
public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
return Builders.augmentationBuilder().withNodeIdentifier(getIdentifier()).build();
Collections.<QName, Object> emptyMap()), list);
}
- @SuppressWarnings("rawtypes")
- @Override
- protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
- return Builders.mapBuilder().withNodeIdentifier(getIdentifier());
- }
-
@Override
public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
return Builders.mapBuilder().withNodeIdentifier(getIdentifier()).build();
this.innerNode = new UnkeyedListItemNormalization(list);
}
- @SuppressWarnings("rawtypes")
- @Override
- protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
- return Builders.unkeyedListBuilder().withNodeIdentifier(getIdentifier());
- }
-
@Override
public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
return Builders.unkeyedListBuilder().withNodeIdentifier(getIdentifier()).build();
super(list);
}
- @SuppressWarnings("rawtypes")
- @Override
- protected NormalizedNodeContainerBuilder createBuilder(final CompositeNode compositeNode) {
- return Builders.orderedMapBuilder().withNodeIdentifier(getIdentifier());
- }
-
@Override
public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
return Builders.orderedMapBuilder().withNodeIdentifier(getIdentifier()).build();
return byQName.get(child);
}
- @Override
- protected NormalizedNodeContainerBuilder<?, ?, ?, ?> createBuilder(final CompositeNode compositeNode) {
- return Builders.choiceBuilder().withNodeIdentifier(getIdentifier());
- }
-
@Override
public NormalizedNode<?, ?> createDefault(final PathArgument currentArg) {
return Builders.choiceBuilder().withNodeIdentifier(getIdentifier()).build();
return null;
}
- @Override
- public NormalizedNode<?, ?> normalize( final Node<?> legacyData ) {
- NormalizedNodeAttrBuilder<NodeIdentifier, DOMSource, AnyXmlNode> builder =
- Builders.anyXmlBuilder().withNodeIdentifier(
- new NodeIdentifier( legacyData.getNodeType() ) );
- // Will be removed
-// builder.withValue(legacyData);
- return builder.build();
- }
-
@Override
public boolean isLeaf() {
return false;
import static com.google.common.base.Preconditions.checkArgument;
-import java.util.AbstractMap;
-import java.util.ArrayList;
+import com.google.common.collect.ImmutableList;
import java.util.Iterator;
-import java.util.Map;
-
-import javax.xml.transform.dom.DOMSource;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MixinNode;
-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.UnkeyedListNode;
-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.opendaylight.yangtools.yang.model.api.SchemaContext;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicates;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-
/**
- * @deprecated This class provides compatibility between {@link CompositeNode} and {@link NormalizedNode}.
- * Users of this class should use {@link NormalizedNode}s directly.
+ * @deprecated This class provides compatibility between XML semantics
+ * and {@link org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree}
*/
@Deprecated
public class DataNormalizer {
return currentOp;
}
- public Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalized(
- final Map.Entry<YangInstanceIdentifier, CompositeNode> legacy) {
- return toNormalized(legacy.getKey(), legacy.getValue());
- }
-
- public Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalized(final YangInstanceIdentifier legacyPath,
- final CompositeNode legacyData) {
-
- YangInstanceIdentifier normalizedPath = toNormalized(legacyPath);
-
- DataNormalizationOperation<?> currentOp = operation;
- for (PathArgument arg : normalizedPath.getPathArguments()) {
- try {
- currentOp = currentOp.getChild(arg);
- } catch (DataNormalizationException e) {
- throw new IllegalArgumentException(String.format("Failed to validate normalized path %s",
- normalizedPath), e);
- }
- }
- Preconditions.checkArgument(currentOp != null,
- "Instance Identifier %s does not reference correct schema Node.", normalizedPath);
- return new AbstractMap.SimpleEntry<YangInstanceIdentifier, NormalizedNode<?, ?>>(normalizedPath,
- currentOp.normalize(legacyData));
- }
-
public YangInstanceIdentifier toLegacy(final YangInstanceIdentifier normalized) throws DataNormalizationException {
ImmutableList.Builder<PathArgument> legacyArgs = ImmutableList.builder();
DataNormalizationOperation<?> currentOp = operation;
return YangInstanceIdentifier.create(legacyArgs.build());
}
- public CompositeNode toLegacy(final YangInstanceIdentifier normalizedPath, final NormalizedNode<?, ?> normalizedData) {
- // Preconditions.checkArgument(normalizedData instanceof
- // DataContainerNode<?>,"Node object %s, %s should be of type DataContainerNode",normalizedPath,normalizedData);
- if (normalizedData instanceof DataContainerNode<?>) {
- return toLegacyFromDataContainer((DataContainerNode<?>) normalizedData);
- } else if (normalizedData instanceof AnyXmlNode) {
- DOMSource value = ((AnyXmlNode) normalizedData).getValue();
- return value instanceof CompositeNode ? (CompositeNode) value : null;
- }
- return null;
- }
-
- public static Node<?> toLegacy(final NormalizedNode<?, ?> node) {
- if (node instanceof MixinNode) {
- /**
- * Direct reading of MixinNodes is not supported, since it is not
- * possible in legacy APIs create pointer to Mixin Nodes.
- *
- */
- return null;
- }
-
- if (node instanceof DataContainerNode<?>) {
- return toLegacyFromDataContainer((DataContainerNode<?>) node);
- } else if (node instanceof AnyXmlNode) {
- return null;
- }
- return toLegacySimple(node);
-
- }
-
- private static SimpleNode<?> toLegacySimple(final NormalizedNode<?, ?> node) {
- return new SimpleNodeTOImpl<Object>(node.getNodeType(), null, node.getValue());
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- private static CompositeNode toLegacyFromDataContainer(final DataContainerNode<?> node) {
- CompositeNodeBuilder<ImmutableCompositeNode> builder = ImmutableCompositeNode.builder();
- builder.setQName(node.getNodeType());
- for (NormalizedNode<?, ?> child : node.getValue()) {
- if (child instanceof MixinNode && child instanceof NormalizedNodeContainer<?, ?, ?>) {
- builder.addAll(toLegacyNodesFromMixin((NormalizedNodeContainer) child));
- } else if (child instanceof UnkeyedListNode) {
- builder.addAll(toLegacyNodesFromUnkeyedList((UnkeyedListNode) child));
- } else {
- addToBuilder(builder, toLegacy(child));
- }
- }
- return builder.toInstance();
- }
-
- private static Iterable<? extends Node<?>> toLegacyNodesFromUnkeyedList(final UnkeyedListNode mixin) {
- ArrayList<Node<?>> ret = new ArrayList<>();
- for (NormalizedNode<?, ?> child : mixin.getValue()) {
- ret.add(toLegacy(child));
- }
- return FluentIterable.from(ret).filter(Predicates.notNull());
- }
-
- private static void addToBuilder(final CompositeNodeBuilder<ImmutableCompositeNode> builder, final Node<?> legacy) {
- if (legacy != null) {
- builder.add(legacy);
- }
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- private static Iterable<Node<?>> toLegacyNodesFromMixin(
- final NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> mixin) {
- ArrayList<Node<?>> ret = new ArrayList<>();
- for (NormalizedNode<?, ?> child : mixin.getValue()) {
- if (child instanceof MixinNode && child instanceof NormalizedNodeContainer<?, ?, ?>) {
- Iterables.addAll(ret, toLegacyNodesFromMixin((NormalizedNodeContainer) child));
- } else {
- ret.add(toLegacy(child));
- }
- }
- return FluentIterable.from(ret).filter(Predicates.notNull());
- }
-
public DataNormalizationOperation<?> getRootOperation() {
return operation;
}
+++ /dev/null
-/*
- * Copyright (c) 2014 Brocade Communications 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.common.impl.util.compat;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import java.util.AbstractMap;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
-import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
-import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
-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.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.api.schema.UnkeyedListNode;
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
-import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
-import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
-import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
-
-@Deprecated
-public class DataNormalizerTest {
-
- static class NormalizedNodeData {
- PathArgument nodeID;
- Class<?> nodeClass;
- Object nodeData; // List for a container, value Object for a leaf
-
- NormalizedNodeData(final PathArgument nodeID, final Class<?> nodeClass, final Object nodeData) {
- this.nodeID = nodeID;
- this.nodeClass = nodeClass;
- this.nodeData = nodeData;
- }
- }
-
- static class LegacyNodeData {
- QName nodeKey;
- Object nodeData; // List for a CompositeNode, value Object for a
- // SimpeNode
-
- LegacyNodeData(final QName nodeKey, final Object nodeData) {
- this.nodeKey = nodeKey;
- this.nodeData = nodeData;
- }
-
- @Override
- public String toString() {
- return nodeKey.toString();
- }
- }
-
- static final QName TEST_QNAME = QName.create(
- "urn:opendaylight:params:xml:ns:yang:controller:md:sal:normalization:test", "2014-03-13", "test");
- static final QName OUTER_LIST_QNAME = QName.create(TEST_QNAME, "outer-list");
- static final QName INNER_LIST_QNAME = QName.create(TEST_QNAME, "inner-list");
- static final QName OUTER_CHOICE_QNAME = QName.create(TEST_QNAME, "outer-choice");
- static final QName ID_QNAME = QName.create(TEST_QNAME, "id");
- static final QName NAME_QNAME = QName.create(TEST_QNAME, "name");
- static final QName VALUE_QNAME = QName.create(TEST_QNAME, "value");
-
- static final YangInstanceIdentifier TEST_PATH = YangInstanceIdentifier.of(TEST_QNAME);
- static final YangInstanceIdentifier OUTER_LIST_PATH = YangInstanceIdentifier.builder(TEST_PATH).node(OUTER_LIST_QNAME)
- .build();
- static final QName ONE_QNAME = QName.create(TEST_QNAME, "one");
- static final QName TWO_QNAME = QName.create(TEST_QNAME, "two");
- static final QName THREE_QNAME = QName.create(TEST_QNAME, "three");
-
- static final QName ANY_XML_DATA_QNAME = QName.create(TEST_QNAME, "any-xml-data");
- static final QName OUTER_CONTAINER_QNAME = QName.create(TEST_QNAME, "outer-container");
- static final QName AUGMENTED_LEAF_QNAME = QName.create(TEST_QNAME, "augmented-leaf");
- static final QName UNKEYED_LIST_QNAME = QName.create(TEST_QNAME, "unkeyed-list");
- static final QName UNORDERED_LEAF_LIST_QNAME = QName.create(TEST_QNAME, "unordered-leaf-list");
- static final QName ORDERED_LEAF_LIST_QNAME = QName.create(TEST_QNAME, "ordered-leaf-list");
-
- static final Short OUTER_LIST_ID = (short) 10;
-
- static final YangInstanceIdentifier OUTER_LIST_PATH_LEGACY = YangInstanceIdentifier.builder(TEST_PATH)
- .nodeWithKey(OUTER_LIST_QNAME, ID_QNAME, OUTER_LIST_ID).build();
-
- static final YangInstanceIdentifier LEAF_TWO_PATH_LEGACY = YangInstanceIdentifier.builder(OUTER_LIST_PATH_LEGACY)
- .node(TWO_QNAME).build();
-
- static final QName ANY_XML_LEAF_QNAME = QName.create(TEST_QNAME, "leaf");;
- static final QName ANY_XML_INNER_QNAME = QName.create(TEST_QNAME, "inner");
- static final QName ANY_XML_INNER_LEAF_QNAME = QName.create(TEST_QNAME, "inner-leaf");
-
- SchemaContext createTestContext() {
- YangParserImpl parser = new YangParserImpl();
- Set<Module> modules = parser.parseYangModelsFromStreams(Collections.singletonList(DataNormalizerTest.class
- .getResourceAsStream("/normalization-test.yang")));
- return parser.resolveSchemaContext(modules);
- }
-
- @Test
- public void testToNormalizedInstanceIdentifier() {
- SchemaContext testCtx = createTestContext();
- DataNormalizer normalizer = new DataNormalizer(testCtx);
-
- YangInstanceIdentifier normalizedPath = normalizer.toNormalized(LEAF_TWO_PATH_LEGACY);
-
- verifyNormalizedInstanceIdentifier(normalizedPath, TEST_QNAME, OUTER_LIST_QNAME, new Object[] {
- OUTER_LIST_QNAME, ID_QNAME, OUTER_LIST_ID }, OUTER_CHOICE_QNAME, TWO_QNAME);
- }
-
- private void verifyNormalizedInstanceIdentifier(final YangInstanceIdentifier actual, final Object... expPath) {
-
- assertNotNull("Actual InstanceIdentifier is null", actual);
- assertEquals("InstanceIdentifier path length", expPath.length, Iterables.size(actual.getPathArguments()));
-
- for (int i = 0; i < expPath.length; i++) {
- PathArgument actualArg = Iterables.get(actual.getPathArguments(), i);
- if (expPath[i] instanceof Object[]) { // NodeIdentifierWithPredicates
- Object[] exp = (Object[]) expPath[i];
- assertEquals("Actual path arg " + (i + 1) + " class", NodeIdentifierWithPredicates.class,
- actualArg.getClass());
- NodeIdentifierWithPredicates actualNode = (NodeIdentifierWithPredicates) actualArg;
- assertEquals("Actual path arg " + (i + 1) + " node type", exp[0], actualNode.getNodeType());
- assertEquals("Actual path arg " + (i + 1) + " key values map size", 1, actualNode.getKeyValues().size());
- Entry<QName, Object> keyValuesEntry = actualNode.getKeyValues().entrySet().iterator().next();
- assertEquals("Actual path arg " + (i + 1) + " key values map key", exp[1], keyValuesEntry.getKey());
- assertEquals("Actual path arg " + (i + 1) + " key values map value", exp[2], keyValuesEntry.getValue());
- } else if (expPath[i] instanceof Set) { // AugmentationIdentifier
- assertEquals("Actual path arg " + (i + 1) + " class", AugmentationIdentifier.class,
- actualArg.getClass());
- AugmentationIdentifier actualNode = (AugmentationIdentifier) actualArg;
- assertEquals("Actual path arg " + (i + 1) + " PossibleChildNames", expPath[i],
- actualNode.getPossibleChildNames());
- } else {
- assertEquals("Actual path arg " + (i + 1) + " node type", expPath[i], actualArg.getNodeType());
- }
- }
- }
-
- @Test
- public void testToLegacyInstanceIdentifier() throws DataNormalizationException {
-
- DataNormalizer normalizer = new DataNormalizer(createTestContext());
-
- YangInstanceIdentifier normalized = YangInstanceIdentifier.builder().node(TEST_QNAME).node(OUTER_LIST_QNAME)
- .nodeWithKey(OUTER_LIST_QNAME, ID_QNAME, OUTER_LIST_ID).node(OUTER_CHOICE_QNAME).node(TWO_QNAME)
- .build();
-
- YangInstanceIdentifier legacy = normalizer.toLegacy(normalized);
-
- assertEquals("Legacy InstanceIdentifier", LEAF_TWO_PATH_LEGACY, legacy);
- }
-
- @Test
- public void testToLegacyNormalizedNode() {
-
- ChoiceNode choiceNode1 = Builders.choiceBuilder().withNodeIdentifier(new NodeIdentifier(OUTER_CHOICE_QNAME))
- .withChild(ImmutableNodes.leafNode(TWO_QNAME, "two"))
- .withChild(ImmutableNodes.leafNode(THREE_QNAME, "three")).build();
-
- MapEntryNode innerListEntryNode1 = Builders.mapEntryBuilder()
- .withNodeIdentifier(new NodeIdentifierWithPredicates(INNER_LIST_QNAME, NAME_QNAME, "inner-name1"))
- .withChild(ImmutableNodes.leafNode(NAME_QNAME, "inner-name1"))
- .withChild(ImmutableNodes.leafNode(VALUE_QNAME, "inner-value1")).build();
-
- MapEntryNode innerListEntryNode2 = Builders.mapEntryBuilder()
- .withNodeIdentifier(new NodeIdentifierWithPredicates(INNER_LIST_QNAME, NAME_QNAME, "inner-name2"))
- .withChild(ImmutableNodes.leafNode(NAME_QNAME, "inner-name2"))
- .withChild(ImmutableNodes.leafNode(VALUE_QNAME, "inner-value2")).build();
-
- OrderedMapNode innerListNode = Builders.orderedMapBuilder()
- .withNodeIdentifier(new NodeIdentifier(INNER_LIST_QNAME)).withChild(innerListEntryNode1)
- .withChild(innerListEntryNode2).build();
-
- Short outerListID1 = Short.valueOf((short) 10);
- MapEntryNode outerListEntryNode1 = Builders.mapEntryBuilder()
- .withNodeIdentifier(new NodeIdentifierWithPredicates(OUTER_LIST_QNAME, ID_QNAME, outerListID1))
- .withChild(ImmutableNodes.leafNode(ID_QNAME, outerListID1)).withChild(choiceNode1)
- .withChild(innerListNode).build();
-
- ChoiceNode choiceNode2 = Builders.choiceBuilder().withNodeIdentifier(new NodeIdentifier(OUTER_CHOICE_QNAME))
- .withChild(ImmutableNodes.leafNode(ONE_QNAME, "one")).build();
-
- Short outerListID2 = Short.valueOf((short) 20);
- MapEntryNode outerListEntryNode2 = Builders.mapEntryBuilder()
- .withNodeIdentifier(new NodeIdentifierWithPredicates(OUTER_LIST_QNAME, ID_QNAME, outerListID2))
- .withChild(ImmutableNodes.leafNode(ID_QNAME, outerListID2)).withChild(choiceNode2).build();
-
- MapNode outerListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(OUTER_LIST_QNAME))
- .withChild(outerListEntryNode1).withChild(outerListEntryNode2).build();
-
- UnkeyedListEntryNode unkeyedListEntryNode1 = Builders.unkeyedListEntryBuilder()
- .withNodeIdentifier(new NodeIdentifier(UNKEYED_LIST_QNAME))
- .withChild(ImmutableNodes.leafNode(NAME_QNAME, "unkeyed1")).build();
-
- UnkeyedListEntryNode unkeyedListEntryNode2 = Builders.unkeyedListEntryBuilder()
- .withNodeIdentifier(new NodeIdentifier(UNKEYED_LIST_QNAME))
- .withChild(ImmutableNodes.leafNode(NAME_QNAME, "unkeyed2")).build();
-
- UnkeyedListNode unkeyedListNode = Builders.unkeyedListBuilder()
- .withNodeIdentifier(new NodeIdentifier(UNKEYED_LIST_QNAME)).withChild(unkeyedListEntryNode1)
- .withChild(unkeyedListEntryNode2).build();
-
- ContainerNode testContainerNode = Builders.containerBuilder()
- .withNodeIdentifier(new NodeIdentifier(TEST_QNAME)).withChild(outerListNode).withChild(unkeyedListNode)
- .build();
-
- Node<?> legacyNode = DataNormalizer.toLegacy(testContainerNode);
-
- verifyLegacyNode(
- legacyNode,
- expectCompositeNode(
- TEST_QNAME,
- expectCompositeNode(
- OUTER_LIST_QNAME,
- expectSimpleNode(ID_QNAME, outerListID1),
- expectSimpleNode(TWO_QNAME, "two"),
- expectSimpleNode(THREE_QNAME, "three"),
-
- expectCompositeNode(INNER_LIST_QNAME, expectSimpleNode(NAME_QNAME, "inner-name1"),
- expectSimpleNode(VALUE_QNAME, "inner-value1")),
-
- expectCompositeNode(INNER_LIST_QNAME, expectSimpleNode(NAME_QNAME, "inner-name2"),
- expectSimpleNode(VALUE_QNAME, "inner-value2"))),
- expectCompositeNode(OUTER_LIST_QNAME, expectSimpleNode(ID_QNAME, outerListID2),
- expectSimpleNode(ONE_QNAME, "one")),
- expectCompositeNode(UNKEYED_LIST_QNAME, expectSimpleNode(NAME_QNAME, "unkeyed1")),
- expectCompositeNode(UNKEYED_LIST_QNAME, expectSimpleNode(NAME_QNAME, "unkeyed2"))));
-
- // Conversion of Mixin type nodes is not supported.
-
- assertNull("Expected null returned for Mixin type node", DataNormalizer.toLegacy(outerListNode));
- }
-
- /**
- * Following data are constructed: <any-xml-data> <inner>
- * <inner-leaf>inner-leaf-value</inner-leaf> </inner>
- * <leaf>leaf-value</leaf> <any-xml-data>
- */
- @Ignore
- @Test
- public void testToLegacyNormalizedNodeWithAnyXml() {
-
- Node<?> innerLeafChild = NodeFactory.createImmutableSimpleNode(ANY_XML_INNER_LEAF_QNAME, null,
- "inner-leaf-value");
- CompositeNode innerContainer = NodeFactory.createImmutableCompositeNode(ANY_XML_INNER_QNAME, null,
- Collections.<Node<?>> singletonList(innerLeafChild));
-
- Node<?> leafChild = NodeFactory.createImmutableSimpleNode(ANY_XML_LEAF_QNAME, null, "leaf-value");
- CompositeNode anyXmlNodeValue = NodeFactory.createImmutableCompositeNode(ANY_XML_DATA_QNAME, null,
- Arrays.asList(leafChild, innerContainer));
-
- AnyXmlNode testAnyXmlNode = Builders.anyXmlBuilder().withNodeIdentifier(new NodeIdentifier(TEST_QNAME)).build();
-
- ContainerNode testContainerNode = Builders.containerBuilder()
- .withNodeIdentifier(new NodeIdentifier(TEST_QNAME)).withChild(testAnyXmlNode).build();
-
- DataNormalizer normalizer = new DataNormalizer(createTestContext());
- Node<?> legacyNode = normalizer.toLegacy(YangInstanceIdentifier.builder().node(TEST_QNAME).build(), testContainerNode);
-
- verifyLegacyNode(
- legacyNode,
- expectCompositeNode(
- TEST_QNAME,
- expectCompositeNode(
- ANY_XML_DATA_QNAME,
- expectSimpleNode(ANY_XML_LEAF_QNAME, "leaf-value"),
- expectCompositeNode(ANY_XML_INNER_QNAME,
- expectSimpleNode(ANY_XML_INNER_LEAF_QNAME, "inner-leaf-value")))));
- }
-
- @Test
- public void testToLegacyNormalizedNodeWithLeafLists() {
-
- CompositeNodeBuilder<ImmutableCompositeNode> testBuilder = ImmutableCompositeNode.builder();
- testBuilder.setQName(TEST_QNAME);
-
- ListNodeBuilder<Object, LeafSetEntryNode<Object>> leafSetBuilder = Builders.leafSetBuilder()
- .withNodeIdentifier(new NodeIdentifier(UNORDERED_LEAF_LIST_QNAME));
- for (int i = 1; i <= 3; i++) {
- leafSetBuilder.withChildValue("unordered-value" + i);
- }
-
- ListNodeBuilder<Object, LeafSetEntryNode<Object>> orderedLeafSetBuilder = Builders.orderedLeafSetBuilder()
- .withNodeIdentifier(new NodeIdentifier(ORDERED_LEAF_LIST_QNAME));
- for (int i = 3; i > 0; i--) {
- orderedLeafSetBuilder.withChildValue("ordered-value" + i);
- }
-
- ContainerNode testContainerNode = Builders.containerBuilder()
- .withNodeIdentifier(new NodeIdentifier(TEST_QNAME)).withChild(leafSetBuilder.build())
- .withChild(orderedLeafSetBuilder.build()).build();
-
- DataNormalizer normalizer = new DataNormalizer(createTestContext());
-
- Node<?> legacyNode = normalizer.toLegacy(YangInstanceIdentifier.builder().node(TEST_QNAME).build(), testContainerNode);
-
- verifyLegacyNode(
- legacyNode,
- expectCompositeNode(TEST_QNAME, expectSimpleNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value1"),
- expectSimpleNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value2"),
- expectSimpleNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value3"),
- expectSimpleNode(ORDERED_LEAF_LIST_QNAME, "ordered-value3"),
- expectSimpleNode(ORDERED_LEAF_LIST_QNAME, "ordered-value2"),
- expectSimpleNode(ORDERED_LEAF_LIST_QNAME, "ordered-value1")));
- }
-
- @Test
- public void testToLegacyNormalizedNodeWithAugmentation() {
-
- AugmentationNode augmentationNode = Builders.augmentationBuilder()
- .withNodeIdentifier(new AugmentationIdentifier(Sets.newHashSet(AUGMENTED_LEAF_QNAME)))
- .withChild(ImmutableNodes.leafNode(AUGMENTED_LEAF_QNAME, "augmented-value")).build();
-
- ContainerNode outerContainerNode = Builders.containerBuilder()
- .withNodeIdentifier(new NodeIdentifier(OUTER_CONTAINER_QNAME)).withChild(augmentationNode).build();
-
- ContainerNode testContainerNode = Builders.containerBuilder()
- .withNodeIdentifier(new NodeIdentifier(TEST_QNAME)).withChild(outerContainerNode).build();
-
- DataNormalizer normalizer = new DataNormalizer(createTestContext());
-
- Node<?> legacyNode = normalizer.toLegacy(YangInstanceIdentifier.builder().node(TEST_QNAME).build(), testContainerNode);
-
- verifyLegacyNode(
- legacyNode,
- expectCompositeNode(
- TEST_QNAME,
- expectCompositeNode(OUTER_CONTAINER_QNAME,
- expectSimpleNode(AUGMENTED_LEAF_QNAME, "augmented-value"))));
- }
-
- private boolean isOrdered(final QName nodeName) {
- return ORDERED_LEAF_LIST_QNAME.equals(nodeName) || INNER_LIST_QNAME.equals(nodeName);
- }
-
- @SuppressWarnings("unchecked")
- private void verifyLegacyNode(final Node<?> actual, final LegacyNodeData expNodeData) {
-
- assertNotNull("Actual Node is null", actual);
- assertTrue("Expected CompositeNode instance", actual instanceof CompositeNode);
- CompositeNode actualCN = (CompositeNode) actual;
- assertEquals("Node key", expNodeData.nodeKey, actualCN.getKey());
-
- List<LegacyNodeData> expChildData = Lists.newArrayList();
- List<LegacyNodeData> unorderdChildData = Lists.newArrayList();
- for (LegacyNodeData data : (List<LegacyNodeData>) expNodeData.nodeData) {
- if (isOrdered(data.nodeKey)) {
- expChildData.add(data);
- } else {
- unorderdChildData.add(data);
- }
- }
-
- Collections.sort(unorderdChildData, new Comparator<LegacyNodeData>() {
- @Override
- public int compare(final LegacyNodeData arg1, final LegacyNodeData arg2) {
- if (!(arg1.nodeData instanceof List) && !(arg2.nodeData instanceof List)) {
- // if neither is a list, just compare them
- String str1 = arg1.nodeKey.getLocalName() + arg1.nodeData;
- String str2 = arg2.nodeKey.getLocalName() + arg2.nodeData;
- return str1.compareTo(str2);
- } else if (arg1.nodeData instanceof List && arg2.nodeData instanceof List) {
- // if both are lists, first check their local name
- String str1 = arg1.nodeKey.getLocalName();
- String str2 = arg2.nodeKey.getLocalName();
- if (!str1.equals(str2)) {
- return str1.compareTo(str2);
- } else {
- // if local names are the same, then look at the list contents
- List<LegacyNodeData> l1 = (List<LegacyNodeData>) arg1.nodeData;
- List<LegacyNodeData> l2 = (List<LegacyNodeData>) arg2.nodeData;
-
- if (l1.size() != l2.size()) {
- // if the sizes are different, use that
- return l2.size() - l1.size();
- } else {
- // lastly sort and recursively check the list contents
- Collections.sort(l1, this);
- Collections.sort(l2, this);
-
- for (int i = 0 ; i < l1.size() ; i++) {
- int diff = this.compare(l1.get(i), l2.get(i));
- if (diff != 0) {
- return diff;
- }
- }
- return 0;
- }
- }
- } else if( arg1.nodeData instanceof List ) {
- return -1;
- } else{
- return 1;
- }
- }
- });
-
- expChildData.addAll(unorderdChildData);
-
- List<Node<?>> actualChildNodes = Lists.newArrayList();
- List<Node<?>> unorderedChildNodes = Lists.newArrayList();
- for (Node<?> node : actualCN.getValue()) {
- if (isOrdered(node.getKey())) {
- actualChildNodes.add(node);
- } else {
- unorderedChildNodes.add(node);
- }
- }
-
- Collections.sort(unorderedChildNodes, new Comparator<Node<?>>() {
- @Override
- public int compare(final Node<?> n1, final Node<?> n2) {
- if (n1 instanceof SimpleNode && n2 instanceof SimpleNode) {
- // if they're SimpleNodes just compare their strings
- String str1 = n1.getKey().getLocalName() + ((SimpleNode<?>)n1).getValue();
- String str2 = n2.getKey().getLocalName() + ((SimpleNode<?>)n2).getValue();
- return str1.compareTo(str2);
- } else if (n1 instanceof CompositeNode && n2 instanceof CompositeNode) {
- // if they're CompositeNodes, things are more interesting
- String str1 = n1.getKey().getLocalName();
- String str2 = n2.getKey().getLocalName();
- if (!str1.equals(str2)) {
- // if their local names differ, return that difference
- return str1.compareTo(str2);
- } else {
- // otherwise, we need to look at their contents
- ArrayList<Node<?>> l1 = new ArrayList<Node<?>>( ((CompositeNode)n1).getValue() );
- ArrayList<Node<?>> l2 = new ArrayList<Node<?>>( ((CompositeNode)n2).getValue() );
-
- if (l1.size() != l2.size()) {
- // if they have different numbers of things in them return that
- return l2.size() - l1.size();
- } else {
- // otherwise, compare the individual elements, first sort them
- Collections.sort(l1, this);
- Collections.sort(l2, this);
-
- // then compare them individually
- for(int i = 0 ; i < l2.size() ; i++) {
- int diff = this.compare(l1.get(i), l2.get(i));
- if(diff != 0){
- return diff;
- }
- }
- return 0;
- }
- }
- } else if (n1 instanceof CompositeNode && n2 instanceof SimpleNode) {
- return -1;
- } else if (n2 instanceof CompositeNode && n1 instanceof SimpleNode) {
- return 1;
- } else {
- assertTrue("Expected either SimpleNodes CompositeNodes", false);
- return 0;
- }
- }
- });
-
- actualChildNodes.addAll(unorderedChildNodes);
-
- for (Node<?> actualChild : actualChildNodes) {
- LegacyNodeData expData = expChildData.isEmpty() ? null : expChildData.remove(0);
- assertNotNull("Unexpected child node with key " + actualChild.getKey(), expData);
- assertEquals("Child node QName", expData.nodeKey, actualChild.getKey());
-
- if (expData.nodeData instanceof List) { // List represents a
- // composite node
- verifyLegacyNode(actualChild, expData);
- } else { // else a simple node
- assertTrue("Expected SimpleNode instance", actualChild instanceof SimpleNode);
- assertEquals("Child node value with key " + actualChild.getKey(), expData.nodeData,
- ((SimpleNode<?>) actualChild).getValue());
- }
- }
-
- if (!expChildData.isEmpty()) {
- fail("Missing child nodes: " + expChildData);
- }
- }
-
- private LegacyNodeData expectCompositeNode(final QName key, final LegacyNodeData... childData) {
- return new LegacyNodeData(key, Lists.newArrayList(childData));
- }
-
- private LegacyNodeData expectSimpleNode(final QName key, final Object value) {
- return new LegacyNodeData(key, value);
- }
-
- @Test
- public void testToNormalizedCompositeNode() {
- SchemaContext testCtx = createTestContext();
- DataNormalizer normalizer = new DataNormalizer(testCtx);
-
- CompositeNodeBuilder<ImmutableCompositeNode> testBuilder = ImmutableCompositeNode.builder();
- testBuilder.setQName(TEST_QNAME);
-
- CompositeNodeBuilder<ImmutableCompositeNode> outerListBuilder = ImmutableCompositeNode.builder();
- outerListBuilder.setQName(OUTER_LIST_QNAME);
- outerListBuilder.addLeaf(ID_QNAME, 10);
- outerListBuilder.addLeaf(ONE_QNAME, "one");
-
- for (int i = 3; i > 0; i--) {
- CompositeNodeBuilder<ImmutableCompositeNode> innerListBuilder = ImmutableCompositeNode.builder();
- innerListBuilder.setQName(INNER_LIST_QNAME);
- innerListBuilder.addLeaf(NAME_QNAME, "inner-name" + i);
- innerListBuilder.addLeaf(VALUE_QNAME, "inner-value" + i);
- outerListBuilder.add(innerListBuilder.toInstance());
- }
-
- testBuilder.add(outerListBuilder.toInstance());
-
- outerListBuilder = ImmutableCompositeNode.builder();
- outerListBuilder.setQName(OUTER_LIST_QNAME);
- outerListBuilder.addLeaf(ID_QNAME, 20);
- outerListBuilder.addLeaf(TWO_QNAME, "two");
- outerListBuilder.addLeaf(THREE_QNAME, "three");
- testBuilder.add(outerListBuilder.toInstance());
-
- for (int i = 1; i <= 2; i++) {
- CompositeNodeBuilder<ImmutableCompositeNode> unkeyedListBuilder = ImmutableCompositeNode.builder();
- unkeyedListBuilder.setQName(UNKEYED_LIST_QNAME);
- unkeyedListBuilder.addLeaf(NAME_QNAME, "unkeyed-name" + i);
- testBuilder.add(unkeyedListBuilder.toInstance());
- }
-
- Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedNodeEntry = normalizer
- .toNormalized(new AbstractMap.SimpleEntry<YangInstanceIdentifier, CompositeNode>(YangInstanceIdentifier.create(
- ImmutableList.<PathArgument> of(new NodeIdentifier(TEST_QNAME))), testBuilder.toInstance()));
-
- verifyNormalizedInstanceIdentifier(normalizedNodeEntry.getKey(), TEST_QNAME);
-
- verifyNormalizedNode(
- normalizedNodeEntry.getValue(),
- expectContainerNode(
- TEST_QNAME,
- expectMapNode(
- OUTER_LIST_QNAME,
- expectMapEntryNode(
- OUTER_LIST_QNAME,
- ID_QNAME,
- 10,
- expectLeafNode(ID_QNAME, 10),
- expectChoiceNode(OUTER_CHOICE_QNAME, expectLeafNode(ONE_QNAME, "one")),
- expectOrderedMapNode(
- INNER_LIST_QNAME,
- expectMapEntryNode(INNER_LIST_QNAME, NAME_QNAME, "inner-name3",
- expectLeafNode(NAME_QNAME, "inner-name3"),
- expectLeafNode(VALUE_QNAME, "inner-value3")),
- expectMapEntryNode(INNER_LIST_QNAME, NAME_QNAME, "inner-name2",
- expectLeafNode(NAME_QNAME, "inner-name2"),
- expectLeafNode(VALUE_QNAME, "inner-value2")),
- expectMapEntryNode(INNER_LIST_QNAME, NAME_QNAME, "inner-name1",
- expectLeafNode(NAME_QNAME, "inner-name1"),
- expectLeafNode(VALUE_QNAME, "inner-value1")))),
- expectMapEntryNode(
- OUTER_LIST_QNAME,
- ID_QNAME,
- 20,
- expectLeafNode(ID_QNAME, 20),
- expectChoiceNode(OUTER_CHOICE_QNAME, expectLeafNode(TWO_QNAME, "two"),
- expectLeafNode(THREE_QNAME, "three")))),
- expectUnkeyedListNode(
- UNKEYED_LIST_QNAME,
- expectUnkeyedListEntryNode(UNKEYED_LIST_QNAME,
- expectLeafNode(NAME_QNAME, "unkeyed-name1")),
- expectUnkeyedListEntryNode(UNKEYED_LIST_QNAME,
- expectLeafNode(NAME_QNAME, "unkeyed-name2")))));
- }
-
- @Ignore
- @Test
- public void testToNormalizedCompositeNodeWithAnyXml() {
- SchemaContext testCtx = createTestContext();
- DataNormalizer normalizer = new DataNormalizer(testCtx);
-
- CompositeNodeBuilder<ImmutableCompositeNode> testBuilder = ImmutableCompositeNode.builder();
- testBuilder.setQName(TEST_QNAME);
-
- CompositeNodeBuilder<ImmutableCompositeNode> anyXmlBuilder = ImmutableCompositeNode.builder();
- anyXmlBuilder.setQName(ANY_XML_DATA_QNAME);
- anyXmlBuilder.addLeaf(ANY_XML_LEAF_QNAME, "leaf-value");
-
- CompositeNodeBuilder<ImmutableCompositeNode> innerBuilder = ImmutableCompositeNode.builder();
- innerBuilder.setQName(ANY_XML_INNER_QNAME);
- innerBuilder.addLeaf(ANY_XML_INNER_LEAF_QNAME, "inner-leaf-value");
-
- anyXmlBuilder.add(innerBuilder.toInstance());
- CompositeNode anyXmlLegacy = anyXmlBuilder.toInstance();
- testBuilder.add(anyXmlLegacy);
-
- Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedNodeEntry = normalizer
- .toNormalized(new AbstractMap.SimpleEntry<YangInstanceIdentifier, CompositeNode>(YangInstanceIdentifier.create(
- ImmutableList.<PathArgument> of(new NodeIdentifier(TEST_QNAME))), testBuilder.toInstance()));
-
- verifyNormalizedInstanceIdentifier(normalizedNodeEntry.getKey(), TEST_QNAME);
-
- verifyNormalizedNode(normalizedNodeEntry.getValue(),
- expectContainerNode(TEST_QNAME, expectAnyXmlNode(ANY_XML_DATA_QNAME, anyXmlLegacy)));
- }
-
- @Test
- public void testToNormalizedCompositeNodeWithAugmentation() {
- SchemaContext testCtx = createTestContext();
- DataNormalizer normalizer = new DataNormalizer(testCtx);
-
- CompositeNodeBuilder<ImmutableCompositeNode> testBuilder = ImmutableCompositeNode.builder();
- testBuilder.setQName(TEST_QNAME);
-
- CompositeNodeBuilder<ImmutableCompositeNode> outerContBuilder = ImmutableCompositeNode.builder();
- outerContBuilder.setQName(OUTER_CONTAINER_QNAME);
- outerContBuilder.addLeaf(AUGMENTED_LEAF_QNAME, "augmented-value");
-
- testBuilder.add(outerContBuilder.toInstance());
-
- Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedNodeEntry = normalizer
- .toNormalized(new AbstractMap.SimpleEntry<YangInstanceIdentifier, CompositeNode>(YangInstanceIdentifier.create(
- ImmutableList.<PathArgument> of(new NodeIdentifier(TEST_QNAME))), testBuilder.toInstance()));
-
- verifyNormalizedInstanceIdentifier(normalizedNodeEntry.getKey(), TEST_QNAME);
-
- NormalizedNodeData expAugmentation = expectAugmentation(AUGMENTED_LEAF_QNAME,
- expectLeafNode(AUGMENTED_LEAF_QNAME, "augmented-value"));
-
- verifyNormalizedNode(normalizedNodeEntry.getValue(),
- expectContainerNode(TEST_QNAME, expectContainerNode(OUTER_CONTAINER_QNAME, expAugmentation)));
-
- normalizedNodeEntry = normalizer.toNormalized(new AbstractMap.SimpleEntry<YangInstanceIdentifier, CompositeNode>(
- YangInstanceIdentifier.create(Lists.newArrayList(new NodeIdentifier(TEST_QNAME), new NodeIdentifier(
- OUTER_CONTAINER_QNAME))), outerContBuilder.toInstance()));
-
- }
-
- @Test
- public void testToNormalizedCompositeNodeWithLeafLists() {
- SchemaContext testCtx = createTestContext();
- DataNormalizer normalizer = new DataNormalizer(testCtx);
-
- CompositeNodeBuilder<ImmutableCompositeNode> testBuilder = ImmutableCompositeNode.builder();
- testBuilder.setQName(TEST_QNAME);
-
- for (int i = 1; i <= 3; i++) {
- testBuilder.addLeaf(UNORDERED_LEAF_LIST_QNAME, "unordered-value" + i);
- }
-
- for (int i = 3; i > 0; i--) {
- testBuilder.addLeaf(ORDERED_LEAF_LIST_QNAME, "ordered-value" + i);
- }
-
- Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedNodeEntry = normalizer
- .toNormalized(new AbstractMap.SimpleEntry<YangInstanceIdentifier, CompositeNode>(YangInstanceIdentifier.create(
- ImmutableList.<PathArgument> of(new NodeIdentifier(TEST_QNAME))), testBuilder.toInstance()));
-
- verifyNormalizedInstanceIdentifier(normalizedNodeEntry.getKey(), TEST_QNAME);
-
- verifyNormalizedNode(
- normalizedNodeEntry.getValue(),
- expectContainerNode(
- TEST_QNAME,
- expectLeafSetNode(UNORDERED_LEAF_LIST_QNAME,
- expectLeafSetEntryNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value1"),
- expectLeafSetEntryNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value2"),
- expectLeafSetEntryNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value3")),
- expectOrderedLeafSetNode(ORDERED_LEAF_LIST_QNAME,
- expectLeafSetEntryNode(ORDERED_LEAF_LIST_QNAME, "ordered-value3"),
- expectLeafSetEntryNode(ORDERED_LEAF_LIST_QNAME, "ordered-value2"),
- expectLeafSetEntryNode(ORDERED_LEAF_LIST_QNAME, "ordered-value1"))));
- }
-
- @SuppressWarnings("unchecked")
- private void verifyNormalizedNode(final NormalizedNode<?, ?> actual, final NormalizedNodeData expNodeData) {
-
- Class<?> expNodeClass = expNodeData.nodeClass;
- PathArgument expNodeID = expNodeData.nodeID;
-
- assertNotNull("Actual NormalizedNode is null", actual);
- assertTrue("NormalizedNode instance " + actual.getClass() + " is not derived from " + expNodeClass,
- expNodeClass.isAssignableFrom(actual.getClass()));
- assertEquals("NormalizedNode identifier", expNodeID, actual.getIdentifier());
-
- if (expNodeData.nodeData instanceof List) {
- Map<PathArgument, Integer> orderingMap = null;
- if (expNodeClass.equals(OrderedMapNode.class) || expNodeClass.equals(OrderedLeafSetNode.class)) {
- orderingMap = Maps.newHashMap();
- }
-
- int i = 1;
- Map<PathArgument, NormalizedNodeData> expChildDataMap = Maps.newHashMap();
- List<NormalizedNodeData> expChildDataList = (List<NormalizedNodeData>) expNodeData.nodeData;
- for (NormalizedNodeData data : expChildDataList) {
- expChildDataMap.put(data.nodeID, data);
-
- if (orderingMap != null) {
- orderingMap.put(data.nodeID, i++);
- }
- }
-
- assertNotNull("Actual value is null for node " + actual.getIdentifier(), actual.getValue());
- assertTrue("Expected value instance Iterable for node " + actual.getIdentifier(),
- Iterable.class.isAssignableFrom(actual.getValue().getClass()));
-
- i = 1;
- for (NormalizedNode<?, ?> actualChild : (Iterable<NormalizedNode<?, ?>>) actual.getValue()) {
- NormalizedNodeData expChildData = expNodeClass.equals(UnkeyedListNode.class) ? expChildDataList
- .remove(0) : expChildDataMap.remove(actualChild.getIdentifier());
-
- assertNotNull(
- "Unexpected child node " + actualChild.getClass() + " with identifier "
- + actualChild.getIdentifier() + " for parent node " + actual.getClass()
- + " with identifier " + actual.getIdentifier(), expChildData);
-
- if (orderingMap != null) {
- assertEquals("Order index for child node " + actualChild.getIdentifier(),
- orderingMap.get(actualChild.getIdentifier()), Integer.valueOf(i));
- }
-
- verifyNormalizedNode(actualChild, expChildData);
- i++;
- }
-
- if (expNodeClass.equals(UnkeyedListNode.class)) {
- if (expChildDataList.size() > 0) {
- fail("Missing " + expChildDataList.size() + " child nodes for parent " + actual.getIdentifier());
- }
- } else {
- if (!expChildDataMap.isEmpty()) {
- fail("Missing child nodes for parent " + actual.getIdentifier() + ": " + expChildDataMap.keySet());
- }
- }
- } else {
- assertEquals("Leaf value for node " + actual.getIdentifier(), expNodeData.nodeData, actual.getValue());
- }
- }
-
- private NormalizedNodeData expectOrderedLeafSetNode(final QName nodeName, final NormalizedNodeData... childData) {
- return new NormalizedNodeData(new NodeIdentifier(nodeName), OrderedLeafSetNode.class,
- Lists.newArrayList(childData));
- }
-
- private NormalizedNodeData expectLeafSetNode(final QName nodeName, final NormalizedNodeData... childData) {
- return new NormalizedNodeData(new NodeIdentifier(nodeName), LeafSetNode.class, Lists.newArrayList(childData));
- }
-
- private NormalizedNodeData expectLeafSetEntryNode(final QName nodeName, final Object value) {
- return new NormalizedNodeData(new NodeWithValue(nodeName, value), LeafSetEntryNode.class, value);
- }
-
- private NormalizedNodeData expectUnkeyedListNode(final QName nodeName, final NormalizedNodeData... childData) {
- return new NormalizedNodeData(new NodeIdentifier(nodeName), UnkeyedListNode.class,
- Lists.newArrayList(childData));
- }
-
- private NormalizedNodeData expectUnkeyedListEntryNode(final QName nodeName, final NormalizedNodeData... childData) {
- return new NormalizedNodeData(new NodeIdentifier(nodeName), UnkeyedListEntryNode.class,
- Lists.newArrayList(childData));
- }
-
- private NormalizedNodeData expectAugmentation(final QName augmentedNodeName, final NormalizedNodeData... childData) {
- return new NormalizedNodeData(new AugmentationIdentifier(Sets.newHashSet(augmentedNodeName)),
- AugmentationNode.class, Lists.newArrayList(childData));
- }
-
- private NormalizedNodeData expectAnyXmlNode(final QName nodeName, final Object value) {
- return new NormalizedNodeData(new NodeIdentifier(nodeName), AnyXmlNode.class, value);
- }
-
- private NormalizedNodeData expectContainerNode(final QName nodeName, final NormalizedNodeData... childData) {
- return new NormalizedNodeData(new NodeIdentifier(nodeName), ContainerNode.class, Lists.newArrayList(childData));
- }
-
- private NormalizedNodeData expectChoiceNode(final QName nodeName, final NormalizedNodeData... childData) {
- return new NormalizedNodeData(new NodeIdentifier(nodeName), ChoiceNode.class, Lists.newArrayList(childData));
- }
-
- private NormalizedNodeData expectLeafNode(final QName nodeName, final Object value) {
- return new NormalizedNodeData(new NodeIdentifier(nodeName), LeafNode.class, value);
-
- }
-
- private NormalizedNodeData expectMapEntryNode(final QName nodeName, final QName key, final Object value,
- final NormalizedNodeData... childData) {
- return new NormalizedNodeData(new NodeIdentifierWithPredicates(nodeName, key, value), MapEntryNode.class,
- Lists.newArrayList(childData));
- }
-
- private NormalizedNodeData expectMapNode(final QName key, final NormalizedNodeData... childData) {
- return new NormalizedNodeData(new NodeIdentifier(key), MapNode.class, Lists.newArrayList(childData));
- }
-
- private NormalizedNodeData expectOrderedMapNode(final QName key, final NormalizedNodeData... childData) {
- return new NormalizedNodeData(new NodeIdentifier(key), OrderedMapNode.class, Lists.newArrayList(childData));
- }
-}
+++ /dev/null
-/*
- * 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.connector.api;
-
-import java.util.Set;
-
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-public interface Connector extends RpcImplementation, NotificationListener {
-
-
-
- Set<YangInstanceIdentifier> getConfigurationPrefixes();
- Set<YangInstanceIdentifier> getRuntimePrefixes();
-
- void registerListener(ConnectorListener listener);
- void unregisterListener(ConnectorListener listener);
-}
LOG.info("Beginning to wait for data store to become ready : {}", type);
try {
- waitTillReadyCountDownLatch.await(waitTillReadyTimeInMillis, TimeUnit.MILLISECONDS);
-
- LOG.debug("Data store {} is now ready", type);
+ if (waitTillReadyCountDownLatch.await(waitTillReadyTimeInMillis, TimeUnit.MILLISECONDS)) {
+ LOG.debug("Data store {} is now ready", type);
+ } else {
+ LOG.error("Shared leaders failed to settle in {} seconds, giving up", TimeUnit.MILLISECONDS.toSeconds(waitTillReadyTimeInMillis));
+ }
} catch (InterruptedException e) {
- LOG.error("Interrupted when trying to wait for shards to become leader in a reasonable amount of time - giving up");
+ LOG.error("Interrupted while waiting for shards to settle", e);
}
}
import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier;
import org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification;
import org.opendaylight.controller.cluster.datastore.modification.WriteModification;
-import org.opendaylight.controller.cluster.datastore.utils.InMemoryJournal;
-import org.opendaylight.controller.cluster.datastore.utils.InMemorySnapshotStore;
+import org.opendaylight.controller.cluster.raft.utils.InMemoryJournal;
+import org.opendaylight.controller.cluster.raft.utils.InMemorySnapshotStore;
import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
import org.opendaylight.controller.cluster.datastore.exceptions.NoShardLeaderException;
import org.opendaylight.controller.cluster.datastore.exceptions.NotInitializedException;
import org.opendaylight.controller.cluster.datastore.shardstrategy.ShardStrategyFactory;
-import org.opendaylight.controller.cluster.datastore.utils.InMemoryJournal;
import org.opendaylight.controller.cluster.datastore.utils.MockClusterWrapper;
import org.opendaylight.controller.cluster.datastore.utils.MockDataChangeListener;
+import org.opendaylight.controller.cluster.raft.utils.InMemoryJournal;
import org.opendaylight.controller.md.cluster.datastore.model.CarsModel;
import org.opendaylight.controller.md.cluster.datastore.model.PeopleModel;
import org.opendaylight.controller.md.cluster.datastore.model.SchemaContextHelper;
import org.opendaylight.controller.cluster.datastore.messages.PrimaryNotFound;
import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
import org.opendaylight.controller.cluster.datastore.utils.DoNothingActor;
-import org.opendaylight.controller.cluster.datastore.utils.InMemoryJournal;
import org.opendaylight.controller.cluster.datastore.utils.MockClusterWrapper;
import org.opendaylight.controller.cluster.datastore.utils.MockConfiguration;
import org.opendaylight.controller.cluster.notifications.RoleChangeNotification;
import org.opendaylight.controller.cluster.raft.RaftState;
import org.opendaylight.controller.cluster.raft.base.messages.FollowerInitialSyncUpStatus;
+import org.opendaylight.controller.cluster.raft.utils.InMemoryJournal;
import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
private static class DelegatingShardManagerCreator implements Creator<ShardManager> {
private static final long serialVersionUID = 1L;
- private Creator<ShardManager> delegate;
+ private final Creator<ShardManager> delegate;
public DelegatingShardManagerCreator(Creator<ShardManager> delegate) {
this.delegate = delegate;
import org.opendaylight.controller.cluster.datastore.modification.ModificationPayload;
import org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification;
import org.opendaylight.controller.cluster.datastore.modification.WriteModification;
-import org.opendaylight.controller.cluster.datastore.utils.InMemoryJournal;
-import org.opendaylight.controller.cluster.datastore.utils.InMemorySnapshotStore;
import org.opendaylight.controller.cluster.datastore.utils.MessageCollectorActor;
import org.opendaylight.controller.cluster.datastore.utils.MockDataChangeListener;
import org.opendaylight.controller.cluster.datastore.utils.SerializationUtils;
import org.opendaylight.controller.cluster.raft.base.messages.FollowerInitialSyncUpStatus;
import org.opendaylight.controller.cluster.raft.client.messages.FindLeader;
import org.opendaylight.controller.cluster.raft.client.messages.FindLeaderReply;
+import org.opendaylight.controller.cluster.raft.utils.InMemoryJournal;
+import org.opendaylight.controller.cluster.raft.utils.InMemorySnapshotStore;
import org.opendaylight.controller.md.cluster.datastore.model.SchemaContextHelper;
import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
import org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification;
import org.opendaylight.controller.cluster.datastore.modification.WriteModification;
import org.opendaylight.controller.cluster.datastore.node.NormalizedNodeToNodeCodec;
-import org.opendaylight.controller.cluster.datastore.utils.InMemoryJournal;
-import org.opendaylight.controller.cluster.datastore.utils.InMemorySnapshotStore;
import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
import org.opendaylight.controller.cluster.raft.ReplicatedLogImplEntry;
import org.opendaylight.controller.cluster.raft.Snapshot;
import org.opendaylight.controller.cluster.raft.base.messages.ApplyState;
import org.opendaylight.controller.cluster.raft.protobuff.client.messages.CompositeModificationByteStringPayload;
import org.opendaylight.controller.cluster.raft.protobuff.client.messages.CompositeModificationPayload;
+import org.opendaylight.controller.cluster.raft.utils.InMemoryJournal;
+import org.opendaylight.controller.cluster.raft.utils.InMemorySnapshotStore;
import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreFactory;
}
in-memory-journal {
- class = "org.opendaylight.controller.cluster.datastore.utils.InMemoryJournal"
+ class = "org.opendaylight.controller.cluster.raft.utils.InMemoryJournal"
}
in-memory-snapshot-store {
# Class name of the plugin.
- class = "org.opendaylight.controller.cluster.datastore.utils.InMemorySnapshotStore"
+ class = "org.opendaylight.controller.cluster.raft.utils.InMemorySnapshotStore"
# Dispatcher for the plugin actor.
plugin-dispatcher = "akka.persistence.dispatchers.default-plugin-dispatcher"
}
*/
public interface DOMDataBroker extends
AsyncDataBroker<YangInstanceIdentifier, NormalizedNode<?, ?>, DOMDataChangeListener>,
- TransactionChainFactory<YangInstanceIdentifier, NormalizedNode<?, ?>>, BrokerService, DOMService {
+ TransactionChainFactory<YangInstanceIdentifier, NormalizedNode<?, ?>>, BrokerService, DOMExtensibleService<DOMDataBroker, DOMDataBrokerExtension> {
/**
* {@inheritDoc}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.api;
+
+/**
+ * Type capture of a {@link DOMServiceExtension} applicable to {@link DOMDataBroker}
+ * implementations.
+ */
+public interface DOMDataBrokerExtension extends DOMServiceExtension<DOMDataBroker, DOMDataBrokerExtension> {
+
+}
import org.opendaylight.yangtools.concepts.ListenerRegistration;
/**
- * A {@link DOMService} which allows users to register for changes to a
+ * A {@link DOMServiceExtension} which allows users to register for changes to a
* subtree.
*/
-public interface DOMDataTreeChangeService extends DOMService {
+public interface DOMDataTreeChangeService extends DOMDataBrokerExtension {
/**
* Registers a {@link DOMDataTreeChangeListener} to receive
* notifications when data changes under a given path in the conceptual data
--- /dev/null
+/*
+ * Copyright (c) 2015 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.api;
+
+import com.google.common.annotations.Beta;
+import java.util.Map;
+import javax.annotation.Nonnull;
+
+/**
+ * Marker interface for services which can support {@link DOMServiceExtension}.
+ * Aside for marking these, they also provide runtime query to detect whether
+ * a particular trait is in fact available.
+ *
+ * <T> Base {@link DOMService}
+ * <E> Extension type
+ */
+@Beta
+public interface DOMExtensibleService<T extends DOMExtensibleService<T, E>, E extends DOMServiceExtension<T, E>> extends DOMService {
+ /**
+ * Return a map of currently-supported extensions, along with accessor services
+ * which provide access to the specific functionality bound to this service.
+ *
+ * @return A map of supported functionality.
+ */
+ @Nonnull Map<Class<? extends E>, E> getSupportedExtensions();
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.api;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Marker interface for services which expose additional functionality on top
+ * of some base {@link DOMService}.
+ */
+@Beta
+public interface DOMServiceExtension<T extends DOMExtensibleService<T, E>, E extends DOMServiceExtension<T, E>> {
+
+}
*/
package org.opendaylight.controller.sal.core.api;
-import java.util.Set;
-import java.util.concurrent.Future;
-
-import org.opendaylight.controller.md.sal.common.api.routing.RoutedRegistration;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.ObjectRegistration;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.osgi.framework.BundleContext;
/**
* removes direct dependencies between providers and consumers.
*
*
- * <h3>Infrastructure services</h3> Some examples of infrastructure services:
- *
- * <ul>
- * <li>RPC Invocation - see {@link ConsumerSession#rpc(QName, CompositeNode)},
- * {@link ProviderSession#addRpcImplementation(QName, RpcImplementation)} and
- * {@link RpcImplementation}
- * <li>Notification Service - see {@link org.opendaylight.controller.sal.core.api.notify.NotificationService} and
- * {@link org.opendaylight.controller.sal.core.api.notify.NotificationPublishService}
- * <li>Functionality and Data model
- * <li>Data Store access and modification - see {@link org.opendaylight.controller.sal.core.api.data.DataBrokerService} and
- * {@link org.opendaylight.controller.sal.core.api.data.DataProviderService}
- * </ul>
- *
* The services are exposed via session.
*
* <h3>Session-based access</h3>
* from consumer, using the {@link Provider#getProviderFunctionality()}, and
* register that functionality into system and concrete infrastructure
* services.
- *
- * <p>
- * Note that consumer could register additional functionality at later point
- * by using service and functionality specific APIs (e.g.
- * {@link ProviderSession#addRpcImplementation(QName, RpcImplementation)}
- *
* <p>
* The consumer is <b>required to use</b> returned session for all
* communication with broker or one of the broker services. The session is
*/
public interface ConsumerSession {
- /**
- * Sends an RPC to other components registered to the broker.
- *
- * @see RpcImplementation
- * @param rpc
- * Name of RPC
- * @param input
- * Input data to the RPC
- * @return Result of the RPC call
- */
- Future<RpcResult<CompositeNode>> rpc(QName rpc, CompositeNode input);
-
boolean isClosed();
/**
*
*/
public interface ProviderSession extends ConsumerSession {
- /**
- * Registers an implementation of the rpc.
- *
- * <p>
- * The registered rpc functionality will be available to all other
- * consumers and providers registered to the broker, which are aware of
- * the {@link QName} assigned to the rpc.
- *
- * <p>
- * There is no assumption that rpc type is in the set returned by
- * invoking {@link RpcImplementation#getSupportedRpcs()}. This allows
- * for dynamic rpc implementations.
- *
- * @param rpcType
- * Name of Rpc
- * @param implementation
- * Provider's Implementation of the RPC functionality
- * @throws IllegalArgumentException
- * If the name of RPC is invalid
- */
- RpcRegistration addRpcImplementation(QName rpcType, RpcImplementation implementation)
- throws IllegalArgumentException;
-
- RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation);
-
- RoutedRpcRegistration addMountedRpcImplementation(QName rpcType, RpcImplementation implementation);
-
/**
* Closes a session between provider and SAL.
*
@Override
boolean isClosed();
-
- Set<QName> getSupportedRpcs();
-
- ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(RpcRegistrationListener listener);
- }
-
- public interface RpcRegistration extends ObjectRegistration<RpcImplementation> {
- QName getType();
-
- @Override
- void close();
- }
-
- public interface RoutedRpcRegistration extends RpcRegistration, RoutedRegistration<QName, YangInstanceIdentifier, RpcImplementation> {
}
}
+++ /dev/null
-/*
- * 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.sal.core.api;
-
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-public interface RoutedRpcDefaultImplementation {
-
- ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, YangInstanceIdentifier identifier, CompositeNode input);
-
-}
+++ /dev/null
-/*
- * 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.sal.core.api;
-
-import java.util.concurrent.Future;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-/**
- * @deprecated Use {@link org.opendaylight.controller.md.sal.dom.api.DOMRpcService} instead.
- */
-@Deprecated
-public interface RpcConsumptionRegistry {
- /**
- * Sends an RPC to other components registered to the broker.
- *
- * @see RpcImplementation
- * @param rpc
- * Name of RPC
- * @param input
- * Input data to the RPC
- * @return Result of the RPC call
- */
- Future<RpcResult<CompositeNode>> rpc(QName rpc, CompositeNode input);
-
-}
+++ /dev/null
-/*
- * 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.core.api;
-
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.Set;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-/**
- * {@link Provider}'s implementation of an RPC.
- *
- * In order to expose an RPC to other components, the provider MUST register
- * a concrete implementation of this interface.
- *
- * The registration could be done by :
- * <ul>
- * <li>returning an instance of implementation in the return value of
- * {@link Provider#getProviderFunctionality()}
- * <li>passing an instance of implementation and {@link QName} of rpc as
- * arguments to the
- * {@link org.opendaylight.controller.sal.core.api.Broker.ProviderSession#addRpcImplementation(QName, RpcImplementation)}
- * </ul>
- *
- * The simplified process of the invocation of rpc is following:
- *
- * <ol>
- * <li> {@link Consumer} invokes
- * {@link org.opendaylight.controller.sal.core.api.Broker.ConsumerSession#rpc(QName, CompositeNode)}
- * <li> {@link Broker} finds registered {@link RpcImplementation}s
- * <li> {@link Broker} invokes
- * {@link RpcImplementation#invokeRpc(QName, CompositeNode)}
- * <li> {@link RpcImplementation} processes the data and returns a
- * {@link RpcResult}
- * <li> {@link Broker} returns the {@link RpcResult} to {@link Consumer}
- * </ol>
- *
- * @deprecated Use {@link org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementation} instead.
- */
-@Deprecated
-public interface RpcImplementation extends Provider.ProviderFunctionality {
-
- /**
- * A set of rpc types supported by implementation.
- *
- * The set of rpc {@link QName}s which are supported by this implementation.
- * This set is used, when {@link Provider} is registered to the SAL, to
- * register and expose the implementation of the returned rpcs.
- *
- * @return Set of QNames identifying supported RPCs
- */
- Set<QName> getSupportedRpcs();
-
- /**
- * Invokes a implementation of specified RPC asynchronously.
- *
- * @param rpc
- * RPC to be invoked
- * @param input
- * Input data for the RPC.
- *
- * @throws IllegalArgumentException
- * <ul>
- * <li>If rpc is null.
- * <li>If input is not <code>null</code> and
- * <code>false == rpc.equals(input.getNodeType)</code>
- * </ul>
- * @return Future promising an RpcResult containing the output of
- * the RPC if was executed successfully, the list of errors
- * otherwise.
- */
- ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input);
-}
+++ /dev/null
-/*
- * 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.sal.core.api;
-
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChangePublisher;
-import org.opendaylight.controller.md.sal.dom.api.DOMService;
-import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-/**
- * @deprecated Use {@link org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService} and {@link org.opendaylight.controller.md.sal.dom.api.DOMRpcService} instead.
- */
-@Deprecated
-public interface RpcProvisionRegistry extends RpcImplementation, BrokerService, RouteChangePublisher<RpcRoutingContext, YangInstanceIdentifier>, DOMService {
-
- /**
- * Registers an implementation of the rpc.
- *
- * <p>
- * The registered rpc functionality will be available to all other
- * consumers and providers registered to the broker, which are aware of
- * the {@link QName} assigned to the rpc.
- *
- * <p>
- * There is no assumption that rpc type is in the set returned by
- * invoking {@link RpcImplementation#getSupportedRpcs()}. This allows
- * for dynamic rpc implementations.
- *
- * @param rpcType
- * Name of Rpc
- * @param implementation
- * Provider's Implementation of the RPC functionality
- * @throws IllegalArgumentException
- * If the name of RPC is invalid
- */
- RpcRegistration addRpcImplementation(QName rpcType, RpcImplementation implementation)
- throws IllegalArgumentException;
-
- ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(RpcRegistrationListener listener);
-
- RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation);
-
- /**
- * Sets this RoutedRpc Implementation as a delegate rpc provider and will be asked to invoke rpc if the
- * current provider can't service the rpc request
- *
- * @param defaultImplementation
- * Provider's implementation of RPC functionality
- */
- public void setRoutedRpcDefaultDelegate(RoutedRpcDefaultImplementation defaultImplementation);
-}
+++ /dev/null
-/*
- * 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.core.api;
-
-import java.util.EventListener;
-import org.opendaylight.yangtools.yang.common.QName;
-
-/**
- * @deprecated Use {@link org.opendaylight.controller.md.sal.dom.api.DOMRpcAvailabilityListener} instead.
- */
-@Deprecated
-public interface RpcRegistrationListener extends EventListener {
-
- public void onRpcImplementationAdded(QName name);
-
- public void onRpcImplementationRemoved(QName name);
-}
+++ /dev/null
-/*
- * 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.core.api.data;
-
-import org.opendaylight.controller.md.sal.common.api.data.DataChangePublisher;
-import org.opendaylight.controller.md.sal.common.api.data.DataModificationTransactionFactory;
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.controller.sal.core.api.BrokerService;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-
-/**
- * DataBrokerService provides unified access to the data stores available in the
- * system.
- *
- *
- * @see DataProviderService
- * @deprecated Replaced by {@link org.opendaylight.controller.md.sal.dom.api.DOMDataBroker}
- *
- */
-@Deprecated
-public interface DataBrokerService extends
- BrokerService, //
- DataReader<YangInstanceIdentifier, CompositeNode>, //
- DataModificationTransactionFactory<YangInstanceIdentifier, CompositeNode>, //
- DataChangePublisher<YangInstanceIdentifier, CompositeNode, DataChangeListener> {
-
-
- @Override
- public CompositeNode readConfigurationData(YangInstanceIdentifier path);
-
- @Override
- public CompositeNode readOperationalData(YangInstanceIdentifier path);
-
- @Override
- DataModificationTransaction beginTransaction();
-}
+++ /dev/null
-/*
- * 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.core.api.data;
-
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-/**
- *
- * @deprecated Replaced by {@link org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener}
- */
-@Deprecated
-public interface DataChangeListener
- extends
- org.opendaylight.controller.md.sal.common.api.data.DataChangeListener<YangInstanceIdentifier, CompositeNode> {
-
- @Override
- public void onDataChanged(DataChangeEvent<YangInstanceIdentifier, CompositeNode> change);
-}
+++ /dev/null
-/*
- * 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.core.api.data;
-
-import java.util.EventListener;
-import java.util.concurrent.Future;
-
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-/**
- *
- * @deprecated Replaced by more specific
- * {@link org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction}
- * ,
- * {@link org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction}
- * or {@link org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction}
- *
- */
-@Deprecated
-public interface DataModificationTransaction extends DataModification<YangInstanceIdentifier, CompositeNode> {
-
- /**
- * Returns transaction identifier
- *
- * @return Transaction identifier
- */
- @Override
- Object getIdentifier();
-
- @Override
- TransactionStatus getStatus();
-
- /**
- * Commits transaction to be stored in global data repository.
- *
- *
- * @return Future object which returns RpcResult with TransactionStatus when
- * transaction is processed by store.
- */
- @Override
- Future<RpcResult<TransactionStatus>> commit();
-
- ListenerRegistration<DataTransactionListener> registerListener(DataTransactionListener listener);
-
- public interface DataTransactionListener extends EventListener {
- void onStatusUpdated(DataModificationTransaction transaction, TransactionStatus status);
- }
-}
+++ /dev/null
-/*
- * 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.core.api.data;
-
-import org.opendaylight.controller.md.sal.common.api.data.DataProvisionService;
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.controller.sal.common.DataStoreIdentifier;
-import org.opendaylight.controller.sal.core.api.Provider;
-import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-/**
- *
- * @deprecated Replaced by {@link org.opendaylight.controller.md.sal.dom.api.DOMDataBroker}
- *
- */
-@Deprecated
-public interface DataProviderService extends
- DataBrokerService, //
- DataProvisionService<YangInstanceIdentifier, CompositeNode>
- {
-
- /**
- * Adds {@link DataValidator} for specified Data Store
- *
- * @param store
- * Data Store
- * @param validator
- * Validator
- */
- public void addValidator(DataStoreIdentifier store, DataValidator validator);
-
- /**
- * Removes {@link DataValidator} from specified Data Store
- *
- * @param store
- * @param validator
- * Validator
- */
- public void removeValidator(DataStoreIdentifier store,
- DataValidator validator);
-
- /**
- * Adds {@link DataRefresher} for specified data store
- *
- * @param store
- * @param refresher
- */
- void addRefresher(DataStoreIdentifier store, DataRefresher refresher);
-
- /**
- * Removes {@link DataRefresher} from specified data store
- *
- * @param store
- * @param refresher
- */
- void removeRefresher(DataStoreIdentifier store, DataRefresher refresher);
-
-
- Registration registerConfigurationReader(YangInstanceIdentifier path, DataReader<YangInstanceIdentifier, CompositeNode> reader);
-
- Registration registerOperationalReader(YangInstanceIdentifier path, DataReader<YangInstanceIdentifier, CompositeNode> reader);
-
- public interface DataRefresher extends Provider.ProviderFunctionality {
-
- /**
- * Fired when some component explicitly requested the data refresh.
- *
- * The provider which exposed the {@link DataRefresher} should republish
- * its provided data by editing the data in all affected data stores.
- */
- void refreshData();
- }
-}
+++ /dev/null
-/*
- * 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.sal.core.api.data;
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-/**
- *
- * @deprecated Replaced by org.opendaylight.controller.sal.core.spi.data.DOMStore.
- *
- */
-@Deprecated
-public interface DataStore extends //
- DataReader<YangInstanceIdentifier, CompositeNode>,
- DataCommitHandler<YangInstanceIdentifier, CompositeNode> {
-
-
- Iterable<YangInstanceIdentifier> getStoredConfigurationPaths();
- Iterable<YangInstanceIdentifier> getStoredOperationalPaths();
-
- boolean containsConfigurationPath(YangInstanceIdentifier path);
- boolean containsOperationalPath(YangInstanceIdentifier path);
-
-}
+++ /dev/null
-/*
- * 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.core.api.data;
-
-import java.util.Set;
-
-import org.opendaylight.controller.sal.common.DataStoreIdentifier;
-import org.opendaylight.controller.sal.core.api.Provider;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-
-/**
- * {@link Provider}-supplied Validator of the data.
- *
- * <p>
- * The registration could be done by :
- * <ul>
- * <li>returning an instance of implementation in the return value of
- * {@link Provider#getProviderFunctionality()}
- * <li>passing an instance of implementation and {@link DataStoreIdentifier} rpc
- * as arguments to the
- * {@link DataProviderService#addValidator(DataStoreIdentifier, DataValidator)}
- * </ul>
- *
- * @deprecated Replaced by {@link org.opendaylight.controller.md.sal.common.api.data.AsyncConfigurationCommitHandler}
- *
- **/
-@Deprecated
-public interface DataValidator extends Provider.ProviderFunctionality {
-
- /**
- * A set of Data Stores supported by implementation.
- *
- * The set of {@link DataStoreIdentifier}s which identifies target data
- * stores which are supported by this implementation. This set is used, when
- * {@link Provider} is registered to the SAL, to register and expose the
- * validation functionality to affected data stores.
- *
- * @return Set of Data Store identifiers
- */
- Set<DataStoreIdentifier> getSupportedDataStores();
-
- /**
- * Performs validation on supplied data.
- *
- * @param toValidate
- * Data to validate
- * @return Validation result. The
- * <code>{@link RpcResult#isSuccessful()} == true</code> if the data
- * passed validation, otherwise contains list of errors.
- */
- RpcResult<Void> validate(CompositeNode toValidate);
-
-}
+++ /dev/null
-/*
- * 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.core.api.data;
\ No newline at end of file
+++ /dev/null
-/*
- * 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.core.api.mount;
-
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.core.api.notify.NotificationService;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Interface representing a single mount instance and represents a way for
- * clients to access underlying data, RPCs and notifications.
- */
-@Deprecated
-public interface MountInstance extends //
- NotificationService, //
- DataBrokerService {
-
- /**
- * Invoke an RPC on the system underlying the mount instance.
- *
- * @param type RPC type
- * @param input RPC input arguments
- * @return Future representing execution of the RPC.
- */
- ListenableFuture<RpcResult<CompositeNode>> rpc(QName type, CompositeNode input);
-
- /**
- * Get {@link SchemaContext} of the system underlying the mount instance.
- *
- * @return A schema context.
- */
- SchemaContext getSchemaContext();
-}
+++ /dev/null
-/*
- * 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.sal.core.api.mount;
-
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.opendaylight.controller.sal.core.api.data.DataProviderService;
-import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-@Deprecated
-public interface MountProvisionInstance extends //
- MountInstance,//
- NotificationPublishService, //
- RpcProvisionRegistry,//
- DataProviderService {
-
- void setSchemaContext(SchemaContext optional);
-
-}
+++ /dev/null
-/*
- * 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.sal.core.api.mount;
-
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-/**
- * @deprecated Use org.opendaylight.controller.md.sal.dom.api.DOMMountPointService instead
- */
-@Deprecated
-public interface MountProvisionService extends MountService {
-
- @Override
- public MountProvisionInstance getMountPoint(YangInstanceIdentifier path);
-
- MountProvisionInstance createMountPoint(YangInstanceIdentifier path);
-
- MountProvisionInstance createOrGetMountPoint(YangInstanceIdentifier path);
-
- ListenerRegistration<MountProvisionListener> registerProvisionListener(MountProvisionListener listener);
-
-}
+++ /dev/null
-/*
- * 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.core.api.mount;
-
-import org.opendaylight.controller.sal.core.api.BrokerService;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-/**
- * Client-level interface for interacting with mount points. It provides access
- * to {@link MountInstance} instances based on their path.
- *
- * @deprecated Use org.opendaylight.controller.md.sal.dom.api.DOMMountPointService instead
- */
-@Deprecated
-public interface MountService extends BrokerService {
- /**
- * Obtain access to a mount instance registered at the specified path.
- *
- * @param path Path at which the instance is registered
- * @return Reference to the instance, or null if no such instance exists.
- */
- MountInstance getMountPoint(YangInstanceIdentifier path);
-}
+++ /dev/null
-/*
- * 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.core.api.notify;
-
-import java.util.EventListener;
-import java.util.Set;
-
-import org.opendaylight.controller.sal.core.api.Consumer;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-
-/**
- * Notification listener for SAL notifications.
- */
-public interface NotificationListener extends Consumer.ConsumerFunctionality, EventListener {
- /**
- * A set of notification types supported by listeners.
- *
- * The set of notification {@link QName}s which are supported by this
- * listener. This set is used, when {@link Consumer} is registered to the
- * SAL, to automatically register the listener.
- *
- * @return Set of QNames identifying supported notifications.
- */
- Set<QName> getSupportedNotifications();
-
- /**
- * Fired when the notification occurs.
- *
- * The type of the notification could be learned by
- * <code>QName type = notification.getNodeType();</code>
- *
- * @param notification
- * Notification content
- */
- void onNotification(CompositeNode notification);
-}
+++ /dev/null
-/*
- * 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.core.api.notify;
-
-import org.opendaylight.controller.md.sal.dom.api.DOMService;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-/**
- * Notification Publishing Service
- *
- * The simplified process of the notification publishing is following:
- *
- * <ol>
- * <li> {@link org.opendaylight.controller.sal.core.api.Provider} invokes {@link #sendNotification(CompositeNode)}
- * <li> {@link org.opendaylight.controller.sal.core.api.Broker} finds {@link NotificationListener}s which subscribed for
- * the notification type.
- *
- * <li>For each subscriber {@link org.opendaylight.controller.sal.core.api.Broker} invokes
- * {@link NotificationListener#onNotification(CompositeNode)}
- * </ol>
- */
-public interface NotificationPublishService extends NotificationService, DOMService {
- /**
- * Publishes a notification.
- *
- * Notification type is determined by the
- * {@link CompositeNode#getNodeType()} of the
- * <code>notification<code> parameter.
- *
- * @param notification
- * Notification to publish
- */
- void publish(CompositeNode notification);
-}
+++ /dev/null
-/*
- * 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.core.api.notify;
-
-import org.opendaylight.controller.sal.core.api.BrokerService;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.common.QName;
-
-
-/**
- * NotificationService provides access to the notification functionality of the
- * SAL.
- *
- * NotificationService allows for consumption of notifications by registering
- * implementations of NotificationListener.
- *
- * The registration of notification listeners could be done by:
- * <ul>
- * <li>returning an instance of implementation in the return value of
- * {@link org.opendaylight.controller.sal.core.api.Provider#getProviderFunctionality()}
- * <li>passing an instance of implementation and {@link QName} of an RPC as an
- * argument to
- * {@link org.opendaylight.controller.sal.core.api.Broker.ProviderSession#addRpcImplementation(QName, org.opendaylight.controller.sal.core.api.RpcImplementation)}
- * </ul>
- *
- *
- */
-public interface NotificationService extends BrokerService {
-
- /**
- * Registers a notification listener for supplied notification type.
- *
- * @param notification
- * @param listener
- */
- ListenerRegistration<NotificationListener> addNotificationListener(QName notification,
- NotificationListener listener);
-}
+++ /dev/null
-/*
- * 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
- */
-/**
- * SAL Notification functionality
- */
-package org.opendaylight.controller.sal.core.api.notify;
\ No newline at end of file
}\r
}\r
}\r
- \r
+\r
grouping rpc-state {\r
list rpc-router {\r
uses rpc-router;\r
config:java-class "org.opendaylight.controller.sal.core.api.Broker";
}
- identity dom-data-broker {
- base "config:service-type";
- config:java-class "org.opendaylight.controller.sal.core.api.data.DataProviderService";
- }
-
identity dom-async-data-broker {
base "config:service-type";
config:java-class "org.opendaylight.controller.md.sal.dom.api.DOMDataBroker";
}
- identity dom-data-store {
- base "config:service-type";
- config:java-class "org.opendaylight.controller.sal.core.api.data.DataStore";
- }
-
identity schema-service {
base "config:service-type";
config:java-class "org.opendaylight.controller.sal.core.api.model.SchemaService";
import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
import org.opendaylight.controller.md.sal.dom.broker.impl.DOMNotificationRouter;
import org.opendaylight.controller.md.sal.dom.broker.impl.DOMRpcRouter;
-import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker;
import org.opendaylight.controller.md.sal.dom.broker.impl.mount.DOMMountPointServiceImpl;
import org.opendaylight.controller.sal.core.api.BrokerService;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.core.api.data.DataProviderService;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
-import org.opendaylight.controller.sal.core.api.mount.MountService;
-import org.opendaylight.controller.sal.dom.broker.BackwardsCompatibleMountPointManager;
import org.opendaylight.controller.sal.dom.broker.BrokerImpl;
import org.opendaylight.controller.sal.dom.broker.GlobalBundleScanningSchemaServiceImpl;
-import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker;
-import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProviders;
/**
*
final SchemaService schemaService = getSchemaServiceImpl();
services.putInstance(SchemaService.class, schemaService);
- final SchemaAwareRpcBroker router = new SchemaAwareRpcBroker("/", SchemaContextProviders
- .fromSchemaService(schemaService));
- services.putInstance(RpcProvisionRegistry.class, router);
services.putInstance(DOMDataBroker.class, asyncBroker);
- final DataProviderService legacyData = new BackwardsCompatibleDataBroker(asyncBroker,schemaService);
- services.putInstance(DataProviderService.class,legacyData);
- services.putInstance(DataBrokerService.class, legacyData);
final DOMRpcRouter rpcRouter = new DOMRpcRouter();
schemaService.registerSchemaContextListener(rpcRouter);
final DOMMountPointService mountService = new DOMMountPointServiceImpl();
services.putInstance(DOMMountPointService.class, mountService);
- // TODO remove backwards service, use only new DOMMountPointService
- final MountProvisionService backwardsMountService = new BackwardsCompatibleMountPointManager(mountService);
- services.putInstance(MountService.class, backwardsMountService);
- services.putInstance(MountProvisionService.class, backwardsMountService);
-
- return new BrokerImpl(router, services);
+ return new BrokerImpl(rpcRouter, services);
}
private SchemaService getSchemaServiceImpl() {
+++ /dev/null
-/*
- * 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.config.yang.md.sal.dom.statistics;
-
-import org.opendaylight.controller.config.yang.md.sal.dom.impl.Data;
-import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomBrokerImplRuntimeMXBean;
-import org.opendaylight.controller.config.yang.md.sal.dom.impl.Transactions;
-import org.opendaylight.controller.sal.dom.broker.DataBrokerImpl;
-
-@Deprecated
-public class DomBrokerRuntimeMXBeanImpl implements
- DomBrokerImplRuntimeMXBean {
-
- private final DataBrokerImpl dataService;
- private final Transactions transactions = new Transactions();
- private final Data data = new Data();
-
- public DomBrokerRuntimeMXBeanImpl(DataBrokerImpl dataService) {
- this.dataService = dataService;
- }
-
- public Transactions getTransactions() {
- transactions.setCreated(dataService.getCreatedTransactionsCount().get());
- transactions.setSubmitted(dataService.getSubmittedTransactionsCount().get());
- transactions.setSuccessful(dataService.getFinishedTransactionsCount().get());
- transactions.setFailed(dataService.getFailedTransactionsCount().get());
- return transactions;
- }
-
- @Override
- public Data getData() {
- transactions.setCreated(dataService.getCreatedTransactionsCount().get());
- transactions.setSubmitted(dataService.getSubmittedTransactionsCount().get());
- transactions.setSuccessful(dataService.getFinishedTransactionsCount().get());
- transactions.setFailed(dataService.getFailedTransactionsCount().get());
- data.setTransactions(transactions);
- return data;
- }
-}
package org.opendaylight.controller.md.sal.dom.broker.impl;
import static com.google.common.base.Preconditions.checkState;
+import com.google.common.collect.ImmutableMap;
+import java.util.Collections;
import java.util.EnumMap;
import java.util.Map;
import java.util.Map.Entry;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBrokerExtension;
import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeListener;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
import org.opendaylight.controller.sal.core.spi.data.DOMStore;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTreeChangePublisher;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.slf4j.Logger;
private final AtomicLong txNum = new AtomicLong();
private final AtomicLong chainNum = new AtomicLong();
+ private final Map<Class<? extends DOMDataBrokerExtension>, DOMDataBrokerExtension> extensions;
private volatile AutoCloseable closeable;
protected AbstractDOMDataBroker(final Map<LogicalDatastoreType, DOMStore> datastores) {
super(datastores);
+
+ boolean treeChange = true;
+ for (DOMStore ds : datastores.values()) {
+ if (!(ds instanceof DOMStoreTreeChangePublisher)) {
+ treeChange = false;
+ break;
+ }
+ }
+
+ if (treeChange) {
+ extensions = ImmutableMap.<Class<? extends DOMDataBrokerExtension>, DOMDataBrokerExtension>of(DOMDataTreeChangeService.class, new DOMDataTreeChangeService() {
+ @Override
+ public <L extends DOMDataTreeChangeListener> ListenerRegistration<L> registerDataTreeChangeListener(final DOMDataTreeIdentifier treeId, final L listener) {
+ DOMStore publisher = getTxFactories().get(treeId.getDatastoreType());
+ checkState(publisher != null, "Requested logical data store is not available.");
+
+ return ((DOMStoreTreeChangePublisher)publisher).registerTreeChangeListener(treeId.getRootIdentifier(), listener);
+ }
+ });
+ } else {
+ extensions = Collections.emptyMap();
+ }
}
public void setCloseable(final AutoCloseable closeable) {
return potentialStore.registerChangeListener(path, listener, triggeringScope);
}
+ @Override
+ public Map<Class<? extends DOMDataBrokerExtension>, DOMDataBrokerExtension> getSupportedExtensions() {
+ return extensions;
+ }
+
@Override
public DOMTransactionChain createTransactionChain(final TransactionChainListener listener) {
checkNotClosed();
+++ /dev/null
-/*
- * 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.broker.impl;
-
-import com.google.common.util.concurrent.ListeningExecutorService;
-import java.util.Map;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.sal.core.spi.data.DOMStore;
-
-/**
- * @deprecated Compatibility wrapper around {@link SerializedDOMDataBroker}.
- */
-@Deprecated
-public final class DOMDataBrokerImpl extends SerializedDOMDataBroker {
- public DOMDataBrokerImpl(final Map<LogicalDatastoreType, DOMStore> datastores, final ListeningExecutorService executor) {
- super(datastores, executor);
- }
-}
import javax.annotation.Nonnull;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeListener;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
import org.opendaylight.controller.md.sal.dom.spi.ForwardingDOMDataBroker;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
/**
* An implementation of a {@link DOMDataBroker}, which forwards most requests to a delegate.
* guarantee transaction ordering between transactions allocated directly from the broker
* and its transaction chains.
*/
-public final class PingPongDataBroker extends ForwardingDOMDataBroker implements AutoCloseable {
+public final class PingPongDataBroker extends ForwardingDOMDataBroker implements AutoCloseable, DOMDataTreeChangeService {
private final DOMDataBroker delegate;
/**
public void close() {
// TODO Auto-generated method stub
}
+
+ @Override
+ public <L extends DOMDataTreeChangeListener> ListenerRegistration<L> registerDataTreeChangeListener(final DOMDataTreeIdentifier treeId, final L listener) {
+ if (delegate instanceof DOMDataTreeChangeService) {
+ return ((DOMDataTreeChangeService)delegate).registerDataTreeChangeListener(treeId, listener);
+ }
+
+ throw new UnsupportedOperationException("Delegate " + delegate + " does not support required functionality");
+ }
}
+++ /dev/null
-/*
- * 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.broker.impl.compat;
-
-import javax.annotation.concurrent.ThreadSafe;
-import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
-import org.opendaylight.controller.sal.common.DataStoreIdentifier;
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
-import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.core.api.data.DataProviderService;
-import org.opendaylight.controller.sal.core.api.data.DataValidator;
-import org.opendaylight.controller.sal.core.api.model.SchemaService;
-import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
-
-@Deprecated
-@ThreadSafe
-public class BackwardsCompatibleDataBroker implements DataProviderService {
-
- private final DOMDataBroker backingBroker;
- private volatile DataNormalizer normalizer;
- private final ListenerRegistration<SchemaContextListener> schemaReg;
-
- public BackwardsCompatibleDataBroker(final DOMDataBroker newBiDataImpl, final SchemaService schemaService) {
- backingBroker = newBiDataImpl;
- schemaReg = schemaService.registerSchemaContextListener(new SchemaListener());
- }
-
- @Override
- public CompositeNode readConfigurationData(final YangInstanceIdentifier legacyPath) {
- final BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
- try {
- return tx.readConfigurationData(legacyPath);
- } finally {
- tx.commit();
- }
- }
-
- @Override
- public CompositeNode readOperationalData(final YangInstanceIdentifier legacyPath) {
- final BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
- try {
- return tx.readOperationalData(legacyPath);
- } finally {
- tx.commit();
- }
- }
-
- @Override
- public DataModificationTransaction beginTransaction() {
- return BackwardsCompatibleTransaction.readWriteTransaction(backingBroker.newReadWriteTransaction(), normalizer);
- }
-
- @Override
- public ListenerRegistration<DataChangeListener> registerDataChangeListener(final YangInstanceIdentifier legacyPath,
- final DataChangeListener listener) {
- final YangInstanceIdentifier normalizedPath = normalizer.toNormalized(legacyPath);
-
- final TranslatingListenerInvoker translatingCfgListener =
- TranslatingListenerInvoker.createConfig(listener, normalizer);
- translatingCfgListener.register(backingBroker, normalizedPath);
-
- final TranslatingListenerInvoker translatingOpListener =
- TranslatingListenerInvoker.createOperational(listener, normalizer);
- translatingOpListener.register(backingBroker, normalizedPath);
-
- return new DelegateListenerRegistration(translatingCfgListener, translatingOpListener, listener);
- }
-
- @Override
- public Registration registerCommitHandler(
- final YangInstanceIdentifier path, final DataCommitHandler<YangInstanceIdentifier, CompositeNode> commitHandler) {
- // FIXME Do real forwarding
- return new AbstractObjectRegistration<DataCommitHandler<YangInstanceIdentifier,CompositeNode>>(commitHandler) {
- @Override
- protected void removeRegistration() {
- // NOOP
- }
- };
- }
-
- @Override
- public ListenerRegistration<RegistrationListener<DataCommitHandlerRegistration<YangInstanceIdentifier, CompositeNode>>> registerCommitHandlerListener(
- final RegistrationListener<DataCommitHandlerRegistration<YangInstanceIdentifier, CompositeNode>> commitHandlerListener) {
- return null;
- }
-
- // Obsolete functionality
-
- @Override
- public void addValidator(final DataStoreIdentifier store, final DataValidator validator) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void removeValidator(final DataStoreIdentifier store, final DataValidator validator) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void addRefresher(final DataStoreIdentifier store, final DataRefresher refresher) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void removeRefresher(final DataStoreIdentifier store, final DataRefresher refresher) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Registration registerConfigurationReader(
- final YangInstanceIdentifier path, final DataReader<YangInstanceIdentifier, CompositeNode> reader) {
- throw new UnsupportedOperationException("Data Reader contract is not supported.");
- }
-
- @Override
- public Registration registerOperationalReader(
- final YangInstanceIdentifier path, final DataReader<YangInstanceIdentifier, CompositeNode> reader) {
- throw new UnsupportedOperationException("Data Reader contract is not supported.");
- }
-
- private static class DelegateListenerRegistration implements ListenerRegistration<DataChangeListener> {
- private final TranslatingListenerInvoker translatingCfgListener;
- private final TranslatingListenerInvoker translatingOpListener;
- private final DataChangeListener listener;
-
- public DelegateListenerRegistration(final TranslatingListenerInvoker translatingCfgListener, final TranslatingListenerInvoker translatingOpListener, final DataChangeListener listener) {
- this.translatingCfgListener = translatingCfgListener;
- this.translatingOpListener = translatingOpListener;
- this.listener = listener;
- }
-
- @Override
- public void close() {
- translatingCfgListener.close();
- translatingOpListener.close();
- }
-
- @Override
- public DataChangeListener getInstance() {
- return listener;
- }
- }
-
- private class SchemaListener implements SchemaContextListener {
-
- @Override
- public void onGlobalContextUpdated(final SchemaContext ctx) {
- normalizer = new DataNormalizer(ctx);
- }
-
- }
-}
+++ /dev/null
-/*
- * 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.broker.impl.compat;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataTransaction;
-import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
-import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
-import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
-import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
-import org.opendaylight.yangtools.concepts.Delegator;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Deprecated
-public abstract class BackwardsCompatibleTransaction<T extends DOMDataReadTransaction> implements DataModificationTransaction, Delegator<T> {
-
- private static final Logger LOG = LoggerFactory.getLogger(BackwardsCompatibleTransaction.class);
-
- private final T asyncTx;
- private final DataNormalizer normalizer;
-
- protected BackwardsCompatibleTransaction(final T asyncTx, final DataNormalizer normalizer) {
- super();
- this.asyncTx = asyncTx;
- this.normalizer = normalizer;
- }
-
- public static BackwardsCompatibleTransaction<?> readOnlyTransaction(final DOMDataReadOnlyTransaction readTx,
- final DataNormalizer normalizer) {
-
- return new BackwardsCompatibleTransaction<DOMDataReadOnlyTransaction>(readTx, normalizer) {
-
- @Override
- public TransactionStatus getStatus() {
- return TransactionStatus.NEW;
- }
-
- @Override
- public Future<RpcResult<TransactionStatus>> commit() {
- getDelegate().close();
- return null;
- }
- };
- }
-
- public static BackwardsCompatibleTransaction<?> readWriteTransaction(final DOMDataReadWriteTransaction rwTx,
- final DataNormalizer normalizer) {
- return new ReadWriteTransaction(rwTx, normalizer);
- }
-
- protected DataNormalizer getNormalizer() {
- return normalizer;
- }
-
- @Override
- public T getDelegate() {
- return asyncTx;
- };
-
- @Override
- public CompositeNode readConfigurationData(final YangInstanceIdentifier legacyPath) {
-
- YangInstanceIdentifier normalizedPath = normalizer.toNormalized(legacyPath);
-
- ListenableFuture<Optional<NormalizedNode<?, ?>>> normalizedData = asyncTx.read(
- LogicalDatastoreType.CONFIGURATION, normalizedPath);
-
- try {
- return normalizer.toLegacy(normalizedPath, normalizedData.get().orNull());
- } catch (InterruptedException | ExecutionException e) {
- return null;
- }
- }
-
- @Override
- public CompositeNode readOperationalData(final YangInstanceIdentifier legacyPath) {
- YangInstanceIdentifier normalizedPath = normalizer.toNormalized(legacyPath);
-
- ListenableFuture<Optional<NormalizedNode<?, ?>>> normalizedData = asyncTx.read(
- LogicalDatastoreType.OPERATIONAL, normalizedPath);
-
- try {
- return normalizer.toLegacy(normalizedPath, normalizedData.get().orNull());
- } catch (InterruptedException | ExecutionException e) {
- return null;
- }
- }
-
- @Override
- public ListenerRegistration<DataTransactionListener> registerListener(final DataTransactionListener listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Map<YangInstanceIdentifier, CompositeNode> getCreatedConfigurationData() {
- return Collections.emptyMap();
- }
-
- @Override
- public Map<YangInstanceIdentifier, CompositeNode> getCreatedOperationalData() {
- return Collections.emptyMap();
- }
-
- @Override
- public Map<YangInstanceIdentifier, CompositeNode> getOriginalConfigurationData() {
- return Collections.emptyMap();
- }
-
- @Override
- public Map<YangInstanceIdentifier, CompositeNode> getOriginalOperationalData() {
- return Collections.emptyMap();
- }
-
- @Override
- public Set<YangInstanceIdentifier> getRemovedConfigurationData() {
- return Collections.emptySet();
- }
-
- @Override
- public Set<YangInstanceIdentifier> getRemovedOperationalData() {
- return Collections.emptySet();
- }
-
- @Override
- public Map<YangInstanceIdentifier, CompositeNode> getUpdatedConfigurationData() {
- return Collections.emptyMap();
- }
-
- @Override
- public Map<YangInstanceIdentifier, CompositeNode> getUpdatedOperationalData() {
- return Collections.emptyMap();
- }
-
- @Override
- public void putConfigurationData(final YangInstanceIdentifier path, final CompositeNode data) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void putOperationalData(final YangInstanceIdentifier path, final CompositeNode data) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void removeConfigurationData(final YangInstanceIdentifier path) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void removeOperationalData(final YangInstanceIdentifier path) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Object getIdentifier() {
- return asyncTx.getIdentifier();
- }
-
- private static final class ReadWriteTransaction extends BackwardsCompatibleTransaction<DOMDataReadWriteTransaction> {
-
- private TransactionStatus status = TransactionStatus.NEW;
-
- protected ReadWriteTransaction(final DOMDataReadWriteTransaction asyncTx, final DataNormalizer normalizer) {
- super(asyncTx, normalizer);
- }
-
- @Override
- public TransactionStatus getStatus() {
- return status;
- }
-
- @Override
- public Future<RpcResult<TransactionStatus>> commit() {
- Preconditions.checkState(status == TransactionStatus.NEW);
- status = TransactionStatus.SUBMITED;
- return AbstractDataTransaction.convertToLegacyCommitFuture(getDelegate().submit());
- }
-
- @Override
- public void putConfigurationData(final YangInstanceIdentifier legacyPath, final CompositeNode legacyData) {
- checkNotNull(legacyPath, "Path MUST NOT be null.");
- checkNotNull(legacyData, "Data for path %s MUST NOT be null",legacyData);
- Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedData = getNormalizer().toNormalized(legacyPath, legacyData);
- putWithEnsuredParents(LogicalDatastoreType.CONFIGURATION, normalizedData.getKey(), normalizedData.getValue());
- }
-
- @Override
- public void putOperationalData(final YangInstanceIdentifier legacyPath, final CompositeNode legacyData) {
- checkNotNull(legacyPath, "Path MUST NOT be null.");
- checkNotNull(legacyData, "Data for path %s MUST NOT be null",legacyData);
- Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedData = getNormalizer().toNormalized(legacyPath, legacyData);
- putWithEnsuredParents(LogicalDatastoreType.OPERATIONAL, normalizedData.getKey(), normalizedData.getValue());
- }
-
- private void putWithEnsuredParents(final LogicalDatastoreType store, final YangInstanceIdentifier normalizedPath,
- final NormalizedNode<?, ?> normalizedData) {
-
- LOG.trace("write {}:{} ",store,normalizedPath);
- try {
- List<PathArgument> currentArguments = new ArrayList<>();
- DataNormalizationOperation<?> currentOp = getNormalizer().getRootOperation();
- Iterator<PathArgument> iterator = normalizedPath.getPathArguments().iterator();
- while(iterator.hasNext()) {
- PathArgument currentArg = iterator.next();
- try {
- currentOp = currentOp.getChild(currentArg);
- } catch (DataNormalizationException e) {
- throw new IllegalArgumentException(String.format("Invalid child encountered in path %s", normalizedPath), e);
- }
- currentArguments.add(currentArg);
- YangInstanceIdentifier currentPath = YangInstanceIdentifier.create(currentArguments);
- boolean isPresent = getDelegate().read(store, currentPath).get().isPresent();
- if(isPresent == false && iterator.hasNext()) {
- getDelegate().merge(store, currentPath, currentOp.createDefault(currentArg));
- }
- }
- } catch (InterruptedException | ExecutionException e) {
- LOG.error("Exception durring read.",e);
- }
-
- getDelegate().put(store, normalizedPath, normalizedData);
- }
-
- @Override
- public void removeConfigurationData(final YangInstanceIdentifier legacyPath) {
- checkNotNull(legacyPath, "Path MUST NOT be null.");
- getDelegate().delete(LogicalDatastoreType.CONFIGURATION, getNormalizer().toNormalized(legacyPath));
- }
-
- @Override
- public void removeOperationalData(final YangInstanceIdentifier legacyPath) {
- checkNotNull(legacyPath, "Path MUST NOT be null.");
- getDelegate().delete(LogicalDatastoreType.OPERATIONAL, getNormalizer().toNormalized(legacyPath));
- }
- }
-}
+++ /dev/null
-/*
- * 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.broker.impl.compat;
-
-import com.google.common.collect.Maps;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
-import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
-import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-@Deprecated
-public abstract class TranslatingDataChangeEvent implements DataChangeEvent<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> {
-
- private TranslatingDataChangeEvent() {
- }
-
- public static DataChangeEvent<YangInstanceIdentifier, CompositeNode> createOperational(
- final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change, final DataNormalizer normalizer) {
- return new OperationalChangeEvent(change, normalizer);
- }
-
- public static DataChangeEvent<YangInstanceIdentifier, CompositeNode> createConfiguration(
- final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change, final DataNormalizer normalizer) {
- return new ConfigurationChangeEvent(change, normalizer);
- }
-
- @Override
- public Map<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> getCreatedOperationalData() {
- return Collections.emptyMap();
- }
-
- @Override
- public Map<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> getCreatedConfigurationData() {
- return Collections.emptyMap();
- }
-
- @Override
- public Map<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> getUpdatedOperationalData() {
- return Collections.emptyMap();
- }
-
- @Override
- public Map<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> getUpdatedConfigurationData() {
- return Collections.emptyMap();
- }
-
- @Override
- public Set<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier> getRemovedConfigurationData() {
- return Collections.emptySet();
- }
-
- @Override
- public Set<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier> getRemovedOperationalData() {
- return Collections.emptySet();
- }
-
- @Override
- public Map<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> getOriginalConfigurationData() {
- return Collections.emptyMap();
- }
-
- @Override
- public Map<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> getOriginalOperationalData() {
- return Collections.emptyMap();
- }
-
- @Override
- public CompositeNode getOriginalConfigurationSubtree() {
- return null;
- }
-
- @Override
- public CompositeNode getOriginalOperationalSubtree() {
- return null;
- }
-
- @Override
- public CompositeNode getUpdatedConfigurationSubtree() {
- return null;
- }
-
- @Override
- public CompositeNode getUpdatedOperationalSubtree() {
- return null;
- }
-
- private final static class OperationalChangeEvent extends TranslatingDataChangeEvent {
-
- private final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> delegate;
- private final DataNormalizer normalizer;
- private Map<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> updatedCache;
-
- public OperationalChangeEvent(final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change,
- final DataNormalizer normalizer) {
- this.delegate = change;
- this.normalizer = normalizer;
- }
-
- @Override
- public Map<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> getCreatedOperationalData() {
- return transformToLegacy(normalizer, delegate.getCreatedData());
- }
-
-
- @Override
- public Set<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier> getRemovedOperationalData() {
- return delegate.getRemovedPaths();
- }
-
- @Override
- public CompositeNode getOriginalOperationalSubtree() {
- // first argument is unused
- return normalizer.toLegacy(null, delegate.getOriginalSubtree());
- }
-
- @Override
- public CompositeNode getUpdatedOperationalSubtree() {
- // first argument is unused
- return normalizer.toLegacy(null, delegate.getUpdatedSubtree());
- }
-
- @Override
- public Map<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> getOriginalOperationalData() {
- return transformToLegacy(normalizer, delegate.getOriginalData());
- }
-
- @Override
- public Map<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> getUpdatedOperationalData() {
- if(updatedCache == null) {
- final Map<YangInstanceIdentifier, CompositeNode> updated = transformToLegacy(normalizer, delegate.getUpdatedData());
- final Map<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> created = getCreatedConfigurationData();
- final HashMap<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> updatedComposite = new HashMap<>(created.size() + updated.size());
- updatedComposite.putAll(created);
- updatedComposite.putAll(updated);
- updatedCache = Collections.unmodifiableMap(updatedComposite);
- }
- return updatedCache;
- }
-
- @Override
- public String toString() {
- return "OperationalChangeEvent [delegate=" + delegate + "]";
- }
-
- }
-
- private static Map<YangInstanceIdentifier, CompositeNode> transformToLegacy(final DataNormalizer normalizer, final Map<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> nodes) {
- final Map<YangInstanceIdentifier, CompositeNode> legacy = Maps.newHashMap();
-
- for (final Map.Entry<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : nodes.entrySet()) {
- try {
- legacy.put(normalizer.toLegacy(entry.getKey()), normalizer.toLegacy(entry.getKey(), entry.getValue()));
- } catch (final DataNormalizationException e) {
- throw new IllegalStateException("Unable to transform data change event to legacy format", e);
- }
- }
- return legacy;
- }
-
- private final static class ConfigurationChangeEvent extends TranslatingDataChangeEvent {
-
- private final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> delegate;
- private final DataNormalizer normalizer;
- private Map<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> updatedCache;
-
- public ConfigurationChangeEvent(final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change,
- final DataNormalizer normalizer) {
- this.delegate = change;
- this.normalizer = normalizer;
- }
-
- @Override
- public Map<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> getCreatedConfigurationData() {
- return transformToLegacy(normalizer, delegate.getCreatedData());
- }
-
-
- @Override
- public Set<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier> getRemovedConfigurationData() {
- return delegate.getRemovedPaths();
- }
-
- @Override
- public CompositeNode getOriginalConfigurationSubtree() {
- // first argument is unused
- return normalizer.toLegacy(null, delegate.getOriginalSubtree());
- }
-
- @Override
- public CompositeNode getUpdatedConfigurationSubtree() {
- // first argument is unused
- return normalizer.toLegacy(null, delegate.getUpdatedSubtree());
- }
-
- @Override
- public Map<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> getOriginalConfigurationData() {
- return transformToLegacy(normalizer, delegate.getOriginalData());
- }
-
- @Override
- public Map<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> getUpdatedConfigurationData() {
- if(updatedCache == null) {
- final Map<YangInstanceIdentifier, CompositeNode> updated = transformToLegacy(normalizer, delegate.getUpdatedData());
- final Map<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> created = getCreatedConfigurationData();
- final HashMap<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> updatedComposite = new HashMap<>(created.size() + updated.size());
- updatedComposite.putAll(created);
- updatedComposite.putAll(updated);
- updatedCache = Collections.unmodifiableMap(updatedComposite);
- }
- return updatedCache;
- }
-
- @Override
- public String toString() {
- return "ConfigurationChangeEvent [delegate=" + delegate + "]";
- }
- }
-}
+++ /dev/null
-/*
- * 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.broker.impl.compat;
-
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
-import org.opendaylight.yangtools.concepts.Delegator;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-@Deprecated
-abstract class TranslatingListenerInvoker implements AutoCloseable, DOMDataChangeListener, Delegator<DataChangeListener> {
-
- private final DataChangeListener delegate;
- private final DataNormalizer normalizer;
- protected ListenerRegistration<DOMDataChangeListener> reg;
-
- protected TranslatingListenerInvoker(final DataChangeListener listener, final DataNormalizer normalizer) {
- this.delegate = listener;
- this.normalizer = normalizer;
- }
-
- static TranslatingListenerInvoker createConfig(final DataChangeListener listener, final DataNormalizer normalizer) {
- return new TranslatingConfigListenerInvoker(listener, normalizer);
- }
-
- static TranslatingListenerInvoker createOperational(final DataChangeListener listener, final DataNormalizer normalizer) {
- return new TranslatingOperationalListenerInvoker(listener, normalizer);
- }
-
- @Override
- public void onDataChanged(final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
- delegate.onDataChanged(getLegacyEvent(normalizer, normalizedChange));
- }
-
- abstract DataChangeEvent<YangInstanceIdentifier, CompositeNode> getLegacyEvent(final DataNormalizer normalizer,
- final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedChange);
-
- @Override
- public DataChangeListener getDelegate() {
- return delegate;
- }
-
- abstract void register(final DOMDataBroker backingBroker, final YangInstanceIdentifier normalizedPath);
-
- @Override
- public void close() {
- if (reg != null) {
- reg.close();
- }
- }
-
- @Override
- public String toString() {
- return getDelegate().getClass().getName();
- }
-
- static final class TranslatingConfigListenerInvoker extends TranslatingListenerInvoker {
-
- public TranslatingConfigListenerInvoker(final DataChangeListener listener, final DataNormalizer normalizer) {
- super(listener, normalizer);
- }
-
- @Override
- DataChangeEvent<YangInstanceIdentifier, CompositeNode> getLegacyEvent(final DataNormalizer normalizer, final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
- return TranslatingDataChangeEvent.createConfiguration(normalizedChange, normalizer);
- }
-
- @Override
- void register(final DOMDataBroker backingBroker, final YangInstanceIdentifier normalizedPath) {
- reg = backingBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, normalizedPath, this,
- AsyncDataBroker.DataChangeScope.SUBTREE);
- }
- }
-
- static final class TranslatingOperationalListenerInvoker extends TranslatingListenerInvoker {
-
- public TranslatingOperationalListenerInvoker(final DataChangeListener listener, final DataNormalizer normalizer) {
- super(listener, normalizer);
- }
-
- @Override
- DataChangeEvent<YangInstanceIdentifier, CompositeNode> getLegacyEvent(final DataNormalizer normalizer, final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
- return TranslatingDataChangeEvent.createOperational(normalizedChange, normalizer);
- }
-
- @Override
- void register(final DOMDataBroker backingBroker, final YangInstanceIdentifier normalizedPath) {
- reg = backingBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, normalizedPath, this,
- AsyncDataBroker.DataChangeScope.SUBTREE);
- }
- }
-
-}
+++ /dev/null
-/*
- * 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.sal.dom.broker;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.JdkFutureAdapters;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import javax.annotation.Nullable;
-import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
-import org.opendaylight.controller.md.sal.common.impl.ListenerRegistry;
-import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
-import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
-import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
-import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
-import org.opendaylight.controller.md.sal.dom.api.DOMService;
-import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
-import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker;
-import org.opendaylight.controller.sal.common.DataStoreIdentifier;
-import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
-import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
-import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.core.api.data.DataProviderService;
-import org.opendaylight.controller.sal.core.api.data.DataValidator;
-import org.opendaylight.controller.sal.core.api.model.SchemaService;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
-import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
-import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
-import org.opendaylight.controller.sal.dom.broker.impl.NotificationRouterImpl;
-import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker;
-import org.opendaylight.controller.sal.dom.broker.spi.NotificationRouter;
-import org.opendaylight.controller.sal.dom.broker.util.ProxySchemaContext;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
-import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
-
-@Deprecated
-public class BackwardsCompatibleMountPoint implements MountProvisionInstance, SchemaContextProvider, SchemaService {
-
- private final DataProviderService dataReader;
- private final DataReader<YangInstanceIdentifier,CompositeNode> readWrapper;
-
- private final YangInstanceIdentifier mountPath;
- private final NotificationPublishService notificationPublishService;
- private final RpcProvisionRegistry rpcs;
-
- private final ListenerRegistry<SchemaContextListener> schemaListenerRegistry = new ListenerRegistry<>();
-
- private SchemaContext schemaContext;
-
- public BackwardsCompatibleMountPoint(final YangInstanceIdentifier path, final DOMMountPointService.DOMMountPointBuilder mountPointBuilder) {
- this.mountPath = Preconditions.checkNotNull(path);
- Preconditions.checkNotNull(mountPointBuilder);
-
- dataReader = new DataBrokerImpl();
- readWrapper = new ReadWrapper();
- notificationPublishService = new DelgatingNotificationPublishService();
- rpcs = new SchemaAwareRpcBroker(path.toString(), this);
-
- mountPointBuilder.addService(DOMDataBroker.class, new BackwardsCompatibleDomStore(dataReader, this));
- mountPointBuilder.addService(NotificationPublishService.class, notificationPublishService);
- mountPointBuilder.addService(RpcProvisionRegistry.class, rpcs);
-
- mountPointBuilder.addInitialSchemaContext(new ProxySchemaContext(this));
-
- mountPointBuilder.register();
- }
-
- public BackwardsCompatibleMountPoint(final YangInstanceIdentifier path, final DOMMountPoint mount) {
- this.mountPath = Preconditions.checkNotNull(path);
- Preconditions.checkNotNull(mount);
-
- final DOMDataBroker domBroker = getServiceWithCheck(mount, DOMDataBroker.class);
-
- this.schemaContext = mount.getSchemaContext();
-
- dataReader = new BackwardsCompatibleDataBroker(domBroker, this);
-
- // Set schema context to provide it for BackwardsCompatibleDataBroker
- if(schemaContext != null) {
- setSchemaContext(schemaContext);
- }
-
- readWrapper = new ReadWrapper();
-
- notificationPublishService = getServiceWithCheck(mount, NotificationPublishService.class);
- rpcs = getServiceWithCheck(mount, RpcProvisionRegistry.class);
- }
-
- private <T extends DOMService> T getServiceWithCheck(final DOMMountPoint mount, final Class<T> type) {
- final Optional<T> serviceOptional = mount.getService(type);
- Preconditions.checkArgument(serviceOptional.isPresent(), "Service {} has to be set in {}. " +
- "Cannot construct backwards compatible mount wrapper without it", type, mount);
- return serviceOptional.get();
- }
-
- @Override
- public void addModule(final Module module) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void removeModule(final Module module) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public SchemaContext getSessionContext() {
- return getSchemaContext();
- }
-
- @Override
- public SchemaContext getGlobalContext() {
- return getSchemaContext();
- }
-
- @Override
- public ListenerRegistration<SchemaContextListener> registerSchemaContextListener(final SchemaContextListener listener) {
- return schemaListenerRegistry.register(listener);
- }
-
- @Override
- public void publish(final CompositeNode notification) {
- notificationPublishService.publish(notification);
- }
-
- @Override
- public ListenerRegistration<NotificationListener> addNotificationListener(final QName notification, final NotificationListener listener) {
- return notificationPublishService.addNotificationListener(notification, listener);
- }
-
- // TODO Read wrapper is never used ... same in org.opendaylight.controller.sal.dom.broker.MountPointImpl
- public DataReader<YangInstanceIdentifier, CompositeNode> getReadWrapper() {
- return readWrapper;
- }
-
- @Override
- public CompositeNode readConfigurationData(final YangInstanceIdentifier path) {
- return dataReader.readConfigurationData(path);
- }
-
- @Override
- public CompositeNode readOperationalData(final YangInstanceIdentifier path) {
- return dataReader.readOperationalData(path);
- }
-
- @Override
- public Registration registerOperationalReader(
- final YangInstanceIdentifier path, final DataReader<YangInstanceIdentifier, CompositeNode> reader) {
- return dataReader.registerOperationalReader(path, reader);
- }
-
- @Override
- public Registration registerConfigurationReader(
- final YangInstanceIdentifier path, final DataReader<YangInstanceIdentifier, CompositeNode> reader) {
- return dataReader.registerConfigurationReader(path, reader);
- }
-
- @Override
- public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
- return rpcs.addRoutedRpcImplementation(rpcType, implementation);
- }
-
- @Override
- public void setRoutedRpcDefaultDelegate(final RoutedRpcDefaultImplementation defaultImplementation) {
- rpcs.setRoutedRpcDefaultDelegate(defaultImplementation);
- }
-
- @Override
- public RpcRegistration addRpcImplementation(final QName rpcType, final RpcImplementation implementation)
- throws IllegalArgumentException {
- return rpcs.addRpcImplementation(rpcType, implementation);
- }
-
- @Override
- public Set<QName> getSupportedRpcs() {
- return rpcs.getSupportedRpcs();
- }
-
- @Override
- public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode input) {
- return rpcs.invokeRpc(rpc, input);
- }
-
- @Override
- public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(final RpcRegistrationListener listener) {
- return rpcs.addRpcRegistrationListener(listener);
- }
-
- @Override
- public ListenableFuture<RpcResult<CompositeNode>> rpc(final QName type, final CompositeNode input) {
- return rpcs.invokeRpc(type, input);
- }
-
- @Override
- public DataModificationTransaction beginTransaction() {
- return dataReader.beginTransaction();
- }
-
- @Override
- public ListenerRegistration<DataChangeListener> registerDataChangeListener(final YangInstanceIdentifier path,
- final DataChangeListener listener) {
- return dataReader.registerDataChangeListener(path, listener);
- }
-
- @Override
- public Registration registerCommitHandler(
- final YangInstanceIdentifier path, final DataCommitHandler<YangInstanceIdentifier, CompositeNode> commitHandler) {
- return dataReader.registerCommitHandler(path, commitHandler);
- }
-
- @Override
- public void removeRefresher(final DataStoreIdentifier store, final DataRefresher refresher) {
- // NOOP
- }
-
- @Override
- public void addRefresher(final DataStoreIdentifier store, final DataRefresher refresher) {
- // NOOP
- }
-
- @Override
- public void addValidator(final DataStoreIdentifier store, final DataValidator validator) {
- // NOOP
- }
- @Override
- public void removeValidator(final DataStoreIdentifier store, final DataValidator validator) {
- // NOOP
- }
-
- @Override
- public SchemaContext getSchemaContext() {
- return schemaContext;
- }
-
- @Override
- public void setSchemaContext(final SchemaContext schemaContext) {
- this.schemaContext = schemaContext;
- for (ListenerRegistration<SchemaContextListener> schemaServiceListenerListenerRegistration : schemaListenerRegistry.getListeners()) {
- schemaServiceListenerListenerRegistration.getInstance().onGlobalContextUpdated(schemaContext);
- }
- }
-
- class ReadWrapper implements DataReader<YangInstanceIdentifier, CompositeNode> {
- private YangInstanceIdentifier shortenPath(final YangInstanceIdentifier path) {
- if (!mountPath.contains(path)) {
- return null;
- }
- return YangInstanceIdentifier.create(Iterables.skip(path.getPathArguments(), Iterables.size(mountPath.getPathArguments())));
- }
-
- @Override
- public CompositeNode readConfigurationData(final YangInstanceIdentifier path) {
- final YangInstanceIdentifier newPath = shortenPath(path);
- if(newPath == null) {
- return null;
- }
- return BackwardsCompatibleMountPoint.this.readConfigurationData(newPath);
- }
-
- @Override
- public CompositeNode readOperationalData(final YangInstanceIdentifier path) {
- final YangInstanceIdentifier newPath = shortenPath(path);
- if(newPath == null) {
- return null;
- }
- return BackwardsCompatibleMountPoint.this.readOperationalData(newPath);
- }
- }
-
- @Override
- public ListenerRegistration<RegistrationListener<DataCommitHandlerRegistration<YangInstanceIdentifier, CompositeNode>>> registerCommitHandlerListener(
- final RegistrationListener<DataCommitHandlerRegistration<YangInstanceIdentifier, CompositeNode>> commitHandlerListener) {
- return dataReader.registerCommitHandlerListener(commitHandlerListener);
- }
-
- @Override
- public <L extends RouteChangeListener<RpcRoutingContext, YangInstanceIdentifier>> ListenerRegistration<L> registerRouteChangeListener(
- final L listener) {
- return rpcs.registerRouteChangeListener(listener);
- }
-
- @VisibleForTesting
- static final class BackwardsCompatibleDomStore implements DOMDataBroker {
- private final DataProviderService dataReader;
- private final SchemaContextProvider schemaContextProvider;
-
- public BackwardsCompatibleDomStore(final DataProviderService dataReader, final SchemaContextProvider schemaContextProvider) {
- this.dataReader = dataReader;
- this.schemaContextProvider = schemaContextProvider;
- }
-
- @Override
- public DOMDataReadOnlyTransaction newReadOnlyTransaction() {
- final DataNormalizer dataNormalizer = new DataNormalizer(schemaContextProvider.getSchemaContext());
- return new BackwardsCompatibleReadTransaction(dataReader, dataNormalizer);
- }
-
- @Override
- public DOMDataWriteTransaction newWriteOnlyTransaction() {
- final DataNormalizer dataNormalizer = new DataNormalizer(schemaContextProvider.getSchemaContext());
- return new BackwardsCompatibleWriteTransaction(dataReader, dataNormalizer);
- }
-
- @Override
- public ListenerRegistration<DOMDataChangeListener> registerDataChangeListener(final LogicalDatastoreType store, final YangInstanceIdentifier path, final DOMDataChangeListener listener, final DataChangeScope triggeringScope) {
- throw new UnsupportedOperationException("Register data listener not supported for mount point");
- }
-
- @Override
- public DOMTransactionChain createTransactionChain(final TransactionChainListener listener) {
- throw new UnsupportedOperationException("Transaction chain not supported for mount point");
- }
-
- @Override
- public DOMDataReadWriteTransaction newReadWriteTransaction() {
- final DataNormalizer dataNormalizer = new DataNormalizer(schemaContextProvider.getSchemaContext());
- return new BackwardsCompatibleReadWriteTransaction(dataReader, dataNormalizer);
- }
-
- @VisibleForTesting
- static final class BackwardsCompatibleReadTransaction implements DOMDataReadOnlyTransaction {
- private final DataProviderService dataReader;
- private final DataNormalizer normalizer;
-
- public BackwardsCompatibleReadTransaction(final DataProviderService dataReader, final DataNormalizer normalizer) {
- this.dataReader = dataReader;
- this.normalizer = normalizer;
- }
-
- @Override
- public Object getIdentifier() {
- return this;
- }
-
- @Override
- public void close() {
- // NOOP
- }
-
- @Override
- public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read(
- final LogicalDatastoreType store, final YangInstanceIdentifier path) {
-
- CompositeNode rawData = null;
-
- switch (store) {
- case CONFIGURATION: {
- rawData = dataReader.readConfigurationData(path);
- break;
- }
- case OPERATIONAL: {
- rawData = dataReader.readOperationalData(path);
- break;
- }
- }
- Preconditions.checkNotNull(rawData, "Unable to read %s data on path %s", store, path);
-
- final Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalized = normalizer.toNormalized(path, rawData);
- final Optional<NormalizedNode<?, ?>> normalizedNodeOptional = Optional.<NormalizedNode<?, ?>>fromNullable(normalized.getValue());
- return Futures.immediateCheckedFuture(normalizedNodeOptional);
- }
-
- @Override public CheckedFuture<Boolean, ReadFailedException> exists(final LogicalDatastoreType store,
- final YangInstanceIdentifier path) {
-
- try {
- return Futures.immediateCheckedFuture(read(store, path).get().isPresent());
- } catch (InterruptedException | ExecutionException e) {
- return Futures.immediateFailedCheckedFuture(new ReadFailedException("Exists failed",e));
- }
- }
- }
-
- @VisibleForTesting
- static final class BackwardsCompatibleWriteTransaction implements DOMDataWriteTransaction {
- private DataModificationTransaction oldTx;
- private final DataNormalizer dataNormalizer;
-
- public BackwardsCompatibleWriteTransaction(final DataProviderService dataReader, final DataNormalizer dataNormalizer) {
- this.oldTx = dataReader.beginTransaction();
- this.dataNormalizer = dataNormalizer;
- }
-
- @Override
- public Object getIdentifier() {
- return this;
- }
-
- @Override
- public boolean cancel() {
- oldTx = null;
- return true;
- }
-
- @Override
- public void put(final LogicalDatastoreType store, final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
- final CompositeNode legacyData = dataNormalizer.toLegacy(path, data);
- try {
- final YangInstanceIdentifier legacyPath = dataNormalizer.toLegacy(path);
-
- switch (store) {
- case CONFIGURATION: {
- oldTx.putConfigurationData(legacyPath, legacyData);
- return;
- }
- }
-
- throw new IllegalArgumentException("Cannot put data " + path + " to datastore " + store);
- } catch (final DataNormalizationException e) {
- throw new IllegalArgumentException(String.format("Cannot transform path %s to legacy format", path), e);
- }
- }
-
- @Override
- public void merge(final LogicalDatastoreType store, final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
- // TODO not supported
- throw new UnsupportedOperationException("Merge not supported for mount point");
- }
-
- @Override
- public void delete(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
- try {
- final YangInstanceIdentifier legacyPath = dataNormalizer.toLegacy(path);
-
- switch (store) {
- case CONFIGURATION: {
- oldTx.removeConfigurationData(legacyPath);
- return;
- }
- }
- throw new IllegalArgumentException("Cannot delete data " + path + " from datastore " + store);
- } catch (final DataNormalizationException e) {
- throw new IllegalArgumentException(String.format("Cannot transform path %s to legacy format", path), e);
- }
- }
-
- @Override
- public CheckedFuture<Void, TransactionCommitFailedException> submit() {
- final ListenableFuture<Void> commitAsVoid = Futures.transform(commit(), new Function<RpcResult<TransactionStatus>, Void>() {
- @Override
- public Void apply(@Nullable final RpcResult<TransactionStatus> input) {
- return null;
- }
- });
-
- return Futures.makeChecked(commitAsVoid, new Function<Exception, TransactionCommitFailedException>() {
- @Override
- public TransactionCommitFailedException apply(@Nullable final Exception input) {
- return new TransactionCommitFailedException("Commit failed", input);
- }
- });
- }
-
- @Override
- public ListenableFuture<RpcResult<TransactionStatus>> commit() {
- return JdkFutureAdapters.listenInPoolThread(oldTx.commit());
- }
- }
-
-
- @VisibleForTesting
- static class BackwardsCompatibleReadWriteTransaction implements DOMDataReadWriteTransaction {
-
- private final DataProviderService dataReader;
- private final DataNormalizer dataNormalizer;
- private final BackwardsCompatibleWriteTransaction delegateWriteTx;
-
- public BackwardsCompatibleReadWriteTransaction(final DataProviderService dataReader, final DataNormalizer dataNormalizer) {
- this.dataReader = dataReader;
- this.dataNormalizer = dataNormalizer;
- this.delegateWriteTx = new BackwardsCompatibleWriteTransaction(dataReader, dataNormalizer);
- }
-
- @Override
- public Object getIdentifier() {
- return this;
- }
-
- @Override
- public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read(
- final LogicalDatastoreType store, final YangInstanceIdentifier path) {
- return new BackwardsCompatibleReadTransaction(dataReader, dataNormalizer).read(store, path);
- }
-
- @Override public CheckedFuture<Boolean, ReadFailedException> exists(final LogicalDatastoreType store,
- final YangInstanceIdentifier path) {
-
- try {
- return Futures.immediateCheckedFuture(read(store, path).get().isPresent());
- } catch (InterruptedException | ExecutionException e) {
- return Futures.immediateFailedCheckedFuture(new ReadFailedException("Exists failed",e));
- }
- }
-
- @Override
- public boolean cancel() {
- return delegateWriteTx.cancel();
- }
-
- @Override
- public void put(final LogicalDatastoreType store, final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
- delegateWriteTx.put(store, path, data);
- }
-
- @Override
- public void merge(final LogicalDatastoreType store, final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
- delegateWriteTx.merge(store, path, data);
- }
-
- @Override
- public void delete(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
- delegateWriteTx.delete(store, path);
- }
-
- @Override
- public CheckedFuture<Void, TransactionCommitFailedException> submit() {
- return delegateWriteTx.submit();
- }
-
- @Override
- public ListenableFuture<RpcResult<TransactionStatus>> commit() {
- return delegateWriteTx.commit();
- }
- }
- }
-
- private class DelgatingNotificationPublishService implements NotificationPublishService {
- private final NotificationRouter notificationRouter;
-
- public DelgatingNotificationPublishService(final NotificationRouter notificationRouter) {
- this.notificationRouter = notificationRouter;
- }
-
- private DelgatingNotificationPublishService() {
- this(new NotificationRouterImpl());
- }
-
- @Override
- public void publish(final CompositeNode notification) {
- notificationRouter.publish(notification);
- }
-
- @Override
- public ListenerRegistration<NotificationListener> addNotificationListener(final QName notification, final NotificationListener listener) {
- return notificationRouter.addNotificationListener(notification, listener);
- }
- }
-}
+++ /dev/null
-/*
- * 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.sal.dom.broker;
-
-import static com.google.common.base.Preconditions.checkState;
-
-import com.google.common.base.Optional;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
-import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.util.ListenerRegistry;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-@Deprecated
-public class BackwardsCompatibleMountPointManager implements MountProvisionService, MountProvisionListener {
-
- private final ListenerRegistry<MountProvisionListener> listeners = ListenerRegistry.create();
- private final ConcurrentMap<YangInstanceIdentifier, MountProvisionInstance> mounts = new ConcurrentHashMap<>();
-
- private final DOMMountPointService domMountPointService;
-
- public BackwardsCompatibleMountPointManager(final DOMMountPointService domMountPointService) {
- this.domMountPointService = domMountPointService;
- }
-
- @Override
- public MountProvisionInstance createMountPoint(final YangInstanceIdentifier path) {
- checkState(!mounts.containsKey(path), "Mount already created");
- // Create mount point instance, wrap instance of new API with BackwardsCompatibleMountPoint to preserve backwards comatibility
- final BackwardsCompatibleMountPoint mount = new BackwardsCompatibleMountPoint(path, domMountPointService.createMountPoint(path));
- mounts.put(path, mount);
- return mount;
- }
-
- public void notifyMountCreated(final YangInstanceIdentifier identifier) {
- for (final ListenerRegistration<MountProvisionListener> listener : listeners.getListeners()) {
- listener.getInstance().onMountPointCreated(identifier);
- }
- }
-
- public void notifyMountRemoved(final YangInstanceIdentifier identifier) {
- for (final ListenerRegistration<MountProvisionListener> listener : listeners.getListeners()) {
- listener.getInstance().onMountPointRemoved(identifier);
- }
- }
-
- @Override
- public MountProvisionInstance createOrGetMountPoint(
- final YangInstanceIdentifier path) {
- final MountProvisionInstance mount = getMountPoint(path);
- if (mount == null) {
- return createMountPoint(path);
- }
- return mount;
- }
-
- @Override
- public MountProvisionInstance getMountPoint(final YangInstanceIdentifier path) {
- // If the mount point was created here, return directly
- if(mounts.containsKey(path)) {
- return mounts.get(path);
- }
-
- // If mount was created in underlying DOMMountService, wrap as MountProvisionInstance
- final Optional<DOMMountPoint> mount = domMountPointService.getMountPoint(path);
- if(mount.isPresent()) {
- return new BackwardsCompatibleMountPoint(path, mount.get());
- } else {
- return null;
- }
- }
-
- @Override
- public ListenerRegistration<MountProvisionListener> registerProvisionListener(
- final MountProvisionListener listener) {
- return domMountPointService.registerProvisionListener(listener);
- }
-
- @Override
- public void onMountPointCreated(final YangInstanceIdentifier path) {
- notifyMountCreated(path);
- }
-
- @Override
- public void onMountPointRemoved(final YangInstanceIdentifier path) {
- notifyMountRemoved(path);
- }
-}
*/
package org.opendaylight.controller.sal.dom.broker;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.Future;
-
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ClassToInstanceMap;
+import com.google.common.collect.ImmutableClassToInstanceMap;
+import com.google.common.util.concurrent.CheckedFuture;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcAvailabilityListener;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcException;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcIdentifier;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementation;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationRegistration;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.md.sal.dom.broker.impl.DOMRpcRouter;
import org.opendaylight.controller.sal.core.api.Broker;
import org.opendaylight.controller.sal.core.api.BrokerService;
import org.opendaylight.controller.sal.core.api.Consumer;
import org.opendaylight.controller.sal.core.api.Provider;
-import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
-import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ClassToInstanceMap;
-import com.google.common.collect.ImmutableClassToInstanceMap;
-import com.google.common.util.concurrent.ListenableFuture;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
-public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
+public class BrokerImpl implements Broker, DOMRpcProviderService, DOMRpcService, AutoCloseable {
private final static Logger log = LoggerFactory.getLogger(BrokerImpl.class);
// Broker Generic Context
private AutoCloseable deactivator = null;
- private RpcRouter router = null;
+ private DOMRpcRouter router = null;
private final ClassToInstanceMap<BrokerService> services;
- public BrokerImpl(final RpcRouter router,final ClassToInstanceMap<BrokerService> services) {
+ public BrokerImpl(final DOMRpcRouter router,final ClassToInstanceMap<BrokerService> services) {
this.router = Preconditions.checkNotNull(router, "RPC Router must not be null");
this.services = ImmutableClassToInstanceMap.copyOf(services);
}
return registerProvider(provider);
}
- protected Future<RpcResult<CompositeNode>> invokeRpcAsync(final QName rpc,
- final CompositeNode input) {
- return router.invokeRpc(rpc, input);
- }
-
// Validation
private void checkPredicates(final Provider prov) {
Preconditions.checkNotNull(prov, "Provider should not be null.");
}
}
- @Override
- public RpcRegistration addRpcImplementation(final QName rpcType,
- final RpcImplementation implementation)
- throws IllegalArgumentException {
- return router.addRpcImplementation(rpcType, implementation);
- }
-
- @Override
- public RoutedRpcRegistration addRoutedRpcImplementation(
- final QName rpcType, final RpcImplementation implementation) {
- return router.addRoutedRpcImplementation(rpcType, implementation);
- }
-
- @Override
- public void setRoutedRpcDefaultDelegate(
- final RoutedRpcDefaultImplementation defaultImplementation) {
- router.setRoutedRpcDefaultDelegate(defaultImplementation);
- }
-
- @Override
- public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(
- final RpcRegistrationListener listener) {
- return router.addRpcRegistrationListener(listener);
- }
-
- @Override
- public <L extends RouteChangeListener<RpcRoutingContext, YangInstanceIdentifier>> ListenerRegistration<L> registerRouteChangeListener(
- final L listener) {
- return router.registerRouteChangeListener(listener);
- }
-
- @Override
- public Set<QName> getSupportedRpcs() {
- return router.getSupportedRpcs();
- }
-
- @Override
- public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(
- final QName rpc, final CompositeNode input) {
- return router.invokeRpc(rpc, input);
- }
-
/**
* @return the deactivator
*/
/**
* @return the router
*/
- public RpcRouter getRouter() {
+ public DOMRpcRouter getRouter() {
return router;
}
* @param router
* the router to set
*/
- public void setRouter(final RpcRouter router) {
+ public void setRouter(final DOMRpcRouter router) {
this.router = router;
}
return session;
}
+
+ @Nonnull
+ @Override
+ public <T extends DOMRpcImplementation> DOMRpcImplementationRegistration<T> registerRpcImplementation(@Nonnull final T implementation, @Nonnull final DOMRpcIdentifier... rpcs) {
+ return router.registerRpcImplementation(implementation, rpcs);
+ }
+
+ @Nonnull
+ @Override
+ public <T extends DOMRpcImplementation> DOMRpcImplementationRegistration<T> registerRpcImplementation(@Nonnull final T implementation, @Nonnull final Set<DOMRpcIdentifier> rpcs) {
+ return router.registerRpcImplementation(implementation, rpcs);
+ }
+
+ @Nonnull
+ @Override
+ public CheckedFuture<DOMRpcResult, DOMRpcException> invokeRpc(@Nonnull final SchemaPath type, @Nullable final NormalizedNode<?, ?> input) {
+ return router.invokeRpc(type, input);
+ }
+
+ @Nonnull
+ @Override
+ public <T extends DOMRpcAvailabilityListener> ListenerRegistration<T> registerRpcListener(@Nonnull final T listener) {
+ return router.registerRpcListener(listener);
+ }
}
*/
package org.opendaylight.controller.sal.dom.broker;
-import java.util.Collection;
-import java.util.concurrent.Future;
-
-import javax.annotation.concurrent.GuardedBy;
-
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ClassToInstanceMap;
+import com.google.common.collect.MutableClassToInstanceMap;
import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
import org.opendaylight.controller.sal.core.api.BrokerService;
import org.opendaylight.controller.sal.core.api.Consumer;
import org.opendaylight.controller.sal.dom.broker.osgi.AbstractBrokerServiceProxy;
import org.opendaylight.controller.sal.dom.broker.osgi.ProxyFactory;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ClassToInstanceMap;
-import com.google.common.collect.MutableClassToInstanceMap;
+import javax.annotation.concurrent.GuardedBy;
+import java.util.Collection;
class ConsumerContextImpl implements ConsumerSession {
consumer = provider;
}
- @Override
- public Future<RpcResult<CompositeNode>> rpc(final QName rpc,
- final CompositeNode input) {
- checkNotClosed();
- return broker.invokeRpcAsync(rpc, input);
- }
-
@Override
public <T extends BrokerService> T getService(final Class<T> service) {
checkNotClosed();
broker = null;
}
+
@Override
public synchronized boolean isClosed() {
return closed;
+++ /dev/null
-/*
- * 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.sal.dom.broker;
-
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataBroker;
-import org.opendaylight.controller.sal.common.DataStoreIdentifier;
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
-import org.opendaylight.controller.sal.core.api.data.DataProviderService;
-import org.opendaylight.controller.sal.core.api.data.DataValidator;
-import org.opendaylight.controller.sal.dom.broker.impl.DataReaderRouter;
-import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-import com.google.common.util.concurrent.MoreExecutors;
-
-@Deprecated
-public class DataBrokerImpl extends AbstractDataBroker<YangInstanceIdentifier, CompositeNode, DataChangeListener> implements
- DataProviderService, AutoCloseable {
-
- private AtomicLong nextTransaction = new AtomicLong();
- private final AtomicLong createdTransactionsCount = new AtomicLong();
-
- public DataBrokerImpl() {
- setDataReadRouter(new DataReaderRouter());
- setExecutor(MoreExecutors.sameThreadExecutor());
- }
-
- public AtomicLong getCreatedTransactionsCount() {
- return createdTransactionsCount;
- }
-
- @Override
- public DataTransactionImpl beginTransaction() {
- String transactionId = "DOM-" + nextTransaction.getAndIncrement();
- createdTransactionsCount.getAndIncrement();
- return new DataTransactionImpl(transactionId,this);
- }
-
- @Override
- public Registration registerConfigurationReader(
- YangInstanceIdentifier path, DataReader<YangInstanceIdentifier, CompositeNode> reader) {
- return getDataReadRouter().registerConfigurationReader(path, reader);
- }
-
- @Override
- public Registration registerOperationalReader(
- YangInstanceIdentifier path, DataReader<YangInstanceIdentifier, CompositeNode> reader) {
- return getDataReadRouter().registerOperationalReader(path, reader);
- }
-
- @Deprecated
- @Override
- public void addValidator(DataStoreIdentifier store, DataValidator validator) {
- throw new UnsupportedOperationException("Deprecated");
-
- }
-
- @Deprecated
- @Override
- public void removeValidator(DataStoreIdentifier store, DataValidator validator) {
- throw new UnsupportedOperationException("Deprecated");
- }
-
- @Deprecated
- @Override
- public void addRefresher(DataStoreIdentifier store, DataRefresher refresher) {
- throw new UnsupportedOperationException("Deprecated");
- }
-
- @Deprecated
- @Override
- public void removeRefresher(DataStoreIdentifier store, DataRefresher refresher) {
- throw new UnsupportedOperationException("Deprecated");
- }
-
- @Override
- public void close() throws Exception {
-
- }
-
-}
+++ /dev/null
-/*
- * 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.sal.dom.broker;
-
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataTransaction;
-import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.util.ListenerRegistry;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-@Deprecated
-public class DataTransactionImpl extends AbstractDataTransaction<YangInstanceIdentifier, CompositeNode>
- implements DataModificationTransaction {
- private final ListenerRegistry<DataTransactionListener> listeners = new ListenerRegistry<DataTransactionListener>();
-
-
-
- public DataTransactionImpl(Object identifier,DataBrokerImpl dataBroker) {
- super(identifier,dataBroker);
- }
-
- @Override
- public ListenerRegistration<DataTransactionListener> registerListener(DataTransactionListener listener) {
- return listeners.register(listener);
- }
-
- protected void onStatusChange(TransactionStatus status) {
- for (ListenerRegistration<DataTransactionListener> listenerRegistration : listeners) {
- listenerRegistration.getInstance().onStatusUpdated(this, status);
- }
- }
-}
+++ /dev/null
-/*
- * 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.dom.broker;
-
-import com.google.common.collect.Iterables;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.Set;
-import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
-import org.opendaylight.controller.sal.common.DataStoreIdentifier;
-import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
-import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
-import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.core.api.data.DataValidator;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
-import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
-import org.opendaylight.controller.sal.dom.broker.impl.NotificationRouterImpl;
-import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker;
-import org.opendaylight.controller.sal.dom.broker.spi.NotificationRouter;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
-
-@Deprecated
-public class MountPointImpl implements MountProvisionInstance, SchemaContextProvider {
-
- private final SchemaAwareRpcBroker rpcs;
- private final DataBrokerImpl dataReader;
- private final NotificationRouter notificationRouter;
- private final DataReader<YangInstanceIdentifier,CompositeNode> readWrapper;
-
-
- private final YangInstanceIdentifier mountPath;
-
- private SchemaContext schemaContext;
-
- public MountPointImpl(final YangInstanceIdentifier path) {
- this.mountPath = path;
- rpcs = new SchemaAwareRpcBroker(path.toString(),this);
- dataReader = new DataBrokerImpl();
- notificationRouter = new NotificationRouterImpl();
- readWrapper = new ReadWrapper();
- }
-
- public YangInstanceIdentifier getMountPath() {
- return mountPath;
- }
-
- public DataReader<YangInstanceIdentifier, CompositeNode> getReadWrapper() {
- return readWrapper;
- }
-
- @Override
- public void publish(final CompositeNode notification) {
- notificationRouter.publish(notification);
- }
-
- @Override
- public ListenerRegistration<NotificationListener> addNotificationListener(final QName notification, final NotificationListener listener) {
- return notificationRouter.addNotificationListener(notification, listener);
- }
-
- @Override
- public CompositeNode readConfigurationData(final YangInstanceIdentifier path) {
- return dataReader.readConfigurationData(path);
- }
-
- @Override
- public CompositeNode readOperationalData(final YangInstanceIdentifier path) {
- return dataReader.readOperationalData(path);
- }
-
- @Override
- public Registration registerOperationalReader(
- final YangInstanceIdentifier path, final DataReader<YangInstanceIdentifier, CompositeNode> reader) {
- return dataReader.registerOperationalReader(path, reader);
- }
-
- @Override
- public Registration registerConfigurationReader(
- final YangInstanceIdentifier path, final DataReader<YangInstanceIdentifier, CompositeNode> reader) {
- return dataReader.registerConfigurationReader(path, reader);
- }
-
- @Override
- public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
- return rpcs.addRoutedRpcImplementation(rpcType, implementation);
- }
-
- @Override
- public void setRoutedRpcDefaultDelegate(final RoutedRpcDefaultImplementation defaultImplementation) {
- rpcs.setRoutedRpcDefaultDelegate(defaultImplementation);
- }
-
- @Override
- public RpcRegistration addRpcImplementation(final QName rpcType, final RpcImplementation implementation)
- throws IllegalArgumentException {
- return rpcs.addRpcImplementation(rpcType, implementation);
- }
-
- @Override
- public Set<QName> getSupportedRpcs() {
- return rpcs.getSupportedRpcs();
- }
-
- @Override
- public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode input) {
- return rpcs.invokeRpc(rpc, input);
- }
-
- @Override
- public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(final RpcRegistrationListener listener) {
- return rpcs.addRpcRegistrationListener(listener);
- }
-
- @Override
- public ListenableFuture<RpcResult<CompositeNode>> rpc(final QName type, final CompositeNode input) {
- return rpcs.invokeRpc( type, input );
- }
-
- @Override
- public DataModificationTransaction beginTransaction() {
- return dataReader.beginTransaction();
- }
-
- @Override
- public ListenerRegistration<DataChangeListener> registerDataChangeListener(final YangInstanceIdentifier path,
- final DataChangeListener listener) {
- return dataReader.registerDataChangeListener(path, listener);
- }
-
- @Override
- public Registration registerCommitHandler(
- final YangInstanceIdentifier path, final DataCommitHandler<YangInstanceIdentifier, CompositeNode> commitHandler) {
- return dataReader.registerCommitHandler(path, commitHandler);
- }
-
- @Override
- public void removeRefresher(final DataStoreIdentifier store, final DataRefresher refresher) {
- // NOOP
- }
-
- @Override
- public void addRefresher(final DataStoreIdentifier store, final DataRefresher refresher) {
- // NOOP
- }
-
- @Override
- public void addValidator(final DataStoreIdentifier store, final DataValidator validator) {
- // NOOP
- }
- @Override
- public void removeValidator(final DataStoreIdentifier store, final DataValidator validator) {
- // NOOP
- }
-
- @Override
- public SchemaContext getSchemaContext() {
- return schemaContext;
- }
-
- @Override
- public void setSchemaContext(final SchemaContext schemaContext) {
- this.schemaContext = schemaContext;
- }
-
- class ReadWrapper implements DataReader<YangInstanceIdentifier, CompositeNode> {
- private YangInstanceIdentifier shortenPath(final YangInstanceIdentifier path) {
- if (!mountPath.contains(path)) {
- return null;
- }
-
- return YangInstanceIdentifier.create(Iterables.skip(path.getPathArguments(), Iterables.size(mountPath.getPathArguments())));
- }
-
- @Override
- public CompositeNode readConfigurationData(final YangInstanceIdentifier path) {
- YangInstanceIdentifier newPath = shortenPath(path);
- if(newPath == null) {
- return null;
- }
- return MountPointImpl.this.readConfigurationData(newPath);
- }
-
- @Override
- public CompositeNode readOperationalData(final YangInstanceIdentifier path) {
- YangInstanceIdentifier newPath = shortenPath(path);
- if(newPath == null) {
- return null;
- }
- return MountPointImpl.this.readOperationalData(newPath);
- }
- }
-
- @Override
- public ListenerRegistration<RegistrationListener<DataCommitHandlerRegistration<YangInstanceIdentifier, CompositeNode>>> registerCommitHandlerListener(
- final RegistrationListener<DataCommitHandlerRegistration<YangInstanceIdentifier, CompositeNode>> commitHandlerListener) {
- return dataReader.registerCommitHandlerListener(commitHandlerListener);
- }
-
- @Override
- public <L extends RouteChangeListener<RpcRoutingContext, YangInstanceIdentifier>> ListenerRegistration<L> registerRouteChangeListener(
- final L listener) {
- return rpcs.registerRouteChangeListener(listener);
- }
-}
+++ /dev/null
-/**
- * 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.sal.dom.broker;
-
-import static com.google.common.base.Preconditions.checkState;
-
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import org.opendaylight.controller.sal.core.api.data.DataProviderService;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.util.ListenerRegistry;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-@Deprecated
-public class MountPointManagerImpl implements MountProvisionService {
-
- private final ListenerRegistry<MountProvisionListener> listeners =
- ListenerRegistry.create();
- private final ConcurrentMap<YangInstanceIdentifier, MountPointImpl> mounts =
- new ConcurrentHashMap<>();
- private DataProviderService dataBroker = null;
-
- @Override
- public MountProvisionInstance createMountPoint(final YangInstanceIdentifier path) {
- checkState(!mounts.containsKey(path), "Mount already created");
- final MountPointImpl mount = new MountPointImpl(path);
- registerMountPoint(mount);
- mounts.put(path, mount);
- notifyMountCreated(path);
- return mount;
- }
-
- public void notifyMountCreated(final YangInstanceIdentifier identifier) {
- for (final ListenerRegistration<MountProvisionListener> listener : listeners
- .getListeners()) {
- listener.getInstance().onMountPointCreated(identifier);
- }
- }
-
- public Object registerMountPoint(final MountPointImpl impl) {
- // FIXME: Why is thie commented out? Either we need it or we don't
- // dataBroker?.registerConfigurationReader(impl.mountPath,impl.readWrapper);
- // dataBroker?.registerOperationalReader(impl.mountPath,impl.readWrapper);
- return null;
- }
-
- @Override
- public MountProvisionInstance createOrGetMountPoint(
- final YangInstanceIdentifier path) {
- final MountPointImpl mount = mounts.get(path);
- if (mount == null) {
- return createMountPoint(path);
- }
- return mount;
- }
-
- @Override
- public MountProvisionInstance getMountPoint(final YangInstanceIdentifier path) {
- return mounts.get(path);
- }
-
- /**
- * @return the dataBroker
- */
- public DataProviderService getDataBroker() {
- return dataBroker;
- }
-
- /**
- * @param dataBroker
- * the dataBroker to set
- */
- public void setDataBroker(final DataProviderService dataBroker) {
- this.dataBroker = dataBroker;
- }
-
- @Override
- public ListenerRegistration<MountProvisionListener> registerProvisionListener(
- final MountProvisionListener listener) {
- return listeners.register(listener);
- }
-}
*/
package org.opendaylight.controller.sal.dom.broker;
-import java.util.HashSet;
-import java.util.Set;
-
import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
import org.opendaylight.controller.sal.core.api.Provider;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.common.QName;
class ProviderContextImpl extends ConsumerContextImpl implements ProviderSession {
- private final Set<RpcRegistrationWrapper> registrations = new HashSet<>();
private final Provider provider;
public ProviderContextImpl(final Provider provider, final BrokerImpl broker) {
this.provider = provider;
}
- @Override
- public RpcRegistrationWrapper addRpcImplementation(final QName rpcType,
- final RpcImplementation implementation) throws IllegalArgumentException {
- final RpcRegistration origReg = getBrokerChecked().getRouter()
- .addRpcImplementation(rpcType, implementation);
- final RpcRegistrationWrapper newReg = new RpcRegistrationWrapper(
- origReg);
- registrations.add(newReg);
- return newReg;
- }
-
- protected boolean removeRpcImplementation(final RpcRegistrationWrapper implToRemove) {
- return registrations.remove(implToRemove);
- }
-
@Override
public void close() {
- for (final RpcRegistrationWrapper reg : registrations) {
- reg.close();
- }
- }
-
- @Override
- public RoutedRpcRegistration addMountedRpcImplementation(
- final QName rpcType, final RpcImplementation implementation) {
- throw new UnsupportedOperationException(
- "TODO: auto-generated method stub");
-
- }
-
- @Override
- public RoutedRpcRegistration addRoutedRpcImplementation(
- final QName rpcType, final RpcImplementation implementation) {
- return getBrokerChecked().getRouter().addRoutedRpcImplementation(rpcType, implementation);
- }
-
- @Override
- public Set<QName> getSupportedRpcs() {
- return getBrokerChecked().getRouter().getSupportedRpcs();
- }
-
- @Override
- public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(
- final RpcRegistrationListener listener) {
- return getBrokerChecked().getRouter().addRpcRegistrationListener(listener);
}
/**
+++ /dev/null
-/**
- * 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.sal.dom.broker;
-
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.yangtools.yang.common.QName;
-
-import com.google.common.base.Preconditions;
-
-public class RpcRegistrationWrapper implements RpcRegistration {
-
- private final RpcRegistration delegate;
-
- public RpcRegistrationWrapper(final RpcRegistration delegate) {
- this.delegate = Preconditions.checkNotNull(delegate);
- }
-
- @Override
- public RpcImplementation getInstance() {
- return delegate.getInstance();
- }
-
- @Override
- public void close() {
- delegate.close();
- }
-
- @Override
- public QName getType() {
- return delegate.getType();
- }
-
- /**
- * @return the delegate
- */
- public RpcRegistration getDelegate() {
- return delegate;
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * 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.sal.dom.broker.impl;
-
-import static com.google.common.base.Preconditions.checkState;
-
-import com.google.common.collect.Iterables;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Deprecated
-public class DataReaderRouter extends AbstractDataReadRouter<YangInstanceIdentifier, CompositeNode> {
- private final static Logger LOG = LoggerFactory
- .getLogger(DataReaderRouter.class);
- private final static URI NETCONF_NAMESPACE = URI
- .create("urn:ietf:params:xml:ns:netconf:base:1.0");
- private final static QName NETCONF_DATA = new QName(NETCONF_NAMESPACE,
- "data");
-
- @Override
- protected CompositeNodeTOImpl merge(final YangInstanceIdentifier path,
- final Iterable<CompositeNode> data) {
- PathArgument pathArgument = Iterables.getLast(path.getPathArguments(), null);
- boolean empty = true;
- QName name = (pathArgument == null ? null : pathArgument.getNodeType());
- final ArrayList<Node<?>> nodes = new ArrayList<Node<?>>();
- final HashMap<QName, SimpleNode<?>> keyNodes = new HashMap<QName, SimpleNode<?>>();
- for (final CompositeNode dataBit : data) {
- try {
- if (pathArgument != null && dataBit != null) {
- empty = false;
- final Map<QName, SimpleNode<?>> keyNodesLocal = getKeyNodes(
- pathArgument, dataBit);
- nodes.addAll(this.childrenWithout(dataBit,
- keyNodesLocal.entrySet()));
- } else if (dataBit != null) {
- empty = false;
- nodes.addAll(dataBit.getValue());
- }
- } catch (IllegalStateException e) {
- LOG.error("BUG: Readed data for path {} was invalid", path, e);
- }
- }
- if (empty) {
- return null;
- }
- /**
- * Reading from Root
- *
- */
- if (pathArgument == null) {
- return new CompositeNodeTOImpl(NETCONF_DATA, null, nodes);
- }
- final ArrayList<Node<?>> finalNodes = new ArrayList<Node<?>>(
- nodes.size() + keyNodes.size());
- finalNodes.addAll(keyNodes.values());
- finalNodes.addAll(nodes);
- return new CompositeNodeTOImpl(name, null, finalNodes);
- }
-
- protected Map<QName, SimpleNode<?>> _getKeyNodes(
- final PathArgument argument, final CompositeNode node) {
- return Collections.emptyMap();
- }
-
- protected Map<QName, SimpleNode<?>> _getKeyNodes(
- final NodeIdentifierWithPredicates argument,
- final CompositeNode node) {
- final HashMap<QName, SimpleNode<?>> ret = new HashMap<QName, SimpleNode<?>>();
- for (final Entry<QName, Object> keyValue : argument.getKeyValues()
- .entrySet()) {
- final List<SimpleNode<?>> simpleNode = node
- .getSimpleNodesByName(keyValue.getKey());
- if (simpleNode != null && !simpleNode.isEmpty()) {
- checkState(
- simpleNode.size() <= 1,
- "Only one simple node for key $s is allowed in node $s",
- keyValue.getKey(), node);
- checkState(
- simpleNode.get(0).getValue().equals(keyValue.getValue()),
- "Key node must equal to instance identifier value in node $s",
- node);
- ret.put(keyValue.getKey(), simpleNode.get(0));
- }
- final List<CompositeNode> compositeNode = node
- .getCompositesByName(keyValue.getKey());
- checkState(compositeNode == null || compositeNode.isEmpty(),
- "Key node must be Simple Node, not composite node.");
- }
- return ret;
- }
-
- public Map<QName, SimpleNode<?>> getKeyNodes(
- final YangInstanceIdentifier.PathArgument argument,
- final CompositeNode node) {
- if (argument instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) {
- return _getKeyNodes(
- (YangInstanceIdentifier.NodeIdentifierWithPredicates) argument,
- node);
- } else if (argument != null) {
- return _getKeyNodes(argument, node);
- } else {
- throw new IllegalArgumentException("Unhandled parameter types: "
- + Arrays.<Object> asList(argument, node).toString());
- }
- }
-
- private Collection<? extends Node<?>> childrenWithout(
- final CompositeNode node,
- final Set<Entry<QName, SimpleNode<?>>> entries) {
- if (entries.isEmpty()) {
- return node.getValue();
- }
- final List<Node<?>> filteredNodes = new ArrayList<Node<?>>();
- for (final Node<?> scannedNode : node.getValue()) {
- if (!entries.contains(scannedNode.getNodeType())) {
- filteredNodes.add(scannedNode);
- }
- }
- return filteredNodes;
- }
-
-}
+++ /dev/null
-/*
- * 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.sal.dom.broker.impl;
-
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
-import org.opendaylight.yangtools.yang.common.QName;
-
-class GlobalRpcRegistration extends AbstractObjectRegistration<RpcImplementation> implements
- RpcRegistration {
- private final QName type;
- private SchemaAwareRpcBroker router;
-
- public GlobalRpcRegistration(final QName type, final RpcImplementation instance, final SchemaAwareRpcBroker router) {
- super(instance);
- this.type = type;
- this.router = router;
- }
-
- @Override
- public QName getType() {
- return type;
- }
-
- @Override
- protected void removeRegistration() {
- if (router != null) {
- router.remove(this);
- router = null;
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * 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.dom.broker.impl;
-
-import java.util.Collection;
-
-import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
-import org.opendaylight.controller.sal.dom.broker.spi.NotificationRouter;
-import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Multimaps;
-
-public class NotificationRouterImpl implements NotificationRouter {
- private static Logger log = LoggerFactory.getLogger(NotificationRouterImpl.class);
-
- private final Multimap<QName, MyListenerRegistration> listeners = Multimaps.synchronizedSetMultimap(HashMultimap.<QName, MyListenerRegistration>create());
-// private Registration<NotificationListener> defaultListener;
-
- private void sendNotification(CompositeNode notification) {
- final QName type = notification.getNodeType();
- final Collection<MyListenerRegistration> toNotify = listeners.get(type);
- log.trace("Publishing notification " + type);
-
- if ((toNotify == null) || toNotify.isEmpty()) {
- log.debug("No listener registered for handling of notification {}", type);
- return;
- }
-
- for (MyListenerRegistration listener : toNotify) {
- try {
- // FIXME: ensure that notification is immutable
- listener.getInstance().onNotification(notification);
- } catch (Exception e) {
- log.error("Uncaught exception in NotificationListener", e);
- }
- }
- }
-
- @Override
- public void publish(CompositeNode notification) {
- sendNotification(notification);
- }
-
- @Override
- public ListenerRegistration<NotificationListener> addNotificationListener(QName notification, NotificationListener listener) {
- MyListenerRegistration ret = new MyListenerRegistration(notification, listener);
- listeners.put(notification, ret);
- return ret;
- }
-
- private class MyListenerRegistration extends AbstractListenerRegistration<NotificationListener> {
-
- final QName type;
-
- public MyListenerRegistration(QName type, NotificationListener instance) {
- super(instance);
- this.type = type;
- }
-
- @Override
- protected void removeRegistration() {
- listeners.remove(type, this);
- }
- }
-}
+++ /dev/null
-/*
- * 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.sal.dom.broker.impl;
-
-import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-class RoutedRpcRegImpl extends AbstractObjectRegistration<RpcImplementation> implements
- RoutedRpcRegistration {
-
- private final QName type;
- private final RoutedRpcSelector router;
-
- public RoutedRpcRegImpl(final QName rpcType, final RpcImplementation implementation, final RoutedRpcSelector routedRpcSelector) {
- super(implementation);
- this.type = rpcType;
- router = routedRpcSelector;
- }
-
- @Override
- public void registerPath(final QName context, final YangInstanceIdentifier path) {
- router.addPath(context, path, this);
- }
-
- @Override
- public void unregisterPath(final QName context, final YangInstanceIdentifier path) {
- router.removePath(context, path, this);
- }
-
- @Override
- protected void removeRegistration() {
-
- }
-
- @Override
- public QName getType() {
- return type;
- }
-
-}
\ No newline at end of file
+++ /dev/null
-/*
- * 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.sal.dom.broker.impl;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.util.concurrent.ListenableFuture;
-
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import org.opendaylight.controller.md.sal.dom.broker.spi.rpc.RpcRoutingStrategy;
-import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
-import org.opendaylight.yangtools.concepts.Identifiable;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-class RoutedRpcSelector implements RpcImplementation, AutoCloseable, Identifiable<RpcRoutingContext> {
-
- private final RpcRoutingStrategy strategy;
- private final Set<QName> supportedRpcs;
- private final RpcRoutingContext identifier;
- final ConcurrentMap<YangInstanceIdentifier, RoutedRpcRegImpl> implementations = new ConcurrentHashMap<>();
- private final SchemaAwareRpcBroker router;
-
- public RoutedRpcSelector(final RpcRoutingStrategy strategy, final SchemaAwareRpcBroker router) {
- super();
- this.strategy = strategy;
- supportedRpcs = ImmutableSet.of(strategy.getIdentifier());
- identifier = RpcRoutingContext.create(strategy.getContext(), strategy.getIdentifier());
- this.router = router;
- }
-
- @Override
- public RpcRoutingContext getIdentifier() {
- return identifier;
- }
-
- @Override
- public void close() throws Exception {
-
- }
-
- @Override
- public Set<QName> getSupportedRpcs() {
- return supportedRpcs;
- }
-
- public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
- return new RoutedRpcRegImpl(rpcType, implementation, this);
- }
-
- @Override
- public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode input) {
- CompositeNode inputContainer = input.getFirstCompositeByName(QName.create(rpc,"input"));
- checkArgument(inputContainer != null, "Rpc payload must contain input element");
- SimpleNode<?> routeContainer = inputContainer.getFirstSimpleByName(strategy.getLeaf());
- checkArgument(routeContainer != null, "Leaf %s must be set with value", strategy.getLeaf());
- Object route = routeContainer.getValue();
- checkArgument(route instanceof YangInstanceIdentifier,
- "The routed node %s is not an instance identifier", route);
- RpcImplementation potential = null;
- if (route != null) {
- RoutedRpcRegImpl potentialReg = implementations.get(route);
- if (potentialReg != null) {
- potential = potentialReg.getInstance();
- }
- }
- if (potential == null) {
- return router.invokeRpc(rpc, (YangInstanceIdentifier) route, input);
- } else {
- return potential.invokeRpc(rpc, input);
- }
- }
-
- public void addPath(final QName context, final YangInstanceIdentifier path, final RoutedRpcRegImpl routedRpcRegImpl) {
- //checkArgument(strategy.getContext().equals(context),"Supplied context is not supported.");
- RoutedRpcRegImpl previous = implementations.put(path, routedRpcRegImpl);
- if (previous == null) {
- router.notifyPathAnnouncement(context,strategy.getIdentifier(), path);
- }
-
- }
-
- public void removePath(final QName context, final YangInstanceIdentifier path, final RoutedRpcRegImpl routedRpcRegImpl) {
- boolean removed = implementations.remove(path, routedRpcRegImpl);
- if (removed) {
- router.notifyPathWithdrawal(context, strategy.getIdentifier(), path);
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * 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.sal.dom.broker.impl;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
-import org.opendaylight.controller.md.sal.common.impl.routing.RoutingUtils;
-import org.opendaylight.controller.md.sal.dom.broker.spi.rpc.RpcRoutingStrategy;
-import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
-import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RpcImplementationUnavailableException;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
-import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter;
-import org.opendaylight.yangtools.concepts.Identifiable;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.util.ListenerRegistry;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * RPC broker responsible for routing requests to remote systems.
- */
-public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, RoutedRpcDefaultImplementation {
-
- private static final Logger LOG = LoggerFactory.getLogger(SchemaAwareRpcBroker.class);
-
-
- private final ListenerRegistry<RpcRegistrationListener> rpcRegistrationListeners = new ListenerRegistry<>();
- private final ListenerRegistry<RouteChangeListener<RpcRoutingContext, YangInstanceIdentifier>> routeChangeListeners = new ListenerRegistry<>();
-
-
- private final String identifier;
- private final ConcurrentMap<QName, RpcImplementation> implementations = new ConcurrentHashMap<>();
- private RpcImplementation defaultImplementation;
- private SchemaContextProvider schemaProvider;
- private RoutedRpcDefaultImplementation defaultDelegate;
-
- public SchemaAwareRpcBroker(final String identifier, final SchemaContextProvider schemaProvider) {
- super();
- this.identifier = identifier;
- this.schemaProvider = schemaProvider;
- }
-
- public RpcImplementation getDefaultImplementation() {
- return defaultImplementation;
- }
-
- public void setDefaultImplementation(final RpcImplementation defaultImplementation) {
- this.defaultImplementation = defaultImplementation;
- }
-
- public SchemaContextProvider getSchemaProvider() {
- return schemaProvider;
- }
-
- public void setSchemaProvider(final SchemaContextProvider schemaProvider) {
- this.schemaProvider = schemaProvider;
- }
-
- public RoutedRpcDefaultImplementation getRoutedRpcDefaultDelegate() {
- return defaultDelegate;
- }
-
- @Override
- public void setRoutedRpcDefaultDelegate(final RoutedRpcDefaultImplementation defaultDelegate) {
- this.defaultDelegate = defaultDelegate;
- }
-
- @Override
- public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
- checkArgument(rpcType != null, "RPC Type should not be null");
- checkArgument(implementation != null, "RPC Implementatoin should not be null");
- return getOrCreateRoutedRpcRouter(rpcType).addRoutedRpcImplementation(rpcType, implementation);
- }
-
- private RoutedRpcSelector getOrCreateRoutedRpcRouter(final QName rpcType) {
- RoutedRpcSelector potential = getRoutedRpcRouter(rpcType);
- if (potential != null) {
- return potential;
- }
- synchronized (implementations) {
- potential = getRoutedRpcRouter(rpcType);
- if (potential != null) {
- return potential;
- }
- RpcDefinition definition = findRpcDefinition(rpcType);
- RpcRoutingStrategy strategy = RpcRoutingStrategy.from(definition);
- checkState(strategy.isContextBasedRouted(), "Rpc %s is not routed.", rpcType);
- potential = new RoutedRpcSelector( strategy, this);
- implementations.put(rpcType, potential);
- return potential;
- }
- }
-
- private RoutedRpcSelector getRoutedRpcRouter(final QName rpcType) {
- RpcImplementation potential = implementations.get(rpcType);
- if (potential != null) {
- checkState(potential instanceof RoutedRpcSelector, "Rpc %s is not routed.", rpcType);
- return (RoutedRpcSelector) potential;
- }
- return null;
-
- }
-
- @Override
- public RpcRegistration addRpcImplementation(final QName rpcType, final RpcImplementation implementation)
- throws IllegalArgumentException {
- checkArgument(rpcType != null, "RPC Type should not be null");
- checkArgument(implementation != null, "RPC Implementatoin should not be null");
- checkState(!hasRpcImplementation(rpcType), "Implementation already registered");
- RpcDefinition definition = findRpcDefinition(rpcType);
- checkArgument(!RpcRoutingStrategy.from(definition).isContextBasedRouted(), "RPC Type must not be content routed.");
- GlobalRpcRegistration reg = new GlobalRpcRegistration(rpcType, implementation, this);
- final RpcImplementation previous = implementations.putIfAbsent(rpcType, implementation);
- Preconditions.checkState(previous == null, "Rpc %s is already registered.",rpcType);
- notifyRpcAdded(rpcType);
- return reg;
- }
-
- private void notifyRpcAdded(final QName rpcType) {
- for (ListenerRegistration<RpcRegistrationListener> listener : rpcRegistrationListeners) {
- try {
- listener.getInstance().onRpcImplementationAdded(rpcType);
- } catch (Exception ex) {
- LOG.error("Unhandled exception during invoking listener {}", listener.getInstance(), ex);
- }
-
- }
- }
-
- @Override
- public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(final RpcRegistrationListener listener) {
- ListenerRegistration<RpcRegistrationListener> reg = rpcRegistrationListeners.register(listener);
- for (QName impl : implementations.keySet()) {
- listener.onRpcImplementationAdded(impl);
- }
- return reg;
- }
-
- @Override
- public String getIdentifier() {
- return identifier;
- }
-
- @Override
- public Set<QName> getSupportedRpcs() {
- return ImmutableSet.copyOf(implementations.keySet());
- }
-
- @Override
- public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode input) {
- return findRpcImplemention(rpc).invokeRpc(rpc, input);
- }
-
- private RpcImplementation findRpcImplemention(final QName rpc) {
- checkArgument(rpc != null, "Rpc name should not be null");
- RpcImplementation potentialImpl = implementations.get(rpc);
- if (potentialImpl != null) {
- return potentialImpl;
- }
-
- potentialImpl = defaultImplementation;
- if( potentialImpl == null ) {
- throw new UnsupportedOperationException( "No implementation for this operation is available." );
- }
-
- return potentialImpl;
- }
-
- private boolean hasRpcImplementation(final QName rpc) {
- return implementations.containsKey(rpc);
- }
-
- private RpcDefinition findRpcDefinition(final QName rpcType) {
- checkArgument(rpcType != null, "Rpc name must be supplied.");
- checkState(schemaProvider != null, "Schema Provider is not available.");
- SchemaContext ctx = schemaProvider.getSchemaContext();
- checkState(ctx != null, "YANG Schema Context is not available.");
- Module module = ctx.findModuleByNamespaceAndRevision(rpcType.getNamespace(), rpcType.getRevision());
- checkState(module != null, "YANG Module is not available.");
- return findRpcDefinition(rpcType, module.getRpcs());
- }
-
- static private RpcDefinition findRpcDefinition(final QName rpcType, final Set<RpcDefinition> rpcs) {
- checkState(rpcs != null, "Rpc schema is not available.");
- for (RpcDefinition rpc : rpcs) {
- if (rpcType.equals(rpc.getQName())) {
- return rpc;
- }
- }
- throw new IllegalArgumentException("Supplied Rpc Type is not defined.");
- }
-
- @Override
- public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final YangInstanceIdentifier route, final CompositeNode input) {
- if (defaultDelegate == null) {
- return Futures.immediateFailedCheckedFuture(new RpcImplementationUnavailableException("No RPC implementation found"));
- }
-
- LOG.debug("Forwarding RPC {} path {} to delegate {}", rpc, route);
- return defaultDelegate.invokeRpc(rpc, route, input);
- }
-
- void remove(final GlobalRpcRegistration registration) {
- implementations.remove(registration.getType(), registration);
- }
-
- void notifyPathAnnouncement(final QName context, final QName identifier, final YangInstanceIdentifier path) {
- RpcRoutingContext contextWrapped = RpcRoutingContext.create(context, identifier);
- RouteChange<RpcRoutingContext, YangInstanceIdentifier> change = RoutingUtils.announcementChange(contextWrapped , path);
- for(ListenerRegistration<RouteChangeListener<RpcRoutingContext, YangInstanceIdentifier>> routeListener : routeChangeListeners) {
- try {
- routeListener.getInstance().onRouteChange(change);
- } catch (Exception e) {
- LOG.error("Unhandled exception during invoking onRouteChange for {}",routeListener.getInstance(),e);
- }
- }
-
- }
-
- void notifyPathWithdrawal(final QName context,final QName identifier, final YangInstanceIdentifier path) {
- RpcRoutingContext contextWrapped = RpcRoutingContext.create(context, identifier);
- RouteChange<RpcRoutingContext, YangInstanceIdentifier> change = RoutingUtils.removalChange(contextWrapped , path);
- for(ListenerRegistration<RouteChangeListener<RpcRoutingContext, YangInstanceIdentifier>> routeListener : routeChangeListeners) {
- try {
- routeListener.getInstance().onRouteChange(change);
- } catch (Exception e) {
- LOG.error("Unhandled exception during invoking onRouteChange for {}",routeListener.getInstance(),e);
- }
- }
- }
-
- @Override
- public <L extends RouteChangeListener<RpcRoutingContext, YangInstanceIdentifier>> ListenerRegistration<L> registerRouteChangeListener(
- final L listener) {
- ListenerRegistration<L> reg = routeChangeListeners.registerWithType(listener);
- RouteChange<RpcRoutingContext, YangInstanceIdentifier> initial = createInitialRouteChange();
- try {
- listener.onRouteChange(initial);
- } catch (Exception e) {
- LOG.error("Unhandled exception during sending initial route change event {} to {}",initial,listener, e);
- }
- return reg;
- }
-
- private RouteChange<RpcRoutingContext, YangInstanceIdentifier> createInitialRouteChange() {
- FluentIterable<RoutedRpcSelector> rpcSelectors = FluentIterable.from(implementations.values()).filter(RoutedRpcSelector.class);
-
-
- ImmutableMap.Builder<RpcRoutingContext, Set<YangInstanceIdentifier>> announcements = ImmutableMap.builder();
- ImmutableMap.Builder<RpcRoutingContext, Set<YangInstanceIdentifier>> removals = ImmutableMap.builder();
- for (RoutedRpcSelector routedRpcSelector : rpcSelectors) {
- final RpcRoutingContext context = routedRpcSelector.getIdentifier();
- final Set<YangInstanceIdentifier> paths = ImmutableSet.copyOf(routedRpcSelector.implementations.keySet());
- announcements.put(context, paths);
- }
- return RoutingUtils.change(announcements.build(), removals.build());
- }
-}
package org.opendaylight.controller.sal.dom.broker.osgi;
+import java.util.Map;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBrokerExtension;
import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
return getDelegate().createTransactionChain(listener);
}
+ @Override
+ public Map<Class<? extends DOMDataBrokerExtension>, DOMDataBrokerExtension> getSupportedExtensions() {
+ return getDelegate().getSupportedExtensions();
+ }
}
+++ /dev/null
-/*
- * 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.sal.dom.broker.osgi;
-
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
-import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.osgi.framework.ServiceReference;
-
-@Deprecated
-public class DataBrokerServiceProxy extends AbstractBrokerServiceProxy<DataBrokerService> implements DataBrokerService {
-
- public DataBrokerServiceProxy(ServiceReference<DataBrokerService> ref, DataBrokerService delegate) {
- super(ref, delegate);
- }
-
- public ListenerRegistration<DataChangeListener> registerDataChangeListener(YangInstanceIdentifier path,
- DataChangeListener listener) {
- return addRegistration(getDelegate().registerDataChangeListener(path, listener));
- }
-
- public CompositeNode readConfigurationData(YangInstanceIdentifier path) {
- return getDelegate().readConfigurationData(path);
- }
-
- public CompositeNode readOperationalData(YangInstanceIdentifier path) {
- return getDelegate().readOperationalData(path);
- }
-
- public DataModificationTransaction beginTransaction() {
- return getDelegate().beginTransaction();
- }
-}
+++ /dev/null
-/*
- * 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.sal.dom.broker.osgi;
-
-import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.controller.sal.common.DataStoreIdentifier;
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
-import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.core.api.data.DataProviderService;
-import org.opendaylight.controller.sal.core.api.data.DataValidator;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.osgi.framework.ServiceReference;
-
-@Deprecated
-public class DataProviderServiceProxy extends AbstractBrokerServiceProxy<DataProviderService> implements DataProviderService {
-
- public DataProviderServiceProxy(final ServiceReference<DataProviderService> ref, final DataProviderService delegate) {
- super(ref, delegate);
- }
-
- @Override
- public ListenerRegistration<DataChangeListener> registerDataChangeListener(final YangInstanceIdentifier path,
- final DataChangeListener listener) {
- return addRegistration(getDelegate().registerDataChangeListener(path, listener));
- }
-
- @Override
- public CompositeNode readConfigurationData(final YangInstanceIdentifier path) {
- return getDelegate().readConfigurationData(path);
- }
-
- @Override
- public CompositeNode readOperationalData(final YangInstanceIdentifier path) {
- return getDelegate().readOperationalData(path);
- }
-
- @Override
- public DataModificationTransaction beginTransaction() {
- return getDelegate().beginTransaction();
- }
-
- @Override
- public void addRefresher(final DataStoreIdentifier store, final DataRefresher refresher) {
- getDelegate().addRefresher(store, refresher);
- }
-
- @Override
- public void addValidator(final DataStoreIdentifier store, final DataValidator validator) {
- getDelegate().addValidator(store, validator);
- }
-
- @Override
- public Registration registerCommitHandler(
- final YangInstanceIdentifier path, final DataCommitHandler<YangInstanceIdentifier, CompositeNode> commitHandler) {
- return addRegistration(getDelegate().registerCommitHandler(path, commitHandler));
- }
-
- @Override
- public Registration registerConfigurationReader(
- final YangInstanceIdentifier path, final DataReader<YangInstanceIdentifier, CompositeNode> reader) {
- return addRegistration(getDelegate().registerConfigurationReader(path, reader));
- }
-
- @Override
- public Registration registerOperationalReader(
- final YangInstanceIdentifier path, final DataReader<YangInstanceIdentifier, CompositeNode> reader) {
- return addRegistration(getDelegate().registerOperationalReader(path, reader));
- }
-
- @Override
- public void removeRefresher(final DataStoreIdentifier store, final DataRefresher refresher) {
- getDelegate().removeRefresher(store, refresher);
- }
-
- @Override
- public void removeValidator(final DataStoreIdentifier store, final DataValidator validator) {
- getDelegate().removeValidator(store, validator);
- }
-
- @Override
- public ListenerRegistration<RegistrationListener<DataCommitHandlerRegistration<YangInstanceIdentifier, CompositeNode>>> registerCommitHandlerListener(
- final RegistrationListener<DataCommitHandlerRegistration<YangInstanceIdentifier, CompositeNode>> commitHandlerListener) {
- return addRegistration(getDelegate().registerCommitHandlerListener(commitHandlerListener));
- }
-}
+++ /dev/null
-/*
- * 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.sal.dom.broker.osgi;
-
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.osgi.framework.ServiceReference;
-
-@Deprecated
-public class MountProviderServiceProxy extends AbstractBrokerServiceProxy<MountProvisionService> implements MountProvisionService{
-
-
- public MountProviderServiceProxy(ServiceReference<MountProvisionService> ref, MountProvisionService delegate) {
- super(ref, delegate);
- }
-
- @Override
- public MountProvisionInstance getMountPoint(YangInstanceIdentifier path) {
- return getDelegate().getMountPoint(path);
- }
-
- @Override
- public MountProvisionInstance createMountPoint(YangInstanceIdentifier path) {
- return getDelegate().createMountPoint(path);
- }
-
- @Override
- public MountProvisionInstance createOrGetMountPoint(YangInstanceIdentifier path) {
- return getDelegate().createOrGetMountPoint(path);
- }
-
- @Override
- public ListenerRegistration<MountProvisionListener> registerProvisionListener(MountProvisionListener listener) {
- return getDelegate().registerProvisionListener(listener);
- }
-}
+++ /dev/null
-/*
- * 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.sal.dom.broker.osgi;
-
-import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
-import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.osgi.framework.ServiceReference;
-
-public class NotificationPublishServiceProxy extends AbstractBrokerServiceProxy<NotificationPublishService> implements NotificationPublishService {
-
- public NotificationPublishServiceProxy(ServiceReference<NotificationPublishService> ref,
- NotificationPublishService delegate) {
- super(ref, delegate);
- }
-
- @Override
- public ListenerRegistration<NotificationListener> addNotificationListener(QName notification, NotificationListener listener) {
- return addRegistration(getDelegate().addNotificationListener(notification, listener));
-
- }
-
- @Override
- public void publish(CompositeNode notification) {
- getDelegate().publish(notification);
- }
-}
+++ /dev/null
-/*
- * 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.sal.dom.broker.osgi;
-
-import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
-import org.opendaylight.controller.sal.core.api.notify.NotificationService;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.osgi.framework.ServiceReference;
-
-public class NotificationServiceProxy extends AbstractBrokerServiceProxy<NotificationService> implements
- NotificationService {
-
- public NotificationServiceProxy(ServiceReference<NotificationService> ref, NotificationService delegate) {
- super(ref, delegate);
- }
-
- @Override
- public ListenerRegistration<NotificationListener> addNotificationListener(QName notification, NotificationListener listener) {
- return addRegistration(getDelegate().addNotificationListener(notification, listener));
- }
-}
*/
package org.opendaylight.controller.sal.dom.broker.osgi;
-import java.util.Arrays;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
import org.opendaylight.controller.sal.core.api.BrokerService;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.core.api.data.DataProviderService;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
-import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
-import org.opendaylight.controller.sal.core.api.notify.NotificationService;
import org.osgi.framework.ServiceReference;
+import java.util.Arrays;
+
@SuppressWarnings("unchecked")
public class ProxyFactory {
return ((T) _createProxyImpl);
}
- @Deprecated
- private static Object _createProxyImpl(final ServiceReference<?> ref,
- final DataBrokerService service) {
-
- return new DataBrokerServiceProxy(
- ((ServiceReference<DataBrokerService>) ref), service);
- }
-
- @Deprecated
- private static Object _createProxyImpl(final ServiceReference<?> ref,
- final DataProviderService service) {
-
- return new DataProviderServiceProxy(
- ((ServiceReference<DataProviderService>) ref), service);
- }
-
- private static Object _createProxyImpl(final ServiceReference<?> ref,
- final NotificationPublishService service) {
-
- return new NotificationPublishServiceProxy(
- ((ServiceReference<NotificationPublishService>) ref), service);
- }
-
- private static Object _createProxyImpl(final ServiceReference<?> ref,
- final NotificationService service) {
-
- return new NotificationServiceProxy(
- ((ServiceReference<NotificationService>) ref), service);
- }
-
- @Deprecated
- private static Object _createProxyImpl(final ServiceReference<?> ref,
- final MountProvisionService service) {
-
- return new MountProviderServiceProxy(
- ((ServiceReference<MountProvisionService>) ref), service);
- }
-
private static Object _createProxyImpl(final ServiceReference<?> ref,
final DOMMountPointService service) {
service);
}
- private static Object _createProxyImpl(final ServiceReference<?> ref,
- final RpcProvisionRegistry service) {
-
- return new RpcProvisionRegistryProxy(
- ((ServiceReference<RpcProvisionRegistry>) ref), service);
- }
-
private static DOMDataBrokerProxy _createProxyImpl(
final ServiceReference<?> ref, final DOMDataBroker service) {
if (service instanceof DOMDataBroker) {
return _createProxyImpl(ref, (DOMDataBroker) service);
- } else if (service instanceof RpcProvisionRegistry) {
- return _createProxyImpl(ref, (RpcProvisionRegistry) service);
- } else if (service instanceof DataProviderService) {
- return _createProxyImpl(ref, (DataProviderService) service);
- } else if (service instanceof MountProvisionService) {
- return _createProxyImpl(ref, (MountProvisionService) service);
- } else if (service instanceof NotificationPublishService) {
- return _createProxyImpl(ref, (NotificationPublishService) service);
- } else if (service instanceof DataBrokerService) {
- return _createProxyImpl(ref, (DataBrokerService) service);
} else if (service instanceof SchemaService) {
return _createProxyImpl(ref, (SchemaService) service);
- } else if (service instanceof NotificationService) {
- return _createProxyImpl(ref, (NotificationService) service);
} else if (service instanceof DOMMountPointService) {
return _createProxyImpl(ref, (DOMMountPointService) service);
} else if (service != null) {
+++ /dev/null
-/*
- * 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.dom.broker.osgi;
-
-import java.util.Set;
-
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
-import org.opendaylight.controller.sal.core.api.Broker;
-import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.osgi.framework.ServiceReference;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-public class RpcProvisionRegistryProxy extends AbstractBrokerServiceProxy<RpcProvisionRegistry> implements RpcProvisionRegistry {
-
- public RpcProvisionRegistryProxy(final ServiceReference<RpcProvisionRegistry> ref, final RpcProvisionRegistry delegate) {
- super(ref, delegate);
- }
-
- @Override
- public Broker.RpcRegistration addRpcImplementation(final QName rpcType, final RpcImplementation implementation) throws IllegalArgumentException {
- return getDelegate().addRpcImplementation(rpcType, implementation);
- }
-
- @Override
- public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(final RpcRegistrationListener listener) {
- return getDelegate().addRpcRegistrationListener(listener);
- }
-
- @Override
- public Broker.RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
- return getDelegate().addRoutedRpcImplementation(rpcType, implementation);
- }
-
- @Override
- public void setRoutedRpcDefaultDelegate(final RoutedRpcDefaultImplementation defaultImplementation) {
- getDelegate().setRoutedRpcDefaultDelegate(defaultImplementation);
- }
-
- @Override
- public <L extends RouteChangeListener<RpcRoutingContext, YangInstanceIdentifier>> ListenerRegistration<L> registerRouteChangeListener(final L listener) {
- return getDelegate().registerRouteChangeListener(listener);
- }
-
- @Override
- public Set<QName> getSupportedRpcs() {
- return getDelegate().getSupportedRpcs();
- }
-
- @Override
- public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode input) {
- return getDelegate().invokeRpc(rpc, input);
- }
-}
+++ /dev/null
-/*
- * 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.sal.dom.broker.spi;
-
-import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-public interface NotificationRouter {
-
- void publish(CompositeNode notification);
-
- /**
- * Registers a notification listener for supplied notification type.
- *
- * @param notification
- * @param listener
- */
- ListenerRegistration<NotificationListener> addNotificationListener(QName notification,
- NotificationListener listener);
-
-}
+++ /dev/null
-/*
- * 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.sal.dom.broker.spi;
-
-import java.util.Map;
-
-import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-public interface RoutedRpcProcessor extends RpcImplementation {
-
- RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation);
-
- QName getRpcType();
-
- Map<YangInstanceIdentifier,RpcImplementation> getRoutes();
-
- RpcImplementation getDefaultRoute();
-
-}
+++ /dev/null
-/*
- * 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.sal.dom.broker.spi;
-
-import java.util.Set;
-
-import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.opendaylight.yangtools.yang.common.QName;
-
-public interface RpcRouter extends RpcProvisionRegistry, RpcImplementation {
-
- @Override
- public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation);
-
- @Override
- public RpcRegistration addRpcImplementation(QName rpcType, RpcImplementation implementation)
- throws IllegalArgumentException;
-
- @Override
- public Set<QName> getSupportedRpcs();
-}
augment "/config:modules/config:module/config:configuration" {
case dom-broker-impl {
when "/config:modules/config:module/config:type = 'dom-broker-impl'";
- container data-store {
- uses config:service-ref {
- refine type {
- mandatory false;
- config:required-identity sal:dom-data-store;
- }
- }
- }
container async-data-broker {
uses config:service-ref {
+++ /dev/null
-/*
- * 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.sal.dom.broker;
-
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import com.google.common.base.Optional;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
-import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
-import org.opendaylight.controller.md.sal.dom.api.DOMService;
-import org.opendaylight.controller.md.sal.dom.broker.impl.mount.DOMMountPointServiceImpl;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener;
-import org.opendaylight.yangtools.concepts.ObjectRegistration;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Deprecated
-public class BackwardsCompatibleMountPointManagerTest {
- private static final Logger log = LoggerFactory.getLogger(BackwardsCompatibleMountPointManagerTest.class);
-
- @Mock
- private DOMMountPointServiceImpl domMountPointService;
- @Mock
- private DOMMountPointService.DOMMountPointBuilder mountBuilder;
-
- private BackwardsCompatibleMountPointManager compatibleMountPointManager;
- static final QName qName = QName.create("namespace", "12-12-1212", "mount");
- static final YangInstanceIdentifier id = YangInstanceIdentifier.of(qName);
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- stubMountService();
- compatibleMountPointManager = new BackwardsCompatibleMountPointManager(domMountPointService);
- }
-
- @Test
- public void testCreateMountpointAlreadyCreated() throws Exception {
- compatibleMountPointManager.createMountPoint(id);
- verify(domMountPointService).createMountPoint(id);
- verify(mountBuilder, times(3)).addService(any(Class.class), any(DOMService.class));
- verify(mountBuilder).addInitialSchemaContext(any(SchemaContext.class));
-
- try {
- compatibleMountPointManager.createMountPoint(id);
- } catch (final IllegalStateException e) {
- log.debug("", e);
- return;
- }
- fail("Should fail to create duplicate mount");
- }
-
- @Test
- public void testCreateMountpointGetOrCreate() throws Exception {
- compatibleMountPointManager = new BackwardsCompatibleMountPointManager(new DOMMountPointServiceImpl());
-
- final MountProvisionListener listener = new MountProvisionListener() {
- public int createdMounts = 0;
-
- @Override
- public void onMountPointCreated(final YangInstanceIdentifier path) {
- if(createdMounts++ > 1 ) {
- fail("Only one mount point should have been created");
- }
- }
-
- @Override
- public void onMountPointRemoved(final YangInstanceIdentifier path) {}
- };
-
- compatibleMountPointManager.registerProvisionListener(listener);
-
- final MountProvisionInstance m1 = compatibleMountPointManager.createOrGetMountPoint(id);
- m1.setSchemaContext(mockSchemaContext());
- compatibleMountPointManager.createOrGetMountPoint(id);
- compatibleMountPointManager.createOrGetMountPoint(id);
- }
-
- private void stubMountService() {
- doReturn(mockMountPointBuilder()).when(domMountPointService).createMountPoint(any(YangInstanceIdentifier.class));
- doReturn(Optional.of(mockMountPoint())).when(domMountPointService).getMountPoint(any(YangInstanceIdentifier.class));
- }
-
- private DOMMountPoint mockMountPoint() {
- final DOMMountPoint mock = mock(DOMMountPoint.class);
- doAnswer(new Answer<Object>() {
- @Override
- public Object answer(final InvocationOnMock invocation) throws Throwable {
- return Optional.of(mock(((Class<?>) invocation.getArguments()[0])));
- }
- }).when(mock).getService(any(Class.class));
- doReturn(mockSchemaContext()).when(mock).getSchemaContext();
- return mock;
- }
-
- static SchemaContext mockSchemaContext() {
- final SchemaContext mock = mock(SchemaContext.class);
- doReturn(qName).when(mock).getQName();
- doReturn("schema").when(mock).toString();
- doReturn(mock(DataSchemaNode.class)).when(mock).getDataChildByName(any(QName.class));
- return mock;
- }
-
- private DOMMountPointService.DOMMountPointBuilder mockMountPointBuilder() {
- doReturn(mountBuilder).when(mountBuilder).addService(any(Class.class), any(DOMService.class));
- doReturn(mockObjectRegistration()).when(mountBuilder).register();
- doReturn(mountBuilder).when(mountBuilder).addInitialSchemaContext(any(SchemaContext.class));
- return mountBuilder;
- }
-
- private ObjectRegistration<?> mockObjectRegistration() {
- return mock(ObjectRegistration.class);
- }
-
-}
+++ /dev/null
-/*
- * 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.sal.dom.broker;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.AbstractMap;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
-import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
-import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.core.api.data.DataProviderService;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Deprecated
-public class BackwardsCompatibleMountPointTest {
- private static final Logger log = LoggerFactory.getLogger(BackwardsCompatibleMountPointManagerTest.class);
-
- private static final YangInstanceIdentifier id = BackwardsCompatibleMountPointManagerTest.id;
- private final NormalizedNode<?, ?> normalizedNode = mockNormalizedNode();
- private final CompositeNode compositeNode = mockCompositeNode();
-
- @Mock
- private DataProviderService oldBroker;
- @Mock
- private SchemaContextProvider schemaContextProvider;
- @Mock
- private DataModificationTransaction mockTx;
-
- private BackwardsCompatibleMountPoint.BackwardsCompatibleDomStore backwardsCompatibleDomStore;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- stubSchemaProvider();
- stubOldBroker();
- backwardsCompatibleDomStore = new BackwardsCompatibleMountPoint.BackwardsCompatibleDomStore(oldBroker, schemaContextProvider);
- }
-
- private void stubOldBroker() {
- doReturn(compositeNode).when(oldBroker).readConfigurationData(id);
- doReturn(compositeNode).when(oldBroker).readOperationalData(id);
- doReturn(mockTx).when(oldBroker).beginTransaction();
- doNothing().when(mockTx).putConfigurationData(id, compositeNode);
- doNothing().when(mockTx).putOperationalData(id, compositeNode);
- doReturn(com.google.common.util.concurrent.Futures.immediateFuture(RpcResultBuilder.success(TransactionStatus.COMMITED))).when(mockTx).commit();
- }
-
- private CompositeNode mockCompositeNode() {
- final CompositeNode mock = mock(CompositeNode.class);
- doReturn("node").when(mock).toString();
- return mock;
- }
-
- private void stubSchemaProvider() {
- doReturn(BackwardsCompatibleMountPointManagerTest.mockSchemaContext()).when(schemaContextProvider).getSchemaContext();
- }
-
- @Test
- public void testBackwardsCompatibleBroker() throws Exception {
- backwardsCompatibleDomStore.newReadOnlyTransaction();
- backwardsCompatibleDomStore.newWriteOnlyTransaction();
- backwardsCompatibleDomStore.newReadWriteTransaction();
- }
-
- @Test
- public void testReadTransaction() throws Exception {
- final BackwardsCompatibleMountPoint.BackwardsCompatibleDomStore.BackwardsCompatibleReadTransaction tx =
- new BackwardsCompatibleMountPoint.BackwardsCompatibleDomStore.BackwardsCompatibleReadTransaction(oldBroker, mockNormalizer());
-
- ListenableFuture<Optional<NormalizedNode<?, ?>>> read = tx.read(LogicalDatastoreType.CONFIGURATION, id);
- assertEquals(normalizedNode, read.get().get());
- verify(oldBroker).readConfigurationData(id);
-
- read = tx.read(LogicalDatastoreType.OPERATIONAL, id);
- assertEquals(normalizedNode, read.get().get());
-
- verify(oldBroker).readOperationalData(id);
- }
-
- @Test
- public void testReadWriteTransactionOperational() throws Exception {
- final BackwardsCompatibleMountPoint.BackwardsCompatibleDomStore.BackwardsCompatibleWriteTransaction tx =
- new BackwardsCompatibleMountPoint.BackwardsCompatibleDomStore.BackwardsCompatibleWriteTransaction(oldBroker, mockNormalizer());
-
- verify(oldBroker).beginTransaction();
-
- tx.put(LogicalDatastoreType.CONFIGURATION, id, normalizedNode);
- verify(mockTx).putConfigurationData(id, compositeNode);
-
- tx.put(LogicalDatastoreType.CONFIGURATION, id, normalizedNode);
- verify(mockTx, times(2)).putConfigurationData(id, compositeNode);
-
- tx.commit();
- verify(mockTx).commit();
- }
-
-
- @Test
- public void testCannotPutOperational() throws Exception {
- final BackwardsCompatibleMountPoint.BackwardsCompatibleDomStore.BackwardsCompatibleWriteTransaction tx =
- new BackwardsCompatibleMountPoint.BackwardsCompatibleDomStore.BackwardsCompatibleWriteTransaction(oldBroker, mockNormalizer());
-
- try {
- tx.put(LogicalDatastoreType.OPERATIONAL, id, normalizedNode);
- } catch (IllegalArgumentException e) {
- // Cannot put operational data
- log.debug("", e);
- return;
- }
-
- fail("Should fail when putting operational data");
- }
-
- private DataNormalizer mockNormalizer() throws DataNormalizationException {
- final DataNormalizer mock = mock(DataNormalizer.class);
- doReturn(new AbstractMap.SimpleEntry<YangInstanceIdentifier, NormalizedNode<?, ?>>(id, normalizedNode))
- .when(mock).toNormalized(any(YangInstanceIdentifier.class), any(CompositeNode.class));
- doReturn(compositeNode).when(mock).toLegacy(any(YangInstanceIdentifier.class), any(NormalizedNode.class));
- doReturn(id).when(mock).toLegacy(any(YangInstanceIdentifier.class));
- return mock;
- }
-
- private NormalizedNode<?, ?> mockNormalizedNode() {
- final NormalizedNode<?, ?> mock = mock(NormalizedNode.class);
- doReturn("mockNormalizedNode").when(mock).toString();
- return mock;
- }
-}
package org.opendaylight.controller.md.sal.dom.spi;
import com.google.common.collect.ForwardingObject;
+import java.util.Map;
import javax.annotation.Nonnull;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBrokerExtension;
import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
public DOMTransactionChain createTransactionChain(final TransactionChainListener listener) {
return delegate().createTransactionChain(listener);
}
+
+ @Override
+ public Map<Class<? extends DOMDataBrokerExtension>, DOMDataBrokerExtension> getSupportedExtensions() {
+ return delegate().getSupportedExtensions();
+ }
}
*/
package org.opendaylight.controller.sal.core.spi;
-import java.util.concurrent.Future;
import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
import org.opendaylight.controller.sal.core.api.BrokerService;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
public abstract class ForwardingConsumerSession implements ConsumerSession {
return delegate().isClosed();
}
- @Override
- @Deprecated
- public Future<RpcResult<CompositeNode>> rpc(QName arg0, CompositeNode arg1) {
- return delegate().rpc(arg0, arg1);
- }
-
-
}
package org.opendaylight.controller.sal.core.spi;
-import java.util.Set;
-import java.util.concurrent.Future;
import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
import org.opendaylight.controller.sal.core.api.BrokerService;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
public abstract class ForwardingProviderSession implements ProviderSession {
-
protected abstract ProviderSession delegate();
- @Override
- @Deprecated
- public RoutedRpcRegistration addMountedRpcImplementation(QName arg0, RpcImplementation arg1) {
- return delegate().addMountedRpcImplementation(arg0, arg1);
- }
-
- @Override
- @Deprecated
- public RoutedRpcRegistration addRoutedRpcImplementation(QName arg0, RpcImplementation arg1) {
- return delegate().addRoutedRpcImplementation(arg0, arg1);
- }
-
- @Override
- @Deprecated
- public RpcRegistration addRpcImplementation(QName arg0, RpcImplementation arg1)
- throws IllegalArgumentException {
- return delegate().addRpcImplementation(arg0, arg1);
- }
-
- @Deprecated
- @Override
- public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(
- RpcRegistrationListener arg0) {
- return delegate().addRpcRegistrationListener(arg0);
- }
-
@Override
public void close() {
delegate().close();
return delegate().getService(arg0);
}
- @Override
- public Set<QName> getSupportedRpcs() {
- return delegate().getSupportedRpcs();
- }
-
@Override
public boolean isClosed() {
return delegate().isClosed();
}
- @Override
- public Future<RpcResult<CompositeNode>> rpc(QName arg0, CompositeNode arg1) {
- return delegate().rpc(arg0, arg1);
- }
-
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class JDBCProxy implements InvocationHandler {
-
+ private static final Logger LOG = LoggerFactory.getLogger(JDBCProxy.class);
private Object myObject = null;
private Class<?> myObjectClass = null;
}
@Override
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- System.err.println("Class " + this.myObjectClass.getSimpleName()
- + " Method " + method.getName());
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ LOG.debug("Class {} Method {}", this.myObjectClass.getSimpleName(), method.getName());
return method.invoke(this.myObject, args);
}
-
}
public class JDBCResultSet implements Serializable, ResultSet,
ResultSetMetaData {
private static final long serialVersionUID = -7450200738431047057L;
+ private static final ClassLoader CLASS_LOADER = JDBCResultSet.class.getClassLoader();
+ private static final Class<?>[] PROXY_INTERFACES = new Class[] { ResultSet.class };
+ private static int nextID = 0;
private String sql = null;
private List<XSQLBluePrintNode> tablesInQuery = new ArrayList<XSQLBluePrintNode>();
private transient Map<String, Object> currentRecord = null;
private boolean finished = false;
private int id = 0;
- private static Integer nextID = new Integer(0);
public int numberOfTasks = 0;
private Map<String, Map<XSQLColumn, List<XSQLCriteria>>> criteria = new ConcurrentHashMap<String, Map<XSQLColumn, List<XSQLCriteria>>>();
private Exception err = null;
private transient Map<String,JDBCResultSet> subQueries = new HashMap<String,JDBCResultSet>();
public ResultSet getProxy() {
- return (ResultSet) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] {ResultSet.class }, new JDBCProxy(this));
+ return (ResultSet) Proxy.newProxyInstance(CLASS_LOADER, PROXY_INTERFACES, new JDBCProxy(this));
}
public void setSQL(String _sql) {
import java.util.Collection;
import java.util.Map.Entry;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.dom.spi.RegistrationTreeSnapshot;
import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.Builder;
import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.SimpleEventFactory;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerWalker;
import org.opendaylight.yangtools.util.concurrent.NotificationManager;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
* Resolves and submits notification tasks to the specified manager.
*/
public synchronized void resolve(final NotificationManager<DataChangeListenerRegistration<?>, DOMImmutableDataChangeEvent> manager) {
- try (final ListenerWalker w = listenerRoot.getWalker()) {
+ try (final RegistrationTreeSnapshot<DataChangeListenerRegistration<?>> w = listenerRoot.takeSnapshot()) {
// Defensive: reset internal state
collectedEvents = ArrayListMultimap.create();
* @return True if the subtree changed, false otherwise
*/
private boolean resolveAnyChangeEvent(final ResolveDataChangeState state, final DataTreeCandidateNode node) {
- if (node.getModificationType() != ModificationType.UNMODIFIED &&
- !node.getDataAfter().isPresent() && !node.getDataBefore().isPresent()) {
+ final Optional<NormalizedNode<?, ?>> maybeBefore = node.getDataBefore();
+ final Optional<NormalizedNode<?, ?>> maybeAfter = node.getDataAfter();
+ final ModificationType type = node.getModificationType();
+
+ if (type != ModificationType.UNMODIFIED && !maybeAfter.isPresent() && !maybeBefore.isPresent()) {
LOG.debug("Modification at {} has type {}, but no before- and after-data. Assuming unchanged.",
- state.getPath(), node.getModificationType());
+ state.getPath(), type);
return false;
}
// no before and after state is present
- switch (node.getModificationType()) {
+ switch (type) {
case SUBTREE_MODIFIED:
return resolveSubtreeChangeEvent(state, node);
case MERGE:
case WRITE:
- Preconditions.checkArgument(node.getDataAfter().isPresent(),
- "Modification at {} has type {} but no after-data", state.getPath(), node.getModificationType());
- if (!node.getDataBefore().isPresent()) {
+ Preconditions.checkArgument(maybeAfter.isPresent(),
+ "Modification at {} has type {} but no after-data", state.getPath(), type);
+ if (!maybeBefore.isPresent()) {
@SuppressWarnings({ "unchecked", "rawtypes" })
- final NormalizedNode<PathArgument, ?> afterNode = (NormalizedNode)node.getDataAfter().get();
+ final NormalizedNode<PathArgument, ?> afterNode = (NormalizedNode)maybeAfter.get();
resolveSameEventRecursivelly(state, afterNode, DOMImmutableDataChangeEvent.getCreateEventFactory());
return true;
}
- return resolveReplacedEvent(state, node.getDataBefore().get(), node.getDataAfter().get());
+ return resolveReplacedEvent(state, maybeBefore.get(), maybeAfter.get());
case DELETE:
- Preconditions.checkArgument(node.getDataBefore().isPresent(),
- "Modification at {} has type {} but no before-data", state.getPath(), node.getModificationType());
+ Preconditions.checkArgument(maybeBefore.isPresent(),
+ "Modification at {} has type {} but no before-data", state.getPath(), type);
@SuppressWarnings({ "unchecked", "rawtypes" })
- final NormalizedNode<PathArgument, ?> beforeNode = (NormalizedNode)node.getDataBefore().get();
+ final NormalizedNode<PathArgument, ?> beforeNode = (NormalizedNode)maybeBefore.get();
resolveSameEventRecursivelly(state, beforeNode, DOMImmutableDataChangeEvent.getRemoveEventFactory());
return true;
case UNMODIFIED:
return false;
}
- throw new IllegalStateException(String.format("Unhandled node state %s at %s", node.getModificationType(), state.getPath()));
+ throw new IllegalStateException(String.format("Unhandled node state %s at %s", type, state.getPath()));
}
private boolean resolveReplacedEvent(final ResolveDataChangeState state,
}
private boolean resolveSubtreeChangeEvent(final ResolveDataChangeState state, final DataTreeCandidateNode modification) {
- Preconditions.checkArgument(modification.getDataBefore().isPresent(), "Subtree change with before-data not present at path %s", state.getPath());
- Preconditions.checkArgument(modification.getDataAfter().isPresent(), "Subtree change with after-data not present at path %s", state.getPath());
+ final Optional<NormalizedNode<?, ?>> maybeBefore = modification.getDataBefore();
+ final Optional<NormalizedNode<?, ?>> maybeAfter = modification.getDataAfter();
+
+ Preconditions.checkArgument(maybeBefore.isPresent(), "Subtree change with before-data not present at path %s", state.getPath());
+ Preconditions.checkArgument(maybeAfter.isPresent(), "Subtree change with after-data not present at path %s", state.getPath());
if (!state.needsProcessing()) {
LOG.trace("Not processing modified subtree {}", state.getPath());
}
}
- final NormalizedNode<?, ?> before = modification.getDataBefore().get();
- final NormalizedNode<?, ?> after = modification.getDataAfter().get();
+ final NormalizedNode<?, ?> before = maybeBefore.get();
+ final NormalizedNode<?, ?> after = maybeAfter.get();
if (scope != null) {
DOMImmutableDataChangeEvent one = DOMImmutableDataChangeEvent.builder(scope).addUpdated(state.getPath(), before, after).build();
*/
package org.opendaylight.controller.md.sal.dom.store.impl;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
-
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.dom.spi.RegistrationTreeNode;
import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.Builder;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Multimap;
-
/**
* Recursion state used in {@link ResolveDataChangeEventsTask}. Instances of this
* method track which listeners are affected by a particular change node. It takes
*/
private final Collection<Builder> inheritedOne;
private final YangInstanceIdentifier nodeId;
- private final Collection<ListenerNode> nodes;
+ private final Collection<RegistrationTreeNode<DataChangeListenerRegistration<?>>> nodes;
private final Map<DataChangeListenerRegistration<?>, Builder> subBuilders;
private final Map<DataChangeListenerRegistration<?>, Builder> oneBuilders;
private ResolveDataChangeState(final YangInstanceIdentifier nodeId,
final Iterable<Builder> inheritedSub, final Collection<Builder> inheritedOne,
- final Collection<ListenerNode> nodes) {
+ final Collection<RegistrationTreeNode<DataChangeListenerRegistration<?>>> nodes) {
this.nodeId = Preconditions.checkNotNull(nodeId);
this.nodes = Preconditions.checkNotNull(nodes);
this.inheritedSub = Preconditions.checkNotNull(inheritedSub);
final Map<DataChangeListenerRegistration<?>, Builder> sub = new HashMap<>();
final Map<DataChangeListenerRegistration<?>, Builder> one = new HashMap<>();
final Map<DataChangeListenerRegistration<?>, Builder> base = new HashMap<>();
- for (ListenerNode n : nodes) {
- for (DataChangeListenerRegistration<?> l : n.getListeners()) {
+ for (RegistrationTreeNode<DataChangeListenerRegistration<?>> n : nodes) {
+ for (DataChangeListenerRegistration<?> l : n.getRegistrations()) {
final Builder b = DOMImmutableDataChangeEvent.builder(DataChangeScope.BASE);
switch (l.getScope()) {
case BASE:
* Create an initial state handle at a particular root node.
*
* @param rootId root instance identifier
- * @param root root node
+ * @param registrationTreeNode root node
* @return
*/
- public static ResolveDataChangeState initial(final YangInstanceIdentifier rootId, final ListenerNode root) {
+ public static ResolveDataChangeState initial(final YangInstanceIdentifier rootId, final RegistrationTreeNode<DataChangeListenerRegistration<?>> registrationTreeNode) {
return new ResolveDataChangeState(rootId, Collections.<Builder>emptyList(),
- Collections.<Builder>emptyList(), Collections.singletonList(root));
+ Collections.<Builder>emptyList(), Collections.singletonList(registrationTreeNode));
}
/**
LOG.trace("Collected events {}", map);
}
- private static Collection<ListenerNode> getListenerChildrenWildcarded(final Collection<ListenerNode> parentNodes,
+ private static Collection<RegistrationTreeNode<DataChangeListenerRegistration<?>>> getListenerChildrenWildcarded(final Collection<RegistrationTreeNode<DataChangeListenerRegistration<?>>> parentNodes,
final PathArgument child) {
if (parentNodes.isEmpty()) {
return Collections.emptyList();
}
- final List<ListenerNode> result = new ArrayList<>();
+ final List<RegistrationTreeNode<DataChangeListenerRegistration<?>>> result = new ArrayList<>();
if (child instanceof NodeWithValue || child instanceof NodeIdentifierWithPredicates) {
NodeIdentifier wildcardedIdentifier = new NodeIdentifier(child.getNodeType());
addChildNodes(result, parentNodes, wildcardedIdentifier);
return result;
}
- private static void addChildNodes(final List<ListenerNode> result, final Collection<ListenerNode> parentNodes, final PathArgument childIdentifier) {
- for (ListenerNode node : parentNodes) {
- Optional<ListenerNode> child = node.getChild(childIdentifier);
- if (child.isPresent()) {
- result.add(child.get());
+ private static void addChildNodes(final List<RegistrationTreeNode<DataChangeListenerRegistration<?>>> result, final Collection<RegistrationTreeNode<DataChangeListenerRegistration<?>>> parentNodes, final PathArgument childIdentifier) {
+ for (RegistrationTreeNode<DataChangeListenerRegistration<?>> node : parentNodes) {
+ RegistrationTreeNode<DataChangeListenerRegistration<?>> child = node.getExactChild(childIdentifier);
+ if (child != null) {
+ result.add(child);
}
}
}
* unclosed.
*
* @author Robert Varga
+ *
+ * @deprecated Use {@link RegistrationTreeNode} instead.
*/
+@Deprecated
public class ListenerNode implements StoreTreeNode<ListenerNode>, Identifiable<PathArgument> {
final RegistrationTreeNode<DataChangeListenerRegistration<?>> delegate;
* the listener tree.
*
* @return A walker instance.
+ *
+ * @deprecated Use {@link #takeSnapshot()} instead.
*/
+ @Deprecated
public ListenerWalker getWalker() {
/*
* TODO: The only current user of this method is local to the datastore.
* exposes the underlying tree structure.
*
* @author Robert Varga
+ *
+ * @deprecated Superseded by {@link RegistrationTreeSnapshot}.
*/
+@Deprecated
public class ListenerWalker implements AutoCloseable {
private final RegistrationTreeSnapshot<DataChangeListenerRegistration<?>> delegate;
+++ /dev/null
-/*
- * 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.sal.connect.api;
-
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider;
-
-public interface SchemaSourceProviderFactory<T> {
-
- SchemaSourceProvider<T> createSourceProvider(final RpcImplementation deviceRpc);
-}
@Override
public void operationComplete(Future<Object> future) throws Exception {
- if (!future.isSuccess()) {
+ if (!future.isSuccess() && !future.isCancelled()) {
logger.debug("{}: Connection failed", id, future.cause());
NetconfDeviceCommunicator.this.remoteDevice.onRemoteSessionFailed(future.cause());
}
// Disconnect from device
if(session != null) {
session.close();
+ // tear down not necessary, called indirectly by above close
}
-
- tearDown(id + ": Netconf session closed");
}
@Override
package org.opendaylight.controller.sal.connect.netconf.sal;
+import java.util.Collections;
+import java.util.Map;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBrokerExtension;
import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
throw new UnsupportedOperationException(id + ": Transaction chains not supported for netconf mount point");
}
+ @Override
+ public Map<Class<? extends DOMDataBrokerExtension>, DOMDataBrokerExtension> getSupportedExtensions() {
+ return Collections.emptyMap();
+ }
+
}
}
@Override
- public void onDeviceFailed(final Throwable throwable) {
+ public synchronized void onDeviceFailed(final Throwable throwable) {
salProvider.getTopologyDatastoreAdapter().setDeviceAsFailed(throwable);
salProvider.getMountInstance().onDeviceDisconnected();
salProvider.getMountInstance().onTopologyDeviceDisconnected();
}
@Override
- public void close() {
+ public synchronized void close() {
for (final AutoCloseable reg : Lists.reverse(salRegistrations)) {
closeGracefully(reg);
}
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyCollectionOf;
-import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.controller.sal.connect.api.MessageTransformer;
import org.opendaylight.controller.sal.connect.api.RemoteDeviceHandler;
-import org.opendaylight.controller.sal.connect.api.SchemaSourceProviderFactory;
import org.opendaylight.controller.sal.connect.netconf.listener.NetconfDeviceCommunicator;
import org.opendaylight.controller.sal.connect.netconf.listener.NetconfSessionPreferences;
import org.opendaylight.controller.sal.connect.netconf.sal.NetconfDeviceRpc;
import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
-import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider;
import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
public class NetconfDeviceTest {
return mock;
}
- public SchemaSourceProviderFactory<InputStream> getSourceProviderFactory() {
- final SchemaSourceProviderFactory<InputStream> mock = mockClass(SchemaSourceProviderFactory.class);
-
- final SchemaSourceProvider<InputStream> schemaSourceProvider = mockClass(SchemaSourceProvider.class);
- doReturn(Optional.<String>absent()).when(schemaSourceProvider).getSchemaSource(anyString(), any(Optional.class));
-
- doReturn(schemaSourceProvider).when(mock).createSourceProvider(any(RpcImplementation.class));
- return mock;
- }
-
private static <T> T mockClass(final Class<T> remoteDeviceHandlerClass) {
final T mock = mock(remoteDeviceHandlerClass);
Mockito.doReturn(remoteDeviceHandlerClass.getSimpleName()).when(mock).toString();
package org.opendaylight.controller.remote.rpc;
+import static akka.pattern.Patterns.ask;
import akka.actor.ActorRef;
import akka.dispatch.OnComplete;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.concurrent.ExecutionException;
+import org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeSerializer;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcException;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcIdentifier;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementation;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationNotAvailableException;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
+import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
import org.opendaylight.controller.remote.rpc.messages.InvokeRpc;
import org.opendaylight.controller.remote.rpc.messages.RpcResponse;
-import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.xml.codec.XmlUtils;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
-import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import scala.concurrent.ExecutionContext;
-import java.util.Collections;
-import java.util.Set;
-
-import static akka.pattern.Patterns.ask;
-
-public class RemoteRpcImplementation implements RpcImplementation, RoutedRpcDefaultImplementation {
+public class RemoteRpcImplementation implements DOMRpcImplementation {
private static final Logger LOG = LoggerFactory.getLogger(RemoteRpcImplementation.class);
private final ActorRef rpcBroker;
- private final SchemaContext schemaContext;
private final RemoteRpcProviderConfig config;
- public RemoteRpcImplementation(ActorRef rpcBroker, SchemaContext schemaContext, RemoteRpcProviderConfig config) {
+ public RemoteRpcImplementation(final ActorRef rpcBroker, final RemoteRpcProviderConfig config) {
this.rpcBroker = rpcBroker;
- this.schemaContext = schemaContext;
this.config = config;
}
@Override
- public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc,
- YangInstanceIdentifier identifier, CompositeNode input) {
- InvokeRpc rpcMsg = new InvokeRpc(rpc, identifier, input);
-
- return executeMsg(rpcMsg);
- }
-
- @Override
- public Set<QName> getSupportedRpcs() {
- // TODO : check if we need to get this from routing registry
- return Collections.emptySet();
- }
+ public CheckedFuture<DOMRpcResult, DOMRpcException> invokeRpc(final DOMRpcIdentifier rpc, final NormalizedNode<?, ?> input) {
+ final InvokeRpc rpcMsg = new InvokeRpc(rpc.getType().getLastComponent(), rpc.getContextReference(), input);
- @Override
- public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
- InvokeRpc rpcMsg = new InvokeRpc(rpc, null, input);
- return executeMsg(rpcMsg);
- }
+ final SettableFuture<DOMRpcResult> settableFuture = SettableFuture.create();
- private ListenableFuture<RpcResult<CompositeNode>> executeMsg(InvokeRpc rpcMsg) {
+ final ListenableFuture<DOMRpcResult> listenableFuture =
+ JdkFutureAdapters.listenInPoolThread(settableFuture);
- final SettableFuture<RpcResult<CompositeNode>> listenableFuture = SettableFuture.create();
+ final scala.concurrent.Future<Object> future = ask(rpcBroker, rpcMsg, config.getAskDuration());
- scala.concurrent.Future<Object> future = ask(rpcBroker, rpcMsg, config.getAskDuration());
-
- OnComplete<Object> onComplete = new OnComplete<Object>() {
+ final OnComplete<Object> onComplete = new OnComplete<Object>() {
@Override
- public void onComplete(Throwable failure, Object reply) throws Throwable {
+ public void onComplete(final Throwable failure, final Object reply) throws Throwable {
if(failure != null) {
LOG.error("InvokeRpc failed", failure);
- RpcResult<CompositeNode> rpcResult;
- if(failure instanceof RpcErrorsException) {
- rpcResult = RpcResultBuilder.<CompositeNode>failed().withRpcErrors(
- ((RpcErrorsException)failure).getRpcErrors()).build();
- } else {
- rpcResult = RpcResultBuilder.<CompositeNode>failed().withError(
- ErrorType.RPC, failure.getMessage(), failure).build();
+ final String message = String.format("Execution of RPC %s failed", rpcMsg.getRpc());
+ Collection<RpcError> errors = ((RpcErrorsException)failure).getRpcErrors();
+ if(errors == null || errors.size() == 0) {
+ errors = Arrays.asList(RpcResultBuilder.newError(ErrorType.RPC, null, message));
}
+ final DOMRpcResult rpcResult = new DefaultDOMRpcResult(errors);
- listenableFuture.set(rpcResult);
+ settableFuture.set(rpcResult);
return;
}
- RpcResponse rpcReply = (RpcResponse)reply;
- CompositeNode result = XmlUtils.xmlToCompositeNode(rpcReply.getResultCompositeNode());
- listenableFuture.set(RpcResultBuilder.success(result).build());
+ final RpcResponse rpcReply = (RpcResponse)reply;
+ final NormalizedNode<?, ?> result =
+ NormalizedNodeSerializer.deSerialize(rpcReply.getResultNormalizedNode());
+ settableFuture.set(new DefaultDOMRpcResult(result));
}
};
- future.onComplete(onComplete, ExecutionContext.Implicits$.MODULE$.global());
- return listenableFuture;
+ future.onComplete(onComplete, ExecutionContext.Implicits$.MODULE$.global());
+ // FIXME find non blocking way for implementation
+ try {
+ return Futures.immediateCheckedFuture(listenableFuture.get());
+ }
+ catch (InterruptedException | ExecutionException e) {
+ LOG.debug("Unexpected remote RPC exception.", e);
+ return Futures.immediateFailedCheckedFuture((DOMRpcException) new DOMRpcImplementationNotAvailableException(e, "Unexpected remote RPC exception"));
+ }
}
}
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
+import java.util.Collection;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
import org.opendaylight.controller.remote.rpc.messages.UpdateSchemaContext;
import org.opendaylight.controller.sal.core.api.Broker;
import org.opendaylight.controller.sal.core.api.Provider;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Collection;
-
/**
* This is the base class which initialize all the actors, listeners and
* default RPc implementation so remote invocation of rpcs.
private static final Logger LOG = LoggerFactory.getLogger(RemoteRpcProvider.class);
- private final RpcProvisionRegistry rpcProvisionRegistry;
+ private final DOMRpcProviderService rpcProvisionRegistry;
+ private ListenerRegistration<SchemaContextListener> schemaListenerRegistration;
private ActorSystem actorSystem;
private Broker.ProviderSession brokerSession;
private SchemaContext schemaContext;
private ActorRef rpcManager;
- private RemoteRpcProviderConfig config;
+ private final RemoteRpcProviderConfig config;
- public RemoteRpcProvider(ActorSystem actorSystem, RpcProvisionRegistry rpcProvisionRegistry) {
+ public RemoteRpcProvider(final ActorSystem actorSystem, final DOMRpcProviderService rpcProvisionRegistry) {
this.actorSystem = actorSystem;
this.rpcProvisionRegistry = rpcProvisionRegistry;
- this.config = new RemoteRpcProviderConfig(actorSystem.settings().config());
+ config = new RemoteRpcProviderConfig(actorSystem.settings().config());
}
@Override
public void close() throws Exception {
- if (this.actorSystem != null)
- this.actorSystem.shutdown();
+ if (actorSystem != null) {
+ actorSystem.shutdown();
+ actorSystem = null;
+ }
+ if (schemaListenerRegistration != null) {
+ schemaListenerRegistration.close();
+ schemaListenerRegistration = null;
+ }
}
@Override
- public void onSessionInitiated(Broker.ProviderSession session) {
- this.brokerSession = session;
+ public void onSessionInitiated(final Broker.ProviderSession session) {
+ brokerSession = session;
start();
}
private void start() {
LOG.info("Starting remote rpc service...");
- SchemaService schemaService = brokerSession.getService(SchemaService.class);
+ final SchemaService schemaService = brokerSession.getService(SchemaService.class);
+ final DOMRpcService rpcService = brokerSession.getService(DOMRpcService.class);
schemaContext = schemaService.getGlobalContext();
-
- rpcManager = actorSystem.actorOf(RpcManager.props(schemaContext, brokerSession, rpcProvisionRegistry),
- config.getRpcManagerName());
-
+ rpcManager = actorSystem.actorOf(RpcManager.props(schemaContext,
+ rpcProvisionRegistry, rpcService), config.getRpcManagerName());
+ schemaListenerRegistration = schemaService.registerSchemaContextListener(this);
LOG.debug("rpc manager started");
-
- schemaService.registerSchemaContextListener(this);
}
@Override
- public void onGlobalContextUpdated(SchemaContext schemaContext) {
+ public void onGlobalContextUpdated(final SchemaContext schemaContext) {
this.schemaContext = schemaContext;
rpcManager.tell(new UpdateSchemaContext(schemaContext), null);
-
}
}
import akka.actor.ActorSystem;
import akka.osgi.BundleDelegatingClassLoader;
import com.typesafe.config.Config;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService;
import org.opendaylight.controller.sal.core.api.Broker;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public static RemoteRpcProvider createInstance(
final Broker broker, final BundleContext bundleContext, final RemoteRpcProviderConfig config){
- RemoteRpcProvider rpcProvider =
- new RemoteRpcProvider(createActorSystem(bundleContext, config), (RpcProvisionRegistry) broker);
+ final RemoteRpcProvider rpcProvider =
+ new RemoteRpcProvider(createActorSystem(bundleContext, config), (DOMRpcProviderService) broker);
broker.registerProvider(rpcProvider);
return rpcProvider;
}
- private static ActorSystem createActorSystem(BundleContext bundleContext, RemoteRpcProviderConfig config){
+ private static ActorSystem createActorSystem(final BundleContext bundleContext, final RemoteRpcProviderConfig config){
// Create an OSGi bundle classloader for actor system
- BundleDelegatingClassLoader classLoader =
+ final BundleDelegatingClassLoader classLoader =
new BundleDelegatingClassLoader(bundleContext.getBundle(),
Thread.currentThread().getContextClassLoader());
- Config actorSystemConfig = config.get();
+ final Config actorSystemConfig = config.get();
if(LOG.isDebugEnabled()) {
LOG.debug("Actor system configuration\n{}", actorSystemConfig.root().render());
}
package org.opendaylight.controller.remote.rpc;
import com.google.common.base.Preconditions;
+import java.io.Serializable;
import org.opendaylight.controller.sal.connector.api.RpcRouter;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-import java.io.Serializable;
-
public class RouteIdentifierImpl implements RpcRouter.RouteIdentifier<QName, QName, YangInstanceIdentifier>,Serializable {
private static final long serialVersionUID = 1L;
@Override
public QName getContext() {
- return this.context;
+ return context;
}
@Override
public QName getType() {
- return this.type;
+ return type;
}
@Override
public YangInstanceIdentifier getRoute() {
- return this.route;
+ return route;
}
@Override
- public boolean equals(Object o) {
+ public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- RouteIdentifierImpl that = (RouteIdentifierImpl) o;
+ final RouteIdentifierImpl that = (RouteIdentifierImpl) o;
if (context == null){
if (that.getContext() != null) return false;
@Override
public int hashCode() {
- int prime = 31;
+ final int prime = 31;
int result = 0;
result = prime * result + (context == null ? 0:context.hashCode());
result = prime * result + (type == null ? 0:type.hashCode());
import akka.actor.ActorRef;
import com.google.common.base.Preconditions;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
public class RoutedRpcListener implements RouteChangeListener<RpcRoutingContext, YangInstanceIdentifier>{
- private static final Logger LOG = LoggerFactory.getLogger(RoutedRpcListener.class);
- private final ActorRef rpcRegistry;
+ private static final Logger LOG = LoggerFactory.getLogger(RoutedRpcListener.class);
+ private final ActorRef rpcRegistry;
- public RoutedRpcListener(ActorRef rpcRegistry) {
- Preconditions.checkNotNull(rpcRegistry, "rpc registry actor should not be null");
-
- this.rpcRegistry = rpcRegistry;
- }
-
- @Override
- public void onRouteChange(RouteChange<RpcRoutingContext, YangInstanceIdentifier> routeChange) {
- Map<RpcRoutingContext, Set<YangInstanceIdentifier>> announcements = routeChange.getAnnouncements();
- if(announcements != null && announcements.size() > 0){
- announce(getRouteIdentifiers(announcements));
+ public RoutedRpcListener(final ActorRef rpcRegistry) {
+ Preconditions.checkNotNull(rpcRegistry, "rpc registry actor should not be null");
+ this.rpcRegistry = rpcRegistry;
}
- Map<RpcRoutingContext, Set<YangInstanceIdentifier>> removals = routeChange.getRemovals();
- if(removals != null && removals.size() > 0 ) {
- remove(getRouteIdentifiers(removals));
+ @Override
+ public void onRouteChange(final RouteChange<RpcRoutingContext, YangInstanceIdentifier> routeChange) {
+ final Map<RpcRoutingContext, Set<YangInstanceIdentifier>> announcements = routeChange.getAnnouncements();
+ if(announcements != null && announcements.size() > 0){
+ announce(getRouteIdentifiers(announcements));
+ }
+
+ final Map<RpcRoutingContext, Set<YangInstanceIdentifier>> removals = routeChange.getRemovals();
+ if(removals != null && removals.size() > 0 ) {
+ remove(getRouteIdentifiers(removals));
+ }
}
- }
- /**
- *
- * @param announcements
- */
- private void announce(Set<RpcRouter.RouteIdentifier<?, ?, ?>> announcements) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("Announcing [{}]", announcements);
+ /**
+ *
+ * @param announcements
+ */
+ private void announce(final Set<RpcRouter.RouteIdentifier<?, ?, ?>> announcements) {
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("Announcing [{}]", announcements);
+ }
+ final RpcRegistry.Messages.AddOrUpdateRoutes addRpcMsg =
+ new RpcRegistry.Messages.AddOrUpdateRoutes(new ArrayList<>(announcements));
+ rpcRegistry.tell(addRpcMsg, ActorRef.noSender());
}
- RpcRegistry.Messages.AddOrUpdateRoutes addRpcMsg = new RpcRegistry.Messages.AddOrUpdateRoutes(new ArrayList<>(announcements));
- rpcRegistry.tell(addRpcMsg, ActorRef.noSender());
- }
- /**
- *
- * @param removals
- */
- private void remove(Set<RpcRouter.RouteIdentifier<?, ?, ?>> removals){
- if(LOG.isDebugEnabled()) {
- LOG.debug("Removing [{}]", removals);
+ /**
+ *
+ * @param removals
+ */
+ private void remove(final Set<RpcRouter.RouteIdentifier<?, ?, ?>> removals){
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("Removing [{}]", removals);
+ }
+ final RpcRegistry.Messages.RemoveRoutes removeRpcMsg =
+ new RpcRegistry.Messages.RemoveRoutes(new ArrayList<>(removals));
+ rpcRegistry.tell(removeRpcMsg, ActorRef.noSender());
}
- RpcRegistry.Messages.RemoveRoutes removeRpcMsg = new RpcRegistry.Messages.RemoveRoutes(new ArrayList<>(removals));
- rpcRegistry.tell(removeRpcMsg, ActorRef.noSender());
- }
- /**
- *
- * @param changes
- * @return
- */
- private Set<RpcRouter.RouteIdentifier<?, ?, ?>> getRouteIdentifiers(Map<RpcRoutingContext, Set<YangInstanceIdentifier>> changes) {
- RouteIdentifierImpl routeId = null;
- Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIdSet = new HashSet<>();
+ /**
+ *
+ * @param changes
+ * @return
+ */
+ private Set<RpcRouter.RouteIdentifier<?, ?, ?>> getRouteIdentifiers(
+ final Map<RpcRoutingContext, Set<YangInstanceIdentifier>> changes) {
- for (RpcRoutingContext context : changes.keySet()){
- for (YangInstanceIdentifier instanceId : changes.get(context)){
- routeId = new RouteIdentifierImpl(null, context.getRpc(), instanceId);
- routeIdSet.add(routeId);
- }
+ final Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIdSet = new HashSet<>();
+ for (final RpcRoutingContext context : changes.keySet()){
+ for (final YangInstanceIdentifier instanceId : changes.get(context)){
+ final RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, context.getRpc(), instanceId);
+ routeIdSet.add(routeId);
+ }
+ }
+ return routeIdSet;
}
- return routeIdSet;
- }
}
package org.opendaylight.controller.remote.rpc;
+import static akka.pattern.Patterns.ask;
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.dispatch.OnComplete;
import akka.japi.Creator;
import akka.japi.Pair;
-
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.JdkFutureAdapters;
import com.google.common.util.concurrent.ListenableFuture;
-
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
import org.opendaylight.controller.cluster.common.actor.AbstractUntypedActor;
+import org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeSerializer;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcException;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node;
import org.opendaylight.controller.remote.rpc.messages.ExecuteRpc;
import org.opendaylight.controller.remote.rpc.messages.InvokeRpc;
import org.opendaylight.controller.remote.rpc.messages.RpcResponse;
-import org.opendaylight.controller.remote.rpc.messages.UpdateSchemaContext;
import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
import org.opendaylight.controller.remote.rpc.utils.LatestEntryRoutingLogic;
import org.opendaylight.controller.remote.rpc.utils.RoutingLogic;
import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.opendaylight.controller.sal.core.api.Broker;
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.xml.codec.XmlUtils;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
-import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.Future;
-
-import static akka.pattern.Patterns.ask;
-
/**
* Actor to initiate execution of remote RPC on other nodes of the cluster.
*/
public class RpcBroker extends AbstractUntypedActor {
private static final Logger LOG = LoggerFactory.getLogger(RpcBroker.class);
- private final Broker.ProviderSession brokerSession;
private final ActorRef rpcRegistry;
- private SchemaContext schemaContext;
private final RemoteRpcProviderConfig config;
+ private final DOMRpcService rpcService;
- private RpcBroker(Broker.ProviderSession brokerSession, ActorRef rpcRegistry,
- SchemaContext schemaContext) {
- this.brokerSession = brokerSession;
+ private RpcBroker(final DOMRpcService rpcService, final ActorRef rpcRegistry) {
+ this.rpcService = rpcService;
this.rpcRegistry = rpcRegistry;
- this.schemaContext = schemaContext;
config = new RemoteRpcProviderConfig(getContext().system().settings().config());
}
- public static Props props(Broker.ProviderSession brokerSession, ActorRef rpcRegistry,
- SchemaContext schemaContext) {
- return Props.create(new RpcBrokerCreator(brokerSession, rpcRegistry, schemaContext));
+ public static Props props(final DOMRpcService rpcService, final ActorRef rpcRegistry) {
+ Preconditions.checkNotNull(rpcRegistry, "ActorRef can not be null!");
+ Preconditions.checkNotNull(rpcService, "DOMRpcService can not be null");
+ return Props.create(new RpcBrokerCreator(rpcService, rpcRegistry));
}
@Override
- protected void handleReceive(Object message) throws Exception {
+ protected void handleReceive(final Object message) throws Exception {
if(message instanceof InvokeRpc) {
invokeRemoteRpc((InvokeRpc) message);
} else if(message instanceof ExecuteRpc) {
executeRpc((ExecuteRpc) message);
- } else if(message instanceof UpdateSchemaContext) {
- updateSchemaContext((UpdateSchemaContext) message);
}
}
- private void updateSchemaContext(UpdateSchemaContext message) {
- this.schemaContext = message.getSchemaContext();
- }
-
private void invokeRemoteRpc(final InvokeRpc msg) {
if(LOG.isDebugEnabled()) {
LOG.debug("Looking up the remote actor for rpc {}", msg.getRpc());
}
- RpcRouter.RouteIdentifier<?,?,?> routeId = new RouteIdentifierImpl(
+ final RpcRouter.RouteIdentifier<?,?,?> routeId = new RouteIdentifierImpl(
null, msg.getRpc(), msg.getIdentifier());
- RpcRegistry.Messages.FindRouters findMsg = new RpcRegistry.Messages.FindRouters(routeId);
+ final RpcRegistry.Messages.FindRouters findMsg = new RpcRegistry.Messages.FindRouters(routeId);
- scala.concurrent.Future<Object> future = ask(rpcRegistry, findMsg, config.getAskDuration());
+ final scala.concurrent.Future<Object> future = ask(rpcRegistry, findMsg, config.getAskDuration());
final ActorRef sender = getSender();
final ActorRef self = self();
- OnComplete<Object> onComplete = new OnComplete<Object>() {
+ final OnComplete<Object> onComplete = new OnComplete<Object>() {
@Override
- public void onComplete(Throwable failure, Object reply) throws Throwable {
+ public void onComplete(final Throwable failure, final Object reply) throws Throwable {
if(failure != null) {
LOG.error("FindRouters failed", failure);
sender.tell(new akka.actor.Status.Failure(failure), self);
return;
}
- RpcRegistry.Messages.FindRoutersReply findReply =
+ final RpcRegistry.Messages.FindRoutersReply findReply =
(RpcRegistry.Messages.FindRoutersReply)reply;
- List<Pair<ActorRef, Long>> actorRefList = findReply.getRouterWithUpdateTime();
+ final List<Pair<ActorRef, Long>> actorRefList = findReply.getRouterWithUpdateTime();
if(actorRefList == null || actorRefList.isEmpty()) {
- String message = String.format(
+ final String message = String.format(
"No remote implementation found for rpc %s", msg.getRpc());
sender.tell(new akka.actor.Status.Failure(new RpcErrorsException(
message, Arrays.asList(RpcResultBuilder.newError(ErrorType.RPC,
protected void finishInvokeRpc(final List<Pair<ActorRef, Long>> actorRefList,
final InvokeRpc msg, final ActorRef sender, final ActorRef self) {
- RoutingLogic logic = new LatestEntryRoutingLogic(actorRefList);
+ final RoutingLogic logic = new LatestEntryRoutingLogic(actorRefList);
- ExecuteRpc executeMsg = new ExecuteRpc(XmlUtils.inputCompositeNodeToXml(msg.getInput(),
- schemaContext), msg.getRpc());
+ final Node serializedNode = NormalizedNodeSerializer.serialize(msg.getInput());
+ final ExecuteRpc executeMsg = new ExecuteRpc(serializedNode, msg.getRpc());
- scala.concurrent.Future<Object> future = ask(logic.select(), executeMsg, config.getAskDuration());
+ final scala.concurrent.Future<Object> future = ask(logic.select(), executeMsg, config.getAskDuration());
- OnComplete<Object> onComplete = new OnComplete<Object>() {
+ final OnComplete<Object> onComplete = new OnComplete<Object>() {
@Override
- public void onComplete(Throwable failure, Object reply) throws Throwable {
+ public void onComplete(final Throwable failure, final Object reply) throws Throwable {
if(failure != null) {
LOG.error("ExecuteRpc failed", failure);
sender.tell(new akka.actor.Status.Failure(failure), self);
if(LOG.isDebugEnabled()) {
LOG.debug("Executing rpc {}", msg.getRpc());
}
- Future<RpcResult<CompositeNode>> future = brokerSession.rpc(msg.getRpc(),
- XmlUtils.inputXmlToCompositeNode(msg.getRpc(), msg.getInputCompositeNode(),
- schemaContext));
+ final NormalizedNode<?, ?> input = NormalizedNodeSerializer.deSerialize(msg.getInputNormalizedNode());
+ final SchemaPath schemaPath = SchemaPath.create(true, msg.getRpc());
+
+ final CheckedFuture<DOMRpcResult, DOMRpcException> future = rpcService.invokeRpc(schemaPath, input);
- ListenableFuture<RpcResult<CompositeNode>> listenableFuture =
+ final ListenableFuture<DOMRpcResult> listenableFuture =
JdkFutureAdapters.listenInPoolThread(future);
final ActorRef sender = getSender();
final ActorRef self = self();
- Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<CompositeNode>>() {
+ Futures.addCallback(listenableFuture, new FutureCallback<DOMRpcResult>() {
@Override
- public void onSuccess(RpcResult<CompositeNode> result) {
- if(result.isSuccessful()) {
- sender.tell(new RpcResponse(XmlUtils.outputCompositeNodeToXml(result.getResult(),
- schemaContext)), self);
- } else {
- String message = String.format("Execution of RPC %s failed", msg.getRpc());
+ public void onSuccess(final DOMRpcResult result) {
+ if (result.getErrors() != null && ( ! result.getErrors().isEmpty())) {
+ final String message = String.format("Execution of RPC %s failed", msg.getRpc());
Collection<RpcError> errors = result.getErrors();
if(errors == null || errors.size() == 0) {
errors = Arrays.asList(RpcResultBuilder.newError(ErrorType.RPC,
sender.tell(new akka.actor.Status.Failure(new RpcErrorsException(
message, errors)), self);
+ } else {
+ final Node serializedResultNode = NormalizedNodeSerializer.serialize(result.getResult());
+ sender.tell(new RpcResponse(serializedResultNode), self);
}
}
@Override
- public void onFailure(Throwable t) {
+ public void onFailure(final Throwable t) {
LOG.error("executeRpc for {} failed: {}", msg.getRpc(), t);
sender.tell(new akka.actor.Status.Failure(t), self);
}
private static class RpcBrokerCreator implements Creator<RpcBroker> {
private static final long serialVersionUID = 1L;
- final Broker.ProviderSession brokerSession;
+ final DOMRpcService rpcService;
final ActorRef rpcRegistry;
- final SchemaContext schemaContext;
- RpcBrokerCreator(ProviderSession brokerSession, ActorRef rpcRegistry,
- SchemaContext schemaContext) {
- this.brokerSession = brokerSession;
+ RpcBrokerCreator(final DOMRpcService rpcService, final ActorRef rpcRegistry) {
+ this.rpcService = rpcService;
this.rpcRegistry = rpcRegistry;
- this.schemaContext = schemaContext;
}
@Override
public RpcBroker create() throws Exception {
- return new RpcBroker(brokerSession, rpcRegistry, schemaContext);
+ return new RpcBroker(rpcService, rpcRegistry);
}
}
}
import akka.actor.ActorRef;
+import com.google.common.base.Preconditions;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcAvailabilityListener;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcIdentifier;
import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.yangtools.yang.common.QName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.ArrayList;
-import java.util.List;
-
-public class RpcListener implements RpcRegistrationListener{
+public class RpcListener implements DOMRpcAvailabilityListener{
private static final Logger LOG = LoggerFactory.getLogger(RpcListener.class);
private final ActorRef rpcRegistry;
- public RpcListener(ActorRef rpcRegistry) {
+ public RpcListener(final ActorRef rpcRegistry) {
this.rpcRegistry = rpcRegistry;
}
- @Override
- public void onRpcImplementationAdded(QName rpc) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("Adding registration for [{}]", rpc);
+ @Override
+ public void onRpcAvailable(@Nonnull final Collection<DOMRpcIdentifier> rpcs) {
+ Preconditions.checkArgument(rpcs != null, "Input Collection of DOMRpcIdentifier can not be null.");
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Adding registration for [{}]", rpcs);
+ }
+ final List<RpcRouter.RouteIdentifier<?,?,?>> routeIds = new ArrayList<>();
+
+ for (final DOMRpcIdentifier rpc : rpcs) {
+ final RpcRouter.RouteIdentifier<?,?,?> routeId = new RouteIdentifierImpl(null, rpc.getType().getLastComponent(), null);
+ routeIds.add(routeId);
+ }
+ final RpcRegistry.Messages.AddOrUpdateRoutes addRpcMsg = new RpcRegistry.Messages.AddOrUpdateRoutes(routeIds);
+ rpcRegistry.tell(addRpcMsg, ActorRef.noSender());
}
- RpcRouter.RouteIdentifier<?,?,?> routeId = new RouteIdentifierImpl(null, rpc, null);
- List<RpcRouter.RouteIdentifier<?,?,?>> routeIds = new ArrayList<>();
- routeIds.add(routeId);
- RpcRegistry.Messages.AddOrUpdateRoutes addRpcMsg = new RpcRegistry.Messages.AddOrUpdateRoutes(routeIds);
- rpcRegistry.tell(addRpcMsg, ActorRef.noSender());
- }
- @Override
- public void onRpcImplementationRemoved(QName rpc) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("Removing registration for [{}]", rpc);
+ @Override
+ public void onRpcUnavailable(@Nonnull final Collection<DOMRpcIdentifier> rpcs) {
+ Preconditions.checkArgument(rpcs != null, "Input Collection of DOMRpcIdentifier can not be null.");
+ if(LOG.isDebugEnabled()) {
+ LOG.debug("Removing registration for [{}]", rpcs);
+ }
+ final List<RpcRouter.RouteIdentifier<?,?,?>> routeIds = new ArrayList<>();
+ for (final DOMRpcIdentifier rpc : rpcs) {
+ final RpcRouter.RouteIdentifier<?,?,?> routeId = new RouteIdentifierImpl(null, rpc.getType().getLastComponent(), null);
+ routeIds.add(routeId);
+ }
+ final RpcRegistry.Messages.RemoveRoutes removeRpcMsg = new RpcRegistry.Messages.RemoveRoutes(routeIds);
+ rpcRegistry.tell(removeRpcMsg, ActorRef.noSender());
}
- RpcRouter.RouteIdentifier<?,?,?> routeId = new RouteIdentifierImpl(null, rpc, null);
- List<RpcRouter.RouteIdentifier<?,?,?>> routeIds = new ArrayList<>();
- routeIds.add(routeId);
- RpcRegistry.Messages.RemoveRoutes removeRpcMsg = new RpcRegistry.Messages.RemoveRoutes(routeIds);
- rpcRegistry.tell(removeRpcMsg, ActorRef.noSender());
- }
}
import akka.actor.Props;
import akka.actor.SupervisorStrategy;
import akka.japi.Function;
+import com.google.common.base.Preconditions;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Set;
import org.opendaylight.controller.cluster.common.actor.AbstractUntypedActor;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcIdentifier;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
import org.opendaylight.controller.remote.rpc.messages.UpdateSchemaContext;
import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
-import org.opendaylight.controller.sal.core.api.Broker;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RpcManager extends AbstractUntypedActor {
- private static final Logger LOG = LoggerFactory.getLogger(RpcManager.class);
-
- private SchemaContext schemaContext;
- private ActorRef rpcBroker;
- private ActorRef rpcRegistry;
- private final Broker.ProviderSession brokerSession;
- private final RemoteRpcProviderConfig config;
- private RpcListener rpcListener;
- private RoutedRpcListener routeChangeListener;
- private RemoteRpcImplementation rpcImplementation;
- private final RpcProvisionRegistry rpcProvisionRegistry;
-
- private RpcManager(SchemaContext schemaContext,
- Broker.ProviderSession brokerSession,
- RpcProvisionRegistry rpcProvisionRegistry) {
- this.schemaContext = schemaContext;
- this.brokerSession = brokerSession;
- this.rpcProvisionRegistry = rpcProvisionRegistry;
- this.config = new RemoteRpcProviderConfig(getContext().system().settings().config());
-
- createRpcActors();
- startListeners();
- }
-
-
- public static Props props(final SchemaContext schemaContext, final Broker.ProviderSession brokerSession,
- final RpcProvisionRegistry rpcProvisionRegistry) {
- return Props.create(RpcManager.class, schemaContext, brokerSession, rpcProvisionRegistry);
+ private static final Logger LOG = LoggerFactory.getLogger(RpcManager.class);
+
+ private SchemaContext schemaContext;
+ private ActorRef rpcBroker;
+ private ActorRef rpcRegistry;
+ private final RemoteRpcProviderConfig config;
+ private RpcListener rpcListener;
+ private RoutedRpcListener routeChangeListener;
+ private RemoteRpcImplementation rpcImplementation;
+ private final DOMRpcProviderService rpcProvisionRegistry;
+ private final DOMRpcService rpcServices;
+
+ private RpcManager(final SchemaContext schemaContext,
+ final DOMRpcProviderService rpcProvisionRegistry,
+ final DOMRpcService rpcSevices) {
+ this.schemaContext = schemaContext;
+ this.rpcProvisionRegistry = rpcProvisionRegistry;
+ rpcServices = rpcSevices;
+ config = new RemoteRpcProviderConfig(getContext().system().settings().config());
+
+ createRpcActors();
+ startListeners();
}
- private void createRpcActors() {
- LOG.debug("Create rpc registry and broker actors");
-
- rpcRegistry =
- getContext().actorOf(Props.create(RpcRegistry.class).
- withMailbox(config.getMailBoxName()), config.getRpcRegistryName());
-
- rpcBroker =
- getContext().actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext).
- withMailbox(config.getMailBoxName()), config.getRpcBrokerName());
-
- RpcRegistry.Messages.SetLocalRouter localRouter = new RpcRegistry.Messages.SetLocalRouter(rpcBroker);
- rpcRegistry.tell(localRouter, self());
- }
-
- private void startListeners() {
- LOG.debug("Registers rpc listeners");
-
- rpcListener = new RpcListener(rpcRegistry);
- routeChangeListener = new RoutedRpcListener(rpcRegistry);
- rpcImplementation = new RemoteRpcImplementation(rpcBroker, schemaContext, config);
-
- brokerSession.addRpcRegistrationListener(rpcListener);
- rpcProvisionRegistry.registerRouteChangeListener(routeChangeListener);
- rpcProvisionRegistry.setRoutedRpcDefaultDelegate(rpcImplementation);
- announceSupportedRpcs();
- }
-
- /**
- * Add all the locally registered RPCs in the clustered routing table
- */
- private void announceSupportedRpcs(){
- LOG.debug("Adding all supported rpcs to routing table");
- Set<QName> currentlySupported = brokerSession.getSupportedRpcs();
- for (QName rpc : currentlySupported) {
- rpcListener.onRpcImplementationAdded(rpc);
+
+ public static Props props(final SchemaContext schemaContext,
+ final DOMRpcProviderService rpcProvisionRegistry, final DOMRpcService rpcServices) {
+ Preconditions.checkNotNull(schemaContext, "SchemaContext can not be null!");
+ Preconditions.checkNotNull(rpcProvisionRegistry, "RpcProviderService can not be null!");
+ Preconditions.checkNotNull(rpcServices, "RpcService can not be null!");
+ return Props.create(RpcManager.class, schemaContext, rpcProvisionRegistry, rpcServices);
+ }
+
+ private void createRpcActors() {
+ LOG.debug("Create rpc registry and broker actors");
+
+ rpcRegistry =
+ getContext().actorOf(Props.create(RpcRegistry.class).
+ withMailbox(config.getMailBoxName()), config.getRpcRegistryName());
+
+ rpcBroker =
+ getContext().actorOf(RpcBroker.props(rpcServices, rpcRegistry).
+ withMailbox(config.getMailBoxName()), config.getRpcBrokerName());
+
+ final RpcRegistry.Messages.SetLocalRouter localRouter = new RpcRegistry.Messages.SetLocalRouter(rpcBroker);
+ rpcRegistry.tell(localRouter, self());
}
- }
+ private void startListeners() {
+ LOG.debug("Registers rpc listeners");
+
+ rpcListener = new RpcListener(rpcRegistry);
+ routeChangeListener = new RoutedRpcListener(rpcRegistry);
+ rpcImplementation = new RemoteRpcImplementation(rpcBroker, config);
+
+ rpcServices.registerRpcListener(rpcListener);
+
+// rpcProvisionRegistry.registerRouteChangeListener(routeChangeListener);
+// rpcProvisionRegistry.setRoutedRpcDefaultDelegate(rpcImplementation);
+ announceSupportedRpcs();
+ }
- @Override
- protected void handleReceive(Object message) throws Exception {
- if(message instanceof UpdateSchemaContext) {
- updateSchemaContext((UpdateSchemaContext) message);
+ /**
+ * Add all the locally registered RPCs in the clustered routing table
+ */
+ private void announceSupportedRpcs(){
+ LOG.debug("Adding all supported rpcs to routing table");
+ final Set<RpcDefinition> currentlySupportedRpc = schemaContext.getOperations();
+ final List<DOMRpcIdentifier> rpcs = new ArrayList<>();
+ for (final RpcDefinition rpcDef : currentlySupportedRpc) {
+ rpcs.add(DOMRpcIdentifier.create(rpcDef.getPath()));
+ }
+ rpcListener.onRpcAvailable(rpcs);
}
- }
- private void updateSchemaContext(UpdateSchemaContext message) {
- this.schemaContext = message.getSchemaContext();
- rpcBroker.tell(message, ActorRef.noSender());
- }
+ @Override
+ protected void handleReceive(final Object message) throws Exception {
+ if(message instanceof UpdateSchemaContext) {
+ updateSchemaContext((UpdateSchemaContext) message);
+ }
+
+ }
+
+ private void updateSchemaContext(final UpdateSchemaContext message) {
+ schemaContext = message.getSchemaContext();
+ rpcBroker.tell(message, ActorRef.noSender());
+ }
- @Override
- public SupervisorStrategy supervisorStrategy() {
- return new OneForOneStrategy(10, Duration.create("1 minute"),
- new Function<Throwable, SupervisorStrategy.Directive>() {
- @Override
- public SupervisorStrategy.Directive apply(Throwable t) {
- return SupervisorStrategy.resume();
+ @Override
+ public SupervisorStrategy supervisorStrategy() {
+ return new OneForOneStrategy(10, Duration.create("1 minute"),
+ new Function<Throwable, SupervisorStrategy.Directive>() {
+ @Override
+ public SupervisorStrategy.Directive apply(final Throwable t) {
+ return SupervisorStrategy.resume();
+ }
}
- }
- );
- }
+ );
+ }
}
import com.google.common.base.Preconditions;
import java.io.Serializable;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
import org.opendaylight.yangtools.yang.common.QName;
public class ExecuteRpc implements Serializable {
private static final long serialVersionUID = 1128904894827335676L;
- private final String inputCompositeNode;
+ private final NormalizedNodeMessages.Node inputNormalizedNode;
private final QName rpc;
- public ExecuteRpc(final String inputCompositeNode, final QName rpc) {
- Preconditions.checkNotNull(inputCompositeNode, "Composite Node input string should be present");
+ public ExecuteRpc(final NormalizedNodeMessages.Node inputNormalizedNode, final QName rpc) {
+ Preconditions.checkNotNull(inputNormalizedNode, "Normalized Node input string should be present");
Preconditions.checkNotNull(rpc, "rpc Qname should not be null");
- this.inputCompositeNode = inputCompositeNode;
+ this.inputNormalizedNode = inputNormalizedNode;
this.rpc = rpc;
}
- public String getInputCompositeNode() {
- return inputCompositeNode;
+ public NormalizedNodeMessages.Node getInputNormalizedNode() {
+ return inputNormalizedNode;
}
public QName getRpc() {
import com.google.common.base.Preconditions;
import java.io.Serializable;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
public class InvokeRpc implements Serializable {
private static final long serialVersionUID = -2813459607858108953L;
private final QName rpc;
private final YangInstanceIdentifier identifier;
- private final CompositeNode input;
+ private final NormalizedNode<?,?> input;
- public InvokeRpc(final QName rpc, final YangInstanceIdentifier identifier, final CompositeNode input) {
+ public InvokeRpc(final QName rpc, final YangInstanceIdentifier identifier, final NormalizedNode<?,?> input) {
Preconditions.checkNotNull(rpc, "rpc qname should not be null");
Preconditions.checkNotNull(input, "rpc input should not be null");
return identifier;
}
- public CompositeNode getInput() {
+ public NormalizedNode<?,?> getInput() {
return input;
}
}
package org.opendaylight.controller.remote.rpc.messages;
import java.io.Serializable;
+import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
public class RpcResponse implements Serializable {
private static final long serialVersionUID = -4211279498688989245L;
- private final String resultCompositeNode;
+ private final NormalizedNodeMessages.Node resultNormalizedNode;
- public RpcResponse(final String resultCompositeNode) {
- this.resultCompositeNode = resultCompositeNode;
+ public RpcResponse(final NormalizedNodeMessages.Node inputNormalizedNode) {
+ resultNormalizedNode = inputNormalizedNode;
}
- public String getResultCompositeNode() {
- return resultCompositeNode;
+ public NormalizedNodeMessages.Node getResultNormalizedNode() {
+ return resultNormalizedNode;
}
}
package org.opendaylight.controller.remote.rpc;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.testkit.JavaTestKit;
-import com.google.common.collect.ImmutableList;
+import java.io.File;
+import java.net.URI;
+import java.util.Arrays;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
import org.opendaylight.controller.sal.core.api.Broker;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
-import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
-import java.io.File;
-import java.net.URI;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
/**
* Base class for RPC tests.
*
protected JavaTestKit probeReg2;
protected Broker.ProviderSession brokerSession;
protected SchemaContext schemaContext;
+ protected DOMRpcService rpcService;
@BeforeClass
public static void setup() throws InterruptedException {
- RemoteRpcProviderConfig config1 = new RemoteRpcProviderConfig.Builder("memberA").build();
- RemoteRpcProviderConfig config2 = new RemoteRpcProviderConfig.Builder("memberB").build();
+ final RemoteRpcProviderConfig config1 = new RemoteRpcProviderConfig.Builder("memberA").build();
+ final RemoteRpcProviderConfig config2 = new RemoteRpcProviderConfig.Builder("memberB").build();
node1 = ActorSystem.create("opendaylight-rpc", config1.get());
node2 = ActorSystem.create("opendaylight-rpc", config2.get());
}
new File(RpcBrokerTest.class.getResource("/test-rpc.yang").getPath())));
brokerSession = Mockito.mock(Broker.ProviderSession.class);
+ rpcService = Mockito.mock(DOMRpcService.class);
+
probeReg1 = new JavaTestKit(node1);
- rpcBroker1 = node1.actorOf(RpcBroker.props(brokerSession, probeReg1.getRef(), schemaContext));
+ rpcBroker1 = node1.actorOf(RpcBroker.props(rpcService, probeReg1.getRef()));
probeReg2 = new JavaTestKit(node2);
- rpcBroker2 = node2.actorOf(RpcBroker.props(brokerSession, probeReg2.getRef(), schemaContext));
+ rpcBroker2 = node2.actorOf(RpcBroker.props(rpcService, probeReg2.getRef()));
}
- static void assertRpcErrorEquals(RpcError rpcError, ErrorSeverity severity,
- ErrorType errorType, String tag, String message, String applicationTag, String info,
- String causeMsg) {
+ static void assertRpcErrorEquals(final RpcError rpcError, final ErrorSeverity severity,
+ final ErrorType errorType, final String tag, final String message, final String applicationTag, final String info,
+ final String causeMsg) {
assertEquals("getSeverity", severity, rpcError.getSeverity());
assertEquals("getErrorType", errorType, rpcError.getErrorType());
assertEquals("getTag", tag, rpcError.getTag());
}
}
- static void assertCompositeNodeEquals(CompositeNode exp, CompositeNode actual) {
- assertEquals("NodeType getNamespace", exp.getNodeType().getNamespace(),
- actual.getNodeType().getNamespace());
- assertEquals("NodeType getLocalName", exp.getNodeType().getLocalName(),
- actual.getNodeType().getLocalName());
- for(Node<?> child: exp.getValue()) {
- List<Node<?>> c = actual.get(child.getNodeType());
- assertNotNull("Missing expected child " + child.getNodeType(), c);
- if(child instanceof CompositeNode) {
- assertCompositeNodeEquals((CompositeNode) child, (CompositeNode)c.get(0));
- } else {
- assertEquals("Value for Node " + child.getNodeType(), child.getValue(),
- c.get(0).getValue());
- }
- }
- }
-
- static CompositeNode makeRPCInput(String data) {
- CompositeNodeBuilder<ImmutableCompositeNode> builder = ImmutableCompositeNode.builder()
- .setQName(TEST_RPC_INPUT).addLeaf(TEST_RPC_INPUT_DATA, data);
- return ImmutableCompositeNode.create(
- TEST_RPC, ImmutableList.<Node<?>>of(builder.toInstance()));
- }
-
- static CompositeNode makeRPCOutput(String data) {
- CompositeNodeBuilder<ImmutableCompositeNode> builder = ImmutableCompositeNode.builder()
- .setQName(TEST_RPC_OUTPUT).addLeaf(TEST_RPC_OUTPUT_DATA, data);
- return ImmutableCompositeNode.create(
- TEST_RPC, ImmutableList.<Node<?>>of(builder.toInstance()));
- }
-
- static void assertFailedRpcResult(RpcResult<CompositeNode> rpcResult, ErrorSeverity severity,
- ErrorType errorType, String tag, String message, String applicationTag, String info,
- String causeMsg) {
-
- assertNotNull("RpcResult was null", rpcResult);
- assertEquals("isSuccessful", false, rpcResult.isSuccessful());
- Collection<RpcError> rpcErrors = rpcResult.getErrors();
- assertEquals("RpcErrors count", 1, rpcErrors.size());
- assertRpcErrorEquals(rpcErrors.iterator().next(), severity, errorType, tag, message,
- applicationTag, info, causeMsg);
- }
-
- static void assertSuccessfulRpcResult(RpcResult<CompositeNode> rpcResult,
- CompositeNode expOutput) {
-
- assertNotNull("RpcResult was null", rpcResult);
- assertEquals("isSuccessful", true, rpcResult.isSuccessful());
- assertCompositeNodeEquals(expOutput, rpcResult.getResult());
- }
-
static class TestException extends Exception {
private static final long serialVersionUID = 1L;
package org.opendaylight.controller.remote.rpc;
-import akka.testkit.JavaTestKit;
-import com.google.common.util.concurrent.ListenableFuture;
-import org.junit.Test;
-import org.opendaylight.controller.remote.rpc.messages.InvokeRpc;
-import org.opendaylight.controller.remote.rpc.messages.RpcResponse;
-import org.opendaylight.controller.xml.codec.XmlUtils;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
-import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-
-import java.net.URI;
-import java.util.Arrays;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static org.junit.Assert.assertEquals;
/***
* Unit tests for RemoteRpcImplementation.
*/
public class RemoteRpcImplementationTest extends AbstractRpcTest {
- @Test
- public void testInvokeRpc() throws Exception {
- final AtomicReference<AssertionError> assertError = new AtomicReference<>();
- try {
- RemoteRpcImplementation rpcImpl = new RemoteRpcImplementation(
- probeReg1.getRef(), schemaContext, getConfig());
-
- final CompositeNode input = makeRPCInput("foo");
- final CompositeNode output = makeRPCOutput("bar");
- final AtomicReference<InvokeRpc> invokeRpcMsg = setupInvokeRpcReply(assertError, output);
-
- ListenableFuture<RpcResult<CompositeNode>> future = rpcImpl.invokeRpc(TEST_RPC, input);
-
- RpcResult<CompositeNode> rpcResult = future.get(5, TimeUnit.SECONDS);
-
- assertSuccessfulRpcResult(rpcResult, (CompositeNode)output.getValue().get(0));
-
- assertEquals("getRpc", TEST_RPC, invokeRpcMsg.get().getRpc());
- assertEquals("getInput", input, invokeRpcMsg.get().getInput());
- } finally {
- if(assertError.get() != null) {
- throw assertError.get();
- }
- }
- }
-
- @Test
- public void testInvokeRpcWithIdentifier() throws Exception {
- final AtomicReference<AssertionError> assertError = new AtomicReference<>();
- try {
- RemoteRpcImplementation rpcImpl = new RemoteRpcImplementation(
- probeReg1.getRef(), schemaContext, getConfig());
-
- QName instanceQName = new QName(new URI("ns"), "instance");
- YangInstanceIdentifier identifier = YangInstanceIdentifier.of(instanceQName);
-
- CompositeNode input = makeRPCInput("foo");
- CompositeNode output = makeRPCOutput("bar");
- final AtomicReference<InvokeRpc> invokeRpcMsg = setupInvokeRpcReply(assertError, output);
-
- ListenableFuture<RpcResult<CompositeNode>> future = rpcImpl.invokeRpc(
- TEST_RPC, identifier, input);
-
- RpcResult<CompositeNode> rpcResult = future.get(5, TimeUnit.SECONDS);
-
- assertSuccessfulRpcResult(rpcResult, (CompositeNode)output.getValue().get(0));
-
- assertEquals("getRpc", TEST_RPC, invokeRpcMsg.get().getRpc());
- assertEquals("getInput", input, invokeRpcMsg.get().getInput());
- assertEquals("getRoute", identifier, invokeRpcMsg.get().getIdentifier());
- } finally {
- if(assertError.get() != null) {
- throw assertError.get();
- }
- }
- }
-
- @Test
- public void testInvokeRpcWithRpcErrorsException() throws Exception {
- final AtomicReference<AssertionError> assertError = new AtomicReference<>();
- try {
- RemoteRpcImplementation rpcImpl = new RemoteRpcImplementation(
- probeReg1.getRef(), schemaContext, getConfig());
-
- final CompositeNode input = makeRPCInput("foo");
-
- setupInvokeRpcErrorReply(assertError, new RpcErrorsException(
- "mock", Arrays.asList(RpcResultBuilder.newError(ErrorType.RPC, "tag",
- "error", "appTag", "info", null))));
-
- ListenableFuture<RpcResult<CompositeNode>> future = rpcImpl.invokeRpc(TEST_RPC, input);
-
- RpcResult<CompositeNode> rpcResult = future.get(5, TimeUnit.SECONDS);
-
- assertFailedRpcResult(rpcResult, ErrorSeverity.ERROR, ErrorType.RPC, "tag",
- "error", "appTag", "info", null);
- } finally {
- if(assertError.get() != null) {
- throw assertError.get();
- }
- }
- }
-
- @Test
- public void testInvokeRpcWithOtherException() throws Exception {
- final AtomicReference<AssertionError> assertError = new AtomicReference<>();
- try {
- RemoteRpcImplementation rpcImpl = new RemoteRpcImplementation(
- probeReg1.getRef(), schemaContext, getConfig());
-
- final CompositeNode input = makeRPCInput("foo");
-
- setupInvokeRpcErrorReply(assertError, new TestException());
-
- ListenableFuture<RpcResult<CompositeNode>> future = rpcImpl.invokeRpc(TEST_RPC, input);
-
- RpcResult<CompositeNode> rpcResult = future.get(5, TimeUnit.SECONDS);
-
- assertFailedRpcResult(rpcResult, ErrorSeverity.ERROR, ErrorType.RPC, "operation-failed",
- TestException.MESSAGE, null, null, TestException.MESSAGE);
- } finally {
- if(assertError.get() != null) {
- throw assertError.get();
- }
- }
- }
-
- private AtomicReference<InvokeRpc> setupInvokeRpcReply(
- final AtomicReference<AssertionError> assertError, final CompositeNode output) {
- return setupInvokeRpcReply(assertError, output, null);
- }
-
- private AtomicReference<InvokeRpc> setupInvokeRpcErrorReply(
- final AtomicReference<AssertionError> assertError, final Exception error) {
- return setupInvokeRpcReply(assertError, null, error);
- }
-
- private AtomicReference<InvokeRpc> setupInvokeRpcReply(
- final AtomicReference<AssertionError> assertError, final CompositeNode output,
- final Exception error) {
- final AtomicReference<InvokeRpc> invokeRpcMsg = new AtomicReference<>();
-
- new Thread() {
- @Override
- public void run() {
- try {
- invokeRpcMsg.set(probeReg1.expectMsgClass(
- JavaTestKit.duration("5 seconds"), InvokeRpc.class));
-
- if(output != null) {
- probeReg1.reply(new RpcResponse(XmlUtils.outputCompositeNodeToXml(
- output, schemaContext)));
- } else {
- probeReg1.reply(new akka.actor.Status.Failure(error));
- }
-
- } catch(AssertionError e) {
- assertError.set(e);
- }
- }
-
- }.start();
-
- return invokeRpcMsg;
- }
private RemoteRpcProviderConfig getConfig(){
return new RemoteRpcProviderConfig.Builder("unit-test").build();
package org.opendaylight.controller.remote.rpc;
-import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.testkit.JavaTestKit;
import com.typesafe.config.Config;
import org.junit.AfterClass;
-import org.junit.Assert;
import org.junit.BeforeClass;
-import org.junit.Test;
-import org.opendaylight.controller.sal.core.api.Broker;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.opendaylight.controller.sal.core.api.model.SchemaService;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import scala.concurrent.Await;
-import scala.concurrent.duration.Duration;
-
-import java.util.concurrent.TimeUnit;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
public class RemoteRpcProviderTest {
@BeforeClass
public static void setup() throws InterruptedException {
moduleConfig = new RemoteRpcProviderConfig.Builder("odl-cluster-rpc").build();
- Config config = moduleConfig.get();
+ final Config config = moduleConfig.get();
system = ActorSystem.create("odl-cluster-rpc", config);
}
system = null;
}
- @Test
- public void testRemoteRpcProvider() throws Exception {
- RemoteRpcProvider rpcProvider = new RemoteRpcProvider(system, mock(RpcProvisionRegistry.class));
- Broker.ProviderSession session = mock(Broker.ProviderSession.class);
- SchemaService schemaService = mock(SchemaService.class);
- when(schemaService.getGlobalContext()). thenReturn(mock(SchemaContext.class));
- when(session.getService(SchemaService.class)).thenReturn(schemaService);
-
- rpcProvider.onSessionInitiated(session);
-
- ActorRef actorRef = Await.result(
- system.actorSelection(
- moduleConfig.getRpcManagerPath()).resolveOne(Duration.create(1, TimeUnit.SECONDS)),
- Duration.create(2, TimeUnit.SECONDS));
-
- Assert.assertTrue(actorRef.path().toString().contains(moduleConfig.getRpcManagerPath()));
- }
}
package org.opendaylight.controller.remote.rpc;
-import akka.actor.ActorRef;
-import akka.japi.Pair;
-import akka.testkit.JavaTestKit;
-
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.Futures;
-import static org.junit.Assert.assertEquals;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.opendaylight.controller.remote.rpc.messages.ExecuteRpc;
-import org.opendaylight.controller.remote.rpc.messages.InvokeRpc;
-import org.opendaylight.controller.remote.rpc.messages.RpcResponse;
-import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
-import org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.FindRouters;
-import org.opendaylight.controller.sal.connector.api.RpcRouter.RouteIdentifier;
-import org.opendaylight.controller.xml.codec.XmlUtils;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
-import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.any;
public class RpcBrokerTest extends AbstractRpcTest {
- @Test
- public void testInvokeRpcWithNoRemoteActor() throws Exception {
- new JavaTestKit(node1) {{
- CompositeNode input = makeRPCInput("foo");
-
- InvokeRpc invokeMsg = new InvokeRpc(TEST_RPC, null, input);
- rpcBroker1.tell(invokeMsg, getRef());
-
- probeReg1.expectMsgClass(duration("5 seconds"), RpcRegistry.Messages.FindRouters.class);
- probeReg1.reply(new RpcRegistry.Messages.FindRoutersReply(
- Collections.<Pair<ActorRef, Long>>emptyList()));
-
- akka.actor.Status.Failure failure = expectMsgClass(duration("5 seconds"),
- akka.actor.Status.Failure.class);
-
- assertEquals("failure.cause()", RpcErrorsException.class, failure.cause().getClass());
- }};
- }
-
-
- /**
- * This test method invokes and executes the remote rpc
- */
- //@Test
- public void testInvokeRpc() throws URISyntaxException {
- new JavaTestKit(node1) {{
- QName instanceQName = new QName(new URI("ns"), "instance");
-
- CompositeNode invokeRpcResult = makeRPCOutput("bar");
- RpcResult<CompositeNode> rpcResult =
- RpcResultBuilder.<CompositeNode>success(invokeRpcResult).build();
- ArgumentCaptor<CompositeNode> inputCaptor = new ArgumentCaptor<>();
- when(brokerSession.rpc(eq(TEST_RPC), inputCaptor.capture()))
- .thenReturn(Futures.immediateFuture(rpcResult));
-
- // invoke rpc
- CompositeNode input = makeRPCInput("foo");
- YangInstanceIdentifier instanceID = YangInstanceIdentifier.of(instanceQName);
- InvokeRpc invokeMsg = new InvokeRpc(TEST_RPC, instanceID, input);
- rpcBroker1.tell(invokeMsg, getRef());
-
- FindRouters findRouters = probeReg1.expectMsgClass(RpcRegistry.Messages.FindRouters.class);
- RouteIdentifier<?, ?, ?> routeIdentifier = findRouters.getRouteIdentifier();
- assertEquals("getType", TEST_RPC, routeIdentifier.getType());
- assertEquals("getRoute", instanceID, routeIdentifier.getRoute());
-
- probeReg1.reply(new RpcRegistry.Messages.FindRoutersReply(
- Arrays.asList(new Pair<ActorRef, Long>(rpcBroker2, 200L))));
-
- RpcResponse rpcResponse = expectMsgClass(duration("5 seconds"), RpcResponse.class);
- assertCompositeNodeEquals((CompositeNode)invokeRpcResult.getValue().get(0),
- XmlUtils.xmlToCompositeNode(rpcResponse.getResultCompositeNode()));
- assertCompositeNodeEquals(input, inputCaptor.getValue());
- }};
- }
-
- @Test
- public void testInvokeRpcWithNoOutput() {
- new JavaTestKit(node1) {{
-
- RpcResult<CompositeNode> rpcResult = RpcResultBuilder.<CompositeNode>success().build();
- when(brokerSession.rpc(eq(TEST_RPC), any(CompositeNode.class)))
- .thenReturn(Futures.immediateFuture(rpcResult));
-
- InvokeRpc invokeMsg = new InvokeRpc(TEST_RPC, null, makeRPCInput("foo"));
- rpcBroker1.tell(invokeMsg, getRef());
-
- probeReg1.expectMsgClass(RpcRegistry.Messages.FindRouters.class);
- probeReg1.reply(new RpcRegistry.Messages.FindRoutersReply(
- Arrays.asList(new Pair<ActorRef, Long>(rpcBroker2, 200L))));
-
- RpcResponse rpcResponse = expectMsgClass(duration("5 seconds"), RpcResponse.class);
-
- assertEquals("getResultCompositeNode", "", rpcResponse.getResultCompositeNode());
- }};
- }
-
- @Test
- public void testInvokeRpcWithExecuteFailure() {
- new JavaTestKit(node1) {{
-
- RpcResult<CompositeNode> rpcResult = RpcResultBuilder.<CompositeNode>failed()
- .withError(ErrorType.RPC, "tag", "error", "appTag", "info",
- new Exception("mock"))
- .build();
- when(brokerSession.rpc(eq(TEST_RPC), any(CompositeNode.class)))
- .thenReturn(Futures.immediateFuture(rpcResult));
-
- InvokeRpc invokeMsg = new InvokeRpc(TEST_RPC, null, makeRPCInput("foo"));
- rpcBroker1.tell(invokeMsg, getRef());
-
- probeReg1.expectMsgClass(RpcRegistry.Messages.FindRouters.class);
- probeReg1.reply(new RpcRegistry.Messages.FindRoutersReply(
- Arrays.asList(new Pair<ActorRef, Long>(rpcBroker2, 200L))));
-
- akka.actor.Status.Failure failure = expectMsgClass(duration("5 seconds"),
- akka.actor.Status.Failure.class);
-
- assertEquals("failure.cause()", RpcErrorsException.class, failure.cause().getClass());
-
- RpcErrorsException errorsEx = (RpcErrorsException)failure.cause();
- List<RpcError> rpcErrors = Lists.newArrayList(errorsEx.getRpcErrors());
- assertEquals("RpcErrors count", 1, rpcErrors.size());
- assertRpcErrorEquals(rpcErrors.get(0), ErrorSeverity.ERROR, ErrorType.RPC, "tag",
- "error", "appTag", "info", "mock");
- }};
- }
-
- @Test
- public void testInvokeRpcWithFindRoutersFailure() {
- new JavaTestKit(node1) {{
-
- InvokeRpc invokeMsg = new InvokeRpc(TEST_RPC, null, makeRPCInput("foo"));
- rpcBroker1.tell(invokeMsg, getRef());
-
- probeReg1.expectMsgClass(RpcRegistry.Messages.FindRouters.class);
- probeReg1.reply(new akka.actor.Status.Failure(new TestException()));
-
- akka.actor.Status.Failure failure = expectMsgClass(duration("5 seconds"),
- akka.actor.Status.Failure.class);
-
- assertEquals("failure.cause()", TestException.class, failure.cause().getClass());
- }};
- }
-
- @Test
- public void testExecuteRpc() {
- new JavaTestKit(node1) {{
-
- String xml = "<input xmlns=\"urn:test\"><input-data>foo</input-data></input>";
-
- CompositeNode invokeRpcResult = makeRPCOutput("bar");
- RpcResult<CompositeNode> rpcResult =
- RpcResultBuilder.<CompositeNode>success(invokeRpcResult).build();
- ArgumentCaptor<CompositeNode> inputCaptor = new ArgumentCaptor<>();
- when(brokerSession.rpc(eq(TEST_RPC), inputCaptor.capture()))
- .thenReturn(Futures.immediateFuture(rpcResult));
-
- ExecuteRpc executeMsg = new ExecuteRpc(xml, TEST_RPC);
-
- rpcBroker1.tell(executeMsg, getRef());
-
- RpcResponse rpcResponse = expectMsgClass(duration("5 seconds"), RpcResponse.class);
-
- assertCompositeNodeEquals((CompositeNode)invokeRpcResult.getValue().get(0),
- XmlUtils.xmlToCompositeNode(rpcResponse.getResultCompositeNode()));
- }};
- }
-
- @Test
- public void testExecuteRpcFailureWithRpcErrors() {
- new JavaTestKit(node1) {{
-
- String xml = "<input xmlns=\"urn:test\"><input-data>foo</input-data></input>";
-
- RpcResult<CompositeNode> rpcResult = RpcResultBuilder.<CompositeNode>failed()
- .withError(ErrorType.RPC, "tag1", "error", "appTag1", "info1",
- new Exception("mock"))
- .withWarning(ErrorType.PROTOCOL, "tag2", "warning", "appTag2", "info2", null)
- .build();
- when(brokerSession.rpc(eq(TEST_RPC), any(CompositeNode.class)))
- .thenReturn(Futures.immediateFuture(rpcResult));
-
- ExecuteRpc executeMsg = new ExecuteRpc(xml, TEST_RPC);
-
- rpcBroker1.tell(executeMsg, getRef());
-
- akka.actor.Status.Failure failure = expectMsgClass(duration("5 seconds"),
- akka.actor.Status.Failure.class);
-
- assertEquals("failure.cause()", RpcErrorsException.class, failure.cause().getClass());
-
- RpcErrorsException errorsEx = (RpcErrorsException)failure.cause();
- List<RpcError> rpcErrors = Lists.newArrayList(errorsEx.getRpcErrors());
- assertEquals("RpcErrors count", 2, rpcErrors.size());
- assertRpcErrorEquals(rpcErrors.get(0), ErrorSeverity.ERROR, ErrorType.RPC, "tag1",
- "error", "appTag1", "info1", "mock");
- assertRpcErrorEquals(rpcErrors.get(1), ErrorSeverity.WARNING, ErrorType.PROTOCOL, "tag2",
- "warning", "appTag2", "info2", null);
- }};
- }
-
- @Test
- public void testExecuteRpcFailureWithNoRpcErrors() {
- new JavaTestKit(node1) {{
-
- String xml = "<input xmlns=\"urn:test\"><input-data>foo</input-data></input>";
-
- RpcResult<CompositeNode> rpcResult = RpcResultBuilder.<CompositeNode>failed().build();
- when(brokerSession.rpc(eq(TEST_RPC), any(CompositeNode.class)))
- .thenReturn(Futures.immediateFuture(rpcResult));
-
- ExecuteRpc executeMsg = new ExecuteRpc(xml, TEST_RPC);
-
- rpcBroker1.tell(executeMsg, getRef());
-
- akka.actor.Status.Failure failure = expectMsgClass(duration("5 seconds"),
- akka.actor.Status.Failure.class);
-
- assertEquals("failure.cause()", RpcErrorsException.class, failure.cause().getClass());
-
- RpcErrorsException errorsEx = (RpcErrorsException)failure.cause();
- List<RpcError> rpcErrors = Lists.newArrayList(errorsEx.getRpcErrors());
- assertEquals("RpcErrors count", 1, rpcErrors.size());
- assertRpcErrorEquals(rpcErrors.get(0), ErrorSeverity.ERROR, ErrorType.RPC,
- "operation-failed", "failed", null, null, null);
- }};
- }
-
- @Test
- public void testExecuteRpcFailureWithException() {
- new JavaTestKit(node1) {{
-
- String xml = "<input xmlns=\"urn:test\"><input-data>foo</input-data></input>";
-
- when(brokerSession.rpc(eq(TEST_RPC), any(CompositeNode.class)))
- .thenReturn(Futures.<RpcResult<CompositeNode>>immediateFailedFuture(
- new TestException()));
-
- ExecuteRpc executeMsg = new ExecuteRpc(xml, TEST_RPC);
-
- rpcBroker1.tell(executeMsg, getRef());
-
- akka.actor.Status.Failure failure = expectMsgClass(duration("5 seconds"),
- akka.actor.Status.Failure.class);
- assertEquals("failure.cause()", TestException.class, failure.cause().getClass());
- }};
- }
}
package org.opendaylight.controller.remote.rpc;
-import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.testkit.JavaTestKit;
import com.typesafe.config.ConfigFactory;
import org.junit.AfterClass;
import org.junit.BeforeClass;
-import org.junit.Test;
-import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
-import org.opendaylight.yangtools.yang.common.QName;
-
-import java.net.URI;
-import java.net.URISyntaxException;
public class RpcListenerTest {
system = null;
}
- @Test
- public void testRpcAdd() throws URISyntaxException {
- new JavaTestKit(system) {
- {
- JavaTestKit probeReg = new JavaTestKit(system);
- ActorRef rpcRegistry = probeReg.getRef();
-
- RpcListener rpcListener = new RpcListener(rpcRegistry);
-
- QName qName = new QName(new URI("actor2"), "actor2");
-
- rpcListener.onRpcImplementationAdded(qName);
- probeReg.expectMsgClass(RpcRegistry.Messages.AddOrUpdateRoutes.class);
- }};
-
- }
-
- @Test
- public void testRpcRemove() throws URISyntaxException {
- new JavaTestKit(system) {
- {
- JavaTestKit probeReg = new JavaTestKit(system);
- ActorRef rpcRegistry = probeReg.getRef();
-
- RpcListener rpcListener = new RpcListener(rpcRegistry);
-
- QName qName = new QName(new URI("actor2"), "actor2");
-
- rpcListener.onRpcImplementationRemoved(qName);
- probeReg.expectMsgClass(RpcRegistry.Messages.RemoveRoutes.class);
- }};
-
- }
}
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-core-spi</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-data-composite-node</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-codec-gson</artifactId>
+++ /dev/null
-/*
- * 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.sal.rest.gson;
-
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonIOException;
-import com.google.gson.JsonNull;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParseException;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.JsonSyntaxException;
-import com.google.gson.internal.LazilyParsedNumber;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.MalformedJsonException;
-import java.io.EOFException;
-import java.io.IOException;
-
-/**
- * @deprecated class will be removed in Lithium release
- *
- * This class parses JSON elements from a gson JsonReader. It disallows multiple elements of the same name unlike the
- * default gson JsonParser."
- */
-@Deprecated
-public class JsonParser {
- public JsonElement parse(final JsonReader reader) throws JsonIOException, JsonSyntaxException {
- // code copied from gson's JsonParser and Stream classes
-
- final boolean lenient = reader.isLenient();
- reader.setLenient(true);
- boolean isEmpty = true;
- try {
- reader.peek();
- isEmpty = false;
- return read(reader);
- } catch (final EOFException e) {
- if (isEmpty) {
- return JsonNull.INSTANCE;
- }
- // The stream ended prematurely so it is likely a syntax error.
- throw new JsonSyntaxException(e);
- } catch (final MalformedJsonException e) {
- throw new JsonSyntaxException(e);
- } catch (final IOException e) {
- throw new JsonIOException(e);
- } catch (final NumberFormatException e) {
- throw new JsonSyntaxException(e);
- } catch (StackOverflowError | OutOfMemoryError e) {
- throw new JsonParseException("Failed parsing JSON source: " + reader + " to Json", e);
- } finally {
- reader.setLenient(lenient);
- }
- }
-
- public JsonElement read(final JsonReader in) throws IOException {
- switch (in.peek()) {
- case STRING:
- return new JsonPrimitive(in.nextString());
- case NUMBER:
- final String number = in.nextString();
- return new JsonPrimitive(new LazilyParsedNumber(number));
- case BOOLEAN:
- return new JsonPrimitive(in.nextBoolean());
- case NULL:
- in.nextNull();
- return JsonNull.INSTANCE;
- case BEGIN_ARRAY:
- final JsonArray array = new JsonArray();
- in.beginArray();
- while (in.hasNext()) {
- array.add(read(in));
- }
- in.endArray();
- return array;
- case BEGIN_OBJECT:
- final JsonObject object = new JsonObject();
- in.beginObject();
- while (in.hasNext()) {
- final String childName = in.nextName();
- if (object.has(childName)) {
- throw new JsonSyntaxException("Duplicate name " + childName + " in JSON input.");
- }
- object.add(childName, read(in));
- }
- in.endObject();
- return object;
- case END_DOCUMENT:
- case NAME:
- case END_OBJECT:
- case END_ARRAY:
- default:
- throw new IllegalArgumentException();
- }
- }
-}
+++ /dev/null
-/*
- * 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.sal.rest.impl;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.google.common.base.Preconditions;
-import com.google.gson.stream.JsonWriter;
-import java.io.IOException;
-import java.net.URI;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import javax.activation.UnsupportedDataTypeException;
-import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
-import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
-import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
-import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO.IdentityValue;
-import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO.Predicate;
-import org.opendaylight.controller.sal.restconf.impl.RestCodec;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-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.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-class JsonMapper {
- private static final Logger LOG = LoggerFactory.getLogger(JsonMapper.class);
- private final DOMMountPoint mountPoint;
-
- public JsonMapper(final DOMMountPoint mountPoint) {
- this.mountPoint = mountPoint;
- }
-
- public void write(final JsonWriter writer, final CompositeNode data, final DataNodeContainer schema)
- throws IOException {
- Preconditions.checkNotNull(writer);
- Preconditions.checkNotNull(data);
- Preconditions.checkNotNull(schema);
-
- writer.beginObject();
-
- if (schema instanceof ContainerSchemaNode) {
- writeContainer(writer, data, (ContainerSchemaNode) schema);
- } else if (schema instanceof ListSchemaNode) {
- writeList(writer, null, data, (ListSchemaNode) schema);
- } else {
- throw new UnsupportedDataTypeException(
- "Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet.");
- }
-
- writer.endObject();
- }
-
- private void writeChildrenOfParent(final JsonWriter writer, final CompositeNode parent,
- final DataNodeContainer parentSchema) throws IOException {
- checkNotNull(parent);
-
- final Set<QName> foundLists = new HashSet<>();
-
- Collection<DataSchemaNode> parentSchemaChildNodes = parentSchema == null ? Collections.<DataSchemaNode> emptySet()
- : parentSchema.getChildNodes();
-
- for (Node<?> child : parent.getValue()) {
- DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchemaChildNodes);
-
- if (childSchema == null) {
- // Node may not conform to schema or allows "anyxml" - we'll process it.
-
- LOG.debug("No schema found for data node \"{}\"", child.getNodeType());
-
- if (!foundLists.contains(child.getNodeType())) {
- handleNoSchemaFound(writer, child, parent);
-
- // Since we don't have a schema, we don't know which nodes are supposed to be
- // lists so treat every one as a potential list to avoid outputting duplicates.
-
- foundLists.add(child.getNodeType());
- }
- } else if (childSchema instanceof ContainerSchemaNode) {
- Preconditions.checkState(child instanceof CompositeNode,
- "Data representation of Container should be CompositeNode - %s", child.getNodeType());
- writeContainer(writer, (CompositeNode) child, (ContainerSchemaNode) childSchema);
- } else if (childSchema instanceof ListSchemaNode) {
- if (!foundLists.contains(child.getNodeType())) {
- Preconditions.checkState(child instanceof CompositeNode,
- "Data representation of List should be CompositeNode - %s", child.getNodeType());
- foundLists.add(child.getNodeType());
- writeList(writer, parent, (CompositeNode) child, (ListSchemaNode) childSchema);
- }
- } else if (childSchema instanceof LeafListSchemaNode) {
- if (!foundLists.contains(child.getNodeType())) {
- Preconditions.checkState(child instanceof SimpleNode<?>,
- "Data representation of LeafList should be SimpleNode - %s", child.getNodeType());
- foundLists.add(child.getNodeType());
- writeLeafList(writer, parent, (SimpleNode<?>) child, (LeafListSchemaNode) childSchema);
- }
- } else if (childSchema instanceof LeafSchemaNode) {
- Preconditions.checkState(child instanceof SimpleNode<?>,
- "Data representation of LeafList should be SimpleNode - %s", child.getNodeType());
- writeLeaf(writer, (SimpleNode<?>) child, (LeafSchemaNode) childSchema);
- } else if (childSchema instanceof AnyXmlSchemaNode) {
- if (child instanceof CompositeNode) {
- writeContainer(writer, (CompositeNode) child, null);
- } else {
- handleNoSchemaFound(writer, child, parent);
- }
- } else {
- throw new UnsupportedDataTypeException("Schema can be ContainerSchemaNode, ListSchemaNode, "
- + "LeafListSchemaNode, or LeafSchemaNode. Other types are not supported yet.");
- }
- }
- }
-
- private static void writeValue(final JsonWriter writer, final Object value) throws IOException {
- writer.value(value == null ? "" : String.valueOf(value));
- }
-
- private void handleNoSchemaFound(final JsonWriter writer, final Node<?> node, final CompositeNode parent)
- throws IOException {
- if (node instanceof SimpleNode<?>) {
- List<SimpleNode<?>> nodeLeafList = parent.getSimpleNodesByName(node.getNodeType());
- if (nodeLeafList.size() == 1) {
- writeName(node, null, writer);
- writeValue(writer, node.getValue());
- } else { // more than 1, write as a json array
- writeName(node, null, writer);
- writer.beginArray();
- for (SimpleNode<?> leafNode : nodeLeafList) {
- writeValue(writer, leafNode.getValue());
- }
-
- writer.endArray();
- }
- } else { // CompositeNode
- Preconditions.checkState(node instanceof CompositeNode,
- "Data representation of Container should be CompositeNode - %s", node.getNodeType());
-
- List<CompositeNode> nodeList = parent.getCompositesByName(node.getNodeType());
- if (nodeList.size() == 1) {
- writeContainer(writer, (CompositeNode) node, null);
- } else { // more than 1, write as a json array
- writeList(writer, parent, (CompositeNode) node, null);
- }
- }
- }
-
- private static DataSchemaNode findFirstSchemaForNode(final Node<?> node, final Iterable<DataSchemaNode> dataSchemaNode) {
- for (DataSchemaNode dsn : dataSchemaNode) {
- if (node.getNodeType().equals(dsn.getQName())) {
- return dsn;
- }
- if (dsn instanceof ChoiceSchemaNode) {
- for (ChoiceCaseNode choiceCase : ((ChoiceSchemaNode) dsn).getCases()) {
- DataSchemaNode foundDsn = findFirstSchemaForNode(node, choiceCase.getChildNodes());
- if (foundDsn != null) {
- return foundDsn;
- }
- }
- }
- }
- return null;
- }
-
- 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(final JsonWriter writer, final CompositeNode nodeParent, final CompositeNode node,
- final ListSchemaNode schema) throws IOException {
- writeName(node, schema, writer);
- writer.beginArray();
-
- if (nodeParent != null) {
- List<CompositeNode> nodeLists = nodeParent.getCompositesByName(node.getNodeType());
- for (CompositeNode nodeList : nodeLists) {
- writer.beginObject();
- writeChildrenOfParent(writer, nodeList, schema);
- writer.endObject();
- }
- } else {
- writer.beginObject();
- writeChildrenOfParent(writer, node, schema);
- writer.endObject();
- }
-
- writer.endArray();
- }
-
- private void writeLeafList(final JsonWriter writer, final CompositeNode nodeParent, final SimpleNode<?> node,
- final LeafListSchemaNode schema) throws IOException {
- writeName(node, schema, writer);
- writer.beginArray();
-
- List<SimpleNode<?>> nodeLeafLists = nodeParent.getSimpleNodesByName(node.getNodeType());
- for (SimpleNode<?> nodeLeafList : nodeLeafLists) {
- writeValueOfNodeByType(writer, nodeLeafList, schema.getType(), schema);
- }
- writer.endArray();
- }
-
- 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(final JsonWriter writer, final SimpleNode<?> node,
- final TypeDefinition<?> type, final DataSchemaNode schema) throws IOException {
-
- TypeDefinition<?> baseType = RestUtil.resolveBaseTypeFrom(type);
-
- if (node.getValue() == null && !(baseType instanceof EmptyTypeDefinition)) {
- LOG.debug("While generationg JSON output null value was found for type {}.", baseType.getClass()
- .getSimpleName());
- }
-
- if (baseType instanceof IdentityrefTypeDefinition) {
- if (node.getValue() instanceof QName) {
- IdentityValuesDTO valueDTO = (IdentityValuesDTO) RestCodec.from(baseType, mountPoint).serialize(
- node.getValue());
- IdentityValue valueFromDTO = valueDTO.getValuesWithNamespaces().get(0);
- String moduleName;
- if (mountPoint != null) {
- moduleName = ControllerContext.getInstance().findModuleNameByNamespace(mountPoint,
- URI.create(valueFromDTO.getNamespace()));
- } else {
- moduleName = ControllerContext.getInstance().findModuleNameByNamespace(
- URI.create(valueFromDTO.getNamespace()));
- }
- writer.value(moduleName + ":" + valueFromDTO.getValue());
- } else {
- writeStringRepresentation(writer, node, baseType, QName.class);
- }
- } else if (baseType instanceof InstanceIdentifierTypeDefinition) {
- if (node.getValue() instanceof YangInstanceIdentifier) {
- IdentityValuesDTO valueDTO = (IdentityValuesDTO) RestCodec.from(baseType, mountPoint).serialize(
- node.getValue());
- writeIdentityValuesDTOToJson(writer, valueDTO);
- } else {
- writeStringRepresentation(writer, node, baseType, YangInstanceIdentifier.class);
- }
- } else if (baseType instanceof DecimalTypeDefinition || baseType instanceof IntegerTypeDefinition
- || baseType instanceof UnsignedIntegerTypeDefinition) {
- writer.value(new NumberForJsonWriter((String) RestCodec.from(baseType, mountPoint).serialize(
- node.getValue())));
- } else if (baseType instanceof BooleanTypeDefinition) {
- writer.value(Boolean.parseBoolean((String) RestCodec.from(baseType, mountPoint).serialize(node.getValue())));
- } else if (baseType instanceof EmptyTypeDefinition) {
- writeEmptyDataTypeToJson(writer);
- } else {
- String value = String.valueOf(RestCodec.from(baseType, mountPoint).serialize(node.getValue()));
- if (value == null) {
- value = String.valueOf(node.getValue());
- }
- writer.value(value.equals("null") ? "" : value);
- }
- }
-
- private static void writeIdentityValuesDTOToJson(final JsonWriter writer, final IdentityValuesDTO valueDTO)
- throws IOException {
- StringBuilder result = new StringBuilder();
- for (IdentityValue identityValue : valueDTO.getValuesWithNamespaces()) {
- result.append('/');
-
- writeModuleNameAndIdentifier(result, identityValue);
- if (identityValue.getPredicates() != null && !identityValue.getPredicates().isEmpty()) {
- for (Predicate predicate : identityValue.getPredicates()) {
- IdentityValue identityValuePredicate = predicate.getName();
- result.append('[');
- if (identityValuePredicate == null) {
- result.append('.');
- } else {
- writeModuleNameAndIdentifier(result, identityValuePredicate);
- }
- result.append("='");
- result.append(predicate.getValue());
- result.append("']");
- }
- }
- }
-
- writer.value(result.toString());
- }
-
- private static void writeModuleNameAndIdentifier(final StringBuilder result, final IdentityValue identityValue) {
- String moduleName = ControllerContext.getInstance().findModuleNameByNamespace(
- URI.create(identityValue.getNamespace()));
- if (moduleName != null && !moduleName.isEmpty()) {
- result.append(moduleName);
- result.append(':');
- }
- result.append(identityValue.getValue());
- }
-
- private static void writeStringRepresentation(final JsonWriter writer, final SimpleNode<?> node,
- final TypeDefinition<?> baseType, final Class<?> requiredType) throws IOException {
- Object value = node.getValue();
- LOG.debug("Value of {}:{} is not instance of {} but is {}", baseType.getQName().getNamespace(), baseType
- .getQName().getLocalName(), requiredType.getClass(), node.getValue().getClass());
- if (value == null) {
- writer.value("");
- } else {
- writer.value(String.valueOf(value));
- }
- }
-
- private void writeEmptyDataTypeToJson(final JsonWriter writer) throws IOException {
- writer.beginArray();
- writer.nullValue();
- writer.endArray();
- }
-
- private void writeName(final Node<?> node, final DataSchemaNode schema, final JsonWriter writer) throws IOException {
- String nameForOutput = node.getNodeType().getLocalName();
- if (schema != null && schema.isAugmenting()) {
- ControllerContext contContext = ControllerContext.getInstance();
- CharSequence moduleName = null;
- if (mountPoint == null) {
- moduleName = contContext.toRestconfIdentifier(schema.getQName());
- } else {
- moduleName = contContext.toRestconfIdentifier(mountPoint, schema.getQName());
- }
- if (moduleName != null) {
- nameForOutput = moduleName.toString();
- } else {
- LOG.info("Module '{}' was not found in schema from mount point", schema.getQName());
- }
- }
- writer.name(nameForOutput);
- }
-
- private static final class NumberForJsonWriter extends Number {
-
- private static final long serialVersionUID = -3147729419814417666L;
- private final String value;
-
- public NumberForJsonWriter(final String value) {
- this.value = value;
- }
-
- @Override
- public int intValue() {
- throw new IllegalStateException("Should not be invoked");
- }
-
- @Override
- public long longValue() {
- throw new IllegalStateException("Should not be invoked");
- }
-
- @Override
- public float floatValue() {
- throw new IllegalStateException("Should not be invoked");
- }
-
- @Override
- public double doubleValue() {
- throw new IllegalStateException("Should not be invoked");
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- }
-
-}
+++ /dev/null
-/*
- * 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.sal.rest.impl;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.ext.MessageBodyReader;
-import javax.ws.rs.ext.Provider;
-import org.opendaylight.controller.sal.rest.api.Draft02;
-import org.opendaylight.controller.sal.rest.api.RestconfService;
-import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @deprecated class will be removed in Lithium release
- */
-@Provider
-@Consumes({ Draft02.MediaTypes.DATA + RestconfService.JSON, Draft02.MediaTypes.OPERATION + RestconfService.JSON,
- MediaType.APPLICATION_JSON })
-public enum JsonToCompositeNodeProvider implements MessageBodyReader<Node<?>> {
- INSTANCE;
-
- private final static Logger LOG = LoggerFactory.getLogger(JsonToCompositeNodeProvider.class);
-
- @Override
- public boolean isReadable(final Class<?> type, final Type genericType, final Annotation[] annotations,
- final MediaType mediaType) {
- return true;
- }
-
- @Override
- public Node<?> readFrom(final Class<Node<?>> type, final Type genericType,
- final Annotation[] annotations, final MediaType mediaType,
- final MultivaluedMap<String, String> httpHeaders, final InputStream entityStream) throws IOException,
- WebApplicationException {
- try {
- return JsonToCompositeNodeReader.read(entityStream);
- } catch (final Exception e) {
- LOG.debug("Error parsing json input", e);
-
- throw new RestconfDocumentedException("Error parsing input: " + e.getMessage(), ErrorType.PROTOCOL,
- ErrorTag.MALFORMED_MESSAGE);
- }
- }
-}
+++ /dev/null
-/*
- * 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.sal.rest.impl;
-
-import com.google.common.base.Splitter;
-import com.google.common.collect.Iterators;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.stream.JsonReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URI;
-import java.util.Iterator;
-import java.util.Map.Entry;
-import java.util.Set;
-import org.opendaylight.controller.sal.rest.gson.JsonParser;
-import org.opendaylight.controller.sal.rest.impl.RestUtil.PrefixMapingFromJson;
-import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
-import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @deprecated class will be removed in Lithium release
- */
-@Deprecated
-class JsonToCompositeNodeReader {
- private static final Logger LOG = LoggerFactory.getLogger(JsonToCompositeNodeReader.class);
- private static final Splitter COLON_SPLITTER = Splitter.on(':');
-
- private JsonToCompositeNodeReader() {
-
- }
-
- public static CompositeNodeWrapper read(final InputStream entityStream) throws UnsupportedFormatException {
- final JsonParser parser = new JsonParser();
-
- final JsonElement rootElement = parser.parse(new JsonReader(new InputStreamReader(entityStream)));
- if (rootElement.isJsonNull()) {
- // no content, so return null to indicate no input
- return null;
- }
-
- if (!rootElement.isJsonObject()) {
- throw new UnsupportedFormatException("Root element of Json has to be Object");
- }
-
- final Set<Entry<String, JsonElement>> entrySetsOfRootJsonObject = rootElement.getAsJsonObject().entrySet();
- if (entrySetsOfRootJsonObject.size() != 1) {
- throw new UnsupportedFormatException("Json Object should contain one element");
- }
-
- final Entry<String, JsonElement> childEntry = entrySetsOfRootJsonObject.iterator().next();
- final String firstElementName = childEntry.getKey();
- final JsonElement firstElementType = childEntry.getValue();
- if (firstElementType.isJsonObject()) {
- // container in yang
- return createStructureWithRoot(firstElementName, firstElementType.getAsJsonObject());
- }
- if (firstElementType.isJsonArray()) {
- // list in yang
- if (firstElementType.getAsJsonArray().size() == 1) {
- final JsonElement firstElementInArray = firstElementType.getAsJsonArray().get(0);
- if (firstElementInArray.isJsonObject()) {
- return createStructureWithRoot(firstElementName, firstElementInArray.getAsJsonObject());
- }
- throw new UnsupportedFormatException(
- "Array as the first element in Json Object can have only Object element");
- }
- }
- throw new UnsupportedFormatException(
- "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet.");
- }
-
- private static CompositeNodeWrapper createStructureWithRoot(final String rootObjectName, final JsonObject rootObject) {
- final CompositeNodeWrapper firstNode = new CompositeNodeWrapper(getNamespaceFor(rootObjectName),
- getLocalNameFor(rootObjectName));
- for (final Entry<String, JsonElement> childOfFirstNode : rootObject.entrySet()) {
- addChildToParent(childOfFirstNode.getKey(), childOfFirstNode.getValue(), firstNode);
- }
- return firstNode;
- }
-
- private static void addChildToParent(final String childName, final JsonElement childType,
- final CompositeNodeWrapper parent) {
- if (childType.isJsonObject()) {
- final CompositeNodeWrapper child = new CompositeNodeWrapper(getNamespaceFor(childName),
- getLocalNameFor(childName));
- parent.addValue(child);
- for (final Entry<String, JsonElement> childOfChild : childType.getAsJsonObject().entrySet()) {
- addChildToParent(childOfChild.getKey(), childOfChild.getValue(), child);
- }
- } else if (childType.isJsonArray()) {
- if (childType.getAsJsonArray().size() == 1 && childType.getAsJsonArray().get(0).isJsonNull()) {
- parent.addValue(new EmptyNodeWrapper(getNamespaceFor(childName), getLocalNameFor(childName)));
-
- } else {
- for (final JsonElement childOfChildType : childType.getAsJsonArray()) {
- addChildToParent(childName, childOfChildType, parent);
- }
- }
- } else if (childType.isJsonPrimitive()) {
- final JsonPrimitive childPrimitive = childType.getAsJsonPrimitive();
- final String value = childPrimitive.getAsString().trim();
- parent.addValue(new SimpleNodeWrapper(getNamespaceFor(childName), getLocalNameFor(childName),
- resolveValueOfElement(value)));
- } else {
- LOG.debug("Ignoring unhandled child type {}", childType);
- }
- }
-
- /**
- * Transform input value to URI instance.
- *
- * Input string has to be in format moduleName:localName. moduleName part is then transformed to URI instance.
- * If moduleName part contains character like "<" or ">" then null value is returned because they
- * aren't valid URI characters.
- *
- * @param jsonElementName
- * value in format moduleName:localName
- * @return
- */
- private static URI getNamespaceFor(final String jsonElementName) {
- final Iterator<String> it = COLON_SPLITTER.split(jsonElementName).iterator();
-
- // The string needs to be in form "moduleName:localName"
- if (it.hasNext()) {
- final String maybeURI = it.next();
- if (Iterators.size(it) == 1) {
- try {
- return URI.create(maybeURI);
- } catch (final IllegalArgumentException e) {
- LOG.debug("Value {} couldn't be interpreted as URI.", maybeURI);
- }
- }
- }
-
- return null;
- }
-
- private static String getLocalNameFor(final String jsonElementName) {
- final Iterator<String> it = COLON_SPLITTER.split(jsonElementName).iterator();
-
- // The string needs to me in form "moduleName:localName"
- final String ret = Iterators.get(it, 1, null);
- return ret != null && !it.hasNext() ? ret : jsonElementName;
- }
-
- private static Object resolveValueOfElement(final String value) {
- // it could be instance-identifier Built-In Type
- if (!value.isEmpty() && value.charAt(0) == '/') {
- final IdentityValuesDTO resolvedValue = RestUtil.asInstanceIdentifier(value, new PrefixMapingFromJson());
- if (resolvedValue != null) {
- return resolvedValue;
- }
- }
-
- // it could be identityref Built-In Type therefore it is necessary to look at value as module_name:local_name
- final URI namespace = getNamespaceFor(value);
- if (namespace != null) {
- return new IdentityValuesDTO(namespace.toString(), getLocalNameFor(value), null, value);
- }
-
- // it is not "prefix:value" but just "value"
- return value;
- }
-
-}
return;
}
+ @SuppressWarnings("unchecked")
final InstanceIdentifierContext<SchemaNode> context = (InstanceIdentifierContext<SchemaNode>) t.getInstanceIdentifierContext();
SchemaPath path = context.getSchemaNode().getPath();
- boolean isDataRoot = false;
+ final JsonWriter jsonWriter = createJsonWriter(entityStream);
+ jsonWriter.beginObject();
+ writeNormalizedNode(jsonWriter,path,context,data);
+ jsonWriter.endObject();
+ jsonWriter.flush();
+ }
+
+ private void writeNormalizedNode(JsonWriter jsonWriter, SchemaPath path,
+ InstanceIdentifierContext<SchemaNode> context, NormalizedNode<?, ?> data) throws IOException {
+ final NormalizedNodeWriter nnWriter;
if (SchemaPath.ROOT.equals(path)) {
- isDataRoot = true;
+ /*
+ * Creates writer without initialNs and we write children of root data container
+ * which is not visible in restconf
+ */
+ nnWriter = createNormalizedNodeWriter(context,path,jsonWriter);
+ writeChildren(nnWriter,(ContainerNode) data);
} else if (context.getSchemaNode() instanceof RpcDefinition) {
- isDataRoot = true;
+ /*
+ * RpcDefinition is not supported as initial codec in JSONStreamWriter,
+ * so we need to emit initial output declaratation..
+ */
path = ((RpcDefinition) context.getSchemaNode()).getOutput().getPath();
+ nnWriter = createNormalizedNodeWriter(context,path,jsonWriter);
+ jsonWriter.name("output");
+ jsonWriter.beginObject();
+ writeChildren(nnWriter, (ContainerNode) data);
+ jsonWriter.endObject();
} else {
path = path.getParent();
- // FIXME: Add proper handling of reading root.
- }
- final JsonWriter jsonWriter = createJsonWriter(entityStream);
- final NormalizedNodeWriter nnWriter = createNormalizedNodeWriter(context,path,jsonWriter);
-
- jsonWriter.beginObject();
- if(isDataRoot) {
- writeDataRoot(nnWriter,(ContainerNode) data);
- } else {
if(data instanceof MapEntryNode) {
data = ImmutableNodes.mapNodeBuilder(data.getNodeType()).withChild(((MapEntryNode) data)).build();
}
+ nnWriter = createNormalizedNodeWriter(context,path,jsonWriter);
nnWriter.write(data);
}
-
nnWriter.flush();
- jsonWriter.endObject();
- jsonWriter.flush();
+ }
+
+ private void writeChildren(final NormalizedNodeWriter nnWriter, final ContainerNode data) throws IOException {
+ for(final DataContainerChild<? extends PathArgument, ?> child : data.getValue()) {
+ nnWriter.write(child);
+ }
}
private NormalizedNodeWriter createNormalizedNodeWriter(final InstanceIdentifierContext<SchemaNode> context,
final SchemaNode schema = context.getSchemaNode();
final JSONCodecFactory codecs = getCodecFactory(context);
- URI initialNs = null;
- if ( ! (schema instanceof RpcDefinition) && (!((DataSchemaNode)schema).isAugmenting() && !(schema instanceof SchemaContext))) {
+ final URI initialNs;
+ if ((schema instanceof DataSchemaNode)
+ && !((DataSchemaNode)schema).isAugmenting()
+ && !(schema instanceof SchemaContext)) {
+ initialNs = schema.getQName().getNamespace();
+ } else if (schema instanceof RpcDefinition) {
initialNs = schema.getQName().getNamespace();
+ } else {
+ initialNs = null;
}
final NormalizedNodeStreamWriter streamWriter = JSONNormalizedNodeStreamWriter.createNestedWriter(codecs,path,initialNs,jsonWriter);
return NormalizedNodeWriter.forStreamWriter(streamWriter);
}
- private JSONCodecFactory getCodecFactory(final InstanceIdentifierContext context) {
+ private JSONCodecFactory getCodecFactory(final InstanceIdentifierContext<?> context) {
// TODO: Performance: Cache JSON Codec factory and schema context
return JSONCodecFactory.create(context.getSchemaContext());
}
- private void writeDataRoot(final NormalizedNodeWriter nnWriter, final ContainerNode data) throws IOException {
- for(final DataContainerChild<? extends PathArgument, ?> child : data.getValue()) {
- nnWriter.write(child);
- }
- }
-
}
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
+import javax.xml.XMLConstants;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import org.opendaylight.controller.sal.restconf.impl.InstanceIdentifierContext;
import org.opendaylight.controller.sal.restconf.impl.NormalizedNodeContext;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
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.stream.NormalizedNodeStreamWriter;
NormalizedNode<?, ?> data = t.getData();
SchemaPath schemaPath = pathContext.getSchemaNode().getPath();
- boolean isDataRoot = false;
+
+
+ writeNormalizedNode(xmlWriter,schemaPath,pathContext,data);
+ }
+
+ private void writeNormalizedNode(XMLStreamWriter xmlWriter, SchemaPath schemaPath,InstanceIdentifierContext<?> pathContext, NormalizedNode<?, ?> data) throws IOException {
+ final NormalizedNodeWriter nnWriter;
+ final SchemaContext schemaCtx = pathContext.getSchemaContext();
if (SchemaPath.ROOT.equals(schemaPath)) {
- isDataRoot = true;
+ nnWriter = createNormalizedNodeWriter(xmlWriter, schemaCtx, schemaPath);
+ writeElements(xmlWriter, nnWriter, (ContainerNode) data);
} else if (pathContext.getSchemaNode() instanceof RpcDefinition) {
- isDataRoot = true;
- schemaPath = ((RpcDefinition) pathContext.getSchemaNode()).getOutput().getPath();
- } else {
- schemaPath = schemaPath.getParent();
- }
-
- final NormalizedNodeStreamWriter jsonWriter = XMLStreamNormalizedNodeStreamWriter.create(xmlWriter,
- pathContext.getSchemaContext(), schemaPath);
- final NormalizedNodeWriter nnWriter = NormalizedNodeWriter.forStreamWriter(jsonWriter);
- if (isDataRoot) {
- writeRootElement(xmlWriter, nnWriter, (ContainerNode) data);
+ nnWriter = createNormalizedNodeWriter(xmlWriter, schemaCtx, ((RpcDefinition) pathContext.getSchemaNode()).getOutput().getPath());
+ writeElements(xmlWriter, nnWriter, (ContainerNode) data);
} else {
+ nnWriter = createNormalizedNodeWriter(xmlWriter, schemaCtx, schemaPath.getParent());
if (data instanceof MapEntryNode) {
// Restconf allows returning one list item. We need to wrap it
// in map node in order to serialize it properly
data = ImmutableNodes.mapNodeBuilder(data.getNodeType()).addChild((MapEntryNode) data).build();
}
nnWriter.write(data);
- nnWriter.flush();
}
+ nnWriter.flush();
+ }
+
+ private NormalizedNodeWriter createNormalizedNodeWriter(XMLStreamWriter xmlWriter,
+ SchemaContext schemaContext, SchemaPath schemaPath) {
+ NormalizedNodeStreamWriter xmlStreamWriter = XMLStreamNormalizedNodeStreamWriter.create(xmlWriter, schemaContext, schemaPath);
+ return NormalizedNodeWriter.forStreamWriter(xmlStreamWriter);
}
- private void writeRootElement(final XMLStreamWriter xmlWriter, final NormalizedNodeWriter nnWriter, final ContainerNode data)
+ private void writeElements(final XMLStreamWriter xmlWriter, final NormalizedNodeWriter nnWriter, final ContainerNode data)
throws IOException {
try {
- final QName name = SchemaContext.NAME;
- xmlWriter.writeStartElement(name.getNamespace().toString(), name.getLocalName());
- for (final DataContainerChild<? extends PathArgument, ?> child : data.getValue()) {
+ final QName name = data.getNodeType();
+ xmlWriter.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX, name.getLocalName(), name.getNamespace().toString());
+ xmlWriter.writeDefaultNamespace(name.getNamespace().toString());
+ for(NormalizedNode<?,?> child : data.getValue()) {
nnWriter.write(child);
}
nnWriter.flush();
+++ /dev/null
-/*
- * 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.sal.rest.impl;
-
-import com.google.common.base.Charsets;
-import com.google.gson.stream.JsonWriter;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.MessageBodyWriter;
-import javax.ws.rs.ext.Provider;
-import org.opendaylight.controller.sal.rest.api.Draft02;
-import org.opendaylight.controller.sal.rest.api.RestconfService;
-import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
-import org.opendaylight.controller.sal.restconf.impl.StructuredData;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-
-/**
- * @deprecated class will be removed in Lithium release
- */
-@Provider
-@Produces({ Draft02.MediaTypes.API + RestconfService.JSON, Draft02.MediaTypes.DATA + RestconfService.JSON,
- Draft02.MediaTypes.OPERATION + RestconfService.JSON, MediaType.APPLICATION_JSON })
-public enum StructuredDataToJsonProvider implements MessageBodyWriter<StructuredData> {
- INSTANCE;
-
- @Override
- public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) {
- return type.equals(StructuredData.class);
- }
-
- @Override
- public long getSize(final StructuredData t, final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) {
- return -1;
- }
-
- @Override
- public void writeTo(final StructuredData t, final Class<?> type, final Type genericType, final Annotation[] annotations,
- final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream)
- throws IOException, WebApplicationException {
- final CompositeNode data = t.getData();
- if (data == null) {
- throw new RestconfDocumentedException(Response.Status.NOT_FOUND);
- }
-
- final JsonWriter writer = new JsonWriter(new OutputStreamWriter(entityStream, Charsets.UTF_8));
-
- if (t.isPrettyPrintMode()) {
- writer.setIndent(" ");
- } else {
- writer.setIndent("");
- }
- final JsonMapper jsonMapper = new JsonMapper(t.getMountPoint());
- jsonMapper.write(writer, data, (DataNodeContainer) t.getSchema());
- writer.flush();
- }
-}
+++ /dev/null
-/*
- * 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.sal.rest.impl;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.MessageBodyWriter;
-import javax.ws.rs.ext.Provider;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import org.opendaylight.controller.sal.rest.api.Draft02;
-import org.opendaylight.controller.sal.rest.api.RestconfService;
-import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
-import org.opendaylight.controller.sal.restconf.impl.StructuredData;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-
-/**
- * @deprecated class will be removed in Lithium release
- */
-@Provider
-@Produces({ Draft02.MediaTypes.API + RestconfService.XML, Draft02.MediaTypes.DATA + RestconfService.XML,
- Draft02.MediaTypes.OPERATION + RestconfService.XML, MediaType.APPLICATION_XML, MediaType.TEXT_XML })
-public enum StructuredDataToXmlProvider implements MessageBodyWriter<StructuredData> {
- INSTANCE;
-
- private static final Logger LOG = LoggerFactory.getLogger(StructuredDataToXmlProvider.class);
- private static final TransformerFactory FACTORY = TransformerFactory.newInstance();
- private static final ThreadLocal<Transformer> TRANSFORMER = new ThreadLocal<Transformer>() {
- @Override
- protected Transformer initialValue() {
- final Transformer ret;
- try {
- ret = FACTORY.newTransformer();
- } catch (final TransformerConfigurationException e) {
- LOG.error("Failed to instantiate XML transformer", e);
- throw new IllegalStateException("XML encoding currently unavailable", e);
- }
-
- ret.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
- ret.setOutputProperty(OutputKeys.METHOD, "xml");
- ret.setOutputProperty(OutputKeys.INDENT, "yes");
- ret.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
- ret.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
-
- return ret;
- }
- };
-
- @Override
- public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
- final MediaType mediaType) {
- return type.equals(StructuredData.class);
- }
-
- @Override
- public long getSize(final StructuredData t, final Class<?> type, final Type genericType,
- final Annotation[] annotations, final MediaType mediaType) {
- return -1;
- }
-
- @Override
- public void writeTo(final StructuredData t, final Class<?> type, final Type genericType,
- final Annotation[] annotations, final MediaType mediaType,
- final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream) throws IOException,
- WebApplicationException {
- final CompositeNode data = t.getData();
- if (data == null) {
- throw new RestconfDocumentedException(Response.Status.NOT_FOUND);
- }
-
- final Transformer trans;
- try {
- trans = TRANSFORMER.get();
- if (t.isPrettyPrintMode()) {
- trans.setOutputProperty(OutputKeys.INDENT, "yes");
- } else {
- trans.setOutputProperty(OutputKeys.INDENT, "no");
- }
- } catch (final RuntimeException e) {
- throw new RestconfDocumentedException(e.getMessage(), ErrorType.TRANSPORT, ErrorTag.OPERATION_FAILED);
- }
-
- // FIXME: BUG-1281: eliminate the intermediate Document
- final Document domTree = new XmlMapper().write(data, (DataNodeContainer) t.getSchema());
- try {
- trans.transform(new DOMSource(domTree), new StreamResult(entityStream));
- } catch (final TransformerException e) {
- LOG.error("Error during translation of Document to OutputStream", e);
- throw new RestconfDocumentedException(e.getMessage(), ErrorType.TRANSPORT, ErrorTag.OPERATION_FAILED);
- }
- }
-
-}
+++ /dev/null
-/*
- * 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.sal.rest.impl;
-
-import com.google.common.base.Optional;
-import javax.activation.UnsupportedDataTypeException;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.codec.LeafrefCodec;
-import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
-import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
-import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
-import org.opendaylight.yangtools.yang.model.util.Leafref;
-import org.w3c.dom.Document;
-
-/**
- * @deprecated class will be removed for lithium release
- */
-@Deprecated
-public class XmlMapper {
- private static final LeafrefCodecImpl LEAFREF_DEFAULT_CODEC = new LeafrefCodecImpl(
- Optional.<LeafrefTypeDefinition> absent());
-
- private static class LeafrefCodecImpl extends TypeDefinitionAwareCodec<Object, LeafrefTypeDefinition> implements
- LeafrefCodec<String> {
-
- protected LeafrefCodecImpl(final Optional<LeafrefTypeDefinition> typeDef) {
- super(typeDef, Object.class);
- }
-
- @Override
- public String serialize(final Object data) {
- return String.valueOf(data);
- }
-
- @Override
- public Object deserialize(final String data) {
- return data;
- }
- }
-
- private static class XmlCodecProviderImpl implements XmlCodecProvider {
- @Override
- public TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codecFor(final TypeDefinition<?> baseType) {
- final TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codec = TypeDefinitionAwareCodec
- .from(baseType);
-
- if (codec == null) {
- if (baseType instanceof Leafref) {
- return LEAFREF_DEFAULT_CODEC;
- }
- }
- return codec;
- }
- }
-
- private static final XmlCodecProvider XML_CODEC_PROVIDER_IMPL = new XmlCodecProviderImpl();
-
- public Document write(final CompositeNode data, final DataNodeContainer schema) throws UnsupportedDataTypeException {
- return XmlDocumentUtils.toDocument(data, schema, XML_CODEC_PROVIDER_IMPL);
- }
-}
+++ /dev/null
-/*
- * 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.sal.rest.impl;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.ext.MessageBodyReader;
-import javax.ws.rs.ext.Provider;
-import javax.xml.stream.XMLStreamException;
-import org.opendaylight.controller.sal.rest.api.Draft02;
-import org.opendaylight.controller.sal.rest.api.RestconfService;
-import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @deprecated class will be removed in Lithium release
- */
-@Provider
-@Consumes({ Draft02.MediaTypes.DATA + RestconfService.XML, Draft02.MediaTypes.OPERATION + RestconfService.XML,
- MediaType.APPLICATION_XML, MediaType.TEXT_XML })
-public enum XmlToCompositeNodeProvider implements MessageBodyReader<Node<?>> {
- INSTANCE;
- private final static Logger LOG = LoggerFactory.getLogger(XmlToCompositeNodeProvider.class);
-
- @Override
- public boolean isReadable(final Class<?> type, final Type genericType, final Annotation[] annotations,
- final MediaType mediaType) {
- return true;
- }
-
- @Override
- public Node<?> readFrom(final Class<Node<?>> type, final Type genericType, final Annotation[] annotations,
- final MediaType mediaType, final MultivaluedMap<String, String> httpHeaders, final InputStream entityStream)
- throws IOException, WebApplicationException {
- final XmlToCompositeNodeReader xmlReader = new XmlToCompositeNodeReader();
- try {
- return xmlReader.read(entityStream);
- } catch (XMLStreamException | UnsupportedFormatException e) {
- LOG.debug("Error parsing json input", e);
- throw new RestconfDocumentedException("Error parsing input: " + e.getMessage(), ErrorType.PROTOCOL,
- ErrorTag.MALFORMED_MESSAGE);
- }
- }
-
-}
+++ /dev/null
-/*
- * 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.sal.rest.impl;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.Stack;
-import javax.xml.stream.XMLEventReader;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLStreamConstants;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.events.Characters;
-import javax.xml.stream.events.StartElement;
-import javax.xml.stream.events.XMLEvent;
-import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
-import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
-import org.opendaylight.yangtools.yang.data.api.Node;
-
-/**
- * @deprecated class will be removed in Lithium release
- */
-@Deprecated
-public class XmlToCompositeNodeReader {
-
- private final static XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
- static {
- xmlInputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", false);
- }
- private XMLEventReader eventReader;
-
- public Node<?> read(InputStream entityStream) throws XMLStreamException,
- UnsupportedFormatException,
- IOException {
- //Get an XML stream which can be marked, and reset, so we can check and see if there is
- //any content being provided.
- entityStream = getMarkableStream(entityStream);
-
- if (isInputStreamEmpty(entityStream)) {
- return null;
- }
-
- eventReader = xmlInputFactory.createXMLEventReader(entityStream);
- if (eventReader.hasNext()) {
- final XMLEvent element = eventReader.peek();
- if (element.isStartDocument()) {
- eventReader.nextEvent();
- }
- }
-
- final Stack<NodeWrapper<?>> processingQueue = new Stack<>();
- NodeWrapper<?> root = null;
- NodeWrapper<?> element = null;
- while (eventReader.hasNext()) {
- final XMLEvent event = eventReader.nextEvent();
-
- if (event.isStartElement()) {
- final StartElement startElement = event.asStartElement();
- CompositeNodeWrapper compParentNode = null;
- if (!processingQueue.isEmpty() && processingQueue.peek() instanceof CompositeNodeWrapper) {
- compParentNode = (CompositeNodeWrapper) processingQueue.peek();
- }
- NodeWrapper<?> newNode = null;
- if (isCompositeNodeEvent(event)) {
- newNode = resolveCompositeNodeFromStartElement(startElement);
- if (root == null) {
- root = newNode;
- }
- } else if (isSimpleNodeEvent(event)) {
- newNode = resolveSimpleNodeFromStartElement(startElement);
- if (root == null) {
- root = newNode;
- }
- }
-
- if (newNode != null) {
- processingQueue.push(newNode);
- if (compParentNode != null) {
- compParentNode.addValue(newNode);
- }
- }
- } else if (event.isEndElement()) {
- element = processingQueue.pop();
- }
- }
-
- if (!root.getLocalName().equals(element.getLocalName())) {
- throw new UnsupportedFormatException("XML should contain only one root element");
- }
-
- return (Node<?>) root;
- }
-
- /**
- * If the input stream is not markable, then it wraps the input stream with a buffered stream, which is mark able.
- * That way we can check if the stream is empty safely.
- *
- * @param entityStream
- * @return
- */
- private InputStream getMarkableStream(InputStream entityStream) {
- if (!entityStream.markSupported()) {
- entityStream = new BufferedInputStream(entityStream);
- }
- return entityStream;
- }
-
- private boolean isInputStreamEmpty(final InputStream entityStream) throws IOException {
- boolean isEmpty = false;
- entityStream.mark(1);
- if (entityStream.read() == -1) {
- isEmpty = true;
- }
- entityStream.reset();
- return isEmpty;
- }
-
- private boolean isSimpleNodeEvent(final XMLEvent event) throws XMLStreamException {
- checkArgument(event != null, "XML Event cannot be NULL!");
- if (event.isStartElement()) {
- final XMLEvent innerEvent = skipCommentsAndWhitespace();
- if (innerEvent != null && (innerEvent.isCharacters() || innerEvent.isEndElement())) {
- return true;
- }
- }
- return false;
- }
-
- private boolean isCompositeNodeEvent(final XMLEvent event) throws XMLStreamException {
- checkArgument(event != null, "XML Event cannot be NULL!");
- if (event.isStartElement()) {
- final XMLEvent innerEvent = skipCommentsAndWhitespace();
- if (innerEvent != null) {
- if (innerEvent.isStartElement()) {
- return true;
- }
- }
- }
- return false;
- }
-
- private XMLEvent skipCommentsAndWhitespace() throws XMLStreamException {
- while (eventReader.hasNext()) {
- final XMLEvent event = eventReader.peek();
- if (event.getEventType() == XMLStreamConstants.COMMENT) {
- eventReader.nextEvent();
- continue;
- }
-
- if (event.isCharacters()) {
- final Characters chars = event.asCharacters();
- if (chars.isWhiteSpace()) {
- eventReader.nextEvent();
- continue;
- }
- }
- return event;
- }
- return null;
- }
-
- private CompositeNodeWrapper resolveCompositeNodeFromStartElement(final StartElement startElement) {
- checkArgument(startElement != null, "Start Element cannot be NULL!");
- return new CompositeNodeWrapper(getNamespaceFor(startElement), getLocalNameFor(startElement));
- }
-
- private NodeWrapper<? extends Node<?>> resolveSimpleNodeFromStartElement(final StartElement startElement)
- throws XMLStreamException {
- checkArgument(startElement != null, "Start Element cannot be NULL!");
- final String data = getValueOf(startElement);
- if (data == null) {
- return new EmptyNodeWrapper(getNamespaceFor(startElement), getLocalNameFor(startElement));
- }
- return new SimpleNodeWrapper(getNamespaceFor(startElement), getLocalNameFor(startElement),
- resolveValueOfElement(data, startElement));
- }
-
- private String getValueOf(final StartElement startElement) throws XMLStreamException {
- String data = null;
- if (eventReader.hasNext()) {
- final XMLEvent innerEvent = eventReader.peek();
- if (innerEvent.isCharacters()) {
- final Characters chars = innerEvent.asCharacters();
- if (!chars.isWhiteSpace()) {
- data = innerEvent.asCharacters().getData();
- data = data + getAdditionalData(eventReader.nextEvent());
- }
- } else if (innerEvent.isEndElement()) {
- if (startElement.getLocation().getCharacterOffset() == innerEvent.getLocation().getCharacterOffset()) {
- data = null;
- } else {
- data = "";
- }
- }
- }
- return data == null ? null : data.trim();
- }
-
- private String getAdditionalData(final XMLEvent event) throws XMLStreamException {
- String data = "";
- if (eventReader.hasNext()) {
- final XMLEvent innerEvent = eventReader.peek();
- if (innerEvent.isCharacters() && !innerEvent.isEndElement()) {
- final Characters chars = innerEvent.asCharacters();
- if (!chars.isWhiteSpace()) {
- data = innerEvent.asCharacters().getData();
- data = data + getAdditionalData(eventReader.nextEvent());
- }
- }
- }
- return data;
- }
-
- private String getLocalNameFor(final StartElement startElement) {
- return startElement.getName().getLocalPart();
- }
-
- private URI getNamespaceFor(final StartElement startElement) {
- final String namespaceURI = startElement.getName().getNamespaceURI();
- return namespaceURI.isEmpty() ? null : URI.create(namespaceURI);
- }
-
- private Object resolveValueOfElement(final String value, final StartElement startElement) {
- // it could be instance-identifier Built-In Type
- if (value.startsWith("/")) {
- final IdentityValuesDTO iiValue = RestUtil.asInstanceIdentifier(value, new RestUtil.PrefixMapingFromXml(
- startElement));
- if (iiValue != null) {
- return iiValue;
- }
- }
- // it could be identityref Built-In Type
- final String[] namespaceAndValue = value.split(":");
- if (namespaceAndValue.length == 2) {
- final String namespace = startElement.getNamespaceContext().getNamespaceURI(namespaceAndValue[0]);
- if (namespace != null && !namespace.isEmpty()) {
- return new IdentityValuesDTO(namespace, namespaceAndValue[1], namespaceAndValue[0], value);
- }
- }
- // it is not "prefix:value" but just "value"
- return value;
- }
-
-}
+++ /dev/null
-/*
- * 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.sal.restconf.impl;
-
-import com.google.common.base.Preconditions;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.opendaylight.yangtools.yang.common.QName;
-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.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
-
-/**
- * @deprecated class will be removed in Lithium release
- */
-@Deprecated
-public final class CompositeNodeWrapper implements NodeWrapper<CompositeNode>, CompositeNode {
-
- private MutableCompositeNode compositeNode;
-
- private String localName;
- private URI namespace;
- private QName name;
- private List<NodeWrapper<?>> values = new ArrayList<>();
-
- public CompositeNodeWrapper(final String localName) {
- this.localName = Preconditions.checkNotNull(localName);
- }
-
- public CompositeNodeWrapper(final URI namespace, final String localName) {
- this(localName);
- this.namespace = namespace;
- }
-
- @Override
- 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;
- }
-
- @Override
- public String getLocalName() {
- if (compositeNode != null) {
- return compositeNode.getNodeType().getLocalName();
- }
- return localName;
- }
-
- @Override
- public URI getNamespace() {
- if (compositeNode != null) {
- return compositeNode.getNodeType().getNamespace();
- }
- return namespace;
- }
-
- @Override
- public void setNamespace(final URI namespace) {
- Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies.");
- this.namespace = namespace;
- }
-
- public void addValue(final NodeWrapper<?> value) {
- Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies.");
- values.add(value);
- }
-
- public void removeValue(final NodeWrapper<CompositeNode> value) {
- Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies.");
- values.remove(value);
- }
-
- public List<NodeWrapper<?>> getValues() {
- Preconditions.checkState(compositeNode == null, "Data can be inconsistent.");
- return Collections.unmodifiableList(values);
- }
-
- @Override
- public boolean isChangeAllowed() {
- return compositeNode == null ? true : false;
- }
-
- @Override
- public CompositeNode unwrap() {
- if (compositeNode == null) {
- if (name == null) {
- Preconditions.checkNotNull(namespace);
- name = new QName(namespace, localName);
- }
-
- final List<Node<?>> nodeValues = new ArrayList<>(values.size());
- for (final NodeWrapper<?> nodeWrapper : values) {
- nodeValues.add(nodeWrapper.unwrap());
- }
- compositeNode = NodeFactory.createMutableCompositeNode(name, null, nodeValues, null, null);
-
- values = null;
- namespace = null;
- localName = null;
- name = null;
- }
- return compositeNode;
- }
-
- @Override
- public QName getNodeType() {
- return unwrap().getNodeType();
- }
-
- @Deprecated
- @Override
- public CompositeNode getParent() {
- return unwrap().getParent();
- }
-
- @Override
- public List<Node<?>> getValue() {
- return unwrap().getValue();
- }
-
- @Override
- public ModifyAction getModificationAction() {
- return unwrap().getModificationAction();
- }
-
- /**
- * @deprecated Use {@link #getValue()} instead.
- */
- @Deprecated
- @Override
- public List<Node<?>> getChildren() {
- return unwrap().getValue();
- }
-
- @Override
- public List<CompositeNode> getCompositesByName(final QName children) {
- return unwrap().getCompositesByName(children);
- }
-
- @Override
- public List<CompositeNode> getCompositesByName(final String children) {
- return unwrap().getCompositesByName(children);
- }
-
- @Override
- public List<SimpleNode<?>> getSimpleNodesByName(final QName children) {
- return unwrap().getSimpleNodesByName(children);
- }
-
- @Override
- public List<SimpleNode<?>> getSimpleNodesByName(final String children) {
- return unwrap().getSimpleNodesByName(children);
- }
-
- @Override
- public CompositeNode getFirstCompositeByName(final QName container) {
- return unwrap().getFirstCompositeByName(container);
- }
-
- @Override
- public SimpleNode<?> getFirstSimpleByName(final QName leaf) {
- return unwrap().getFirstSimpleByName(leaf);
- }
-
- @Override
- public MutableCompositeNode asMutable() {
- return unwrap().asMutable();
- }
-
- @Override
- public QName getKey() {
- return unwrap().getKey();
- }
-
- @Override
- public List<Node<?>> setValue(final List<Node<?>> value) {
- return unwrap().setValue(value);
- }
-
- @Override
- public int size() {
- return unwrap().size();
- }
-
- @Override
- public boolean isEmpty() {
- return unwrap().isEmpty();
- }
-
- @Override
- public boolean containsKey(final Object key) {
- return unwrap().containsKey(key);
- }
-
- @Override
- public boolean containsValue(final Object value) {
- return unwrap().containsValue(value);
- }
-
- @Override
- public List<Node<?>> get(final Object key) {
- return unwrap().get(key);
- }
-
- @Override
- public List<Node<?>> put(final QName key, final List<Node<?>> value) {
- return unwrap().put(key, value);
- }
-
- @Override
- public List<Node<?>> remove(final Object key) {
- return unwrap().remove(key);
- }
-
- @Override
- public void putAll(final Map<? extends QName, ? extends List<Node<?>>> m) {
- unwrap().putAll(m);
- }
-
- @Override
- public void clear() {
- unwrap().clear();
- }
-
- @Override
- public Set<QName> keySet() {
- return unwrap().keySet();
- }
-
- @Override
- public Collection<List<Node<?>>> values() {
- return unwrap().values();
- }
-
- @Override
- public Set<java.util.Map.Entry<QName, List<Node<?>>>> entrySet() {
- return unwrap().entrySet();
- }
-
-}
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import javax.ws.rs.core.Response.Status;
import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
import org.opendaylight.yangtools.concepts.Codec;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.InstanceIdentifierBuilder;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
}
}
- public Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalized(final YangInstanceIdentifier legacy,
- final CompositeNode compositeNode) {
- try {
- return dataNormalizer.toNormalized(legacy, compositeNode);
- } catch (final NullPointerException e) {
- throw new RestconfDocumentedException("Data normalizer isn't set. Normalization isn't possible", e);
- }
- }
-
public YangInstanceIdentifier toNormalized(final YangInstanceIdentifier legacy) {
try {
return dataNormalizer.toNormalized(legacy);
}
}
- public CompositeNode toLegacy(final YangInstanceIdentifier instanceIdentifier,
- final NormalizedNode<?,?> normalizedNode) {
- try {
- return dataNormalizer.toLegacy(instanceIdentifier, normalizedNode);
- } catch (final NullPointerException e) {
- throw new RestconfDocumentedException("Data normalizer isn't set. Normalization isn't possible", e);
- }
- }
-
public YangInstanceIdentifier toXpathRepresentation(final YangInstanceIdentifier instanceIdentifier) {
try {
return dataNormalizer.toLegacy(instanceIdentifier);
+++ /dev/null
-/*
- * 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.sal.restconf.impl;
-
-import com.google.common.base.Preconditions;
-import java.net.URI;
-import java.util.Collections;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
-
-/**
- * @deprecated class will be removed in Lithium release
- */
-@Deprecated
-public final class EmptyNodeWrapper implements NodeWrapper<Node<?>>, Node<Void> {
-
- private Node<?> unwrapped;
-
- private String localName;
- private URI namespace;
- private QName name;
-
- private boolean composite;
-
- public boolean isComposite() {
- return composite;
- }
-
- public void setComposite(final boolean composite) {
- this.composite = composite;
- }
-
- public EmptyNodeWrapper(final URI namespace, final String localName) {
- this.localName = Preconditions.checkNotNull(localName);
- this.namespace = namespace;
- }
-
- @Override
- public void setQname(final QName name) {
- Preconditions.checkState(unwrapped == null, "Cannot change the object, due to data inconsistencies.");
- this.name = name;
- }
-
- @Override
- public QName getQname() {
- return name;
- }
-
- @Override
- public String getLocalName() {
- if (unwrapped != null) {
- return unwrapped.getNodeType().getLocalName();
- }
- return localName;
- }
-
- @Override
- public URI getNamespace() {
- if (unwrapped != null) {
- return unwrapped.getNodeType().getNamespace();
- }
- return namespace;
- }
-
- @Override
- public void setNamespace(final URI namespace) {
- Preconditions.checkState(unwrapped == null, "Cannot change the object, due to data inconsistencies.");
- this.namespace = namespace;
- }
-
- @Override
- public boolean isChangeAllowed() {
- return unwrapped == null ? true : false;
- }
-
- @Override
- public Node<?> unwrap() {
- if (unwrapped == null) {
- if (name == null) {
- Preconditions.checkNotNull(namespace);
- name = new QName(namespace, localName);
- }
- if (composite) {
- unwrapped = NodeFactory.createImmutableCompositeNode(name, null, Collections.<Node<?>> emptyList(),
- null);
- } else {
- unwrapped = NodeFactory.createImmutableSimpleNode(name, null, null);
- }
- namespace = null;
- localName = null;
- name = null;
- }
- return unwrapped;
- }
-
- @Override
- public QName getNodeType() {
- return unwrap().getNodeType();
- }
-
- @Override
- @Deprecated
- public CompositeNode getParent() {
- return unwrap().getParent();
- }
-
- @Override
- public Void getValue() {
- return null;
- }
-
- @Override
- public QName getKey() {
- return unwrap().getKey();
- }
-
- @Override
- public Void setValue(final Void value) {
- return null;
- }
-
-}
+++ /dev/null
-/*
- * 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.sal.restconf.impl;
-
-import java.net.URI;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.Node;
-
-/**
- * @deprecated class will be removed in Lithium release
- */
-@Deprecated
-public interface NodeWrapper<T extends Node<?>> {
-
- void setQname(QName name);
-
- QName getQname();
-
- T unwrap();
-
- boolean isChangeAllowed();
-
- URI getNamespace();
-
- void setNamespace(URI namespace);
-
- String getLocalName();
-}
*/
package org.opendaylight.controller.sal.restconf.impl;
-import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicates;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.Futures;
import java.math.BigInteger;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcException;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
import org.opendaylight.controller.sal.rest.api.RestconfService;
import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
-import org.opendaylight.controller.sal.restconf.rpc.impl.BrokerRpcExecutor;
-import org.opendaylight.controller.sal.restconf.rpc.impl.MountPointRpcExecutor;
-import org.opendaylight.controller.sal.restconf.rpc.impl.RpcExecutor;
import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
import org.opendaylight.controller.sal.streams.listeners.Notificator;
import org.opendaylight.controller.sal.streams.websockets.WebSocketServer;
-import org.opendaylight.yangtools.concepts.Codec;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.InstanceIdentifierBuilder;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.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.DataContainerChild;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
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.tree.ModifiedNodeDoesNotExistException;
-import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.parser.CnSnToNormalizedNodeParserFactory;
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
-import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
-import org.opendaylight.yangtools.yang.model.util.EmptyType;
import org.opendaylight.yangtools.yang.model.util.ExtendedType;
import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
-import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final URI NAMESPACE_EVENT_SUBSCRIPTION_AUGMENT = URI.create("urn:sal:restconf:event:subscription");
- private static final Date EVENT_SUBSCRIPTION_AUGMENT_REVISION;
-
private static final String DATASTORE_PARAM_NAME = "datastore";
private static final String SCOPE_PARAM_NAME = "scope";
private static final QName NETCONF_BASE_QNAME;
+ private static final QNameModule SAL_REMOTE_AUGMENT;
+
+ private static final YangInstanceIdentifier.AugmentationIdentifier SAL_REMOTE_AUG_IDENTIFIER;
+
static {
try {
- EVENT_SUBSCRIPTION_AUGMENT_REVISION = new SimpleDateFormat("yyyy-MM-dd").parse("2014-07-08");
+ final Date eventSubscriptionAugRevision = new SimpleDateFormat("yyyy-MM-dd").parse("2014-07-08");
NETCONF_BASE_QNAME = QName.create(QNameModule.create(new URI(NETCONF_BASE), null), NETCONF_BASE_PAYLOAD_NAME );
+ SAL_REMOTE_AUGMENT = QNameModule.create(NAMESPACE_EVENT_SUBSCRIPTION_AUGMENT,
+ eventSubscriptionAugRevision);
+ SAL_REMOTE_AUG_IDENTIFIER = new YangInstanceIdentifier.AugmentationIdentifier(Sets.newHashSet(QName.create(SAL_REMOTE_AUGMENT, "scope"),
+ QName.create(SAL_REMOTE_AUGMENT, "datastore")));
} catch (final ParseException e) {
throw new RestconfDocumentedException(
"It wasn't possible to convert revision date of sal-remote-augment to date", ErrorType.APPLICATION,
moduleContainerBuilder.withChild(mountPointModulesMap);
return new NormalizedNodeContext(new InstanceIdentifierContext(null, modulesSchemaNode,
- mountPoint, schemaContext), moduleContainerBuilder.build());
+ mountPoint, controllerContext.getGlobalSchema()), moduleContainerBuilder.build());
}
@Override
throw new RestconfDocumentedException(errMsg, ErrorType.APPLICATION, ErrorTag.OPERATION_NOT_SUPPORTED);
}
- /**
- * @deprecated method will be removed in Lithium release
- */
- @Deprecated
- private StructuredData operationsFromModulesToStructuredData(final Set<Module> modules,
- final DOMMountPoint mountPoint, final boolean prettyPrint) {
- final List<Node<?>> operationsAsData = new ArrayList<Node<?>>();
- final Module restconfModule = getRestconfModule();
- final DataSchemaNode operationsSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
- restconfModule, Draft02.RestConfModule.OPERATIONS_CONTAINER_SCHEMA_NODE);
- final QName qName = operationsSchemaNode.getQName();
- final SchemaPath path = operationsSchemaNode.getPath();
- final ContainerSchemaNodeBuilder containerSchemaNodeBuilder = new ContainerSchemaNodeBuilder(
- Draft02.RestConfModule.NAME, 0, qName, path);
- final ContainerSchemaNodeBuilder fakeOperationsSchemaNode = containerSchemaNodeBuilder;
- for (final Module module : modules) {
- final Set<RpcDefinition> rpcs = module.getRpcs();
- for (final RpcDefinition rpc : rpcs) {
- final QName rpcQName = rpc.getQName();
- final SimpleNode<Object> immutableSimpleNode = NodeFactory.<Object> createImmutableSimpleNode(rpcQName, null,
- null);
- operationsAsData.add(immutableSimpleNode);
-
- final String name = module.getName();
- final LeafSchemaNodeBuilder leafSchemaNodeBuilder = new LeafSchemaNodeBuilder(name, 0, rpcQName,
- SchemaPath.create(true, QName.create("dummy")));
- final LeafSchemaNodeBuilder fakeRpcSchemaNode = leafSchemaNodeBuilder;
- fakeRpcSchemaNode.setAugmenting(true);
-
- final EmptyType instance = EmptyType.getInstance();
- fakeRpcSchemaNode.setType(instance);
- fakeOperationsSchemaNode.addChildNode(fakeRpcSchemaNode.build());
- }
- }
-
- final CompositeNode operationsNode = NodeFactory.createImmutableCompositeNode(qName, null, operationsAsData);
- final ContainerSchemaNode schemaNode = fakeOperationsSchemaNode.build();
- return new StructuredData(operationsNode, schemaNode, mountPoint, prettyPrint);
- }
-
private Module getRestconfModule() {
final Module restconfModule = controllerContext.getRestconfModule();
if (restconfModule == null) {
}
}
- /**
- * @deprecated method will be removed for Lithium release
- * so, please use toStreamEntryNode method
- *
- * @param streamName
- * @param streamSchemaNode
- * @return
- */
- @Deprecated
- private CompositeNode toStreamCompositeNode(final String streamName, final DataSchemaNode streamSchemaNode) {
- final List<Node<?>> streamNodeValues = new ArrayList<Node<?>>();
- List<DataSchemaNode> instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
- ((DataNodeContainer) streamSchemaNode), "name");
- final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
- streamNodeValues
- .add(NodeFactory.<String> createImmutableSimpleNode(nameSchemaNode.getQName(), null, streamName));
-
- instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
- ((DataNodeContainer) streamSchemaNode), "description");
- final DataSchemaNode descriptionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
- streamNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(descriptionSchemaNode.getQName(), null,
- "DESCRIPTION_PLACEHOLDER"));
-
- instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
- ((DataNodeContainer) streamSchemaNode), "replay-support");
- final DataSchemaNode replaySupportSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
- streamNodeValues.add(NodeFactory.<Boolean> createImmutableSimpleNode(replaySupportSchemaNode.getQName(), null,
- Boolean.valueOf(true)));
-
- instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
- ((DataNodeContainer) streamSchemaNode), "replay-log-creation-time");
- final DataSchemaNode replayLogCreationTimeSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
- streamNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(replayLogCreationTimeSchemaNode.getQName(),
- null, ""));
-
- instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
- ((DataNodeContainer) streamSchemaNode), "events");
- final DataSchemaNode eventsSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
- streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(eventsSchemaNode.getQName(), null, ""));
-
- return NodeFactory.createImmutableCompositeNode(streamSchemaNode.getQName(), null, streamNodeValues);
- }
-
- /**
- * @deprecated method will be removed for Lithium release
- * so, please use toModuleEntryNode method
- *
- * @param module
- * @param moduleSchemaNode
- * @return
- */
- @Deprecated
- private CompositeNode toModuleCompositeNode(final Module module, final DataSchemaNode moduleSchemaNode) {
- final List<Node<?>> moduleNodeValues = new ArrayList<Node<?>>();
- List<DataSchemaNode> instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
- ((DataNodeContainer) moduleSchemaNode), "name");
- final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
- moduleNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(nameSchemaNode.getQName(), null,
- module.getName()));
-
- instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
- ((DataNodeContainer) moduleSchemaNode), "revision");
- final DataSchemaNode revisionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
- final Date _revision = module.getRevision();
- moduleNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(revisionSchemaNode.getQName(), null,
- REVISION_FORMAT.format(_revision)));
-
- instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
- ((DataNodeContainer) moduleSchemaNode), "namespace");
- final DataSchemaNode namespaceSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
- moduleNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(namespaceSchemaNode.getQName(), null,
- module.getNamespace().toString()));
-
- instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
- ((DataNodeContainer) moduleSchemaNode), "feature");
- final DataSchemaNode featureSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
- for (final FeatureDefinition feature : module.getFeatures()) {
- moduleNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(featureSchemaNode.getQName(), null,
- feature.getQName().getLocalName()));
- }
-
- return NodeFactory.createImmutableCompositeNode(moduleSchemaNode.getQName(), null, moduleNodeValues);
- }
-
@Override
public Object getRoot() {
return null;
// }
}
- /**
- * @deprecated method will be removed for Lithium release
- *
- * @param inputSchema
- * @param payload
- */
- @Deprecated
- private void validateInput(final DataSchemaNode inputSchema, final Node<?> payload) {
- if (inputSchema != null && payload == null) {
- // expected a non null payload
- throw new RestconfDocumentedException("Input is required.", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
- } else if (inputSchema == null && payload != null) {
- // did not expect any input
- throw new RestconfDocumentedException("No input expected.", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
- }
- // else
- // {
- // TODO: Validate "mandatory" and "config" values here??? Or should those be
- // those be
- // validate in a more central location inside MD-SAL core.
- // }
- }
-
private CheckedFuture<DOMRpcResult, DOMRpcException> invokeSalRemoteRpcSubscribeRPC(final NormalizedNodeContext payload) {
final ContainerNode value = (ContainerNode) payload.getData();
final QName rpcQName = payload.getInstanceIdentifierContext().getSchemaNode().getQName();
schemaContext), resultData);
}
- private RpcExecutor resolveIdentifierInInvokeRpc(final String identifier) {
- String identifierEncoded = null;
- DOMMountPoint mountPoint = null;
- if (identifier.contains(ControllerContext.MOUNT)) {
- // mounted RPC call - look up mount instance.
- final InstanceIdentifierContext mountPointId = controllerContext.toMountPointIdentifier(identifier);
- mountPoint = mountPointId.getMountPoint();
-
- final int startOfRemoteRpcName = identifier.lastIndexOf(ControllerContext.MOUNT)
- + ControllerContext.MOUNT.length() + 1;
- final String remoteRpcName = identifier.substring(startOfRemoteRpcName);
- identifierEncoded = remoteRpcName;
-
- } else if (identifier.indexOf("/") != CHAR_NOT_FOUND) {
- final String slashErrorMsg = String.format("Identifier %n%s%ncan\'t contain slash "
- + "character (/).%nIf slash is part of identifier name then use %%2F placeholder.", identifier);
- throw new RestconfDocumentedException(slashErrorMsg, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
- } else {
- identifierEncoded = identifier;
- }
-
- final String identifierDecoded = controllerContext.urlPathArgDecode(identifierEncoded);
-
- RpcDefinition rpc = null;
- if (mountPoint == null) {
- rpc = controllerContext.getRpcDefinition(identifierDecoded);
- } else {
- rpc = findRpc(mountPoint.getSchemaContext(), identifierDecoded);
- }
-
- if (rpc == null) {
- throw new RestconfDocumentedException("RPC does not exist.", ErrorType.RPC, ErrorTag.UNKNOWN_ELEMENT);
- }
-
- if (mountPoint == null) {
- return new BrokerRpcExecutor(rpc, broker);
- } else {
- return new MountPointRpcExecutor(rpc, mountPoint);
- }
-
- }
-
private RpcDefinition findRpc(final SchemaContext schemaContext, final String identifierDecoded) {
final String[] splittedIdentifier = identifierDecoded.split(":");
if (splittedIdentifier.length != 2) {
return null;
}
- /**
- * @deprecated method will be removed for Lithium release
- */
- @Deprecated
- private StructuredData callRpc(final RpcExecutor rpcExecutor, final CompositeNode payload, final boolean prettyPrint) {
- if (rpcExecutor == null) {
- throw new RestconfDocumentedException("RPC does not exist.", ErrorType.RPC, ErrorTag.UNKNOWN_ELEMENT);
- }
-
- CompositeNode rpcRequest = null;
- final RpcDefinition rpc = rpcExecutor.getRpcDefinition();
- final QName rpcName = rpc.getQName();
-
- if (payload == null) {
- rpcRequest = NodeFactory.createMutableCompositeNode(rpcName, null, null, null, null);
- } else {
- final CompositeNode value = this.normalizeNode(payload, rpc.getInput(), null);
- final List<Node<?>> input = Collections.<Node<?>> singletonList(value);
- rpcRequest = NodeFactory.createMutableCompositeNode(rpcName, null, input, null, null);
- }
-
- final RpcResult<CompositeNode> rpcResult = rpcExecutor.invokeRpc(rpcRequest);
-
- checkRpcSuccessAndThrowException(rpcResult);
-
- if (rpcResult.getResult() == null) {
- return null;
- }
-
- if (rpc.getOutput() == null) {
- return null; // no output, nothing to send back.
- }
-
- return new StructuredData(rpcResult.getResult(), rpc.getOutput(), null, prettyPrint);
- }
-
- private void checkRpcSuccessAndThrowException(final RpcResult<CompositeNode> rpcResult) {
- if (rpcResult.isSuccessful() == false) {
-
- throw new RestconfDocumentedException("The operation was not successful", null,
- rpcResult.getErrors());
- }
- }
-
@Override
public NormalizedNodeContext readConfigurationData(final String identifier, final UriInfo uriInfo) {
final InstanceIdentifierContext iiWithData = controllerContext.toInstanceIdentifier(identifier);
return new NormalizedNodeContext(iiWithData, data);
}
- @SuppressWarnings("unchecked")
- private <T extends Node<?>> T pruneDataAtDepth(final T node, final Integer depth) {
- if (depth == null) {
- return node;
- }
-
- if (node instanceof CompositeNode) {
- final ImmutableList.Builder<Node<?>> newChildNodes = ImmutableList.<Node<?>> builder();
- if (depth > 1) {
- for (final Node<?> childNode : ((CompositeNode) node).getValue()) {
- newChildNodes.add(pruneDataAtDepth(childNode, depth - 1));
- }
- }
-
- return (T) ImmutableCompositeNode.create(node.getNodeType(), newChildNodes.build());
- } else { // SimpleNode
- return node;
- }
- }
-
private Integer parseDepthParameter(final UriInfo info) {
final String param = info.getQueryParameters(false).getFirst(UriParameters.DEPTH.toString());
if (Strings.isNullOrEmpty(param) || "unbounded".equals(param)) {
}
}
- /**
- * @deprecated method will be removed for Lithium release
- *
- * @param node
- * @param identifier
- */
- @Deprecated
- private void validateTopLevelNodeName(final Node<?> node,
- final YangInstanceIdentifier identifier) {
- final String payloadName = getName(node);
- final Iterator<PathArgument> pathArguments = identifier.getReversePathArguments().iterator();
-
- //no arguments
- if (!pathArguments.hasNext()) {
- //no "data" payload
- if (!node.getNodeType().equals(NETCONF_BASE_QNAME)) {
- throw new RestconfDocumentedException("Instance identifier has to contain at least one path argument",
- ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
- }
- //any arguments
- } else {
- final String identifierName = pathArguments.next().getNodeType().getLocalName();
- if (!payloadName.equals(identifierName)) {
- throw new RestconfDocumentedException("Payload name (" + payloadName
- + ") is different from identifier name (" + identifierName + ")", ErrorType.PROTOCOL,
- ErrorTag.MALFORMED_MESSAGE);
- }
- }
- }
-
/**
* Validates whether keys in {@code payload} are equal to values of keys in {@code iiWithData} for list schema node
*
}
}
- /**
- * @deprecated method will be removed for Lithium release
- *
- * Validates whether keys in {@code payload} are equal to values of keys in {@code iiWithData} for list schema node
- *
- * @throws RestconfDocumentedException
- * if key values or key count in payload and URI isn't equal
- *
- */
- @Deprecated
- private void validateListKeysEqualityInPayloadAndUri(final InstanceIdentifierContext iiWithData,
- final CompositeNode payload) {
- if (iiWithData.getSchemaNode() instanceof ListSchemaNode) {
- final List<QName> keyDefinitions = ((ListSchemaNode) iiWithData.getSchemaNode()).getKeyDefinition();
- final PathArgument lastPathArgument = iiWithData.getInstanceIdentifier().getLastPathArgument();
- if (lastPathArgument instanceof NodeIdentifierWithPredicates) {
- final Map<QName, Object> uriKeyValues = ((NodeIdentifierWithPredicates) lastPathArgument)
- .getKeyValues();
- isEqualUriAndPayloadKeyValues(uriKeyValues, payload, keyDefinitions);
- }
- }
- }
-
private void isEqualUriAndPayloadKeyValues(final Map<QName, Object> uriKeyValues, final NormalizedNode<?, ?> payload,
final List<QName> keyDefinitions) {
for (final QName keyDefinition : keyDefinitions) {
}
}
- /**
- * @deprecated method will be removed for Lithium release
- *
- * @param uriKeyValues
- * @param payload
- * @param keyDefinitions
- */
- @Deprecated
- private void isEqualUriAndPayloadKeyValues(final Map<QName, Object> uriKeyValues, final CompositeNode payload,
- final List<QName> keyDefinitions) {
- for (final QName keyDefinition : keyDefinitions) {
- final Object uriKeyValue = uriKeyValues.get(keyDefinition);
- // should be caught during parsing URI to InstanceIdentifier
- if (uriKeyValue == null) {
- throw new RestconfDocumentedException("Missing key " + keyDefinition + " in URI.", ErrorType.PROTOCOL,
- ErrorTag.DATA_MISSING);
- }
- final List<SimpleNode<?>> payloadKeyValues = payload.getSimpleNodesByName(keyDefinition.getLocalName());
- if (payloadKeyValues.isEmpty()) {
- throw new RestconfDocumentedException("Missing key " + keyDefinition.getLocalName()
- + " in the message body.", ErrorType.PROTOCOL, ErrorTag.DATA_MISSING);
- }
-
- final Object payloadKeyValue = payloadKeyValues.iterator().next().getValue();
- if (!uriKeyValue.equals(payloadKeyValue)) {
- throw new RestconfDocumentedException("The value '" + uriKeyValue + "' for key '"
- + keyDefinition.getLocalName() + "' specified in the URI doesn't match the value '"
- + payloadKeyValue + "' specified in the message body. ", ErrorType.PROTOCOL,
- ErrorTag.INVALID_VALUE);
- }
- }
- }
-
@Override
public Response createConfigurationData(final String identifier, final NormalizedNodeContext payload, final UriInfo uriInfo) {
return createConfigurationData(payload, uriInfo);
*/
private <T> T parseEnumTypeParameter(final ContainerNode value, final Class<T> classDescriptor,
final String paramName) {
- final QNameModule salRemoteAugment = QNameModule.create(NAMESPACE_EVENT_SUBSCRIPTION_AUGMENT,
- EVENT_SUBSCRIPTION_AUGMENT_REVISION);
- final Optional<DataContainerChild<? extends PathArgument, ?>> enumNode = value.getChild(new NodeIdentifier(
- QName.create(salRemoteAugment, paramName)));
+ final Optional<DataContainerChild<? extends PathArgument, ?>> augNode = value.getChild(SAL_REMOTE_AUG_IDENTIFIER);
+ if (!augNode.isPresent() && !(augNode instanceof AugmentationNode)) {
+ return null;
+ }
+ final Optional<DataContainerChild<? extends PathArgument, ?>> enumNode =
+ ((AugmentationNode) augNode.get()).getChild(new NodeIdentifier(QName.create(SAL_REMOTE_AUGMENT, paramName)));
if (!enumNode.isPresent()) {
return null;
}
return result;
}
- private Module findModule(final DOMMountPoint mountPoint, final Node<?> data) {
- Module module = null;
- if (data instanceof NodeWrapper) {
- module = findModule(mountPoint, (NodeWrapper<?>) data);
- } else if (data != null) {
- final URI namespace = data.getNodeType().getNamespace();
- if (mountPoint != null) {
- module = controllerContext.findModuleByNamespace(mountPoint, namespace);
- } else {
- module = controllerContext.findModuleByNamespace(namespace);
- }
- }
- if (module != null) {
- return module;
- }
- throw new RestconfDocumentedException(
- "Data has bad format. Root element node has incorrect namespace (XML format) or module name(JSON format)",
- ErrorType.PROTOCOL, ErrorTag.UNKNOWN_NAMESPACE);
- }
-
- private Module findModule(final DOMMountPoint mountPoint, final NodeWrapper<?> data) {
- final URI namespace = data.getNamespace();
- Preconditions.<URI> checkNotNull(namespace);
-
- Module module = null;
- if (mountPoint != null) {
- module = controllerContext.findModuleByNamespace(mountPoint, namespace);
- if (module == null) {
- module = controllerContext.findModuleByName(mountPoint, namespace.toString());
- }
- } else {
- module = controllerContext.findModuleByNamespace(namespace);
- if (module == null) {
- module = controllerContext.findModuleByName(namespace.toString());
- }
- }
-
- return module;
- }
-
- private InstanceIdentifierContext addLastIdentifierFromData(final InstanceIdentifierContext identifierWithSchemaNode,
- final CompositeNode data, final DataSchemaNode schemaOfData, final SchemaContext schemaContext) {
- YangInstanceIdentifier instanceIdentifier = null;
- if (identifierWithSchemaNode != null) {
- instanceIdentifier = identifierWithSchemaNode.getInstanceIdentifier();
- }
-
- final YangInstanceIdentifier iiOriginal = instanceIdentifier;
- InstanceIdentifierBuilder iiBuilder = null;
- if (iiOriginal == null) {
- iiBuilder = YangInstanceIdentifier.builder();
- } else {
- iiBuilder = YangInstanceIdentifier.builder(iiOriginal);
- }
-
- if ((schemaOfData instanceof ListSchemaNode)) {
- final HashMap<QName, Object> keys = resolveKeysFromData(((ListSchemaNode) schemaOfData), data);
- iiBuilder.nodeWithKey(schemaOfData.getQName(), keys);
- } else {
- iiBuilder.node(schemaOfData.getQName());
- }
-
- final YangInstanceIdentifier instance = iiBuilder.toInstance();
- DOMMountPoint mountPoint = null;
- final SchemaContext schemaCtx = null;
- if (identifierWithSchemaNode != null) {
- mountPoint = identifierWithSchemaNode.getMountPoint();
- }
-
- return new InstanceIdentifierContext(instance, schemaOfData, mountPoint,schemaContext);
- }
-
- private HashMap<QName, Object> resolveKeysFromData(final ListSchemaNode listNode, final CompositeNode dataNode) {
- final HashMap<QName, Object> keyValues = new HashMap<QName, Object>();
- final List<QName> _keyDefinition = listNode.getKeyDefinition();
- for (final QName key : _keyDefinition) {
- SimpleNode<? extends Object> head = null;
- final String localName = key.getLocalName();
- final List<SimpleNode<? extends Object>> simpleNodesByName = dataNode.getSimpleNodesByName(localName);
- if (simpleNodesByName != null) {
- head = Iterables.getFirst(simpleNodesByName, null);
- }
-
- Object dataNodeKeyValueObject = null;
- if (head != null) {
- dataNodeKeyValueObject = head.getValue();
- }
-
- if (dataNodeKeyValueObject == null) {
- throw new RestconfDocumentedException("Data contains list \"" + dataNode.getNodeType().getLocalName()
- + "\" which does not contain key: \"" + key.getLocalName() + "\"", ErrorType.PROTOCOL,
- ErrorTag.INVALID_VALUE);
- }
-
- keyValues.put(key, dataNodeKeyValueObject);
- }
-
- return keyValues;
- }
-
private boolean endsWithMountPoint(final String identifier) {
return identifier.endsWith(ControllerContext.MOUNT) || identifier.endsWith(ControllerContext.MOUNT + "/");
}
- private boolean representsMountPointRootData(final Node<?> data) {
- final URI namespace = namespace(data);
- return (SchemaContext.NAME.getNamespace().equals(namespace) /*
- * || MOUNT_POINT_MODULE_NAME .equals( namespace .
- * toString( ) )
- */)
- && SchemaContext.NAME.getLocalName().equals(localName(data));
- }
-
private String addMountPointIdentifier(final String identifier) {
final boolean endsWith = identifier.endsWith("/");
if (endsWith) {
return identifier + "/" + ControllerContext.MOUNT;
}
- /**
- * @deprecated method will be removed in Lithium release
- * we don't wish to use Node and CompositeNode anywhere
- */
- @Deprecated
- public CompositeNode normalizeNode(final Node<?> node, final DataSchemaNode schema, final DOMMountPoint mountPoint) {
- if (schema == null) {
- final String localName = node == null ? null :
- node instanceof NodeWrapper ? ((NodeWrapper<?>)node).getLocalName() :
- node.getNodeType().getLocalName();
-
- throw new RestconfDocumentedException("Data schema node was not found for " + localName,
- ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
- }
-
- if (!(schema instanceof DataNodeContainer)) {
- throw new RestconfDocumentedException("Root element has to be container or list yang datatype.",
- ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
- }
-
- if ((node instanceof NodeWrapper<?>)) {
- NodeWrapper<?> nodeWrap = (NodeWrapper<?>) node;
- final boolean isChangeAllowed = ((NodeWrapper<?>) node).isChangeAllowed();
- if (isChangeAllowed) {
- nodeWrap = topLevelElementAsCompositeNodeWrapper((NodeWrapper<?>) node, schema);
- try {
- this.normalizeNode(nodeWrap, schema, null, mountPoint);
- } catch (final IllegalArgumentException e) {
- final RestconfDocumentedException restconfDocumentedException = new RestconfDocumentedException(e.getMessage(), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
- restconfDocumentedException.addSuppressed(e);
- throw restconfDocumentedException;
- }
- if (nodeWrap instanceof CompositeNodeWrapper) {
- return ((CompositeNodeWrapper) nodeWrap).unwrap();
- }
- }
- }
-
- if (node instanceof CompositeNode) {
- return (CompositeNode) node;
- }
-
- throw new RestconfDocumentedException("Top level element is not interpreted as composite node.",
- ErrorType.APPLICATION, ErrorTag.INVALID_VALUE);
- }
-
- private void normalizeNode(final NodeWrapper<? extends Object> nodeBuilder, final DataSchemaNode schema,
- final QName previousAugment, final DOMMountPoint mountPoint) {
- if (schema == null) {
- throw new RestconfDocumentedException("Data has bad format.\n\"" + nodeBuilder.getLocalName()
- + "\" does not exist in yang schema.", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
- }
-
- QName currentAugment = null;
- if (nodeBuilder.getQname() != null) {
- currentAugment = previousAugment;
- } else {
- currentAugment = normalizeNodeName(nodeBuilder, schema, previousAugment, mountPoint);
- if (nodeBuilder.getQname() == null) {
- throw new RestconfDocumentedException(
- "Data has bad format.\nIf data is in XML format then namespace for \""
- + nodeBuilder.getLocalName() + "\" should be \"" + schema.getQName().getNamespace()
- + "\".\n" + "If data is in JSON format then module name for \""
- + nodeBuilder.getLocalName() + "\" should be corresponding to namespace \""
- + schema.getQName().getNamespace() + "\".", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
- }
- }
-
- if (nodeBuilder instanceof CompositeNodeWrapper) {
- if (schema instanceof DataNodeContainer) {
- normalizeCompositeNode((CompositeNodeWrapper) nodeBuilder, (DataNodeContainer) schema, mountPoint,
- currentAugment);
- } else if (schema instanceof AnyXmlSchemaNode) {
- normalizeAnyXmlNode((CompositeNodeWrapper) nodeBuilder, (AnyXmlSchemaNode) schema);
- }
- } else if (nodeBuilder instanceof SimpleNodeWrapper) {
- normalizeSimpleNode((SimpleNodeWrapper) nodeBuilder, schema, mountPoint);
- } else if ((nodeBuilder instanceof EmptyNodeWrapper)) {
- normalizeEmptyNode((EmptyNodeWrapper) nodeBuilder, schema);
- }
- }
-
- private void normalizeAnyXmlNode(final CompositeNodeWrapper compositeNode, final AnyXmlSchemaNode schema) {
- final List<NodeWrapper<?>> children = compositeNode.getValues();
- for (final NodeWrapper<? extends Object> child : children) {
- child.setNamespace(schema.getQName().getNamespace());
- if (child instanceof CompositeNodeWrapper) {
- normalizeAnyXmlNode((CompositeNodeWrapper) child, schema);
- }
- }
- }
-
- private void normalizeEmptyNode(final EmptyNodeWrapper emptyNodeBuilder, final DataSchemaNode schema) {
- if ((schema instanceof LeafSchemaNode)) {
- emptyNodeBuilder.setComposite(false);
- } else {
- if ((schema instanceof ContainerSchemaNode)) {
- // FIXME: Add presence check
- emptyNodeBuilder.setComposite(true);
- }
- }
- }
-
- private void normalizeSimpleNode(final SimpleNodeWrapper simpleNode, final DataSchemaNode schema,
- final DOMMountPoint mountPoint) {
- final Object value = simpleNode.getValue();
- Object inputValue = value;
- final TypeDef typeDef = this.typeDefinition(schema);
- TypeDefinition<? extends Object> typeDefinition = typeDef != null ? typeDef.typedef : null;
-
- // For leafrefs, extract the type it is pointing to
- if(typeDefinition instanceof LeafrefTypeDefinition) {
- if (schema.getQName().equals(typeDef.qName)) {
- typeDefinition = SchemaContextUtil.getBaseTypeForLeafRef(((LeafrefTypeDefinition) typeDefinition), mountPoint == null ? controllerContext.getGlobalSchema() : mountPoint.getSchemaContext(), schema);
- } else {
- typeDefinition = SchemaContextUtil.getBaseTypeForLeafRef(((LeafrefTypeDefinition) typeDefinition), mountPoint == null ? controllerContext.getGlobalSchema() : mountPoint.getSchemaContext(), typeDef.qName);
- }
- }
-
- if (typeDefinition instanceof IdentityrefTypeDefinition) {
- inputValue = parseToIdentityValuesDTO(simpleNode, value, inputValue);
- }
-
- Object outputValue = inputValue;
-
- if (typeDefinition != null) {
- final Codec<Object, Object> codec = RestCodec.from(typeDefinition, mountPoint);
- outputValue = codec == null ? null : codec.deserialize(inputValue);
- }
-
- simpleNode.setValue(outputValue);
- }
-
- private Object parseToIdentityValuesDTO(final SimpleNodeWrapper simpleNode, final Object value, Object inputValue) {
- if ((value instanceof String)) {
- inputValue = new IdentityValuesDTO(simpleNode.getNamespace().toString(), (String) value, null,
- (String) value);
- } // else value is already instance of IdentityValuesDTO
- return inputValue;
- }
-
- private void normalizeCompositeNode(final CompositeNodeWrapper compositeNodeBuilder,
- final DataNodeContainer schema, final DOMMountPoint mountPoint, final QName currentAugment) {
- final List<NodeWrapper<?>> children = compositeNodeBuilder.getValues();
- checkNodeMultiplicityAccordingToSchema(schema, children);
- for (final NodeWrapper<? extends Object> child : children) {
- final List<DataSchemaNode> potentialSchemaNodes = ControllerContext.findInstanceDataChildrenByName(
- schema, child.getLocalName());
-
- if (potentialSchemaNodes.size() > 1 && child.getNamespace() == null) {
- final StringBuilder builder = new StringBuilder();
- for (final DataSchemaNode potentialSchemaNode : potentialSchemaNodes) {
- builder.append(" ").append(potentialSchemaNode.getQName().getNamespace().toString()).append("\n");
- }
-
- throw new RestconfDocumentedException("Node \"" + child.getLocalName()
- + "\" is added as augment from more than one module. "
- + "Therefore node must have namespace (XML format) or module name (JSON format)."
- + "\nThe node is added as augment from modules with namespaces:\n" + builder,
- ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
- }
-
- boolean rightNodeSchemaFound = false;
- for (final DataSchemaNode potentialSchemaNode : potentialSchemaNodes) {
- if (!rightNodeSchemaFound) {
- final QName potentialCurrentAugment = normalizeNodeName(child, potentialSchemaNode,
- currentAugment, mountPoint);
- if (child.getQname() != null) {
- this.normalizeNode(child, potentialSchemaNode, potentialCurrentAugment, mountPoint);
- rightNodeSchemaFound = true;
- }
- }
- }
-
- if (!rightNodeSchemaFound) {
- throw new RestconfDocumentedException("Schema node \"" + child.getLocalName()
- + "\" was not found in module.", ErrorType.APPLICATION, ErrorTag.UNKNOWN_ELEMENT);
- }
- }
-
- if ((schema instanceof ListSchemaNode)) {
- final ListSchemaNode listSchemaNode = (ListSchemaNode) schema;
- final List<QName> listKeys = listSchemaNode.getKeyDefinition();
- for (final QName listKey : listKeys) {
- boolean foundKey = false;
- for (final NodeWrapper<? extends Object> child : children) {
- if (Objects.equal(child.unwrap().getNodeType().getLocalName(), listKey.getLocalName())) {
- foundKey = true;
- }
- }
-
- if (!foundKey) {
- throw new RestconfDocumentedException("Missing key in URI \"" + listKey.getLocalName()
- + "\" of list \"" + listSchemaNode.getQName().getLocalName() + "\"", ErrorType.PROTOCOL,
- ErrorTag.DATA_MISSING);
- }
- }
- }
- }
-
- private void checkNodeMultiplicityAccordingToSchema(final DataNodeContainer dataNodeContainer,
- final List<NodeWrapper<?>> nodes) {
- final Map<String, Integer> equalNodeNamesToCounts = new HashMap<String, Integer>();
- for (final NodeWrapper<?> child : nodes) {
- Integer count = equalNodeNamesToCounts.get(child.getLocalName());
- equalNodeNamesToCounts.put(child.getLocalName(), count == null ? 1 : ++count);
- }
-
- for (final DataSchemaNode childSchemaNode : dataNodeContainer.getChildNodes()) {
- if (childSchemaNode instanceof ContainerSchemaNode || childSchemaNode instanceof LeafSchemaNode) {
- final String localName = childSchemaNode.getQName().getLocalName();
- final Integer count = equalNodeNamesToCounts.get(localName);
- if (count != null && count > 1) {
- throw new RestconfDocumentedException("Multiple input data elements were specified for '"
- + childSchemaNode.getQName().getLocalName()
- + "'. The data for this element type can only be specified once.", ErrorType.APPLICATION,
- ErrorTag.BAD_ELEMENT);
- }
- }
- }
- }
-
- private QName normalizeNodeName(final NodeWrapper<? extends Object> nodeBuilder, final DataSchemaNode schema,
- final QName previousAugment, final DOMMountPoint mountPoint) {
- QName validQName = schema.getQName();
- QName currentAugment = previousAugment;
- if (schema.isAugmenting()) {
- currentAugment = schema.getQName();
- } else if (previousAugment != null
- && !Objects.equal(schema.getQName().getNamespace(), previousAugment.getNamespace())) {
- validQName = QName.create(currentAugment, schema.getQName().getLocalName());
- }
-
- String moduleName = null;
- if (mountPoint == null) {
- moduleName = controllerContext.findModuleNameByNamespace(validQName.getNamespace());
- } else {
- moduleName = controllerContext.findModuleNameByNamespace(mountPoint, validQName.getNamespace());
- }
-
- if (nodeBuilder.getNamespace() == null || Objects.equal(nodeBuilder.getNamespace(), validQName.getNamespace())
- || Objects.equal(nodeBuilder.getNamespace().toString(), moduleName)) {
- /*
- * || Note : this check is wrong -
- * can never be true as it compares
- * a URI with a String not sure what
- * the intention is so commented out
- * ... Objects . equal ( nodeBuilder
- * . getNamespace ( ) ,
- * MOUNT_POINT_MODULE_NAME )
- */
-
- nodeBuilder.setQname(validQName);
- }
-
- return currentAugment;
- }
-
- private URI namespace(final Node<?> data) {
- if (data instanceof NodeWrapper) {
- return ((NodeWrapper<?>) data).getNamespace();
- } else if (data != null) {
- return data.getNodeType().getNamespace();
- } else {
- throw new IllegalArgumentException("Unhandled parameter types: " + Arrays.<Object> asList(data).toString());
- }
- }
-
- private String localName(final Node<?> data) {
- if (data instanceof NodeWrapper) {
- return ((NodeWrapper<?>) data).getLocalName();
- } else if (data != null) {
- return data.getNodeType().getLocalName();
- } else {
- throw new IllegalArgumentException("Unhandled parameter types: " + Arrays.<Object> asList(data).toString());
- }
- }
-
- /**
- * @deprecated method will be removed for Lithium release
- *
- * @param data
- * @return
- */
- @Deprecated
- private String getName(final Node<?> data) {
- if (data instanceof NodeWrapper) {
- return ((NodeWrapper<?>) data).getLocalName();
- } else if (data != null) {
- return data.getNodeType().getLocalName();
- } else {
- throw new IllegalArgumentException("Unhandled parameter types: " + Arrays.<Object> asList(data).toString());
- }
- }
-
private TypeDef typeDefinition(final TypeDefinition<?> type, final QName nodeQName) {
TypeDefinition<?> baseType = type;
QName qName = nodeQName;
}
}
- private CompositeNode datastoreNormalizedNodeToCompositeNode(final NormalizedNode<?, ?> dataNode, final DataSchemaNode schema) {
- Node<?> nodes = null;
- if (dataNode == null) {
- throw new RestconfDocumentedException(new RestconfError(ErrorType.APPLICATION, ErrorTag.DATA_MISSING,
- "No data was found."));
- }
- nodes = DataNormalizer.toLegacy(dataNode);
- if (nodes != null) {
- if (nodes instanceof CompositeNode) {
- return (CompositeNode) nodes;
- } else {
- LOG.error("The node " + dataNode.getNodeType() + " couldn't be transformed to compositenode.");
- }
- } else {
- LOG.error("Top level node isn't of type Container or List schema node but "
- + schema.getClass().getSimpleName());
- }
-
- throw new RestconfDocumentedException(new RestconfError(ErrorType.APPLICATION, ErrorTag.INVALID_VALUE,
- "It wasn't possible to correctly interpret data."));
- }
-
- private NormalizedNode<?, ?> compositeNodeToDatastoreNormalizedNode(final CompositeNode compNode,
- final DataSchemaNode schema) {
- final List<Node<?>> lst = new ArrayList<Node<?>>();
- lst.add(compNode);
- if (schema instanceof ContainerSchemaNode) {
- return CnSnToNormalizedNodeParserFactory.getInstance().getContainerNodeParser()
- .parse(lst, (ContainerSchemaNode) schema);
- } else if (schema instanceof ListSchemaNode) {
- return CnSnToNormalizedNodeParserFactory.getInstance().getMapEntryNodeParser()
- .parse(lst, (ListSchemaNode) schema);
- }
-
- LOG.error("Top level isn't of type container, list, leaf schema node but " + schema.getClass().getSimpleName());
-
- throw new RestconfDocumentedException(new RestconfError(ErrorType.APPLICATION, ErrorTag.INVALID_VALUE,
- "It wasn't possible to translate specified data to datastore readable form."));
- }
-
private InstanceIdentifierContext normalizeInstanceIdentifierWithSchemaNode(
final InstanceIdentifierContext iiWithSchemaNode) {
return normalizeInstanceIdentifierWithSchemaNode(iiWithSchemaNode, false);
return YangInstanceIdentifier.create(result);
}
- private CompositeNodeWrapper topLevelElementAsCompositeNodeWrapper(final NodeWrapper<?> node,
- final DataSchemaNode schemaNode) {
- if (node instanceof CompositeNodeWrapper) {
- return (CompositeNodeWrapper) node;
- } else if (node instanceof SimpleNodeWrapper && isDataContainerNode(schemaNode)) {
- final SimpleNodeWrapper simpleNodeWrapper = (SimpleNodeWrapper) node;
- return new CompositeNodeWrapper(namespace(simpleNodeWrapper), localName(simpleNodeWrapper));
- }
-
- throw new RestconfDocumentedException(new RestconfError(ErrorType.APPLICATION, ErrorTag.INVALID_VALUE,
- "Top level element has to be composite node or has to represent data container node."));
- }
-
private boolean isDataContainerNode(final DataSchemaNode schemaNode) {
if (schemaNode instanceof ContainerSchemaNode || schemaNode instanceof ListSchemaNode) {
return true;
+++ /dev/null
-/*
- * 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.sal.restconf.impl;
-
-import com.google.common.base.Preconditions;
-import java.net.URI;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.ModifyAction;
-import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
-
-/**
- * @deprecated class will be removed in Lithium release
- */
-@Deprecated
-public final class SimpleNodeWrapper implements NodeWrapper<SimpleNode<?>>, SimpleNode<Object> {
-
- private SimpleNode<Object> simpleNode;
-
- private String localName;
- private Object value;
- private URI namespace;
- private QName name;
-
- public SimpleNodeWrapper(final String localName, final Object value) {
- this.localName = Preconditions.checkNotNull(localName);
- this.value = value;
- }
-
- public SimpleNodeWrapper(final URI namespace, final String localName, final Object value) {
- this(localName, value);
- this.namespace = namespace;
- }
-
- @Override
- public void setQname(final QName name) {
- Preconditions.checkState(simpleNode == null, "Cannot change the object, due to data inconsistencies.");
- this.name = name;
- }
-
- @Override
- public QName getQname() {
- return name;
- }
-
- @Override
- public String getLocalName() {
- if (simpleNode != null) {
- return simpleNode.getNodeType().getLocalName();
- }
- return localName;
- }
-
- @Override
- public URI getNamespace() {
- if (simpleNode != null) {
- return simpleNode.getNodeType().getNamespace();
- }
- return namespace;
- }
-
- @Override
- public void setNamespace(final URI namespace) {
- Preconditions.checkState(simpleNode == null, "Cannot change the object, due to data inconsistencies.");
- this.namespace = namespace;
- }
-
- @Override
- public boolean isChangeAllowed() {
- return simpleNode == null ? true : false;
- }
-
- @Override
- public SimpleNode<Object> unwrap() {
- if (simpleNode == null) {
- if (name == null) {
- Preconditions.checkNotNull(namespace);
- name = new QName(namespace, localName);
- }
- simpleNode = NodeFactory.createImmutableSimpleNode(name, null, value);
-
- value = null;
- namespace = null;
- localName = null;
- name = null;
- }
- return simpleNode;
- }
-
- @Override
- public QName getNodeType() {
- return unwrap().getNodeType();
- }
-
- @Override
- @Deprecated
- public CompositeNode getParent() {
- return unwrap().getParent();
- }
-
- @Override
- public Object getValue() {
- return unwrap().getValue();
- }
-
- @Override
- @Deprecated
- public ModifyAction getModificationAction() {
- return unwrap().getModificationAction();
- }
-
- @Override
- public MutableSimpleNode<Object> asMutable() {
- return unwrap().asMutable();
- }
-
- @Override
- public QName getKey() {
- return unwrap().getKey();
- }
-
- @Override
- public Object setValue(final Object value) {
- return unwrap().setValue(value);
- }
-
-}
+++ /dev/null
-/*
- * 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.sal.restconf.impl;
-
-import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-
-/**
- * @deprecated class will be removed in Lithium release
- */
-@Deprecated
-public class StructuredData {
-
- private final CompositeNode data;
- private final DataSchemaNode schema;
- private final DOMMountPoint mountPoint;
- private final boolean prettyPrintMode;
-
- public StructuredData(final CompositeNode data, final DataSchemaNode schema, final DOMMountPoint mountPoint) {
- this(data, schema, mountPoint, false);
- }
-
- public StructuredData(final CompositeNode data, final DataSchemaNode schema, final DOMMountPoint mountPoint,
- final boolean preattyPrintMode) {
- this.data = data;
- this.schema = schema;
- this.mountPoint = mountPoint;
- prettyPrintMode = preattyPrintMode;
- }
-
- public CompositeNode getData() {
- return data;
- }
-
- public DataSchemaNode getSchema() {
- return schema;
- }
-
- public DOMMountPoint getMountPoint() {
- return mountPoint;
- }
-
- public boolean isPrettyPrintMode() {
- return prettyPrintMode;
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Brocade Communications 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.restconf.rpc.impl;
-
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-
-public abstract class AbstractRpcExecutor implements RpcExecutor {
- private final RpcDefinition rpcDef;
-
- public AbstractRpcExecutor(RpcDefinition rpcDef) {
- this.rpcDef = rpcDef;
- }
-
- @Override
- public RpcDefinition getRpcDefinition() {
- return rpcDef;
- }
-
- @Override
- public RpcResult<CompositeNode> invokeRpc(CompositeNode rpcRequest) throws RestconfDocumentedException {
- try {
- return getRpcResult(invokeRpcUnchecked(rpcRequest));
- } catch (IllegalArgumentException e) {
- throw new RestconfDocumentedException(e.getMessage(), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
- } catch (UnsupportedOperationException e) {
- throw new RestconfDocumentedException(e.getMessage(), ErrorType.RPC, ErrorTag.OPERATION_NOT_SUPPORTED);
- } catch (RestconfDocumentedException e) {
- throw e;
- } catch (Exception e) {
- throw new RestconfDocumentedException("The operation encountered an unexpected error while executing.", e);
- }
- }
-
- protected abstract Future<RpcResult<CompositeNode>> invokeRpcUnchecked(CompositeNode rpcRequest);
-
- protected RpcResult<CompositeNode> getRpcResult(Future<RpcResult<CompositeNode>> fromFuture) {
- try {
- return fromFuture.get();
- } catch (InterruptedException e) {
- throw new RestconfDocumentedException(
- "The operation was interrupted while executing and did not complete.", ErrorType.RPC,
- ErrorTag.PARTIAL_OPERATION);
- } catch (ExecutionException e) {
- Throwable cause = e.getCause();
- if (cause instanceof CancellationException) {
- throw new RestconfDocumentedException("The operation was cancelled while executing.", ErrorType.RPC,
- ErrorTag.PARTIAL_OPERATION);
- } else if (cause != null) {
- while (cause.getCause() != null) {
- cause = cause.getCause();
- }
-
- if (cause instanceof IllegalArgumentException) {
- throw new RestconfDocumentedException(cause.getMessage(), ErrorType.PROTOCOL,
- ErrorTag.INVALID_VALUE);
- }
-
- throw new RestconfDocumentedException("The operation encountered an unexpected error while executing.",
- cause);
- } else {
- throw new RestconfDocumentedException("The operation encountered an unexpected error while executing.",
- e);
- }
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (c) 2014 Brocade Communications 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.restconf.rpc.impl;
-
-import java.util.concurrent.Future;
-import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-
-public class BrokerRpcExecutor extends AbstractRpcExecutor {
- private final BrokerFacade broker;
-
- public BrokerRpcExecutor(final RpcDefinition rpcDef, final BrokerFacade broker) {
- super(rpcDef);
- this.broker = broker;
- }
-
- /**
- * @deprecated Method has to be removed for Lithium release
- */
- @Deprecated
- @Override
- protected Future<RpcResult<CompositeNode>> invokeRpcUnchecked(final CompositeNode rpcRequest) {
- throw new AbstractMethodError("Unsuported functionality");
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (c) 2014 Brocade Communications 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.restconf.rpc.impl;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import java.util.concurrent.Future;
-import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
-import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-
-/**
- * Provides an implementation which invokes rpc methods via a mounted yang data model.
- *
- * @author Devin Avery
- *
- */
-public class MountPointRpcExecutor extends AbstractRpcExecutor {
- private final DOMMountPoint mountPoint;
-
- public MountPointRpcExecutor(RpcDefinition rpcDef, DOMMountPoint mountPoint) {
- super(rpcDef);
- this.mountPoint = mountPoint;
- Preconditions.checkNotNull(mountPoint, "MountInstance can not be null.");
- }
-
- @Override
- protected Future<RpcResult<CompositeNode>> invokeRpcUnchecked(CompositeNode rpcRequest) {
- Optional<RpcProvisionRegistry> service = mountPoint.getService(RpcProvisionRegistry.class);
- if (service.isPresent()) {
- return service.get().invokeRpc(getRpcDefinition().getQName(), rpcRequest);
- }
- throw new RestconfDocumentedException("Rpc service is missing.");
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (c) 2014 Brocade Communications 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.restconf.rpc.impl;
-
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-
-public interface RpcExecutor {
-
- /**
- * @deprecated method will be removed in Lithium release
- */
- @Deprecated
- RpcResult<CompositeNode> invokeRpc(CompositeNode rpcRequest);
-
- RpcDefinition getRpcDefinition();
-}
\ No newline at end of file
import javax.xml.transform.stream.StreamResult;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
-import org.opendaylight.controller.sal.rest.impl.XmlMapper;
import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.common.QName;
private static final TransformerFactory FACTORY = TransformerFactory.newInstance();
private static final Pattern RFC3339_PATTERN = Pattern.compile("(\\d\\d)(\\d\\d)$");
- private final XmlMapper xmlMapper = new XmlMapper();
private final SimpleDateFormat rfc3339 = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssZ");
private final YangInstanceIdentifier path;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import java.io.IOException;
import java.io.StringReader;
import java.util.Map;
import java.util.Set;
-import javax.ws.rs.WebApplicationException;
import org.junit.BeforeClass;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
-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.controller.sal.restconf.impl.test.structures.Cont;
import org.opendaylight.controller.sal.restconf.impl.test.structures.Lf;
import org.opendaylight.controller.sal.restconf.impl.test.structures.LfLst;
import org.opendaylight.controller.sal.restconf.impl.test.structures.Lst;
import org.opendaylight.controller.sal.restconf.impl.test.structures.LstItem;
-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.api.Node;
-import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
public class CnSnJsonBasicYangTypesTest extends YangAndXmlAndDataSchemaLoader {
dataLoad("/cnsn-to-json/simple-yang-types", 1, "simple-yang-types", "cont1");
}
- /**
- * Test of json output when as input are specified composite node with empty data + YANG file
- */
-
- @Test
- public void compositeNodeAndYangWithJsonReaderEmptyDataTest() {
- CompositeNode compositeNode = prepareCompositeNodeWithEmpties();
- TestUtils.normalizeCompositeNode(compositeNode, modules, searchedModuleName + ":" + searchedDataSchemaName);
- String jsonOutput = null;
- try {
- jsonOutput = TestUtils.writeCompNodeWithSchemaContextToOutput(compositeNode, modules, dataSchemaNode,
- StructuredDataToJsonProvider.INSTANCE);
- } catch (WebApplicationException | IOException e) {
- }
-
- verifyJsonOutputForEmptyData(jsonOutput);
- }
-
- /**
- * Test of json output when as input are specified xml file (no empty elements)and YANG file
- */
- @Test
- public void xmlAndYangTypesWithJsonReaderTest() {
- Node<?> node = TestUtils.readInputToCnSn("/cnsn-to-json/simple-yang-types/xml/data.xml",
- XmlToCompositeNodeProvider.INSTANCE);
- TestUtils.normalizeCompositeNode(node, modules, searchedModuleName + ":" + searchedDataSchemaName);
- String jsonOutput = null;
- try {
- jsonOutput = TestUtils.writeCompNodeWithSchemaContextToOutput(node, modules, dataSchemaNode,
- StructuredDataToJsonProvider.INSTANCE);
- } catch (WebApplicationException | IOException e) {
- }
-
- verifyJsonOutput(jsonOutput);
- }
-
private void verifyJsonOutputForEmptyData(final String jsonOutput) {
assertNotNull(jsonOutput);
- StringReader strReader = new StringReader(jsonOutput);
- JsonReader jReader = new JsonReader(strReader);
+ final StringReader strReader = new StringReader(jsonOutput);
+ final JsonReader jReader = new JsonReader(strReader);
String exception = null;
Cont dataFromJson = null;
try {
dataFromJson = jsonReadCont1(jReader);
- } catch (IOException e) {
+ } catch (final IOException e) {
exception = e.getMessage();
}
private void verifyJsonOutput(final String jsonOutput) {
assertNotNull(jsonOutput);
- StringReader strReader = new StringReader(jsonOutput);
- JsonReader jReader = new JsonReader(strReader);
+ final StringReader strReader = new StringReader(jsonOutput);
+ final JsonReader jReader = new JsonReader(strReader);
String exception = null;
Cont dataFromJson = null;
try {
dataFromJson = jsonReadCont1(jReader);
- } catch (IOException e) {
+ } catch (final IOException e) {
exception = e.getMessage();
}
private Cont jsonReadCont1Elements(final JsonReader jReader, final Cont redData) throws IOException {
jReader.beginObject();
while (jReader.hasNext()) {
- String keyName = jReader.nextName();
+ final String keyName = jReader.nextName();
if (keyName.equals("lf11")) {
redData.addLf(new Lf(keyName, nextValue(jReader)));
} else if (keyName.equals("lflst11")) {
lfLst = jsonReadLflstValues(jReader, lfLst);
redData.addLfLst(lfLst);
} else if (keyName.equals("lflst12")) {
- LfLst lfLst = new LfLst(keyName);
+ final LfLst lfLst = new LfLst(keyName);
jsonReadLflstValues(jReader, lfLst);
redData.addLfLst(lfLst);
} else if (keyName.equals("lst11")) {
jReader.beginArray();
while (jReader.hasNext()) {
- LstItem lstItem = jsonReadLst11Elements(jReader);
+ final LstItem lstItem = jsonReadLst11Elements(jReader);
lst.addLstItem(lstItem);
}
jReader.endArray();
}
private LstItem jsonReadLst11Elements(final JsonReader jReader) throws IOException {
- LstItem lstItem = new LstItem();
+ final LstItem lstItem = new LstItem();
jReader.beginObject();
while (jReader.hasNext()) {
- String keyName = jReader.nextName();
+ final String keyName = jReader.nextName();
if (keyName.equals("lf111")) {
lstItem.addLf(new Lf(keyName, nextValue(jReader)));
} else if (keyName.equals("lf112")) {
private Lst jsonReadLst112(final JsonReader jReader, final Lst lst) throws IOException {
jReader.beginArray();
while (jReader.hasNext()) {
- LstItem lstItem = jsonReadLst112Elements(jReader);
+ final LstItem lstItem = jsonReadLst112Elements(jReader);
lst.addLstItem(lstItem);
}
jReader.endArray();
}
private LstItem jsonReadLst112Elements(final JsonReader jReader) throws IOException {
- LstItem lstItem = new LstItem();
+ final LstItem lstItem = new LstItem();
jReader.beginObject();
if (jReader.hasNext()) {
- String keyName = jReader.nextName();
+ final String keyName = jReader.nextName();
if (keyName.equals("lf1121")) {
lstItem.addLf(new Lf(keyName, nextValue(jReader)));
}
private Lst jsonReadLst111(final JsonReader jReader, final Lst lst) throws IOException {
jReader.beginArray();
while (jReader.hasNext()) {
- LstItem lstItem = jsonReadLst111Elements(jReader);
+ final LstItem lstItem = jsonReadLst111Elements(jReader);
lst.addLstItem(lstItem);
}
jReader.endArray();
}
private LstItem jsonReadLst111Elements(final JsonReader jReader) throws IOException {
- LstItem lstItem = new LstItem();
+ final LstItem lstItem = new LstItem();
jReader.beginObject();
if (jReader.hasNext()) {
- String keyName = jReader.nextName();
+ final String keyName = jReader.nextName();
if (keyName.equals("lf1111")) {
lstItem.addLf(new Lf(keyName, nextValue(jReader)));
}
private Cont jsonReadCont111Elements(final JsonReader jReader, final Cont cont) throws IOException {
while (jReader.hasNext()) {
- String keyName = jReader.nextName();
+ final String keyName = jReader.nextName();
if (keyName.equals("lf1111")) {
cont.addLf(new Lf(keyName, nextValue(jReader)));
} else if (keyName.equals("lflst1111")) {
private Lst jsonReadLst1111(final JsonReader jReader, final Lst lst) throws IOException {
jReader.beginArray();
while (jReader.hasNext()) {
- LstItem lstItem = jsonReadLst1111Elements(jReader);
+ final LstItem lstItem = jsonReadLst1111Elements(jReader);
lst.addLstItem(lstItem);
}
jReader.endArray();
private LstItem jsonReadLst1111Elements(final JsonReader jReader) throws IOException {
jReader.beginObject();
- LstItem lstItem = new LstItem();
+ final LstItem lstItem = new LstItem();
while (jReader.hasNext()) {
- String keyName = jReader.nextName();
+ final String keyName = jReader.nextName();
if (keyName.equals("lf1111A") || keyName.equals("lf1111B")) {
lstItem.addLf(new Lf(keyName, nextValue(jReader)));
}
assertTrue(dataFromJson.getLfLsts().isEmpty());
assertTrue(dataFromJson.getConts().isEmpty());
- Map<String, Lst> lsts = dataFromJson.getLsts();
+ final Map<String, Lst> lsts = dataFromJson.getLsts();
assertEquals(1, lsts.size());
- Lst lst11 = lsts.get("lst11");
+ final Lst lst11 = lsts.get("lst11");
assertNotNull(lst11);
- Set<LstItem> lstItems = lst11.getLstItems();
+ final Set<LstItem> lstItems = lst11.getLstItems();
assertNotNull(lstItems);
LstItem lst11_1 = null;
LstItem lst11_2 = null;
LstItem lst11_3 = null;
- for (LstItem lstItem : lstItems) {
+ for (final LstItem lstItem : lstItems) {
if (lstItem.getLfs().get("lf111").getValue().equals(1)) {
lst11_1 = lstItem;
} else if (lstItem.getLfs().get("lf111").getValue().equals(2)) {
assertEquals(1, lst11_2.getConts().size());
assertEquals(1, lst11_2.getLsts().size());
- Cont lst11_2_cont111 = lst11_2.getConts().get("cont111");
+ final Cont lst11_2_cont111 = lst11_2.getConts().get("cont111");
// -cont111
assertNotNull(lst11_2_cont111);
assertTrue(lst11_3.getLsts().isEmpty());
// -cont111
- Cont lst11_3_cont111 = lst11_3.getConts().get("cont111");
+ final Cont lst11_3_cont111 = lst11_3.getConts().get("cont111");
assertEquals(0, lst11_3_cont111.getLfs().size());
assertEquals(0, lst11_3_cont111.getLfLsts().size());
assertEquals(1, lst11_3_cont111.getLsts().size());
assertTrue(lflst12.getLfs().contains(new Lf("lflst12 str3")));
assertEquals(1, dataFromJson.getLsts().size());
- Lst lst11 = dataFromJson.getLsts().get("lst11");
+ final Lst lst11 = dataFromJson.getLsts().get("lst11");
assertNotNull(lst11);
assertEquals(2, lst11.getLstItems().size());
LstItem lst11_1 = null;
LstItem lst11_2 = null;
- for (LstItem lstItem : lst11.getLstItems()) {
- Lf lf = lstItem.getLfs().get("lf111");
+ for (final LstItem lstItem : lst11.getLstItems()) {
+ final Lf lf = lstItem.getLfs().get("lf111");
if (lf != null && lf.getValue().equals(140)) {
lst11_1 = lstItem;
} else if (lf != null && lf.getValue().equals(141)) {
assertEquals(lst11_2.getLfs().get("lf112"), new Lf("lf112", "lf112 str2"));
- Cont lst11_2_cont = lst11_2.getConts().get("cont111");
+ final Cont lst11_2_cont = lst11_2.getConts().get("cont111");
assertEquals(0, lst11_2_cont.getConts().size());
assertEquals(1, lst11_2_cont.getLfLsts().size());
assertEquals(1, lst11_2_cont.getLfs().size());
assertEquals(lst11_1.getLfs().get("lf112"), new Lf("lf112", "lf112 str"));
- Cont lst11_1_cont = lst11_1.getConts().get("cont111");
+ final Cont lst11_1_cont = lst11_1.getConts().get("cont111");
assertEquals(0, lst11_1_cont.getConts().size());
assertEquals(1, lst11_1_cont.getLfLsts().size());
assertEquals(1, lst11_1_cont.getLfs().size());
private void checkLst11x(final Lst lst, final LstItem... lstItems) {
assertNotNull(lst);
- Lst requiredLst = new Lst(lst.getName());
- for (LstItem lstItem : lstItems) {
+ final Lst requiredLst = new Lst(lst.getName());
+ for (final LstItem lstItem : lstItems) {
requiredLst.addLstItem(lstItem);
}
private void checkLst1111(final Set<LstItem> 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) {
+ for (final LstItem lstItem : lstItems) {
if (new LstItem().addLf(lf11).addLf(lf12).equals(lstItem)) {
lst11_1_cont_lst1111_1 = lstItem;
} else if (new LstItem().addLf(lf21).addLf(lf22).equals(lstItem)) {
assertNotNull(lst11_1_cont_lst1111_2);
}
- private CompositeNode prepareCompositeNodeWithEmpties() {
- MutableCompositeNode cont1 = NodeFactory.createMutableCompositeNode(
- TestUtils.buildQName("cont1", "simple:yang:types", "2013-11-5"), null, null, ModifyAction.CREATE, null);
-
- // lst11_1
- MutableCompositeNode lst11_1 = NodeFactory
- .createMutableCompositeNode(TestUtils.buildQName("lst11", "simple:yang:types", "2013-11-5"), cont1,
- null, ModifyAction.CREATE, null);
- 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.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.getValue().add(lst111_1_1);
- MutableSimpleNode<?> lf1111_1_1 = NodeFactory.createMutableSimpleNode(
- TestUtils.buildQName("lf1111", "simple:yang:types", "2013-11-5"), 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.getValue().add(lst111_1_2);
- MutableSimpleNode<?> lf1111_1_2 = NodeFactory.createMutableSimpleNode(
- TestUtils.buildQName("lf1111", "simple:yang:types", "2013-11-5"), 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.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.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.getValue().add(cont111_1);
-
- lst11_1.init();
- // :lst11_1
-
- // lst11_2
- MutableCompositeNode lst11_2 = NodeFactory
- .createMutableCompositeNode(TestUtils.buildQName("lst11", "simple:yang:types", "2013-11-5"), cont1,
- null, ModifyAction.CREATE, null);
- 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.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.getValue().add(cont111_2);
-
- MutableSimpleNode<?> lflst1111_2_2 = NodeFactory.createMutableSimpleNode(
- TestUtils.buildQName("lflst1111", "simple:yang:types", "2013-11-5"), 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, 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.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.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.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.getValue().add(lf1111A_2_2);
- lst1111_2_2.init();
- // :lst1111_2
-
- cont111_2.init();
- // :cont111_2
-
- MutableCompositeNode lst112_2 = NodeFactory.createMutableCompositeNode(
- TestUtils.buildQName("lst112", "simple:yang:types", "2013-11-5"), lst11_2, null, ModifyAction.CREATE,
- null);
- lst11_2.getValue().add(lst112_2);
- lst112_2.init();
- lst11_2.init();
-
- // :lst11_2
-
- // lst11_3
- MutableCompositeNode lst11_3 = NodeFactory
- .createMutableCompositeNode(TestUtils.buildQName("lst11", "simple:yang:types", "2013-11-5"), cont1,
- null, ModifyAction.CREATE, null);
- 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.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.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.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.getValue().add(lst1111_3_2);
- lst1111_3_2.init();
-
- cont111_3.init();
- // :cont111_3
-
- lst11_3.init();
- // :lst11_3
-
- cont1.init();
- return cont1;
- }
-
}
*/
package org.opendaylight.controller.sal.restconf.impl.cnsn.to.json.test;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import javax.ws.rs.WebApplicationException;
import org.junit.BeforeClass;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
-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.Node;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataValidationException;
public class CnSnJsonChoiceCaseTest extends YangAndXmlAndDataSchemaLoader {
dataLoad("/cnsn-to-json/choice");
}
- /**
- * Test when some data are in one case node and other in another. This isn't correct. Next Json validator should
- * return error because nodes has to be from one case below concrete choice.
- *
- */
- @Test(expected=DataValidationException.class)
- public void nodeSchemasOnVariousChoiceCasePathTest() {
- testWrapper("/cnsn-to-json/choice/xml/data_various_path_err.xml", "choice-case-test:cont");
- }
-
- /**
- * Test when some data are in one case node and other in another. Additionally data are loadef from various choices.
- * This isn't correct. Next Json validator should return error because nodes has to be from one case below concrete
- * choice.
- *
- */
- @Test(expected=DataValidationException.class)
- public void nodeSchemasOnVariousChoiceCasePathAndMultipleChoicesTest() {
- testWrapper("/cnsn-to-json/choice/xml/data_more_choices_same_level_various_paths_err.xml",
- "choice-case-test:cont");
- }
-
- /**
- * Test when second level data are red first, then first and at the end third level. Level represents pass through
- * couple choice-case
- */
-
- @Test
- public void nodeSchemasWithRandomOrderAccordingLevel() {
- testWrapper("/cnsn-to-json/choice/xml/data_random_level.xml", "choice-case-test:cont");
- }
-
- /**
- * Test when element from no first case is used
- */
- @Test
- public void nodeSchemasNotInFirstCase() {
- testWrapper("/cnsn-to-json/choice/xml/data_no_first_case.xml", "choice-case-test:cont");
- }
-
- /**
- * Test when element in case is list
- */
- @Test
- public void nodeSchemaAsList() {
- testWrapper("/cnsn-to-json/choice/xml/data_list.xml", "choice-case-test:cont");
- }
-
- /**
- * Test when element in case is container
- */
- @Test
- public void nodeSchemaAsContainer() {
- testWrapper("/cnsn-to-json/choice/xml/data_container.xml", "choice-case-test:cont");
- }
-
- /**
- * Test when element in case is leaflist
- */
- @Test
- public void nodeSchemaAsLeafList() {
- testWrapper("/cnsn-to-json/choice/xml/data_leaflist.xml", "choice-case-test:cont");
- }
-
- /**
- *
- */
- @Test
- public void nodeSchemasInMultipleChoicesTest() {
- testWrapper("/cnsn-to-json/choice/xml/data_more_choices_same_level.xml", "choice-case-test:cont");
- }
-
- /**
- * Test whether is possible to find data schema for node which is specified as dirrect subnode of choice (case
- * without CASE key word)
- */
- @Test
- public void nodeSchemasInCaseNotDefinedWithCaseKeyword() {
- testWrapper("/cnsn-to-json/choice/xml/data_case_defined_without_case.xml", "choice-case-test:cont");
- }
-
- /**
- * Test of multiple use of choices
- */
- @Test
- public void nodeSchemasInThreeChoicesAtSameLevel() {
- testWrapper("/cnsn-to-json/choice/xml/data_three_choices_same_level.xml", "choice-case-test:cont");
- }
-
- private void testWrapper(String xmlPath, String pathToSchemaNode) {
- Node<?> node = TestUtils.readInputToCnSn(xmlPath, XmlToCompositeNodeProvider.INSTANCE);
- TestUtils.normalizeCompositeNode(node, modules, pathToSchemaNode);
- try {
- TestUtils.writeCompNodeWithSchemaContextToOutput(node, modules, dataSchemaNode,
- StructuredDataToJsonProvider.INSTANCE);
- } catch (WebApplicationException | IOException e) {
- // shouldn't end here
- assertTrue(false);
- }
- }
}
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
-
import com.google.common.collect.Maps;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import java.io.StringReader;
import java.util.Map;
import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
-import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
-import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
-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.Node;
public class CnSnToJsonBasicDataTypesTest extends YangAndXmlAndDataSchemaLoader {
dataLoad("/cnsn-to-json/simple-data-types");
}
- @Test
- @Ignore
- public void simpleYangDataTest() throws Exception {
-
- final Node<?> node = TestUtils.readInputToCnSn("/cnsn-to-json/simple-data-types/xml/data.xml",
- XmlToCompositeNodeProvider.INSTANCE);
-
- TestUtils.normalizeCompositeNode(node, modules, "simple-data-types:cont");
-
- final String jsonOutput = TestUtils.writeCompNodeWithSchemaContextToOutput(node, modules, dataSchemaNode,
- StructuredDataToJsonProvider.INSTANCE);
-
- assertNotNull(jsonOutput);
-
- verifyJsonOutput(jsonOutput);
- }
-
private void verifyJsonOutput(final String jsonOutput) {
final StringReader strReader = new StringReader(jsonOutput);
final JsonReader jReader = new JsonReader(strReader);
jReader.endObject();
}
- @Test
- public void testBadData() throws Exception {
-
- try {
- final Node<?> node = TestUtils.readInputToCnSn("/cnsn-to-json/simple-data-types/xml/bad-data.xml",
- XmlToCompositeNodeProvider.INSTANCE);
-
- TestUtils.normalizeCompositeNode(node, modules, "simple-data-types:cont");
- fail("Expected RestconfDocumentedException");
- } catch (final RestconfDocumentedException e) {
- assertEquals("getErrorTag", ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
- }
- }
}
*/
package org.opendaylight.controller.sal.restconf.impl.cnsn.to.json.test;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.ws.rs.WebApplicationException;
import org.junit.BeforeClass;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
-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.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;
public class CnSnToJsonIdentityrefTest extends YangAndXmlAndDataSchemaLoader {
dataLoad("/cnsn-to-json/identityref", 2, "identityref-module", "cont");
}
- @Test
- public void identityrefToJsonTest() {
- String json = null;
- try {
- QName valueAsQname = TestUtils.buildQName("name_test", "identityref:module", "2013-12-2");
- json = TestUtils.writeCompNodeWithSchemaContextToOutput(prepareCompositeNode(valueAsQname), modules,
- dataSchemaNode, StructuredDataToJsonProvider.INSTANCE);
- } catch (WebApplicationException | IOException e) {
- // shouldn't end here
- assertTrue(false);
- }
- assertNotNull(json);
- Pattern ptrn = Pattern.compile(".*\"lf1\"\\p{Space}*:\\p{Space}*\"identityref-module:name_test\".*",
- Pattern.DOTALL);
- Matcher mtch = ptrn.matcher(json);
-
- assertTrue(mtch.matches());
- }
-
- @Test
- public void identityrefToJsonWithoutQNameTest() {
- String json = null;
- try {
- String value = "not q name value";
- json = TestUtils.writeCompNodeWithSchemaContextToOutput(prepareCompositeNode(value), modules,
- dataSchemaNode, StructuredDataToJsonProvider.INSTANCE);
- } catch (WebApplicationException | IOException e) {
- // shouldn't end here
- assertTrue(false);
- }
- System.out.println(json);
- assertNotNull(json);
- Pattern ptrn = Pattern.compile(".*\"lf1\"\\p{Space}*:\\p{Space}*\"not q name value\".*", Pattern.DOTALL);
- Matcher mtch = ptrn.matcher(json);
-
- assertTrue(mtch.matches());
- }
-
- 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.getValue().add(cont1);
-
- MutableSimpleNode<?> lf1 = NodeFactory
- .createMutableSimpleNode(TestUtils.buildQName("lf1", "identityref:module", "2013-12-2"), cont1, value,
- ModifyAction.CREATE, null);
-
- cont1.getValue().add(lf1);
- cont1.init();
- cont.init();
-
- return cont;
- }
-
}
*/
package org.opendaylight.controller.sal.restconf.impl.cnsn.to.json.test;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
import java.util.List;
import java.util.Set;
-import javax.activation.UnsupportedDataTypeException;
-import javax.ws.rs.WebApplicationException;
import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
-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.common.QName;
-import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
}
- @Test
- @Ignore
- public void incorrectTopLevelElementTest() {
-
- final Node<?> node = TestUtils.readInputToCnSn("/cnsn-to-json/simple-data-types/xml/data.xml", XmlToCompositeNodeProvider.INSTANCE);
- DataSchemaNode incorrectDataSchema = null;
- incorrectDataSchema = new IncorrectDataSchema();
-
- TestUtils.normalizeCompositeNode(node, modules, "simple-data-types:cont");
-
- boolean exceptionRaised = false;
- try {
- TestUtils.writeCompNodeWithSchemaContextToOutput(node, modules, incorrectDataSchema,
- StructuredDataToJsonProvider.INSTANCE);
- } catch (final UnsupportedDataTypeException e) {
- exceptionRaised = true;
- } catch (WebApplicationException | IOException e) {
- LOG.error("WebApplicationException or IOException was raised");
- }
-
- assertTrue(exceptionRaised);
- }
-
}
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import javax.ws.rs.WebApplicationException;
import org.junit.BeforeClass;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
-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.Node;
/**
*
dataLoad("/cnsn-to-json/leafref", 2, "main-module", "cont");
}
- @Test
- public void leafrefAbsolutePathToExistingLeafTest() {
- String json = toJson("/cnsn-to-json/leafref/xml/data_absolut_ref_to_existing_leaf.xml");
- validateJson(".*\"lf3\":\\p{Blank}*\"true\".*", json);
- }
-
- @Test
- public void leafrefRelativePathToExistingLeafTest() {
- String json = toJson("/cnsn-to-json/leafref/xml/data_relativ_ref_to_existing_leaf.xml");
- validateJson(".*\"lf2\":\\p{Blank}*\"121\".*", json);
- }
-
- /**
- * Tests case when reference to not existing element is present. In this case value from single node is printed as
- * string.
- */
- @Test
- public void leafrefToNonExistingLeafTest() {
- String json = toJson("/cnsn-to-json/leafref/xml/data_ref_to_non_existing_leaf.xml");
- validateJson(".*\"lf5\":\\p{Blank}*\"137\".*", json);
- }
-
- /**
- * Tests case when non leaf element is referenced. In this case value from single node is printed as string.
- */
- @Test
- public void leafrefToNotLeafTest() {
- String json = toJson("/cnsn-to-json/leafref/xml/data_ref_to_not_leaf.xml");
- validateJson(".*\"cont-augment-module\\p{Blank}*:\\p{Blank}*lf6\":\\p{Blank}*\"44\".*", json);
- }
-
- /**
- * Tests case when leaflist element is refers to leaf.
- */
- @Test
- public void leafrefFromLeafListToLeafTest() {
- String json = toJson("/cnsn-to-json/leafref/xml/data_relativ_ref_from_leaflist_to_existing_leaf.xml");
- validateJson(
- ".*\"cont-augment-module\\p{Blank}*:\\p{Blank}*lflst1\":\\p{Blank}*.*\"345\",\\p{Space}*\"346\",\\p{Space}*\"347\".*",
- json);
- }
-
- /**
- * Tests case when leaflist element is refers to leaf.
- */
- @Test
- public void leafrefFromLeafrefToLeafrefTest() {
- String json = toJson("/cnsn-to-json/leafref/xml/data_from_leafref_to_leafref.xml");
- validateJson(".*\"cont-augment-module\\p{Blank}*:\\p{Blank}*lf7\":\\p{Blank}*\"200\".*", json);
- }
-
- private void validateJson(String regex, String value) {
+ private void validateJson(final String regex, final String value) {
assertNotNull(value);
- Pattern ptrn = Pattern.compile(regex, Pattern.DOTALL);
- Matcher mtch = ptrn.matcher(value);
+ final Pattern ptrn = Pattern.compile(regex, Pattern.DOTALL);
+ final Matcher mtch = ptrn.matcher(value);
assertTrue(mtch.matches());
}
- private String toJson(String xmlDataPath) {
- try {
- Node<?> node = TestUtils.readInputToCnSn(xmlDataPath, XmlToCompositeNodeProvider.INSTANCE);
- TestUtils.normalizeCompositeNode(node, modules, searchedModuleName + ":" + searchedDataSchemaName);
- return TestUtils.writeCompNodeWithSchemaContextToOutput(node, modules, dataSchemaNode,
- StructuredDataToJsonProvider.INSTANCE);
- } catch (WebApplicationException | IOException e) {
- }
- return "";
- }
-
}
*/
package org.opendaylight.controller.sal.restconf.impl.cnsn.to.json.test;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.opendaylight.controller.sal.restconf.impl.test.TestUtils.containsStringData;
-
-import java.io.IOException;
-import java.util.Collections;
-import javax.ws.rs.WebApplicationException;
import org.junit.BeforeClass;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
import org.opendaylight.controller.sal.restconf.impl.test.DummyType;
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.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;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
dataLoad("/cnsn-to-json/simple-data-types");
}
- @Test
- public void incorrectTopLevelElementTest() throws WebApplicationException, IOException {
- String jsonOutput = null;
- jsonOutput = TestUtils.writeCompNodeWithSchemaContextToOutput(prepareCompositeNode(),
- Collections.<Module> emptySet(), prepareDataSchemaNode(), StructuredDataToJsonProvider.INSTANCE);
- assertNotNull(jsonOutput);
-
- // pattern for e.g. > "lf1" : "" < or >"lf1":""<
- assertTrue(containsStringData(jsonOutput, "\"lf1\"", ":", "\"\""));
- }
-
- private CompositeNode prepareCompositeNode() {
- MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(
- 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.getValue().add(lf1);
- cont.init();
- return cont;
- }
-
private DataSchemaNode prepareDataSchemaNode() {
- ContainerSchemaNodeBuilder contBuild = new ContainerSchemaNodeBuilder("module", 1, TestUtils.buildQName("cont",
+ final ContainerSchemaNodeBuilder contBuild = new ContainerSchemaNodeBuilder("module", 1, TestUtils.buildQName("cont",
"simple:uri", "2012-12-17"), SchemaPath.create(true, QName.create("dummy")));
- LeafSchemaNodeBuilder leafBuild = new LeafSchemaNodeBuilder("module", 2, TestUtils.buildQName("lf1",
+ final LeafSchemaNodeBuilder leafBuild = new LeafSchemaNodeBuilder("module", 2, TestUtils.buildQName("lf1",
"simple:uri", "2012-12-17"), SchemaPath.create(true, QName.create("dummy")));
leafBuild.setType(new DummyType());
leafBuild.setConfiguration(true);
*/
package org.opendaylight.controller.sal.restconf.impl.cnsn.to.json.test;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.opendaylight.controller.sal.restconf.impl.test.TestUtils.containsStringData;
-
-import java.io.IOException;
-import javax.ws.rs.WebApplicationException;
import org.junit.BeforeClass;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
-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.Node;
public class CnSnToJsonWithAugmentTest extends YangAndXmlAndDataSchemaLoader {
dataLoad("/cnsn-to-json/augmentation", 5, "yang", "cont");
}
- /**
- * Test of json output when as input are specified composite node with empty data + YANG file
- */
- @Test
- public void augmentedElementsToJson() {
- Node<?> node = TestUtils.readInputToCnSn("/cnsn-to-json/augmentation/xml/data.xml",
- XmlToCompositeNodeProvider.INSTANCE);
- TestUtils.normalizeCompositeNode(node, modules, searchedModuleName + ":" + searchedDataSchemaName);
-
- String jsonOutput = null;
- try {
- jsonOutput = TestUtils.writeCompNodeWithSchemaContextToOutput(node, modules, dataSchemaNode,
- StructuredDataToJsonProvider.INSTANCE);
- } catch (WebApplicationException | IOException e) {
- }
- assertNotNull(jsonOutput);
-
- assertTrue(containsStringData(jsonOutput, "\"augment-leaf:lf2\"", ":", "\"lf2\""));
- assertTrue(containsStringData(jsonOutput, "\"augment-container:cont1\"", ":", "\\{"));
- assertTrue(containsStringData(jsonOutput, "\"augment-container:lf11\"", ":", "\"lf11\""));
- assertTrue(containsStringData(jsonOutput, "\"augment-list:lst1\"", ":", "\\["));
- assertTrue(containsStringData(jsonOutput, "\"augment-list:lf11\"", ":", "\"lf1_1\""));
- assertTrue(containsStringData(jsonOutput, "\"augment-list:lf11\"", ":", "\"lf1_2\""));
- assertTrue(containsStringData(jsonOutput, "\"augment-leaflist:lflst1\"", ":", "\\["));
- }
-}
+}
\ No newline at end of file
*/
package org.opendaylight.controller.sal.restconf.impl.cnsn.to.json.test;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.ws.rs.WebApplicationException;
import org.junit.BeforeClass;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
-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.CompositeNode;
-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.SchemaContext;
public class CnSnToJsonWithDataFromSeveralModulesTest extends YangAndXmlAndDataSchemaLoader {
public static void initialize() {
dataLoad("/xml-to-cnsn/data-of-several-modules/yang", 2, "module1", "cont_m1");
}
-
- @Test
- public void dataFromSeveralModulesToJsonTest() throws WebApplicationException, IOException, URISyntaxException {
- SchemaContext schemaContext = TestUtils.loadSchemaContext(modules);
- String output = TestUtils.writeCompNodeWithSchemaContextToOutput(prepareCnSn(), modules, schemaContext,
- StructuredDataToJsonProvider.INSTANCE);
-
- // String output =
- // String.format("\"data\" : {\n" +
- // "\t\"cont_m1\" : {\n" +
- // "\t\t\"lf1_m1\" : \"lf1 m1 value\"\n" +
- // "\t}\n" +
- // "\t\"cont_m2\" : {\n" +
- // "\t\t\"lf1_m2\" : \"lf1 m2 value\"\n" +
- // "\t}\n" +
- // "}");
-
- StringBuilder regex = new StringBuilder();
- regex.append("^");
-
- regex.append(".*\"data\"");
- regex.append(".*:");
- regex.append(".*\\{");
-
- regex.append(".*\"cont_m1\"");
- regex.append(".*:");
- regex.append(".*\\{");
- regex.append(".*\\}");
-
- regex.append(".*\"contB_m1\"");
- regex.append(".*:");
- regex.append(".*\\{");
- regex.append(".*\\}");
-
- regex.append(".*\"cont_m2\"");
- regex.append(".*:");
- regex.append(".*\\{");
- regex.append(".*\\}");
-
- regex.append(".*\"contB_m2\"");
- regex.append(".*:");
- regex.append(".*\\{");
- regex.append(".*\\}");
-
- regex.append(".*\\}");
-
- regex.append(".*");
- regex.append("$");
-
- Pattern ptrn = Pattern.compile(regex.toString(), Pattern.DOTALL);
- Matcher matcher = ptrn.matcher(output);
-
- assertTrue(matcher.find());
-
- }
-
- private CompositeNode prepareCnSn() throws URISyntaxException {
- String uri1 = "module:one";
- String rev1 = "2014-01-17";
-
- MutableCompositeNode data = NodeFactory.createMutableCompositeNode(
- TestUtils.buildQName("data", "urn:ietf:params:xml:ns:netconf:base:1.0", "2000-01-01"), null, null,
- null, null);
-
- MutableCompositeNode cont_m1 = NodeFactory.createMutableCompositeNode(
- TestUtils.buildQName("cont_m1", uri1, rev1), data, null, null, null);
- 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.getValue().add(lf1_m1);
- cont_m1.init();
-
- MutableCompositeNode contB_m1 = NodeFactory.createMutableCompositeNode(
- TestUtils.buildQName("contB_m1", uri1, rev1), data, null, null, null);
- 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.getValue().add(cont_m2);
-
- MutableSimpleNode<?> lf1_m2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1_m2", uri2, rev2),
- cont_m1, "lf1 m2 value", null, null);
- 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.getValue().add(contB_m2);
- contB_m2.init();
-
- data.init();
- return data;
- }
-
}
*/
package org.opendaylight.controller.sal.restconf.impl.cnsn.to.xml.test;
-import static org.junit.Assert.assertNotNull;
-
-import java.io.IOException;
-import java.net.URI;
import java.net.URISyntaxException;
-import javax.ws.rs.WebApplicationException;
import org.junit.BeforeClass;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
-import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
-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.CompositeNode;
/**
*
dataLoad("/instanceidentifier/yang", 4, "instance-identifier-module", "cont");
}
- @Test
- public void snAsYangInstanceIdentifier() throws WebApplicationException, IOException, URISyntaxException {
- CompositeNode cnSnData = prepareCnStructForYangData();
- String xmlOutput = TestUtils.writeCompNodeWithSchemaContextToOutput(cnSnData, modules, dataSchemaNode,
- StructuredDataToXmlProvider.INSTANCE);
- assertNotNull(xmlOutput);
- }
-
- private CompositeNode prepareCnStructForYangData() throws URISyntaxException {
- CompositeNodeWrapper cont = new CompositeNodeWrapper(new URI("instance:identifier:module"), "cont");
- CompositeNodeWrapper cont1 = new CompositeNodeWrapper(new URI("augment:module"), "cont1");
- cont.addValue(cont1);
- SimpleNodeWrapper lf11 = new SimpleNodeWrapper(new URI("augment:augment:module"), "lf11", "/cont/cont1/lf12");
- SimpleNodeWrapper lf12 = new SimpleNodeWrapper(new URI("augment:augment:module"), "lf12", "lf12 value");
- cont1.addValue(lf11);
- cont1.addValue(lf12);
- cont.unwrap();
- return cont;
- }
-
}
*/
package org.opendaylight.controller.sal.restconf.impl.cnsn.to.xml.test;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.util.Collections;
-import javax.ws.rs.WebApplicationException;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
import org.opendaylight.controller.sal.restconf.impl.test.DummyType;
import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
-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;
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;
private static final Logger LOG = LoggerFactory.getLogger(CnSnToXmlNotExistingLeafTypeTest.class);
- @Ignore
- @Test
- public void incorrectTopLevelElementTest() {
-
- boolean nullPointerExceptionRaised = false;
- try {
- TestUtils.writeCompNodeWithSchemaContextToOutput(prepareCompositeNode(), Collections.<Module> emptySet(),
- prepareDataSchemaNode(), StructuredDataToXmlProvider.INSTANCE);
- } catch (WebApplicationException | IOException e) {
- LOG.error("WebApplicationException or IOException was raised");
- } catch (NullPointerException e) {
- nullPointerExceptionRaised = true;
- }
- assertTrue(nullPointerExceptionRaised);
-
- }
-
- private CompositeNode prepareCompositeNode() {
- MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(
- 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.getValue().add(lf1);
- cont.init();
- return cont;
- }
private DataSchemaNode prepareDataSchemaNode() {
- ContainerSchemaNodeBuilder contBuild = new ContainerSchemaNodeBuilder("module", 1, TestUtils.buildQName("cont",
+ final ContainerSchemaNodeBuilder contBuild = new ContainerSchemaNodeBuilder("module", 1, TestUtils.buildQName("cont",
"simple:uri", "2012-12-17"), null);
- LeafSchemaNodeBuilder leafBuild = new LeafSchemaNodeBuilder("module", 2, TestUtils.buildQName("lf1",
+ final LeafSchemaNodeBuilder leafBuild = new LeafSchemaNodeBuilder("module", 2, TestUtils.buildQName("lf1",
"simple:uri", "2012-12-17"), null);
leafBuild.setType(new DummyType());
leafBuild.setConfiguration(true);
*/
package org.opendaylight.controller.sal.restconf.impl.cnsn.to.xml.test;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import com.google.common.base.Optional;
-import com.google.common.collect.Lists;
-import java.io.IOException;
-import java.util.List;
-import javax.ws.rs.WebApplicationException;
-import javax.xml.transform.TransformerFactoryConfigurationError;
import org.junit.BeforeClass;
-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.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;
-import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
-import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair;
-import org.opendaylight.yangtools.yang.model.util.BinaryType;
-import org.opendaylight.yangtools.yang.model.util.BitsType;
-import org.opendaylight.yangtools.yang.model.util.BooleanType;
-import org.opendaylight.yangtools.yang.model.util.EmptyType;
-import org.opendaylight.yangtools.yang.model.util.EnumerationType;
-import org.opendaylight.yangtools.yang.model.util.Int16;
-import org.opendaylight.yangtools.yang.model.util.Int32;
-import org.opendaylight.yangtools.yang.model.util.Int64;
-import org.opendaylight.yangtools.yang.model.util.Int8;
-import org.opendaylight.yangtools.yang.model.util.StringType;
-import org.opendaylight.yangtools.yang.model.util.Uint16;
-import org.opendaylight.yangtools.yang.model.util.Uint32;
-import org.opendaylight.yangtools.yang.model.util.Uint64;
-import org.opendaylight.yangtools.yang.model.util.Uint8;
-import org.opendaylight.yangtools.yang.model.util.UnionType;
/**
*
dataLoad("/cnsn-to-xml/yang", 2, "basic-module", "cont");
}
- @Test
- public void snAsYangIdentityrefToXMLTest() {
- serializeToXml(prepareIdentityrefData(null, true), "<lf11 xmlns:x=\"referenced:module\">x:iden</lf11>");
- }
-
- @Test
- public void snAsYangIdentityrefWithQNamePrefixToXMLTest() {
- serializeToXml(prepareIdentityrefData("prefix", true),
- "<lf11 xmlns","=\"referenced:module\">",":iden</lf11>");
- }
-
- @Test
- public void snAsYangIdentityrefWithPrefixToXMLTest() {
- serializeToXml(prepareIdentityrefData("prefix", false), "<lf11>no qname value</lf11>");
- }
-
- @Test
- public void snAsYangLeafrefWithPrefixToXMLTest() {
- serializeToXml(prepareLeafrefData(), "<lfBoolean>true</lfBoolean>", "<lfLfref>true</lfLfref>");
- }
-
- @Test
- public void snAsYangStringToXmlTest() {
- serializeToXml(
- prepareCnStructForYangData(
- TypeDefinitionAwareCodec.from(StringType.getInstance()).deserialize("lfStr value"), "lfStr"),
- "<lfStr>lfStr value</lfStr>");
- }
-
- @Test
- public void snAsYangInt8ToXmlTest() {
- final String elName = "lfInt8";
- serializeToXml(
- prepareCnStructForYangData(TypeDefinitionAwareCodec.from(Int8.getInstance()).deserialize("14"), elName),
- "<" + elName + ">14</" + elName + ">");
- }
-
- @Test
- public void snAsYangInt16ToXmlTest() {
- final String elName = "lfInt16";
- serializeToXml(
- prepareCnStructForYangData(TypeDefinitionAwareCodec.from(Int16.getInstance()).deserialize("3000"),
- elName), "<" + elName + ">3000</" + elName + ">");
- }
-
- @Test
- public void snAsYangInt32ToXmlTest() {
- final String elName = "lfInt32";
- serializeToXml(
- prepareCnStructForYangData(TypeDefinitionAwareCodec.from(Int32.getInstance()).deserialize("201234"),
- elName), "<" + elName + ">201234</" + elName + ">");
- }
-
- @Test
- public void snAsYangInt64ToXmlTest() {
- final String elName = "lfInt64";
- serializeToXml(
- prepareCnStructForYangData(
- TypeDefinitionAwareCodec.from(Int64.getInstance()).deserialize("5123456789"), elName), "<"
- + elName + ">5123456789</" + elName + ">");
- }
-
- @Test
- public void snAsYangUint8ToXmlTest() {
- final String elName = "lfUint8";
- serializeToXml(
- prepareCnStructForYangData(TypeDefinitionAwareCodec.from(Uint8.getInstance()).deserialize("200"),
- elName), "<" + elName + ">200</" + elName + ">");
- }
-
- @Test
- public void snAsYangUint16ToXmlTest() {
- final String elName = "lfUint16";
- serializeToXml(
- prepareCnStructForYangData(TypeDefinitionAwareCodec.from(Uint16.getInstance()).deserialize("4000"),
- elName), "<" + elName + ">4000</" + elName + ">");
- }
-
- @Test
- public void snAsYangUint32ToXmlTest() {
- final String elName = "lfUint32";
- serializeToXml(
- prepareCnStructForYangData(TypeDefinitionAwareCodec.from(Uint32.getInstance())
- .deserialize("4123456789"), elName), "<" + elName + ">4123456789</" + elName + ">");
- }
-
- @Test
- public void snAsYangUint64ToXmlTest() {
- final String elName = "lfUint64";
- serializeToXml(
- prepareCnStructForYangData(TypeDefinitionAwareCodec.from(Uint64.getInstance())
- .deserialize("5123456789"), elName), "<" + elName + ">5123456789</" + elName + ">");
- }
-
- @Test
- public void snAsYangBinaryToXmlTest() {
- final String elName = "lfBinary";
- serializeToXml(
- prepareCnStructForYangData(
- TypeDefinitionAwareCodec.from(BinaryType.getInstance()).deserialize(
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567"), elName), "<" + elName
- + ">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567</" + elName + ">");
- }
-
- @Test
- public void snAsYangBitsToXmlTest() {
- final BitsTypeDefinition.Bit mockBit1 = mock(BitsTypeDefinition.Bit.class);
- when(mockBit1.getName()).thenReturn("one");
- final BitsTypeDefinition.Bit mockBit2 = mock(BitsTypeDefinition.Bit.class);
- when(mockBit2.getName()).thenReturn("two");
- final List<BitsTypeDefinition.Bit> bitList = Lists.newArrayList(mockBit1, mockBit2);
-
- final String elName = "lfBits";
- serializeToXml(
- prepareCnStructForYangData(
- TypeDefinitionAwareCodec.from(BitsType.create(mock(SchemaPath.class), bitList)).deserialize(
- "one two"), elName), "<" + elName + ">one two</" + elName + ">", "<" + elName
- + ">two one</" + elName + ">");
- }
-
- @Test
- public void snAsYangEnumerationToXmlTest() {
- final EnumTypeDefinition.EnumPair mockEnum = mock(EnumTypeDefinition.EnumPair.class);
- when(mockEnum.getName()).thenReturn("enum2");
- final List<EnumPair> enumList = Lists.newArrayList(mockEnum);
-
- final String elName = "lfEnumeration";
- serializeToXml(
- prepareCnStructForYangData(
- TypeDefinitionAwareCodec.from(
- EnumerationType.create(mock(SchemaPath.class), enumList,
- Optional.<EnumTypeDefinition.EnumPair> absent())).deserialize("enum2"), elName),
- "<" + elName + ">enum2</" + elName + ">");
- }
-
- @Test
- public void snAsYangEmptyToXmlTest() {
- final String elName = "lfEmpty";
- serializeToXml(
- prepareCnStructForYangData(TypeDefinitionAwareCodec.from(EmptyType.getInstance()).deserialize(null),
- elName), "<" + elName + "/>");
- }
-
- @Test
- public void snAsYangBooleanToXmlTest() {
- final String elName = "lfBoolean";
- serializeToXml(
- prepareCnStructForYangData(TypeDefinitionAwareCodec.from(BooleanType.getInstance()).deserialize("str"),
- elName), "<" + elName + ">false</" + elName + ">");
- serializeToXml(
- prepareCnStructForYangData(
- TypeDefinitionAwareCodec.from(BooleanType.getInstance()).deserialize("true"), elName), "<"
- + elName + ">true</" + elName + ">");
- }
-
- @Test
- public void snAsYangUnionToXmlTest() {
-
- final BitsTypeDefinition.Bit mockBit1 = mock(BitsTypeDefinition.Bit.class);
- when(mockBit1.getName()).thenReturn("first");
- final BitsTypeDefinition.Bit mockBit2 = mock(BitsTypeDefinition.Bit.class);
- when(mockBit2.getName()).thenReturn("second");
- final List<BitsTypeDefinition.Bit> bitList = Lists.newArrayList(mockBit1, mockBit2);
-
- final List<TypeDefinition<?>> types = Lists.<TypeDefinition<?>> newArrayList(Int8.getInstance(),
- BitsType.create(mock(SchemaPath.class), bitList), BooleanType.getInstance());
- final UnionType unionType = UnionType.create(types);
-
- final String elName = "lfUnion";
- final String int8 = "15";
- serializeToXml(prepareCnStructForYangData(TypeDefinitionAwareCodec.from(unionType).deserialize(int8), elName),
- "<" + elName + ">15</" + elName + ">");
-
- final String bits = "first second";
- serializeToXml(prepareCnStructForYangData(TypeDefinitionAwareCodec.from(unionType).deserialize(bits), elName),
- "<" + elName + ">first second</" + elName + ">");
-
- final String bool = "str";
- serializeToXml(prepareCnStructForYangData(TypeDefinitionAwareCodec.from(unionType).deserialize(bool), elName),
- "<" + elName + ">str</" + elName + ">");
- }
-
- private void serializeToXml(final CompositeNode compositeNode, final String... xmlRepresentation)
- throws TransformerFactoryConfigurationError {
- String xmlString = "";
- try {
- xmlString = TestUtils.writeCompNodeWithSchemaContextToOutput(compositeNode, modules, dataSchemaNode,
- StructuredDataToXmlProvider.INSTANCE);
- } catch (WebApplicationException | IOException e) {
- }
- assertNotNull(xmlString);
- boolean containSearchedStr = false;
- String strRepresentation = "";
- for (final String searchedStr : xmlRepresentation) {
- if (xmlString.contains(searchedStr)) {
- containSearchedStr = true;
- break;
- }
- strRepresentation = strRepresentation + "[" + searchedStr + "]";
- }
- assertTrue("At least one of specified strings " + strRepresentation + " wasn't found.", containSearchedStr);
-
- }
-
- private CompositeNode prepareIdentityrefData(final String prefix, final boolean valueAsQName) {
- final MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(
- TestUtils.buildQName("cont", "basic:module", "2013-12-2"), null, null, ModifyAction.CREATE, null);
- final MutableCompositeNode cont1 = NodeFactory.createMutableCompositeNode(
- TestUtils.buildQName("cont1", "basic:module", "2013-12-2"), cont, null, ModifyAction.CREATE, null);
- cont.getValue().add(cont1);
-
- Object value = null;
- if (valueAsQName) {
- value = TestUtils.buildQName("iden", "referenced:module", "2013-12-2", prefix);
- } else {
- value = "no qname value";
- }
- final MutableSimpleNode<Object> lf11 = NodeFactory.createMutableSimpleNode(
- TestUtils.buildQName("lf11", "basic:module", "2013-12-2"), cont1, value, ModifyAction.CREATE, null);
- cont1.getValue().add(lf11);
- cont1.init();
- cont.init();
-
- return cont;
- }
-
- private CompositeNode prepareCnStructForYangData(final Object data, final String leafName) {
- final MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(
- TestUtils.buildQName("cont", "basic:module", "2013-12-2"), null, null, ModifyAction.CREATE, null);
-
- final MutableSimpleNode<Object> lf1 = NodeFactory.createMutableSimpleNode(
- TestUtils.buildQName(leafName, "basic:module", "2013-12-2"), cont, data, ModifyAction.CREATE, null);
- cont.getValue().add(lf1);
- cont.init();
-
- return cont;
- }
-
- private CompositeNode prepareLeafrefData() {
- final MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont"), null, null,
- ModifyAction.CREATE, null);
-
- final MutableSimpleNode<Object> lfBoolean = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfBoolean"),
- cont, Boolean.TRUE, ModifyAction.CREATE, null);
- final MutableSimpleNode<Object> lfLfref = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lfLfref"), cont,
- "true", ModifyAction.CREATE, null);
- cont.getValue().add(lfBoolean);
- cont.getValue().add(lfLfref);
- cont.init();
-
- return cont;
- }
-
-}
+}
\ No newline at end of file
*/
package org.opendaylight.controller.sal.restconf.impl.cnsn.to.xml.test;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import javax.ws.rs.WebApplicationException;
import org.junit.BeforeClass;
-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.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;
/**
*
dataLoad("/cnsn-to-xml/choice", 1, "module-with-choice", "cont");
}
- @Test
- public void cnSnToXmlWithYangChoice() {
- String xmlOutput = "";
- try {
- xmlOutput = TestUtils.writeCompNodeWithSchemaContextToOutput(
- prepareCnStructForYangData("lf1", "String data1"), modules, dataSchemaNode,
- StructuredDataToXmlProvider.INSTANCE);
- } catch (WebApplicationException | IOException e) {
- }
-
- assertTrue(xmlOutput.contains("<lf1>String data1</lf1>"));
-
- try {
- xmlOutput = TestUtils.writeCompNodeWithSchemaContextToOutput(
- prepareCnStructForYangData("lf2", "String data2"), modules, dataSchemaNode,
- StructuredDataToXmlProvider.INSTANCE);
- } catch (WebApplicationException | IOException e) {
- }
- assertTrue(xmlOutput.contains("<lf2>String data2</lf2>"));
-
- }
-
- private CompositeNode prepareCnStructForYangData(final String lfName, final Object data) {
- MutableCompositeNode cont = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont"), null, null,
- ModifyAction.CREATE, null);
-
- MutableSimpleNode<Object> lf1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName(lfName), cont, data,
- ModifyAction.CREATE, null);
- cont.getValue().add(lf1);
- cont.init();
-
- return cont;
- }
-
}
*/
package org.opendaylight.controller.sal.restconf.impl.cnsn.to.xml.test;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.ws.rs.WebApplicationException;
import org.junit.BeforeClass;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
-import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
-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.CompositeNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
public class CnSnToXmlWithDataFromSeveralModulesTest extends YangAndXmlAndDataSchemaLoader {
dataLoad("/xml-to-cnsn/data-of-several-modules/yang", 2, "module1", "cont_m1");
}
- @Test
- public void dataFromSeveralModulesToXmlTest() throws WebApplicationException, IOException, URISyntaxException {
- SchemaContext schemaContext = TestUtils.loadSchemaContext(modules);
- String output = TestUtils.writeCompNodeWithSchemaContextToOutput(prepareCnSn(), modules, schemaContext,
- StructuredDataToXmlProvider.INSTANCE);
-
- // String output =
- // String.format("<data>" +
- // "\n<cont_m1>" +
- // "\n\t<lf1_m1>" +
- // "\n\t\tlf1 m1 value" +
- // "\n\t</lf1_m1>" +
- // "\n</cont_m1>" +
- // "\n<cont_m2>" +
- // "\n\t<lf1_m2>" +
- // "\n\t\tlf1 m2 value" +
- // "\n\t</lf1_m2>" +
- // "\n</cont_m2>" +
- // "\n</data>");
-
- StringBuilder regex = new StringBuilder();
- regex.append("^");
-
- regex.append(".*<data.*");
- regex.append(".*xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"");
- regex.append(".*>");
-
- regex.append(".*<contB_m1.*\\/>");
- regex.append(".*xmlns=\"module:one\"");
- regex.append(".*>");
- regex.append(".*<lf1_m1.*>");
- regex.append(".*<\\/lf1_m1>");
- regex.append(".*<\\/cont_m1>");
-
- regex.append(".*<contB_m2.*/>");
- regex.append(".*<cont_m2.*");
- regex.append(".*xmlns=\"module:two\"");
- regex.append(".*>");
- regex.append(".*<lf1_m2.*>");
- regex.append(".*<\\/lf1_m2>");
- regex.append(".*<\\/cont_m2>");
-
- regex.append(".*<\\/data.*>");
-
- regex.append(".*");
- regex.append("$");
-
- Pattern ptrn = Pattern.compile(regex.toString(), Pattern.DOTALL);
- Matcher matcher = ptrn.matcher(output);
-
- assertTrue(matcher.find());
-
- }
-
- private CompositeNode prepareCnSn() throws URISyntaxException {
- CompositeNodeWrapper data = new CompositeNodeWrapper(new URI("urn:ietf:params:xml:ns:netconf:base:1.0"), "data");
-
- URI uriModule1 = new URI("module:one");
- CompositeNodeWrapper cont_m1 = new CompositeNodeWrapper(uriModule1, "cont_m1");
- SimpleNodeWrapper lf1_m1 = new SimpleNodeWrapper(uriModule1, "lf1_m1", "lf1 m1 value");
- cont_m1.addValue(lf1_m1);
- CompositeNodeWrapper contB_m1 = new CompositeNodeWrapper(uriModule1, "contB_m1");
-
- data.addValue(contB_m1);
- data.addValue(cont_m1);
-
- URI uriModule2 = new URI("module:two");
- CompositeNodeWrapper cont_m2 = new CompositeNodeWrapper(uriModule2, "cont_m2");
- SimpleNodeWrapper lf1_m2 = new SimpleNodeWrapper(uriModule2, "lf1_m2", "lf1 m2 value");
- cont_m2.addValue(lf1_m2);
- CompositeNodeWrapper contB_m2 = new CompositeNodeWrapper(uriModule2, "contB_m2");
- data.addValue(contB_m2);
- data.addValue(cont_m2);
- return data;
- }
-
}
*/
package org.opendaylight.controller.sal.restconf.impl.json.to.cnsn.test;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.List;
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.common.QName;
-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 {
dataLoad("/json-to-cnsn/identityref", 2, "identityref-module", "cont");
}
- @Test
- public void jsonIdentityrefToCompositeNode() {
- Node<?> node = TestUtils.readInputToCnSn("/json-to-cnsn/identityref/json/data.json", false,
- JsonToCompositeNodeProvider.INSTANCE);
- assertNotNull(node);
-
- TestUtils.normalizeCompositeNode(node, modules, searchedModuleName + ":" + searchedDataSchemaName);
-
- assertEquals("cont", node.getNodeType().getLocalName());
-
- assert(node instanceof CompositeNode);
- List<Node<?>> childs = ((CompositeNode)node).getValue();
- assertEquals(1, childs.size());
- Node<?> nd = childs.iterator().next();
- assertTrue(nd instanceof CompositeNode);
- assertEquals("cont1", nd.getNodeType().getLocalName());
-
- childs = ((CompositeNode) nd).getValue();
- assertEquals(4, childs.size());
- SimpleNode<?> lf11 = null;
- SimpleNode<?> lf12 = null;
- SimpleNode<?> lf13 = null;
- SimpleNode<?> lf14 = null;
- for (Node<?> child : childs) {
- assertTrue(child instanceof SimpleNode);
- if (child.getNodeType().getLocalName().equals("lf11")) {
- lf11 = (SimpleNode<?>) child;
- } else if (child.getNodeType().getLocalName().equals("lf12")) {
- lf12 = (SimpleNode<?>) child;
- } else if (child.getNodeType().getLocalName().equals("lf13")) {
- lf13 = (SimpleNode<?>) child;
- } else if (child.getNodeType().getLocalName().equals("lf14")) {
- lf14 = (SimpleNode<?>) child;
- }
- }
-
- assertTrue(lf11.getValue() instanceof QName);
- assertEquals("iden", ((QName) lf11.getValue()).getLocalName());
- assertEquals("identity:module", ((QName) lf11.getValue()).getNamespace().toString());
-
- assertTrue(lf12.getValue() instanceof QName);
- assertEquals("iden_local", ((QName) lf12.getValue()).getLocalName());
- assertEquals("identityref:module", ((QName) lf12.getValue()).getNamespace().toString());
-
- assertTrue(lf13.getValue() instanceof QName);
- assertEquals("iden_local", ((QName) lf13.getValue()).getLocalName());
- assertEquals("identityref:module", ((QName) lf13.getValue()).getNamespace().toString());
-
- assertTrue(lf14.getValue() instanceof QName);
- assertEquals("iden_local", ((QName) lf14.getValue()).getLocalName());
- assertEquals("identity:module", ((QName) lf14.getValue()).getNamespace().toString());
- }
-
}
*/
package org.opendaylight.controller.sal.restconf.impl.json.to.cnsn.test;
-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.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
public class JsonLeafrefToCnSnTest extends YangAndXmlAndDataSchemaLoader {
dataLoad("/json-to-cnsn/leafref",2,"leafref-module","cont");
}
- /**
- * JSON values which represents leafref are always loaded to simple node as string
- */
- @Test
- public void jsonIdentityrefToCompositeNode() {
- Node<?> node = TestUtils.readInputToCnSn("/json-to-cnsn/leafref/json/data.json", false,
- JsonToCompositeNodeProvider.INSTANCE);
- assertNotNull(node);
- TestUtils.normalizeCompositeNode(node, modules, searchedModuleName + ":" + searchedDataSchemaName);
-
- assertEquals("cont", node.getNodeType().getLocalName());
-
- SimpleNode<?> lf2 = null;
- assertTrue(node instanceof CompositeNode);
- for (Node<?> childNode : ((CompositeNode) node).getValue()) {
- if (childNode instanceof SimpleNode) {
- if (childNode.getNodeType().getLocalName().equals("lf2")) {
- lf2 = (SimpleNode<?>) childNode;
- break;
- }
- }
- }
-
- assertNotNull(lf2);
- assertEquals(121, lf2.getValue());
- }
-
}
*/
package org.opendaylight.controller.sal.restconf.impl.json.to.cnsn.test;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
-import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
-import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.model.api.Module;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JsonToCnSnTest {
private static final Logger LOG = LoggerFactory.getLogger(JsonToCnSnTest.class);
-
- @Test
- public void simpleListTest() {
- simpleTest("/json-to-cnsn/simple-list.json", "/json-to-cnsn/simple-list-yang/1", "lst", "simple:list:yang1",
- "simple-list-yang1");
- }
-
- @Test
- public void simpleContainerTest() {
- simpleTest("/json-to-cnsn/simple-container.json", "/json-to-cnsn/simple-container-yang", "cont",
- "simple:container:yang", "simple-container-yang");
- }
-
- /**
- * test if for every leaf list item is simple node instance created
- */
- @Test
- public void multipleItemsInLeafList() {
- Node<?> node = TestUtils.readInputToCnSn("/json-to-cnsn/multiple-leaflist-items.json", true,
- JsonToCompositeNodeProvider.INSTANCE);
- assertNotNull(node);
- assertTrue(node instanceof CompositeNode);
- CompositeNode compositeNode = (CompositeNode)node;
- assertEquals(3, compositeNode.getValue().size());
-
- boolean lflst1_1 = false;
- boolean lflst1_2 = false;
- boolean lflst1_3 = false;
-
- for (Node<?> nd : compositeNode.getValue()) {
- assertEquals("lflst1", nd.getNodeType().getLocalName());
- assertTrue(nd instanceof SimpleNode<?>);
- SimpleNode<?> simpleNode = (SimpleNode<?>) nd;
- if (simpleNode.getValue().equals("45")) {
- lflst1_1 = true;
- } else if (simpleNode.getValue().equals("55")) {
- lflst1_2 = true;
- } else if (simpleNode.getValue().equals("66")) {
- lflst1_3 = true;
- }
- }
-
- assertTrue(lflst1_1);
- assertTrue(lflst1_2);
- assertTrue(lflst1_3);
-
- }
-
- /**
- * List contains 4 items and in every item are other elements. It is supposed that there should be: lf11, lflst11,
- * cont11, lst11
- */
- @Test
- public void multipleItemsInListTest() {
- Node<?> node = TestUtils.readInputToCnSn("/json-to-cnsn/multiple-items-in-list.json", true,
- JsonToCompositeNodeProvider.INSTANCE);
-
- assertTrue(node instanceof CompositeNode);
- CompositeNode compositeNode = (CompositeNode)node;
-
- assertNotNull(compositeNode);
- assertEquals("lst", compositeNode.getNodeType().getLocalName());
-
- verityMultipleItemsInList(compositeNode);
- }
-
- @Test
- public void nullArrayToSimpleNodeWithNullValueTest() {
- Node<?> node = TestUtils.readInputToCnSn("/json-to-cnsn/array-with-null.json", true,
- JsonToCompositeNodeProvider.INSTANCE);
- assertTrue(node instanceof CompositeNode);
- CompositeNode compositeNode = (CompositeNode)node;
- assertEquals("cont", compositeNode.getNodeType().getLocalName());
-
- assertNotNull(compositeNode.getValue());
- assertEquals(1, compositeNode.getValue().size());
- Node<?> lfNode = compositeNode.getValue().iterator().next();
-
- assertTrue(lfNode instanceof SimpleNode<?>);
- assertEquals(null, ((SimpleNode<?>) lfNode).getValue());
-
- }
-
- @Test
- public void incorrectTopLevelElementsTest() {
- RestconfDocumentedException cause1 = null;
- try {
- TestUtils
- .readInputToCnSn("/json-to-cnsn/wrong-top-level1.json", true, JsonToCompositeNodeProvider.INSTANCE);
- } catch (RestconfDocumentedException e) {
- cause1 = e;
- }
-
- assertNotNull(cause1);
- assertTrue(cause1
- .getErrors()
- .get(0)
- .getErrorMessage()
- .contains(
- "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet."));
-
- RestconfDocumentedException cause2 = null;
- try {
- TestUtils
- .readInputToCnSn("/json-to-cnsn/wrong-top-level2.json", true, JsonToCompositeNodeProvider.INSTANCE);
- } catch (RestconfDocumentedException e) {
- cause2 = e;
- }
- assertNotNull(cause2);
- assertTrue(cause2.getErrors().get(0).getErrorMessage().contains("Json Object should contain one element"));
-
- RestconfDocumentedException cause3 = null;
- try {
- TestUtils
-
- .readInputToCnSn("/json-to-cnsn/wrong-top-level3.json", true, JsonToCompositeNodeProvider.INSTANCE);
- } catch (RestconfDocumentedException e) {
- cause3 = e;
- }
- assertNotNull(cause3);
- assertTrue(cause3
- .getErrors()
- .get(0)
- .getErrorMessage()
- .contains(
- "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet."));
-
- }
-
- /**
- * if leaf list with no data is in json then no corresponding data is created in composite node. if leaf with no
- * data then exception is raised
- */
- @Test
- public void emptyDataReadTest() {
- Node<?> node = TestUtils.readInputToCnSn("/json-to-cnsn/empty-data.json", true,
- JsonToCompositeNodeProvider.INSTANCE);
- assertTrue(node instanceof CompositeNode);
- CompositeNode compositeNode = (CompositeNode)node;
-
- assertEquals("cont", compositeNode.getNodeType().getLocalName());
- assertTrue(compositeNode instanceof CompositeNode);
- List<Node<?>> children = compositeNode.getValue();
- assertEquals(1, children.size());
- assertEquals("lflst2", children.get(0).getNodeType().getLocalName());
- assertEquals("45", children.get(0).getValue());
-
- String reason = null;
- try {
- TestUtils.readInputToCnSn("/json-to-cnsn/empty-data1.json", true, JsonToCompositeNodeProvider.INSTANCE);
- } catch (RestconfDocumentedException e) {
- reason = e.getErrors().get(0).getErrorMessage();
- }
-
- assertTrue(reason.contains("Expected value at line"));
-
- }
-
- @Test
- public void testJsonBlankInput() throws Exception {
- InputStream inputStream = new ByteArrayInputStream("".getBytes());
- Node<?> node =
- JsonToCompositeNodeProvider.INSTANCE.readFrom(null, null, null, null, null, inputStream);
- assertNull( node );
- }
-
- /**
- * Tests whether namespace <b>stay unchanged</b> if concrete values are present in composite or simple node and if
- * the method for update is called.
- *
- */
- @Test
- public void notSupplyNamespaceIfAlreadySupplied() {
-
- Node<?> node = TestUtils.readInputToCnSn("/json-to-cnsn/simple-list.json", false,
- JsonToCompositeNodeProvider.INSTANCE);
- assertTrue(node instanceof CompositeNode);
- CompositeNode compositeNode = (CompositeNode)node;
-
- // supplement namespaces according to first data schema -
- // "simple:data:types1"
- Set<Module> modules1 = new HashSet<>();
- Set<Module> modules2 = new HashSet<>();
- modules1 = TestUtils.loadModulesFrom("/json-to-cnsn/simple-list-yang/1");
- modules2 = TestUtils.loadModulesFrom("/json-to-cnsn/simple-list-yang/2");
- assertNotNull(modules1);
- assertNotNull(modules2);
-
- TestUtils.normalizeCompositeNode(compositeNode, modules1, "simple-list-yang1:lst");
-
- assertTrue(compositeNode instanceof CompositeNodeWrapper);
- CompositeNode compNode = ((CompositeNodeWrapper) compositeNode).unwrap();
-
- assertEquals("lst", compNode.getNodeType().getLocalName());
- verifyCompositeNode(compNode, "simple:list:yang1");
-
- try {
- TestUtils.normalizeCompositeNode(compositeNode, modules2, "simple-list-yang2:lst");
- fail("Conversion to normalized node shouldn't be successfull because of different namespaces");
- } catch (IllegalStateException e) {
- }
-// veryfing has still meaning. despite exception, first phase where normalization of NodeWrappers is called passed successfuly.
- verifyCompositeNode(compNode, "simple:list:yang1");
- }
-
- @Test
- public void jsonIdentityrefToCompositeNode() {
- Node<?> node = TestUtils.readInputToCnSn("/json-to-cnsn/identityref/json/data.json", false,
- JsonToCompositeNodeProvider.INSTANCE);
- assertTrue(node instanceof CompositeNode);
- CompositeNode compositeNode = (CompositeNode)node;
-
- Set<Module> modules = TestUtils.loadModulesFrom("/json-to-cnsn/identityref");
- assertEquals(2, modules.size());
-
- TestUtils.normalizeCompositeNode(compositeNode, modules, "identityref-module:cont");
-
- assertEquals("cont", compositeNode.getNodeType().getLocalName());
-
- List<Node<?>> childs = compositeNode.getValue();
- assertEquals(1, childs.size());
- Node<?> nd = childs.iterator().next();
- assertTrue(nd instanceof CompositeNode);
- assertEquals("cont1", nd.getNodeType().getLocalName());
-
- childs = ((CompositeNode) nd).getValue();
- assertEquals(4, childs.size());
- SimpleNode<?> lf11 = null;
- SimpleNode<?> lf12 = null;
- SimpleNode<?> lf13 = null;
- SimpleNode<?> lf14 = null;
- for (Node<?> child : childs) {
- assertTrue(child instanceof SimpleNode);
- if (child.getNodeType().getLocalName().equals("lf11")) {
- lf11 = (SimpleNode<?>) child;
- } else if (child.getNodeType().getLocalName().equals("lf12")) {
- lf12 = (SimpleNode<?>) child;
- } else if (child.getNodeType().getLocalName().equals("lf13")) {
- lf13 = (SimpleNode<?>) child;
- } else if (child.getNodeType().getLocalName().equals("lf14")) {
- lf14 = (SimpleNode<?>) child;
- }
- }
-
- assertTrue(lf11.getValue() instanceof QName);
- assertEquals("iden", ((QName) lf11.getValue()).getLocalName());
- assertEquals("identity:module", ((QName) lf11.getValue()).getNamespace().toString());
-
- assertTrue(lf12.getValue() instanceof QName);
- assertEquals("iden_local", ((QName) lf12.getValue()).getLocalName());
- assertEquals("identityref:module", ((QName) lf12.getValue()).getNamespace().toString());
-
- assertTrue(lf13.getValue() instanceof QName);
- assertEquals("iden_local", ((QName) lf13.getValue()).getLocalName());
- assertEquals("identityref:module", ((QName) lf13.getValue()).getNamespace().toString());
-
- assertTrue(lf14.getValue() instanceof QName);
- assertEquals("iden_local", ((QName) lf14.getValue()).getLocalName());
- assertEquals("identity:module", ((QName) lf14.getValue()).getNamespace().toString());
- }
-
- @Ignore
- @Test
- public void loadDataAugmentedSchemaMoreEqualNamesTest() {
- loadAndNormalizeData("/common/augment/json/dataa.json", "/common/augment/yang", "cont", "main");
- loadAndNormalizeData("/common/augment/json/datab.json", "/common/augment/yang", "cont", "main");
-
- }
-
- 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(final String jsonPath, final String yangPath,
- final String topLevelElementName, final String moduleName) {
- Node<?> node = TestUtils.readInputToCnSn(jsonPath, false, JsonToCompositeNodeProvider.INSTANCE);
- assertTrue(node instanceof CompositeNode);
- CompositeNode compositeNode = (CompositeNode)node;
-
- Set<Module> modules = null;
- modules = TestUtils.loadModulesFrom(yangPath);
- assertNotNull(modules);
-
- TestUtils.normalizeCompositeNode(compositeNode, modules, moduleName + ":" + topLevelElementName);
-
- assertTrue(compositeNode instanceof CompositeNodeWrapper);
- CompositeNode compNode = ((CompositeNodeWrapper) compositeNode).unwrap();
-
- assertEquals(topLevelElementName, compNode.getNodeType().getLocalName());
- return compNode;
- }
-
- private void verityMultipleItemsInList(final CompositeNode compositeNode) {
- List<Node<?>> childrenNodes = compositeNode.getValue();
- assertEquals(4, childrenNodes.size());
- boolean lf11Found = false;
- boolean cont11Found = false;
- boolean lst11Found = false;
- for (Node<?> lst1Item : childrenNodes) {
- assertEquals("lst1", lst1Item.getNodeType().getLocalName());
- assertTrue(lst1Item instanceof CompositeNode);
-
- List<Node<?>> childrenLst1 = ((CompositeNode) lst1Item).getValue();
- assertEquals(1, childrenLst1.size());
- String localName = childrenLst1.get(0).getNodeType().getLocalName();
- if (localName.equals("lf11")) {
- assertTrue(childrenLst1.get(0) instanceof SimpleNode);
- lf11Found = true;
- } else if (localName.equals("lflst11")) {
- assertTrue(childrenLst1.get(0) instanceof SimpleNode);
- assertEquals("45", ((SimpleNode<?>) childrenLst1.get(0)).getValue());
- lf11Found = true;
- } else if (localName.equals("cont11")) {
- assertTrue(childrenLst1.get(0) instanceof CompositeNode);
- cont11Found = true;
- } else if (localName.equals("lst11")) {
- lst11Found = true;
- assertTrue(childrenLst1.get(0) instanceof CompositeNode);
- assertEquals(0, ((CompositeNode) childrenLst1.get(0)).getValue().size());
- }
-
- }
- assertTrue(lf11Found);
- assertTrue(cont11Found);
- assertTrue(lst11Found);
- }
-
- private void verifyCompositeNode(final CompositeNode compositeNode, final String namespace) {
- boolean cont1Found = false;
- boolean lst1Found = false;
- boolean lflst1_1Found = false;
- boolean lflst1_2Found = false;
- boolean lf1Found = false;
-
- // assertEquals(namespace,
- // compositeNode.getNodeType().getNamespace().toString());
-
- for (Node<?> node : compositeNode.getValue()) {
- if (node.getNodeType().getLocalName().equals("cont1")) {
- if (node instanceof CompositeNode) {
- cont1Found = true;
- assertEquals(0, ((CompositeNode) node).getValue().size());
- }
- } else if (node.getNodeType().getLocalName().equals("lst1")) {
- if (node instanceof CompositeNode) {
- lst1Found = true;
- assertEquals(0, ((CompositeNode) node).getValue().size());
- }
- } else if (node.getNodeType().getLocalName().equals("lflst1")) {
- if (node instanceof SimpleNode) {
- if (((SimpleNode<?>) node).getValue().equals("lflst1_1")) {
- lflst1_1Found = true;
- } else if (((SimpleNode<?>) node).getValue().equals("lflst1_2")) {
- lflst1_2Found = true;
- }
- }
-
- } else if (node.getNodeType().getLocalName().equals("lf1")) {
- if (node instanceof SimpleNode) {
- if (((SimpleNode<?>) node).getValue().equals("lf1")) {
- lf1Found = true;
- }
- }
- }
- assertEquals(namespace, node.getNodeType().getNamespace().toString());
- }
- assertTrue(cont1Found);
- assertTrue(lst1Found);
- assertTrue(lflst1_1Found);
- assertTrue(lflst1_2Found);
- assertTrue(lf1Found);
- }
-
- @Test
- public void unsupportedDataFormatTest() {
- String exceptionMessage = "";
- try {
- TestUtils.readInputToCnSn("/json-to-cnsn/unsupported-json-format.json", true,
- JsonToCompositeNodeProvider.INSTANCE);
- } catch (RestconfDocumentedException e) {
- exceptionMessage = e.getErrors().get(0).getErrorMessage();
- }
- assertTrue(exceptionMessage.contains("Root element of Json has to be Object"));
- }
-
- /**
- * Tests case when JSON input data value is in format string1:string2 and first string contain characters "<" or ">" (invalid URI characters).
- *
- * During loading data it is also interpreting as data value in moduleName:localName (potential leafref value).
- * ModuleName part is transformed to URI which causes exception which is caught and URI value is null which cause that potential value in simple node is
- * simple string (value from JSON input) and not IdentityValueDTO instance which is used for leaf-ref candidates.
- */
- @Test
- public void invalidUriCharacterInValue() {
- final Node<?> rootNode = TestUtils.readInputToCnSn("/json-to-cnsn/invalid-uri-character-in-value.json", true,
- JsonToCompositeNodeProvider.INSTANCE);
-
- assertTrue(rootNode instanceof CompositeNode);
- Node<?> lf1 = null;
- Node<?> lf2 = null;
- for(Node<?> child : ((CompositeNode)rootNode).getChildren()) {
- if (child.getNodeType().getLocalName().equals("lf1")) {
- lf1 = child;
- } else if (child.getNodeType().getLocalName().equals("lf2")) {
- lf2 = child;
- }
- }
-
- assertNotNull(lf1);
- assertNotNull(lf2);
- assertTrue(lf1 instanceof SimpleNode<?>);
- assertTrue(lf2 instanceof SimpleNode<?>);
-
- assertEquals("module<Name:value lf1", ((SimpleNode<?>) lf1).getValue());
- assertEquals("module>Name:value lf2", ((SimpleNode<?>) lf2).getValue());
- }
-
}
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-import static org.opendaylight.controller.sal.restconf.impl.test.TestUtils.containsStringData;
-
import java.io.ByteArrayInputStream;
-import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import javax.ws.rs.WebApplicationException;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import org.junit.BeforeClass;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
-import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
-import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
public class CnSnToXmlAndJsonInstanceIdentifierTest extends YangAndXmlAndDataSchemaLoader {
dataLoad("/instanceidentifier/yang", 4, "instance-identifier-module", "cont");
}
- @Test
- public void saveCnSnToXmlTest() throws WebApplicationException, IOException, URISyntaxException, XMLStreamException {
- CompositeNode cnSn = prepareCnSn(createInstanceIdentifier());
- String output = TestUtils.writeCompNodeWithSchemaContextToOutput(cnSn, modules, dataSchemaNode,
- StructuredDataToXmlProvider.INSTANCE);
- validateXmlOutput(output);
-
- }
-
- @Test
- public void saveCnSnWithLeafListInstIdentifierToXmlTest() throws WebApplicationException, IOException,
- URISyntaxException, XMLStreamException {
- CompositeNode cnSn = prepareCnSn(createInstanceIdentifierWithLeafList());
- String output = TestUtils.writeCompNodeWithSchemaContextToOutput(cnSn, modules, dataSchemaNode,
- StructuredDataToXmlProvider.INSTANCE);
- validateXmlOutputWithLeafList(output);
- }
-
- @Test
- public void saveCnSnToJsonTest() throws WebApplicationException, IOException, URISyntaxException {
- CompositeNode cnSn = prepareCnSn(createInstanceIdentifier());
- String output = TestUtils.writeCompNodeWithSchemaContextToOutput(cnSn, modules, dataSchemaNode,
- StructuredDataToJsonProvider.INSTANCE);
- boolean strInOutput = false;
- strInOutput = containsStringData(
- output,
- "\"augment-augment-module:lf111\"",
- ":",
- "\"/instance-identifier-module:cont/instance-identifier-module:cont1/augment-module:lst11\\[augment-module:keyvalue111=\\\\\"value1\\\\\"\\]\\[augment-module:keyvalue112=\\\\\"value2\\\\\"\\]/augment-augment-module:lf112\"");
-
- if (!strInOutput) {
- strInOutput = containsStringData(
- output,
- "\"augment-augment-module:lf111\"",
- ":",
- "\"/instance-identifier-module:cont/instance-identifier-module:cont1/augment-module:lst11\\[augment-module:keyvalue111='value1'\\]\\[augment-module:keyvalue112='value2'\\]/augment-augment-module:lf112\"");
- }
- assertTrue(strInOutput);
- }
-
- @Test
- public void saveCnSnWithLeafListInstIdentifierToJsonTest() throws WebApplicationException, IOException,
- URISyntaxException {
- CompositeNode cnSn = prepareCnSn(createInstanceIdentifierWithLeafList());
- String output = TestUtils.writeCompNodeWithSchemaContextToOutput(cnSn, modules, dataSchemaNode,
- StructuredDataToJsonProvider.INSTANCE);
- boolean strInOutput = false;
- strInOutput = containsStringData(
- output,
- "\"augment-augment-module:lf111\"",
- ":",
- "\"/instance-identifier-module:cont/instance-identifier-module:cont1/augment-module-leaf-list:lflst11\\[.='lflst11_1'\\]\"");
- if (!strInOutput) {
- strInOutput = containsStringData(
- output,
- "\"augment-augment-module:lf111\"",
- ":",
- "\"/instance-identifier-module:cont/instance-identifier-module:cont1/augment-module-leaf-list:lflst11\\[.=\\\\\"lflst11_1\\\\\"\\]\"");
- }
-
- assertTrue(strInOutput);
- }
private void validateXmlOutput(final String xml) throws XMLStreamException {
- XMLInputFactory xmlInFactory = XMLInputFactory.newInstance();
+ final XMLInputFactory xmlInFactory = XMLInputFactory.newInstance();
XMLEventReader eventReader;
eventReader = xmlInFactory.createXMLEventReader(new ByteArrayInputStream(xml.getBytes()));
String aModulePrefix = null;
String iiModulePrefix = null;
while (eventReader.hasNext()) {
- XMLEvent nextEvent = eventReader.nextEvent();
+ final XMLEvent nextEvent = eventReader.nextEvent();
if (nextEvent.isStartElement()) {
- StartElement startElement = (StartElement) nextEvent;
+ final StartElement startElement = (StartElement) nextEvent;
if (startElement.getName().getLocalPart().equals("lf111")) {
- Iterator<?> prefixes = startElement.getNamespaceContext().getPrefixes("augment:augment:module");
+ final Iterator<?> prefixes = startElement.getNamespaceContext().getPrefixes("augment:augment:module");
while (prefixes.hasNext() && aaModulePrefix == null) {
- String prefix = (String) prefixes.next();
+ final String prefix = (String) prefixes.next();
if (!prefix.isEmpty()) {
aaModulePrefix = prefix;
}
assertNotNull(aModulePrefix);
assertNotNull(iiModulePrefix);
- String instanceIdentifierValue = "/" + iiModulePrefix + ":cont/" + iiModulePrefix + ":cont1/" + aModulePrefix
+ final String instanceIdentifierValue = "/" + iiModulePrefix + ":cont/" + iiModulePrefix + ":cont1/" + aModulePrefix
+ ":lst11[" + aModulePrefix + ":keyvalue111='value1'][" + aModulePrefix + ":keyvalue112='value2']/"
+ aaModulePrefix + ":lf112";
}
private void validateXmlOutputWithLeafList(final String xml) throws XMLStreamException {
- XMLInputFactory xmlInFactory = XMLInputFactory.newInstance();
+ final XMLInputFactory xmlInFactory = XMLInputFactory.newInstance();
XMLEventReader eventReader;
eventReader = xmlInFactory.createXMLEventReader(new ByteArrayInputStream(xml.getBytes()));
String aModuleLfLstPrefix = null;
String iiModulePrefix = null;
while (eventReader.hasNext()) {
- XMLEvent nextEvent = eventReader.nextEvent();
+ final XMLEvent nextEvent = eventReader.nextEvent();
if (nextEvent.isStartElement()) {
- StartElement startElement = (StartElement) nextEvent;
+ final StartElement startElement = (StartElement) nextEvent;
if (startElement.getName().getLocalPart().equals("lf111")) {
- Iterator<?> prefixes = startElement.getNamespaceContext().getPrefixes("augment:module:leaf:list");
+ final Iterator<?> prefixes = startElement.getNamespaceContext().getPrefixes("augment:module:leaf:list");
while (prefixes.hasNext() && aModuleLfLstPrefix == null) {
- String prefix = (String) prefixes.next();
+ final String prefix = (String) prefixes.next();
if (!prefix.isEmpty()) {
aModuleLfLstPrefix = prefix;
}
assertNotNull(aModuleLfLstPrefix);
assertNotNull(iiModulePrefix);
- String instanceIdentifierValue = "/" + iiModulePrefix + ":cont/" + iiModulePrefix + ":cont1/"
+ final String instanceIdentifierValue = "/" + iiModulePrefix + ":cont/" + iiModulePrefix + ":cont1/"
+ aModuleLfLstPrefix + ":lflst11[.='lflst11_1']";
assertTrue(xml.contains(instanceIdentifierValue));
}
- private CompositeNode prepareCnSn(final YangInstanceIdentifier instanceIdentifier) throws URISyntaxException {
- CompositeNodeBuilder<ImmutableCompositeNode> cont = ImmutableCompositeNode.builder();
- cont.setQName(QName.create("instance:identifier:module", "2014-01-17", "cont"));
-
- CompositeNodeBuilder<ImmutableCompositeNode> cont1 = ImmutableCompositeNode.builder();
- cont1.setQName(QName.create("instance:identifier:module", "2014-01-17", "cont1"));
-
- CompositeNodeBuilder<ImmutableCompositeNode> lst11 = ImmutableCompositeNode.builder();
- lst11.setQName(QName.create("augment:module", "2014-01-17", "lst11"));
-
- SimpleNode<?> lf111 = NodeFactory.createImmutableSimpleNode(
- QName.create("augment:augment:module", "2014-01-17", "lf111"), null, instanceIdentifier);
- lst11.add(lf111);
- cont1.add(lst11.toInstance());
- cont.add(cont1.toInstance());
- return cont.toInstance();
- }
-
private YangInstanceIdentifier createInstanceIdentifier() throws URISyntaxException {
- List<PathArgument> pathArguments = new ArrayList<>();
+ final List<PathArgument> pathArguments = new ArrayList<>();
pathArguments.add(new NodeIdentifier(new QName(new URI("instance:identifier:module"), "cont")));
pathArguments.add(new NodeIdentifier(new QName(new URI("instance:identifier:module"), "cont1")));
- QName qName = new QName(new URI("augment:module"), "lst11");
- Map<QName, Object> keyValues = new HashMap<>();
+ final QName qName = new QName(new URI("augment:module"), "lst11");
+ final Map<QName, Object> keyValues = new HashMap<>();
keyValues.put(new QName(new URI("augment:module"), "keyvalue111"), "value1");
keyValues.put(new QName(new URI("augment:module"), "keyvalue112"), "value2");
- NodeIdentifierWithPredicates nodeIdentifierWithPredicates = new NodeIdentifierWithPredicates(qName, keyValues);
+ final NodeIdentifierWithPredicates nodeIdentifierWithPredicates = new NodeIdentifierWithPredicates(qName, keyValues);
pathArguments.add(nodeIdentifierWithPredicates);
pathArguments.add(new NodeIdentifier(new QName(new URI("augment:augment:module"), "lf112")));
}
private YangInstanceIdentifier createInstanceIdentifierWithLeafList() throws URISyntaxException {
- List<PathArgument> pathArguments = new ArrayList<>();
+ final List<PathArgument> pathArguments = new ArrayList<>();
pathArguments.add(new NodeIdentifier(new QName(new URI("instance:identifier:module"), "cont")));
pathArguments.add(new NodeIdentifier(new QName(new URI("instance:identifier:module"), "cont1")));
pathArguments.add(new NodeWithValue(new QName(new URI("augment:module:leaf:list"), "lflst11"), "lflst11_1"));
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
-
import com.google.common.base.Optional;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
import java.io.FileNotFoundException;
import java.net.URI;
import java.net.URISyntaxException;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
-import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcException;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationNotAvailableException;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
import org.opendaylight.controller.sal.restconf.impl.InstanceIdentifierContext;
import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
@Test
@Ignore // FIXME find how to use mockito for it
public void testMountedRpcCallNoPayload_Success() throws Exception {
- final RpcResult<CompositeNode> rpcResult = RpcResultBuilder.<CompositeNode>success().build();
-
- final ListenableFuture<RpcResult<CompositeNode>> mockListener = mock(ListenableFuture.class);
- when(mockListener.get()).thenReturn(rpcResult);
-
- final QName cancelToastQName = QName.create("namespace", "2014-05-28", "cancelToast");
-
- final RpcDefinition mockRpc = mock(RpcDefinition.class);
- when(mockRpc.getQName()).thenReturn(cancelToastQName);
-
- final DOMMountPoint mockMountPoint = mock(DOMMountPoint.class);
- final RpcProvisionRegistry mockedRpcProvisionRegistry = mock(RpcProvisionRegistry.class);
- when(mockedRpcProvisionRegistry.invokeRpc(eq(cancelToastQName), any(CompositeNode.class))).thenReturn(mockListener);
- when(mockMountPoint.getService(eq(RpcProvisionRegistry.class))).thenReturn(Optional.of(mockedRpcProvisionRegistry));
- when(mockMountPoint.getSchemaContext()).thenReturn(TestUtils.loadSchemaContext("/invoke-rpc"));
-
- final InstanceIdentifierContext mockedInstanceId = mock(InstanceIdentifierContext.class);
- when(mockedInstanceId.getMountPoint()).thenReturn(mockMountPoint);
-
- final ControllerContext mockedContext = mock(ControllerContext.class);
- final String rpcNoop = "invoke-rpc-module:rpc-noop";
- when(mockedContext.urlPathArgDecode(rpcNoop)).thenReturn(rpcNoop);
- when(mockedContext.getRpcDefinition(rpcNoop)).thenReturn(mockRpc);
- when(
- mockedContext.toMountPointIdentifier(eq("opendaylight-inventory:nodes/node/"
- + "REMOTE_HOST/yang-ext:mount/invoke-rpc-module:rpc-noop"))).thenReturn(mockedInstanceId);
-
- restconfImpl.setControllerContext(mockedContext);
- try {
- restconfImpl.invokeRpc(
- "opendaylight-inventory:nodes/node/REMOTE_HOST/yang-ext:mount/invoke-rpc-module:rpc-noop", "",
- uriInfo);
- fail("RestconfDocumentedException wasn't raised");
- } catch (final RestconfDocumentedException e) {
- final List<RestconfError> errors = e.getErrors();
- assertNotNull(errors);
- assertEquals(1, errors.size());
- assertEquals(ErrorType.APPLICATION, errors.iterator().next().getErrorType());
- assertEquals(ErrorTag.OPERATION_FAILED, errors.iterator().next().getErrorTag());
- }
-
- // additional validation in the fact that the restconfImpl does not
- // throw an exception.
}
}
*/
package org.opendaylight.controller.sal.restconf.impl.test;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-import java.util.List;
-import java.util.Set;
-import javax.ws.rs.ext.MessageBodyReader;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
-import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
-import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.model.api.Module;
/**
* If more then one data element with equal name exists where container or leaf schema node should be present the
*/
public class MultipleEqualNamesForDataNodesTest {
- @Test
- public void multipleEqualNameDataNodeTestForContainerJsonTest() {
- multipleEqualNameDataNodeTest("/equal-data-node-names/equal-name-data-for-container.json",
- ErrorType.APPLICATION, ErrorTag.BAD_ELEMENT, JsonToCompositeNodeProvider.INSTANCE);
- }
-
- @Test
- public void multipleEqualNameDataNodeTestForLeafJsonTest() {
- multipleEqualNameDataNodeTest("/equal-data-node-names/equal-name-data-for-leaf.json", ErrorType.PROTOCOL,
- ErrorTag.MALFORMED_MESSAGE, JsonToCompositeNodeProvider.INSTANCE);
- }
-
- @Test
- public void multipleEqualNameDataNodeTestForContainerXmlTest() {
- multipleEqualNameDataNodeTest("/equal-data-node-names/equal-name-data-for-container.xml",
- ErrorType.APPLICATION, ErrorTag.BAD_ELEMENT, XmlToCompositeNodeProvider.INSTANCE);
- }
-
- @Test
- public void multipleEqualNameDataNodeTestForLeafXmlTest() {
- multipleEqualNameDataNodeTest("/equal-data-node-names/equal-name-data-for-leaf.xml", ErrorType.APPLICATION,
- ErrorTag.BAD_ELEMENT, XmlToCompositeNodeProvider.INSTANCE);
- }
-
- private void multipleEqualNameDataNodeTest(String path, ErrorType errorType, ErrorTag errorTag,
- MessageBodyReader<Node<?>> messageBodyReader) {
- try {
- Node<?> node = TestUtils.readInputToCnSn(path, false, messageBodyReader);
- assertNotNull(node);
-
- Set<Module> modules = null;
- modules = TestUtils.loadModulesFrom("/equal-data-node-names/yang");
- assertNotNull(modules);
-
- TestUtils.normalizeCompositeNode(node, modules, "equal-data-node-names" + ":" + "cont");
- fail("Exception RestconfDocumentedException should be raised");
- } catch (RestconfDocumentedException e) {
- List<RestconfError> errors = e.getErrors();
- assertNotNull(errors);
-
- assertEquals(1, errors.size());
-
- RestconfError restconfError = errors.get(0);
-
- assertEquals(errorType, restconfError.getErrorType());
- assertEquals(errorTag, restconfError.getErrorTag());
- }
- }
-
}
*/
package org.opendaylight.controller.sal.restconf.impl.test;
-import static org.junit.Assert.assertNotNull;
-
-import java.net.URI;
-import java.net.URISyntaxException;
import org.junit.BeforeClass;
-import org.junit.Test;
-import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
-import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
public class NormalizeNodeTest extends YangAndXmlAndDataSchemaLoader {
dataLoad("/normalize-node/yang/");
}
- @Test(expected = RestconfDocumentedException.class)
- public void namespaceNotNullAndInvalidNamespaceAndNoModuleNameTest() {
-
- TestUtils.normalizeCompositeNode(prepareCnSn("wrongnamespace"), modules, schemaNodePath);
- }
-
- @Test
- public void namespaceNullTest() {
-
- TestUtils.normalizeCompositeNode(prepareCnSn(null), modules, schemaNodePath);
- }
-
- @Test
- public void namespaceValidNamespaceTest() {
-
- TestUtils.normalizeCompositeNode(prepareCnSn("normalize:node:module"), modules, schemaNodePath);
- }
-
- @Test
- public void namespaceValidModuleNameTest() {
-
- TestUtils.normalizeCompositeNode(prepareCnSn("normalize-node-module"), modules, schemaNodePath);
- }
-
- private CompositeNode prepareCnSn(final String namespace) {
- URI uri = null;
- if (namespace != null) {
- try {
- uri = new URI(namespace);
- } catch (URISyntaxException e) {
- }
- assertNotNull(uri);
- }
-
- SimpleNodeWrapper lf1 = new SimpleNodeWrapper(uri, "lf1", 43);
- CompositeNodeWrapper cont = new CompositeNodeWrapper(uri, "cont");
- cont.addValue(lf1);
-
- return cont;
- }
-
}
import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
assertFalse(matcher.matches());
}
- @Test
- @Ignore
- public void getDataWithUriDepthParameterTest() throws UnsupportedEncodingException {
- setControllerContext(schemaContextModules);
-
- final CompositeNode depth1Cont = toCompositeNode(toCompositeNodeData(
- toNestedQName("depth1-cont"),
- toCompositeNodeData(
- toNestedQName("depth2-cont1"),
- toCompositeNodeData(
- toNestedQName("depth3-cont1"),
- toCompositeNodeData(toNestedQName("depth4-cont1"),
- toSimpleNodeData(toNestedQName("depth5-leaf1"), "depth5-leaf1-value")),
- toSimpleNodeData(toNestedQName("depth4-leaf1"), "depth4-leaf1-value")),
- toSimpleNodeData(toNestedQName("depth3-leaf1"), "depth3-leaf1-value")),
- toCompositeNodeData(
- toNestedQName("depth2-cont2"),
- toCompositeNodeData(
- toNestedQName("depth3-cont2"),
- toCompositeNodeData(toNestedQName("depth4-cont2"),
- toSimpleNodeData(toNestedQName("depth5-leaf2"), "depth5-leaf2-value")),
- toSimpleNodeData(toNestedQName("depth4-leaf2"), "depth4-leaf2-value")),
- toSimpleNodeData(toNestedQName("depth3-leaf2"), "depth3-leaf2-value")),
- toSimpleNodeData(toNestedQName("depth2-leaf1"), "depth2-leaf1-value")));
-
- final Module module = TestUtils.findModule(schemaContextModules.getModules(), "nested-module");
- assertNotNull(module);
-
- final DataSchemaNode dataSchemaNode = TestUtils.resolveDataSchemaNode("depth1-cont", module);
- assertNotNull(dataSchemaNode);
-
- when(brokerFacade.readConfigurationData(any(YangInstanceIdentifier.class))).thenReturn(
- TestUtils.compositeNodeToDatastoreNormalizedNode(depth1Cont, dataSchemaNode));
-
- // Test config with depth 1
-
- Response response = target("/config/nested-module:depth1-cont").queryParam("depth", "1")
- .request("application/xml").get();
-
- verifyXMLResponse(response, expectEmptyContainer("depth1-cont"));
-
- // Test config with depth 2
-
- response = target("/config/nested-module:depth1-cont").queryParam("depth", "2").request("application/xml")
- .get();
-
- // String
- // xml="<depth1-cont><depth2-cont1/><depth2-cont2/><depth2-leaf1>depth2-leaf1-value</depth2-leaf1></depth1-cont>";
- // Response mr=mock(Response.class);
- // when(mr.getEntity()).thenReturn( new
- // java.io.StringBufferInputStream(xml) );
-
- verifyXMLResponse(
- response,
- expectContainer("depth1-cont", expectEmptyContainer("depth2-cont1"),
- expectEmptyContainer("depth2-cont2"), expectLeaf("depth2-leaf1", "depth2-leaf1-value")));
-
- // Test config with depth 3
-
- response = target("/config/nested-module:depth1-cont").queryParam("depth", "3").request("application/xml")
- .get();
-
- verifyXMLResponse(
- response,
- expectContainer(
- "depth1-cont",
- expectContainer("depth2-cont1", expectEmptyContainer("depth3-cont1"),
- expectLeaf("depth3-leaf1", "depth3-leaf1-value")),
- expectContainer("depth2-cont2", expectEmptyContainer("depth3-cont2"),
- expectLeaf("depth3-leaf2", "depth3-leaf2-value")),
- expectLeaf("depth2-leaf1", "depth2-leaf1-value")));
-
- // Test config with depth 4
-
- response = target("/config/nested-module:depth1-cont").queryParam("depth", "4").request("application/xml")
- .get();
-
- verifyXMLResponse(
- response,
- expectContainer(
- "depth1-cont",
- expectContainer(
- "depth2-cont1",
- expectContainer("depth3-cont1", expectEmptyContainer("depth4-cont1"),
- expectLeaf("depth4-leaf1", "depth4-leaf1-value")),
- expectLeaf("depth3-leaf1", "depth3-leaf1-value")),
- expectContainer(
- "depth2-cont2",
- expectContainer("depth3-cont2", expectEmptyContainer("depth4-cont2"),
- expectLeaf("depth4-leaf2", "depth4-leaf2-value")),
- expectLeaf("depth3-leaf2", "depth3-leaf2-value")),
- expectLeaf("depth2-leaf1", "depth2-leaf1-value")));
-
- // Test config with depth 5
-
- response = target("/config/nested-module:depth1-cont").queryParam("depth", "5").request("application/xml")
- .get();
-
- verifyXMLResponse(
- response,
- expectContainer(
- "depth1-cont",
- expectContainer(
- "depth2-cont1",
- expectContainer(
- "depth3-cont1",
- expectContainer("depth4-cont1",
- expectLeaf("depth5-leaf1", "depth5-leaf1-value")),
- expectLeaf("depth4-leaf1", "depth4-leaf1-value")),
- expectLeaf("depth3-leaf1", "depth3-leaf1-value")),
- expectContainer(
- "depth2-cont2",
- expectContainer(
- "depth3-cont2",
- expectContainer("depth4-cont2",
- expectLeaf("depth5-leaf2", "depth5-leaf2-value")),
- expectLeaf("depth4-leaf2", "depth4-leaf2-value")),
- expectLeaf("depth3-leaf2", "depth3-leaf2-value")),
- expectLeaf("depth2-leaf1", "depth2-leaf1-value")));
-
- // Test config with depth unbounded
-
- response = target("/config/nested-module:depth1-cont").queryParam("depth", "unbounded")
- .request("application/xml").get();
-
- verifyXMLResponse(
- response,
- expectContainer(
- "depth1-cont",
- expectContainer(
- "depth2-cont1",
- expectContainer(
- "depth3-cont1",
- expectContainer("depth4-cont1",
- expectLeaf("depth5-leaf1", "depth5-leaf1-value")),
- expectLeaf("depth4-leaf1", "depth4-leaf1-value")),
- expectLeaf("depth3-leaf1", "depth3-leaf1-value")),
- expectContainer(
- "depth2-cont2",
- expectContainer(
- "depth3-cont2",
- expectContainer("depth4-cont2",
- expectLeaf("depth5-leaf2", "depth5-leaf2-value")),
- expectLeaf("depth4-leaf2", "depth4-leaf2-value")),
- expectLeaf("depth3-leaf2", "depth3-leaf2-value")),
- expectLeaf("depth2-leaf1", "depth2-leaf1-value")));
-
- // Test operational
-
- final CompositeNode depth2Cont1 = toCompositeNode(toCompositeNodeData(
- toNestedQName("depth2-cont1"),
- toCompositeNodeData(
- toNestedQName("depth3-cont1"),
- toCompositeNodeData(toNestedQName("depth4-cont1"),
- toSimpleNodeData(toNestedQName("depth5-leaf1"), "depth5-leaf1-value")),
- toSimpleNodeData(toNestedQName("depth4-leaf1"), "depth4-leaf1-value")),
- toSimpleNodeData(toNestedQName("depth3-leaf1"), "depth3-leaf1-value")));
-
- assertTrue(dataSchemaNode instanceof DataNodeContainer);
- DataSchemaNode depth2cont1Schema = null;
- for (final DataSchemaNode childNode : ((DataNodeContainer) dataSchemaNode).getChildNodes()) {
- if (childNode.getQName().getLocalName().equals("depth2-cont1")) {
- depth2cont1Schema = childNode;
- break;
- }
- }
- assertNotNull(depth2Cont1);
-
- when(brokerFacade.readOperationalData(any(YangInstanceIdentifier.class))).thenReturn(
- TestUtils.compositeNodeToDatastoreNormalizedNode(depth2Cont1, depth2cont1Schema));
-
- response = target("/operational/nested-module:depth1-cont/depth2-cont1").queryParam("depth", "3")
- .request("application/xml").get();
-
- verifyXMLResponse(
- response,
- expectContainer(
- "depth2-cont1",
- expectContainer("depth3-cont1", expectEmptyContainer("depth4-cont1"),
- expectLeaf("depth4-leaf1", "depth4-leaf1-value")),
- expectLeaf("depth3-leaf1", "depth3-leaf1-value")));
- }
-
/**
* Tests behavior when invalid value of depth URI parameter
*/
return QName.create("urn:nested:module", "2014-06-3", localName);
}
- @SuppressWarnings("unchecked")
- private CompositeNode toCompositeNode(final NodeData nodeData) {
- final CompositeNodeBuilder<ImmutableCompositeNode> builder = ImmutableCompositeNode.builder();
- builder.setQName((QName) nodeData.key);
-
- for (final NodeData child : (List<NodeData>) nodeData.data) {
- if (child.data instanceof List) {
- builder.add(toCompositeNode(child));
- } else {
- builder.addLeaf((QName) child.key, child.data);
- }
- }
-
- return builder.toInstance();
- }
-
private NodeData toCompositeNodeData(final QName key, final NodeData... childData) {
return new NodeData(key, Lists.newArrayList(childData));
}
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
-import java.net.URI;
import java.net.URISyntaxException;
import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
import java.util.Set;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Application;
import org.opendaylight.controller.sal.rest.impl.RestconfDocumentedExceptionMapper;
import org.opendaylight.controller.sal.rest.impl.XmlNormalizedNodeBodyReader;
import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
-import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
-import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
-import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.Module;
private static String xmlDataRpcInput;
private static String xmlBlockData;
private static String xmlTestInterface;
- private static CompositeNodeWrapper cnSnDataOutput;
private static String xmlData3;
private static String xmlData4;
restconfImpl.setControllerContext(context);
}
-// @Test
-// public void postRpcNoPayload() throws Exception {
-// setSchemaControllerContext(schemaContextTestModule);
-// final String uri = "/operations/test-module:no-payload-rpc-test";
-// final String mediaType = MediaType.APPLICATION_XML;
-// final Response response = target(uri).request(mediaType).post(Entity.entity("", mediaType));
-// assertNotNull(response);
-//
-// }
-
- @Test
- @Ignore //FIXME we don't wish to mock CompositeNode as result
- public void postOperationsStatusCodes() throws IOException {
- setSchemaControllerContext(schemaContextTestModule);
- mockInvokeRpc(cnSnDataOutput, true);
- String uri = "/operations/test-module:rpc-test";
- assertEquals(200, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
-
- mockInvokeRpc(null, true);
- assertEquals(204, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
-
- mockInvokeRpc(null, false);
- assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
-
- final List<RpcError> rpcErrors = new ArrayList<>();
- rpcErrors.add(RpcResultBuilder.newError(ErrorType.RPC, "tag1", "message1", "applicationTag1", "info1", null));
- rpcErrors.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "tag2", "message2", "applicationTag2", "info2",
- null));
- mockInvokeRpc(null, false, rpcErrors);
- assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
-
- uri = "/operations/test-module:rpc-wrongtest";
- assertEquals(400, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
- }
-
- @Test
- @Ignore // TODO RestconfDocumentedExceptionMapper needs be fixed before
- public void postConfigOnlyStatusCodes() throws UnsupportedEncodingException {
- setSchemaControllerContext(schemaContextYangsIetf);
- final String uri = "/config";
- mockCommitConfigurationDataPostMethod(true);
- assertEquals(204, post(uri, MediaType.APPLICATION_XML, xmlDataAbsolutePath));
-
- mockCommitConfigurationDataPostMethod(false);
- assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataAbsolutePath));
-
- assertEquals(400, post(uri, MediaType.APPLICATION_XML, ""));
- }
-
- @Test
- @Ignore //jenkins has problem with JerseyTest - we expecting problems with singletons ControllerContext as schemaContext holder
- public void postConfigStatusCodes() throws UnsupportedEncodingException {
- setSchemaControllerContext(schemaContextYangsIetf);
- final String uri = "/config/ietf-interfaces:interfaces";
-
- mockCommitConfigurationDataPostMethod(true);
- assertEquals(204, post(uri, MediaType.APPLICATION_XML, xmlDataInterfaceAbsolutePath));
-
- mockCommitConfigurationDataPostMethod(false);
- assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataInterfaceAbsolutePath));
-
- // FIXME : empty json input post value return NullPointerException by parsing -> err. code 500
-// assertEquals(400, post(uri, MediaType.APPLICATION_JSON, ""));
- }
-
@Test
@Ignore /// xmlData* need netconf-yang
public void postDataViaUrlMountPoint() throws UnsupportedEncodingException {
assertEquals(400, post(uri, MediaType.APPLICATION_JSON, ""));
}
- private void mockInvokeRpc(final CompositeNode result, final boolean sucessful, final Collection<RpcError> errors) {
-
- final DummyRpcResult.Builder<CompositeNode> builder = new DummyRpcResult.Builder<CompositeNode>().result(result)
- .isSuccessful(sucessful);
- if (!errors.isEmpty()) {
- builder.errors(errors);
- }
- final RpcResult<CompositeNode> rpcResult = builder.build();
-// when(brokerFacade.invokeRpc(any(QName.class), any(CompositeNode.class))).thenReturn(
-// Futures.<RpcResult<CompositeNode>> immediateFuture(rpcResult));
- }
-
- /**
- * @deprecated has to be removed for lithium release
- */
- @Deprecated
- private void mockInvokeRpc(final CompositeNode result, final boolean sucessful) {
- mockInvokeRpc(result, sucessful, Collections.<RpcError> emptyList());
- }
-
- private void mockCommitConfigurationDataPostMethod(final boolean succesfulComit) {
- if (succesfulComit) {
- doReturn(mock(CheckedFuture.class)).when(brokerFacade).commitConfigurationDataPost(any(YangInstanceIdentifier.class), any(NormalizedNode.class));
- } else {
- doThrow(RestconfDocumentedException.class).when(brokerFacade).commitConfigurationDataPost(
- any(YangInstanceIdentifier.class), any(NormalizedNode.class));
- }
- }
-
@Test
@Ignore //jenkins has problem with JerseyTest - we expecting problems with singletons ControllerContext as schemaContext holder
public void createConfigurationDataTest() throws UnsupportedEncodingException, ParseException {
final String xmlPathTestInterface = RestconfImplTest.class.getResource("/test-config-data/xml/test-interface.xml")
.getPath();
xmlTestInterface = TestUtils.loadTextFile(xmlPathTestInterface);
- cnSnDataOutput = prepareCnSnRpcOutput();
+// cnSnDataOutput = prepareCnSnRpcOutput();
final String data3Input = RestconfImplTest.class.getResource("/full-versions/test-data2/data3.xml").getPath();
xmlData3 = TestUtils.loadTextFile(data3Input);
final String data4Input = RestconfImplTest.class.getResource("/full-versions/test-data2/data7.xml").getPath();
xmlData4 = TestUtils.loadTextFile(data4Input);
}
- private static CompositeNodeWrapper prepareCnSnRpcOutput() throws URISyntaxException {
- final CompositeNodeWrapper cnSnDataOutput = new CompositeNodeWrapper(new URI("test:module"), "output");
- final CompositeNodeWrapper cont = new CompositeNodeWrapper(new URI("test:module"), "cont-output");
- cnSnDataOutput.addValue(cont);
- cnSnDataOutput.unwrap();
- return cnSnDataOutput;
- }
}
import org.junit.Test;
import org.opendaylight.controller.sal.rest.api.Draft02;
import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.rest.impl.JsonNormalizedNodeBodyReader;
+import org.opendaylight.controller.sal.rest.impl.NormalizedNodeJsonBodyWriter;
+import org.opendaylight.controller.sal.rest.impl.NormalizedNodeXmlBodyWriter;
import org.opendaylight.controller.sal.rest.impl.RestconfDocumentedExceptionMapper;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
+import org.opendaylight.controller.sal.rest.impl.XmlNormalizedNodeBodyReader;
import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
import org.opendaylight.controller.sal.restconf.impl.NormalizedNodeContext;
import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
@Override
protected Application configure() {
ResourceConfig resourceConfig = new ResourceConfig();
- resourceConfig = resourceConfig.registerInstances(mockRestConf, StructuredDataToXmlProvider.INSTANCE,
- StructuredDataToJsonProvider.INSTANCE);
+ resourceConfig = resourceConfig.registerInstances(mockRestConf, new XmlNormalizedNodeBodyReader(),
+ new JsonNormalizedNodeBodyReader(), new NormalizedNodeJsonBodyWriter(), new NormalizedNodeXmlBodyWriter());
resourceConfig.registerClasses(RestconfDocumentedExceptionMapper.class);
return resourceConfig;
}
testJsonResponse(new RestconfDocumentedException("mock error"), Status.INTERNAL_SERVER_ERROR,
ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, "mock error", null, null);
+
// To test verification code
// String json =
// "{ errors: {" +
testXMLResponse(new RestconfDocumentedException("mock error"), Status.INTERNAL_SERVER_ERROR,
ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, "mock error", null, null);
- // To test verification code
+ // To test verification code
// String xml =
// "<errors xmlns=\"urn:ietf:params:xml:ns:yang:ietf-restconf\">"+
// " <error>" +
package org.opendaylight.controller.sal.restconf.impl.test;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.ext.MessageBodyReader;
-import javax.ws.rs.ext.MessageBodyWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
-import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
-import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
-import org.opendaylight.controller.sal.restconf.impl.InstanceIdentifierContext;
-import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.NormalizedNodeContext;
-import org.opendaylight.controller.sal.restconf.impl.RestconfDocumentedException;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
-import org.opendaylight.controller.sal.restconf.impl.StructuredData;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.parser.CnSnToNormalizedNodeParserFactory;
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
}
- /**
- * @deprecated method will be removed in Lithium release
- * we don't wish to use Node and CompositeNode anywhere -
- *
- * Fill missing data (namespaces) and build correct data type in {@code compositeNode} according to
- * {@code dataSchemaNode}. The method {@link RestconfImpl#createConfigurationData createConfigurationData} is used
- * because it contains calling of method {code normalizeNode}
- */
- @Deprecated
- public static void normalizeCompositeNode(final Node<?> node, final Set<Module> modules, final String schemaNodePath) {
- final RestconfImpl restconf = RestconfImpl.getInstance();
- ControllerContext.getInstance().setSchemas(TestUtils.loadSchemaContext(modules));
- prepareMocksForRestconf(modules, restconf);
-
- final InstanceIdentifierContext iiContext = ControllerContext.getInstance().toInstanceIdentifier(schemaNodePath);
- final DOMMountPoint mountPoint = iiContext.getMountPoint();
- final CompositeNode value = RestconfImpl.getInstance().normalizeNode(node, (DataSchemaNode) iiContext.getSchemaNode(), mountPoint);
- final NormalizedNode<?, ?> normNodePayload = compositeNodeToDatastoreNormalizedNode(value, (DataSchemaNode) iiContext.getSchemaNode());
- final NormalizedNodeContext normlNodeContext = new NormalizedNodeContext(iiContext, normNodePayload);
-
- restconf.updateConfigurationData(schemaNodePath, normlNodeContext);
- }
-
/**
* Searches module with name {@code searchedModuleName} in {@code modules}. If module name isn't specified and
* module set has only one element then this element is returned.
return buildQName(name, "", null);
}
- private static void addDummyNamespaceToAllNodes(final NodeWrapper<?> wrappedNode) throws URISyntaxException {
- wrappedNode.setNamespace(new URI(""));
- if (wrappedNode instanceof CompositeNodeWrapper) {
- for (final NodeWrapper<?> childNodeWrapper : ((CompositeNodeWrapper) wrappedNode).getValues()) {
- addDummyNamespaceToAllNodes(childNodeWrapper);
- }
- }
- }
-
private static void prepareMocksForRestconf(final Set<Module> modules, final RestconfImpl restconf) {
final ControllerContext controllerContext = ControllerContext.getInstance();
final BrokerFacade mockedBrokerFacade = mock(BrokerFacade.class);
restconf.setBroker(mockedBrokerFacade);
}
- public static Node<?> readInputToCnSn(final String path, final boolean dummyNamespaces,
- final MessageBodyReader<Node<?>> reader) throws WebApplicationException {
-
- final InputStream inputStream = TestUtils.class.getResourceAsStream(path);
- try {
- final Node<?> node = reader.readFrom(null, null, null, null, null, inputStream);
- assertTrue(node instanceof CompositeNodeWrapper);
- if (dummyNamespaces) {
- try {
- TestUtils.addDummyNamespaceToAllNodes((CompositeNodeWrapper) node);
- return ((CompositeNodeWrapper) node).unwrap();
- } catch (final URISyntaxException e) {
- LOG.error(e.getMessage());
- assertTrue(e.getMessage(), false);
- }
- }
- return node;
- } catch (final IOException e) {
- LOG.error(e.getMessage());
- assertTrue(e.getMessage(), false);
- }
- return null;
- }
-
-// public static Node<?> readInputToCnSnNew(String path, MessageBodyReader<Node<?>> reader) throws WebApplicationException {
-// InputStream inputStream = TestUtils.class.getResourceAsStream(path);
-// try {
-// return reader.readFrom(null, null, null, null, null, inputStream);
-// } catch (IOException e) {
-// LOG.error(e.getMessage());
-// assertTrue(e.getMessage(), false);
-// }
-// return null;
-// }
-
- public static Node<?> readInputToCnSn(final String path, final MessageBodyReader<Node<?>> reader) {
- return readInputToCnSn(path, false, reader);
- }
-
- public static String writeCompNodeWithSchemaContextToOutput(final Node<?> node, final Set<Module> modules,
- final DataSchemaNode dataSchemaNode, final MessageBodyWriter<StructuredData> messageBodyWriter) throws IOException,
- WebApplicationException {
-
- assertNotNull(dataSchemaNode);
- assertNotNull("Composite node can't be null", node);
- final ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
-
- ControllerContext.getInstance().setSchemas(loadSchemaContext(modules));
-
- assertTrue(node instanceof CompositeNode);
- messageBodyWriter.writeTo(new StructuredData((CompositeNode)node, dataSchemaNode, null), null, null, null, null,
- null, byteArrayOS);
-
- return byteArrayOS.toString();
- }
-
public static String loadTextFile(final String filePath) throws IOException {
final FileReader fileReader = new FileReader(filePath);
final BufferedReader bufReader = new BufferedReader(fileReader);
return matcher.matches();
}
- public static NormalizedNode compositeNodeToDatastoreNormalizedNode(final CompositeNode compositeNode,
- final DataSchemaNode schema) {
- final List<Node<?>> lst = new ArrayList<Node<?>>();
- lst.add(compositeNode);
- if (schema instanceof ContainerSchemaNode) {
- return CnSnToNormalizedNodeParserFactory.getInstance().getContainerNodeParser()
- .parse(lst, (ContainerSchemaNode) schema);
- } else if (schema instanceof ListSchemaNode) {
- return CnSnToNormalizedNodeParserFactory.getInstance().getMapNodeParser()
- .parse(lst, (ListSchemaNode) schema);
- }
-
- LOG.error("Top level isn't of type container, list, leaf schema node but " + schema.getClass().getSimpleName());
-
- throw new RestconfDocumentedException(new RestconfError(ErrorType.APPLICATION, ErrorTag.INVALID_VALUE,
- "It wasn't possible to translate specified data to datastore readable form."));
- }
-
public static YangInstanceIdentifier.NodeIdentifier getNodeIdentifier(final String localName, final String namespace,
final String revision) throws ParseException {
return new YangInstanceIdentifier.NodeIdentifier(QName.create(namespace, revision, localName));
predicate);
}
- /**
- * @deprecated method has to be removed for Lithium release
- * so please use prepareNormalizedNodeWithIetfInterfacesInterfacesData method
- */
- @Deprecated
- public static CompositeNode prepareCompositeNodeWithIetfInterfacesInterfacesData() {
- final CompositeNodeBuilder<ImmutableCompositeNode> interfaceBuilder = ImmutableCompositeNode.builder();
- interfaceBuilder.addLeaf(buildQName("name", "dummy", "2014-07-29"), "eth0");
- interfaceBuilder.addLeaf(buildQName("type", "dummy", "2014-07-29"), "ethernetCsmacd");
- interfaceBuilder.addLeaf(buildQName("enabled", "dummy", "2014-07-29"), "false");
- interfaceBuilder.addLeaf(buildQName("description", "dummy", "2014-07-29"), "some interface");
- return interfaceBuilder.toInstance();
- }
-
static NormalizedNode<?,?> prepareNormalizedNodeWithIetfInterfacesInterfacesData() throws ParseException {
final String ietfInterfacesDate = "2013-07-04";
final String namespace = "urn:ietf:params:xml:ns:yang:ietf-interfaces";
import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
import org.opendaylight.controller.sal.streams.listeners.Notificator;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.InstanceIdentifierBuilder;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
-import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
return new NormalizedNodeContext(new InstanceIdentifierContext(null, rpcInputSchemaNode, null, schema), container.build());
}
-
- /**
- * @deprecated method has to be removed for a Lithium release
- */
- @Deprecated
- private CompositeNode prepareRpcNode(final String datastore, final String scope) {
- final CompositeNodeBuilder<ImmutableCompositeNode> inputBuilder = ImmutableCompositeNode.builder();
- inputBuilder.setQName(QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote",
- "2014-01-14", "input"));
- inputBuilder.addLeaf(
- QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote", "2014-01-14", "path"),
- YangInstanceIdentifier.builder().node(QName.create("urn:opendaylight:inventory", "2013-08-19", "nodes")).build());
- inputBuilder.addLeaf(QName.create("urn:sal:restconf:event:subscription", "2014-7-8", "datastore"), datastore);
- inputBuilder.addLeaf(QName.create("urn:sal:restconf:event:subscription", "2014-7-8", "scope"), scope);
- return inputBuilder.toInstance();
- }
}
*/
package org.opendaylight.controller.sal.restconf.impl.test;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.util.Iterator;
-import java.util.Map;
-import javax.ws.rs.WebApplicationException;
import org.junit.BeforeClass;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
-import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
public class XmlAndJsonToCnSnInstanceIdentifierTest extends YangAndXmlAndDataSchemaLoader {
dataLoad("/instanceidentifier/yang", 4, "instance-identifier-module", "cont");
}
- @Test
- public void loadXmlToCnSn() throws WebApplicationException, IOException, URISyntaxException {
- Node<?> node = TestUtils.readInputToCnSn("/instanceidentifier/xml/xmldata.xml",
- XmlToCompositeNodeProvider.INSTANCE);
-
- assertTrue(node instanceof CompositeNode);
- CompositeNode cnSn = (CompositeNode)node;
- TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
- verifyListPredicate(cnSn);
- }
-
- @Test
- public void loadXmlLeafListToCnSn() throws WebApplicationException, IOException, URISyntaxException {
- Node<?> node = TestUtils.readInputToCnSn("/instanceidentifier/xml/xmldata_leaf_list.xml",
- XmlToCompositeNodeProvider.INSTANCE);
-
- assertTrue(node instanceof CompositeNode);
- CompositeNode cnSn = (CompositeNode)node;
- TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
- verifyLeafListPredicate(cnSn);
- }
-
- @Test
- public void loadJsonToCnSn() throws WebApplicationException, IOException, URISyntaxException {
- Node<?> node = TestUtils.readInputToCnSn("/instanceidentifier/json/jsondata.json",
- JsonToCompositeNodeProvider.INSTANCE);
-
- assertTrue(node instanceof CompositeNode);
- CompositeNode cnSn = (CompositeNode)node;
- TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
- verifyListPredicate(cnSn);
- }
-
- @Test
- public void loadJsonLeafListToCnSn() throws WebApplicationException, IOException, URISyntaxException {
- Node<?> node = TestUtils.readInputToCnSn("/instanceidentifier/json/jsondata_leaf_list.json",
- JsonToCompositeNodeProvider.INSTANCE);
- assertTrue(node instanceof CompositeNode);
- CompositeNode cnSn = (CompositeNode)node;
-
- TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
- verifyLeafListPredicate(cnSn);
- }
-
- private void verifyLeafListPredicate(final CompositeNode cnSn) throws URISyntaxException {
- SimpleNode<?> lf11 = getSnWithInstanceIdentifierWhenLeafList(cnSn);
- Object value = lf11.getValue();
- assertTrue(value instanceof YangInstanceIdentifier);
-
- YangInstanceIdentifier instanceIdentifier = (YangInstanceIdentifier) value;
- Iterator<PathArgument> it = instanceIdentifier.getPathArguments().iterator();
- String revisionDate = "2014-01-17";
-
- assertEquals(TestUtils.buildQName("cont", "instance:identifier:module", revisionDate), it.next().getNodeType());
- assertEquals(TestUtils.buildQName("cont1", "instance:identifier:module", revisionDate), it.next().getNodeType());
-
- PathArgument arg = it.next();
- assertFalse(it.hasNext());
- assertEquals(TestUtils.buildQName("lflst11", "augment:module:leaf:list", "2014-01-27"), arg.getNodeType());
-
- assertTrue(arg instanceof NodeWithValue);
- assertEquals("lflst11_1", ((NodeWithValue) arg).getValue());
-
- }
-
- private void verifyListPredicate(final CompositeNode cnSn) throws URISyntaxException {
- SimpleNode<?> lf111 = getSnWithInstanceIdentifierWhenList(cnSn);
- Object value = lf111.getValue();
- assertTrue(value instanceof YangInstanceIdentifier);
-
- YangInstanceIdentifier instanceIdentifier = (YangInstanceIdentifier) value;
- Iterator<PathArgument> it = instanceIdentifier.getPathArguments().iterator();
- String revisionDate = "2014-01-17";
- assertEquals(TestUtils.buildQName("cont", "instance:identifier:module", revisionDate), it.next().getNodeType());
- assertEquals(TestUtils.buildQName("cont1", "instance:identifier:module", revisionDate), it.next().getNodeType());
-
- PathArgument arg = it.next();
- assertEquals(TestUtils.buildQName("lst11", "augment:module", revisionDate), arg.getNodeType());
- assertEquals(TestUtils.buildQName("lf112", "augment:augment:module", revisionDate), it.next().getNodeType());
- assertFalse(it.hasNext());
-
- assertTrue(arg instanceof NodeIdentifierWithPredicates);
- Map<QName, Object> predicates = ((NodeIdentifierWithPredicates) arg).getKeyValues();
- assertEquals(2, predicates.size());
- assertEquals("value1", predicates.get(TestUtils.buildQName("keyvalue111", "augment:module", revisionDate)));
- assertEquals("value2", predicates.get(TestUtils.buildQName("keyvalue112", "augment:module", revisionDate)));
- }
-
- private SimpleNode<?> getSnWithInstanceIdentifierWhenList(final CompositeNode cnSn) throws URISyntaxException {
- CompositeNode cont1 = cnSn.getFirstCompositeByName(TestUtils.buildQName("cont1", "instance:identifier:module",
- "2014-01-17"));
- assertNotNull(cont1);
- CompositeNode lst11 = cont1.getFirstCompositeByName(TestUtils.buildQName("lst11", "augment:module",
- "2014-01-17"));
- assertNotNull(lst11);
- SimpleNode<?> lf111 = lst11.getFirstSimpleByName(TestUtils.buildQName("lf111", "augment:augment:module",
- "2014-01-17"));
- assertNotNull(lf111);
- return lf111;
- }
-
- private SimpleNode<?> getSnWithInstanceIdentifierWhenLeafList(final CompositeNode cnSn) throws URISyntaxException {
- CompositeNode cont1 = cnSn.getFirstCompositeByName(TestUtils.buildQName("cont1", "instance:identifier:module",
- "2014-01-17"));
- assertNotNull(cont1);
- SimpleNode<?> lf11 = cont1.getFirstSimpleByName(TestUtils.buildQName("lf11", "augment:module:leaf:list",
- "2014-01-27"));
- assertNotNull(lf11);
- return lf11;
- }
-
}
*/
package org.opendaylight.controller.sal.restconf.impl.test;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.net.URISyntaxException;
-
-import javax.ws.rs.WebApplicationException;
-
import org.junit.BeforeClass;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
-import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
public class XmlAndJsonToCnSnLeafRefTest extends YangAndXmlAndDataSchemaLoader {
dataLoad("/leafref/yang", 2, "leafref-module", "cont");
}
- @Test
- public void loadXmlToCnSn() throws WebApplicationException, IOException, URISyntaxException {
- Node<?> node = TestUtils.readInputToCnSn("/leafref/xml/xmldata.xml", XmlToCompositeNodeProvider.INSTANCE);
-
- assertTrue(node instanceof CompositeNode);
- CompositeNode cnSn = (CompositeNode)node;
-
- TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
-
- verifyContPredicate(cnSn, "lf4", YangInstanceIdentifier.builder().node(refContQName).node(refLf1QName).build());
- verifyContPredicate(cnSn, "lf2", YangInstanceIdentifier.builder().node(contQName).node(lf1QName).build());
- verifyContPredicate(cnSn, "lf3", YangInstanceIdentifier.builder().node(contQName).node(lf2QName).build());
- verifyContPredicate(cnSn, "lf5", YangInstanceIdentifier.builder().node(contQName).node(lf3QName).build());
- }
-
- @Test
- public void loadJsonToCnSn() throws WebApplicationException, IOException, URISyntaxException {
- Node<?> node = TestUtils.readInputToCnSn("/leafref/json/jsondata.json",
- JsonToCompositeNodeProvider.INSTANCE);
- assertTrue(node instanceof CompositeNode);
- CompositeNode cnSn = (CompositeNode)node;
-
- TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
-
- verifyContPredicate(cnSn, "lf4", YangInstanceIdentifier.builder().node(refContQName).node(refLf1QName).build());
- verifyContPredicate(cnSn, "lf2", YangInstanceIdentifier.builder().node(contQName).node(lf1QName).build());
- verifyContPredicate(cnSn, "lf3", YangInstanceIdentifier.builder().node(contQName).node(lf2QName).build());
- verifyContPredicate(cnSn, "lf5", YangInstanceIdentifier.builder().node(contQName).node(lf3QName).build());
- }
-
- private void verifyContPredicate(CompositeNode cnSn, String leafName, Object value) throws URISyntaxException {
- Object parsed = null;
-
- for (final Node<?> node : cnSn.getValue()) {
- if (node.getNodeType().getLocalName().equals(leafName)) {
- parsed = node.getValue();
- }
- }
-
- assertEquals(value, parsed);
- }
}
*/
package org.opendaylight.controller.sal.restconf.impl.xml.to.cnsn.test;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Set;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
-import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.model.api.Module;
public class XmlAugmentedElementToCnSnTest {
- @Test
- public void loadDataAugmentedSchemaMoreEqualNamesTest() {
- loadAndNormalizeData("/common/augment/xml/dataa.xml", "/common/augment/yang", "main", "cont");
- loadAndNormalizeData("/common/augment/xml/datab.xml", "/common/augment/yang", "main", "cont");
- }
-
- private void loadAndNormalizeData(String xmlPath, String yangPath, String topLevelElementName, String moduleName) {
- Node<?> node = TestUtils.readInputToCnSn(xmlPath, false,
- XmlToCompositeNodeProvider.INSTANCE);
- assertTrue(node instanceof CompositeNode);
- CompositeNode cnSn = (CompositeNode)node;
-
- Set<Module> modules = TestUtils.loadModulesFrom(yangPath);
-
- assertNotNull(modules);
- TestUtils.normalizeCompositeNode(cnSn, modules, topLevelElementName + ":" + moduleName);
- }
-
}
*/
package org.opendaylight.controller.sal.restconf.impl.xml.to.cnsn.test;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.List;
-import java.util.Set;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
-import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.model.api.Module;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class XmlLeafrefToCnSnTest {
private static final Logger LOG = LoggerFactory.getLogger(XmlLeafrefToCnSnTest.class);
- /**
- * top level element represents container. second level element is list with two elements.
- */
- @Test
- public void testXmlDataContainer() {
- Node<?> node = TestUtils.readInputToCnSn("/xml-to-cnsn/data-container.xml", false,
- XmlToCompositeNodeProvider.INSTANCE);
- assertTrue(node instanceof CompositeNode);
- CompositeNode compNode = (CompositeNode)node;
-
- assertNotNull(compNode);
- Set<Module> modules = TestUtils.loadModulesFrom("/xml-to-cnsn/data-container-yang");
-
- assertNotNull(modules);
- TestUtils.normalizeCompositeNode(compNode, modules, "data-container-yang:cont");
-
- String nameSpace = "data:container:yang";
- assertEquals(nameSpace, compNode.getNodeType().getNamespace().toString());
-
- verifyNullAndEmptyStringSingleNode(compNode, nameSpace);
- verifyCommonPartAOfXml(compNode, "", 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.getValue()) {
- if (found == 0x3)
- break;
- if (child instanceof SimpleNode<?>) {
- SimpleNode<?> childSimple = (SimpleNode<?>) child;
- if (childSimple.getNodeType().getLocalName().equals("lf3")) {
- lf3 = childSimple;
- found = found | (1 << 0);
- } else if (childSimple.getNodeType().getLocalName().equals("lf2")) {
- lf2 = childSimple;
- found = found | (1 << 1);
- }
- }
- assertEquals(nameSpace, child.getNodeType().getNamespace().toString());
- }
-
- assertEquals("", lf2.getValue());
- assertEquals(null, lf3.getValue());
- }
-
- @Test
- public void testXmlDataList() {
- Node<?> node = TestUtils.readInputToCnSn("/xml-to-cnsn/data-list.xml", false,
- XmlToCompositeNodeProvider.INSTANCE);
- assertTrue(node instanceof CompositeNode);
- CompositeNode compNode = (CompositeNode)node;
-
-
- Set<Module> modules = TestUtils.loadModulesFrom("/xml-to-cnsn/data-list-yang");
- assertNotNull(modules);
-
- TestUtils.normalizeCompositeNode(compNode, modules, "data-container-yang:cont");
-
- String nameSpaceList = "data:list:yang";
- String nameSpaceCont = "data:container:yang";
- assertEquals(nameSpaceCont, compNode.getNodeType().getNamespace().toString());
- assertEquals("cont", compNode.getNodeType().getLocalName());
- assertEquals(3, compNode.getValue().size());
- CompositeNode lst1_1 = null;
- CompositeNode lst1_2 = null;
- int loopCount = 0;
- for (Node<?> nd : compNode.getValue()) {
- if (nd.getNodeType().getLocalName().equals("lf1")) {
- assertEquals(nameSpaceList, nd.getNodeType().getNamespace().toString());
- assertTrue(nd instanceof SimpleNode<?>);
- assertEquals("lf1", nd.getValue());
- } else {
- assertTrue(nd instanceof CompositeNode);
- switch (loopCount++) {
- case 0:
- lst1_1 = (CompositeNode) nd;
- break;
- case 1:
- lst1_2 = (CompositeNode) nd;
- break;
- }
- assertEquals(nameSpaceCont, nd.getNodeType().getNamespace().toString());
- }
- }
- // lst1_1
- verifyCommonPartAOfXml(lst1_1, "1", nameSpaceCont);
- // :lst1_1
-
- // lst1_2
- SimpleNode<?> lflst11 = null;
- CompositeNode cont11 = null;
- for (Node<?> nd : lst1_2.getValue()) {
- String nodeName = nd.getNodeType().getLocalName();
- if (nodeName.equals("lflst11")) {
- assertTrue(nd instanceof SimpleNode<?>);
- lflst11 = (SimpleNode<?>) nd;
-
- } else if (nodeName.equals("cont11")) {
- assertTrue(nd instanceof CompositeNode);
- cont11 = (CompositeNode) nd;
- }
- assertEquals(nameSpaceCont, compNode.getNodeType().getNamespace().toString());
- }
- assertEquals("221", lflst11.getValue());
-
- 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());
- // :lst1_2
-
- }
-
- @Test
- public void testXmlEmptyData() {
- Node<?> node = TestUtils.readInputToCnSn("/xml-to-cnsn/empty-data.xml", true,
- XmlToCompositeNodeProvider.INSTANCE);
- assertTrue(node instanceof CompositeNode);
- CompositeNode compNode = (CompositeNode)node;
-
- assertEquals("cont", compNode.getNodeType().getLocalName());
- SimpleNode<?> lf1 = null;
- SimpleNode<?> lflst1_1 = null;
- SimpleNode<?> lflst1_2 = null;
- CompositeNode lst1 = null;
- int lflst1Count = 0;
- for (Node<?> nd : compNode.getValue()) {
- if (nd.getNodeType().getLocalName().equals("lf1")) {
- assertTrue(nd instanceof SimpleNode<?>);
- lf1 = (SimpleNode<?>) nd;
- } else if (nd.getNodeType().getLocalName().equals("lflst1")) {
- assertTrue(nd instanceof SimpleNode<?>);
-
- switch (lflst1Count++) {
- case 0:
- lflst1_1 = (SimpleNode<?>) nd;
- break;
- case 1:
- lflst1_2 = (SimpleNode<?>) nd;
- break;
- }
- } else if (nd.getNodeType().getLocalName().equals("lst1")) {
- assertTrue(nd instanceof CompositeNode);
- lst1 = (CompositeNode) nd;
- }
- }
-
- assertNotNull(lf1);
- assertNotNull(lflst1_1);
- assertNotNull(lflst1_2);
- assertNotNull(lst1);
-
- assertEquals("", lf1.getValue());
- assertEquals("", lflst1_1.getValue());
- assertEquals("", lflst1_2.getValue());
- assertEquals(1, lst1.getValue().size());
- assertEquals("lf11", lst1.getValue().get(0).getNodeType().getLocalName());
-
- assertTrue(lst1.getValue().get(0) instanceof SimpleNode<?>);
- assertEquals("", lst1.getValue().get(0).getValue());
-
- }
-
- /**
- * Test case like this <lf11 xmlns:x="namespace">x:identity</lf11>
- */
- @Test
- public void testIdentityrefNmspcInElement() {
- testIdentityrefToCnSn("/xml-to-cnsn/identityref/xml/data-nmspc-in-element.xml", "/xml-to-cnsn/identityref",
- "identityref-module", "cont", 2, "iden", "identity:module");
- }
-
- /**
- *
- * Test case like <lf11 xmlns="namespace1" xmlns:x="namespace">identity</lf11>
- */
-
- @Test
- public void testIdentityrefDefaultNmspcInElement() {
- testIdentityrefToCnSn("/xml-to-cnsn/identityref/xml/data-default-nmspc-in-element.xml",
- "/xml-to-cnsn/identityref/yang-augments", "general-module", "cont", 3, "iden", "identityref:module");
- }
-
- /**
- *
- * Test case like <cont1 xmlns="namespace1"> <lf11 xmlns:x="namespace">identity</lf11> </cont1>
- */
- @Test
- public void testIdentityrefDefaultNmspcInParrentElement() {
- testIdentityrefToCnSn("/xml-to-cnsn/identityref/xml/data-default-nmspc-in-parrent-element.xml",
- "/xml-to-cnsn/identityref", "identityref-module", "cont", 2, "iden", "identityref:module");
- }
-
- /**
- *
- * Test case like <cont1 xmlns="namespace1" xmlns:x="namespace"> <lf11>x:identity</lf11> </cont1>
- */
- @Ignore
- @Test
- public void testIdentityrefNmspcInParrentElement() {
- testIdentityrefToCnSn("/xml-to-cnsn/identityref/xml/data-nmspc-in-parrent-element.xml",
- "/xml-to-cnsn/identityref", "identityref-module", "cont", 2, "iden", "z:namespace");
- }
-
- /**
- *
- * Test case like (without namespace in xml) <cont1> <lf11>x:identity</lf11> </cont1>
- */
- @Test
- public void testIdentityrefNoNmspcValueWithPrefix() {
- testIdentityrefToCnSn("/xml-to-cnsn/identityref/xml/data-no-nmspc-value-with-prefix.xml",
- "/xml-to-cnsn/identityref", "identityref-module", "cont", 2, "x:iden", "identityref:module");
- }
-
- /**
- *
- * Test case like (without namespace in xml) <cont1> <lf11>identity</lf11> </cont1>
- */
- @Test
- public void testIdentityrefNoNmspcValueWithoutPrefix() {
- testIdentityrefToCnSn("/xml-to-cnsn/identityref/xml/data-no-nmspc-value-without-prefix.xml",
- "/xml-to-cnsn/identityref", "identityref-module", "cont", 2, "iden", "identityref:module");
- }
-
- private void verifyCommonPartAOfXml(final CompositeNode compNode, final String suf, final String nameSpace) {
- SimpleNode<?> lf1suf = null;
- SimpleNode<?> lflst1suf_1 = null;
- SimpleNode<?> lflst1suf_2 = null;
- SimpleNode<?> lflst1suf_3 = null;
- CompositeNode cont1suf = null;
- CompositeNode lst1suf = null;
-
- int lflstCount = 0;
-
- for (Node<?> node : compNode.getValue()) {
- String localName = node.getNodeType().getLocalName();
- if (localName.equals("lf1" + suf)) {
- assertTrue(node instanceof SimpleNode<?>);
- lf1suf = (SimpleNode<?>) node;
- } else if (localName.equals("lflst1" + suf)) {
- assertTrue(node instanceof SimpleNode<?>);
- switch (lflstCount++) {
- case 0:
- lflst1suf_1 = (SimpleNode<?>) node;
- break;
- case 1:
- lflst1suf_2 = (SimpleNode<?>) node;
- break;
- case 2:
- lflst1suf_3 = (SimpleNode<?>) node;
- break;
- }
- } else if (localName.equals("lst1" + suf)) {
- assertTrue(node instanceof CompositeNode);
- lst1suf = (CompositeNode) node;
- } else if (localName.equals("cont1" + suf)) {
- assertTrue(node instanceof CompositeNode);
- cont1suf = (CompositeNode) node;
- }
- assertEquals(nameSpace, node.getNodeType().getNamespace().toString());
- }
-
- assertNotNull(lf1suf);
- assertNotNull(lflst1suf_1);
- assertNotNull(lflst1suf_2);
- assertNotNull(lflst1suf_3);
- assertNotNull(lst1suf);
- assertNotNull(cont1suf);
-
- assertEquals("str0", lf1suf.getValue());
- assertEquals("121", lflst1suf_1.getValue());
- assertEquals("131", lflst1suf_2.getValue());
- assertEquals("str1", lflst1suf_3.getValue());
-
- assertEquals(1, lst1suf.getValue().size());
-
- 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.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(final String xmlPath, final String yangPath, final String moduleName,
- final String schemaName, final int moduleCount, final String resultLocalName, final String resultNamespace) {
- Node<?> node = TestUtils.readInputToCnSn(xmlPath, false, XmlToCompositeNodeProvider.INSTANCE);
- assertTrue(node instanceof CompositeNode);
- CompositeNode compositeNode = (CompositeNode)node;
-
-
- Set<Module> modules = TestUtils.loadModulesFrom(yangPath);
- assertEquals(moduleCount, modules.size());
-
- TestUtils.normalizeCompositeNode(compositeNode, modules, moduleName + ":" + schemaName);
-
- SimpleNode<?> lf11 = getLf11(compositeNode);
- assertTrue(lf11.getValue() instanceof QName);
- QName qName = (QName) lf11.getValue();
- assertEquals(resultLocalName, qName.getLocalName());
- assertEquals(resultNamespace, qName.getNamespace().toString());
- }
-
- private SimpleNode<?> getLf11(final CompositeNode compositeNode) {
- assertEquals("cont", compositeNode.getNodeType().getLocalName());
-
- List<Node<?>> childs = compositeNode.getValue();
- assertEquals(1, childs.size());
- Node<?> nd = childs.iterator().next();
- assertTrue(nd instanceof CompositeNode);
- assertEquals("cont1", nd.getNodeType().getLocalName());
-
- childs = ((CompositeNode) nd).getValue();
- SimpleNode<?> lf11 = null;
- for (Node<?> child : childs) {
- assertTrue(child instanceof SimpleNode);
- if (child.getNodeType().getLocalName().equals("lf11")) {
- lf11 = (SimpleNode<?>) child;
- }
- }
- assertNotNull(lf11);
- return lf11;
- }
-
}
*/
package org.opendaylight.controller.sal.restconf.impl.xml.to.cnsn.test;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
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.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
public class XmlToCnSnTest extends YangAndXmlAndDataSchemaLoader {
dataLoad("/xml-to-cnsn/leafref");
}
- @Test
- public void testXmlLeafrefToCnSn() {
- Node<?> node = TestUtils.readInputToCnSn("/xml-to-cnsn/leafref/xml/data.xml", false,
- XmlToCompositeNodeProvider.INSTANCE);
- assertTrue(node instanceof CompositeNode);
- CompositeNode compositeNode = (CompositeNode)node;
-
-
- assertNotNull(dataSchemaNode);
- TestUtils.normalizeCompositeNode(compositeNode, modules, schemaNodePath);
-
- assertEquals("cont", compositeNode.getNodeType().getLocalName());
-
- SimpleNode<?> lf2 = null;
- for (Node<?> childNode : compositeNode.getValue()) {
- if (childNode instanceof SimpleNode) {
- if (childNode.getNodeType().getLocalName().equals("lf2")) {
- lf2 = (SimpleNode<?>) childNode;
- break;
- }
- }
- }
-
- assertNotNull(lf2);
- assertEquals(121, lf2.getValue());
- }
-
- @Test
- public void testXmlBlankInput() throws Exception {
- InputStream inputStream = new ByteArrayInputStream("".getBytes());
- Node<?> node =
- XmlToCompositeNodeProvider.INSTANCE.readFrom(null, null, null, null, null, inputStream);
-
- assertNull( node );
- }
-
- @Test
- public void testXmlBlankInputUnmarkableStream() throws Exception {
- InputStream inputStream = new ByteArrayInputStream("".getBytes()) {
- @Override
- public boolean markSupported() {
- return false;
- }
- };
- Node<?> node =
- XmlToCompositeNodeProvider.INSTANCE.readFrom(null, null, null, null, null, inputStream);
-
- assertNull( node );
- }
-
}
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
-
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
import org.opendaylight.controller.sal.core.api.Broker;
import org.opendaylight.controller.sal.core.api.Provider;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener;
import org.opendaylight.controller.sal.rest.doc.impl.ApiDocGenerator;
import org.opendaylight.controller.sal.rest.doc.mountpoints.MountPointSwagger;
SchemaService schemaService = providerSession.getService(SchemaService.class);
ApiDocGenerator.getInstance().setSchemaService(schemaService);
- MountProvisionService mountService = providerSession
- .getService(MountProvisionService.class);
+ DOMMountPointService mountService = providerSession
+ .getService(DOMMountPointService.class);
ListenerRegistration<MountProvisionListener> registration = mountService
.registerProvisionListener(MountPointSwagger.getInstance());
MountPointSwagger.getInstance().setGlobalSchema(schemaService);
*/
package org.opendaylight.controller.sal.rest.doc.mountpoints;
+import com.google.common.base.Optional;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import javax.ws.rs.core.UriInfo;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener;
import org.opendaylight.controller.sal.rest.doc.impl.BaseYangSwaggerGenerator;
import org.opendaylight.controller.sal.rest.doc.swagger.Api;
private static final String DATASTORES_REVISION = "-";
private static final String DATASTORES_LABEL = "Datastores";
- private MountProvisionService mountService;
+ private DOMMountPointService mountService;
private final Map<YangInstanceIdentifier, Long> instanceIdToLongId = new TreeMap<>(
new Comparator<YangInstanceIdentifier>() {
@Override
return null;
}
- MountProvisionInstance mountPoint = mountService.getMountPoint(id);
- if (mountPoint == null) {
+ Optional<DOMMountPoint> mountPoint = mountService.getMountPoint(id);
+ if (!mountPoint.isPresent()) {
return null;
}
- SchemaContext context = mountPoint.getSchemaContext();
+ SchemaContext context = mountPoint.get().getSchemaContext();
if (context == null) {
return null;
}
return api;
}
- public void setMountService(final MountProvisionService mountService) {
+ public void setMountService(final DOMMountPointService mountService) {
this.mountService = mountService;
}
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import com.google.common.base.Optional;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.HashSet;
import javax.ws.rs.core.UriInfo;
import org.junit.Before;
import org.junit.Test;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
import org.opendaylight.controller.sal.rest.doc.mountpoints.MountPointSwagger;
import org.opendaylight.controller.sal.rest.doc.swagger.Api;
import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration;
SchemaContext context = helper.createMockSchemaContext();
SchemaService schemaService = helper.createMockSchemaService(context);
- MountProvisionInstance mountPoint = mock(MountProvisionInstance.class);
+ DOMMountPoint mountPoint = mock(DOMMountPoint.class);
when(mountPoint.getSchemaContext()).thenReturn(context);
- MountProvisionService service = mock(MountProvisionService.class);
- when(service.getMountPoint(instanceId)).thenReturn(mountPoint);
+ DOMMountPointService service = mock(DOMMountPointService.class);
+ when(service.getMountPoint(instanceId)).thenReturn(Optional.of(mountPoint));
swagger.setMountService(service);
swagger.setGlobalSchema(schemaService);
package org.opendaylight.controller.sal.restconf.binding.impl;
import java.net.URL;
-
import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.yangtools.restconf.client.api.UnsupportedProtocolException;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
import org.opendaylight.yangtools.yang.model.api.SchemaContextHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final RestconfClientContext restconfClientContext;
private final RestconfClientContextFactory restconfClientContextFactory = null;
- public DataBrokerServiceImpl(URL baseUrl, BindingIndependentMappingService mappingService, SchemaContextHolder schemaContextHolder) throws UnsupportedProtocolException {
- this.restconfClientContext = restconfClientContextFactory.getRestconfClientContext(baseUrl, mappingService, schemaContextHolder);
+ public DataBrokerServiceImpl(URL baseUrl, SchemaContextHolder schemaContextHolder) throws UnsupportedProtocolException {
+ this.restconfClientContext = restconfClientContextFactory.getRestconfClientContext(baseUrl, schemaContextHolder);
}
@Override
*/
package org.opendaylight.controller.sal.restconf.broker.client;
+import com.google.common.base.Preconditions;
import java.net.URL;
-
-import javassist.ClassPool;
-
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer;
import org.opendaylight.controller.sal.restconf.broker.SalRemoteServiceBroker;
import org.opendaylight.yangtools.restconf.client.api.RestconfClientContext;
import org.opendaylight.yangtools.restconf.client.api.UnsupportedProtocolException;
import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
-import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
-
-class SalRemoteClientImpl implements SalRemoteClient {
+class SalRemoteClientImpl implements SalRemoteClient, SchemaContextHolder {
private static final Logger logger = LoggerFactory.getLogger(SalRemoteClientImpl.class);
private final RestconfClientContext restconfClientContext;
private final SalRemoteServiceBroker salRemoteBroker;
- private final RuntimeGeneratedMappingServiceImpl mappingService;
+
+ private SchemaContext schemaContext;
public SalRemoteClientImpl(final URL url) {
Preconditions.checkNotNull(url);
- this.mappingService = new RuntimeGeneratedMappingServiceImpl(ClassPool.getDefault());
final ModuleInfoBackedContext moduleInfo = ModuleInfoBackedContext.create();
moduleInfo.addModuleInfos(BindingReflections.loadModuleInfos());
- this.mappingService.onGlobalContextUpdated(moduleInfo.tryToCreateSchemaContext().get());
-
+ schemaContext = moduleInfo.tryToCreateSchemaContext().get();
try {
- this.restconfClientContext = new RestconfClientFactory().getRestconfClientContext(url, this.mappingService,
- this.mappingService);
+ this.restconfClientContext = new RestconfClientFactory().getRestconfClientContext(url,this);
this.salRemoteBroker = new SalRemoteServiceBroker("remote-broker", restconfClientContext);
this.salRemoteBroker.start();
}, null);
}
+ @Override
+ public SchemaContext getSchemaContext() {
+ return schemaContext;
+ }
+
@Override
public void close() throws Exception {
this.restconfClientContext.close();
+++ /dev/null
-/*
- * 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.binding.impl.test;
-
-public class DataBrokerImplTest {
-
- public static void main(String[] args){
-
- }
-}
+++ /dev/null
-/*
- * 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.binding.impl.test;
-
-public class NotificationServiceImplTest {
-
- public static void main(String[] args){
-
- }
-}
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity1;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity2;
-import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
-import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
}
@Override
- protected CodecRegistry getCodecRegistry() {
- IdentityCodec<?> idCodec = mock(IdentityCodec.class);
- doReturn(TestIdentity1.class).when(idCodec).deserialize(TestIdentity1.QNAME);
- doReturn(TestIdentity2.class).when(idCodec).deserialize(TestIdentity2.QNAME);
-
- CodecRegistry codecReg = super.getCodecRegistry();
- doReturn(idCodec).when(codecReg).getIdentityCodec();
- return codecReg;
+ protected BindingRuntimeContext getBindingRuntimeContext() {
+ final BindingRuntimeContext ret = super.getBindingRuntimeContext();
+ doReturn(TestIdentity1.class).when(ret).getIdentityClass(TestIdentity1.QNAME);
+ doReturn(TestIdentity2.class).when(ret).getIdentityClass(TestIdentity2.QNAME);
+ return ret;
}
@Test
<artifactId>xmlunit</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <!--TODO remove this dependency on sal-netconf-connector - move InstanceIdToNodes to netconf-util,
+ remove odl-yangtools-models, sal-netconf-connector, model-inventory dependency from the odl-netconf-mdsal feature in mdsal features with this-->
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-netconf-connector</artifactId>
+ </dependency>
</dependencies>
package org.opendaylight.controller.netconf.mdsal.connector.ops.get;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collections;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.dom.DOMResult;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.mdsal.connector.CurrentSchemaContext;
import org.opendaylight.controller.netconf.mdsal.connector.ops.Datastore;
import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.sal.connect.netconf.util.InstanceIdToNodes;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
import org.opendaylight.yangtools.yang.data.impl.codec.xml.XMLStreamNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
+import org.w3c.dom.Element;
import org.w3c.dom.Node;
public abstract class AbstractGet extends AbstractLastNetconfOperation {
- protected static final YangInstanceIdentifier ROOT = YangInstanceIdentifier.builder().build();
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractGet.class);
+ protected static final String FILTER = "filter";
+ static final YangInstanceIdentifier ROOT = YangInstanceIdentifier.builder().build();
protected final CurrentSchemaContext schemaContext;
-
public AbstractGet(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext) {
super(netconfSessionIdForReporting);
this.schemaContext = schemaContext;
return result.getNode();
}
+
private XMLStreamWriter getXmlStreamWriter(final DOMResult result) {
try {
return XML_OUTPUT_FACTORY.createXMLStreamWriter(result);
// TODO this code is located in Restconf already
private void writeRootElement(final XMLStreamWriter xmlWriter, final NormalizedNodeWriter nnWriter, final ContainerNode data) {
try {
- for (final DataContainerChild<? extends PathArgument, ?> child : data.getValue()) {
- nnWriter.write(child);
+ if (data.getNodeType().equals(SchemaContext.NAME)) {
+ for (final DataContainerChild<? extends PathArgument, ?> child : data.getValue()) {
+ nnWriter.write(child);
+ }
+ } else {
+ nnWriter.write(data);
}
nnWriter.flush();
xmlWriter.flush();
}
}
+ private DataSchemaNode getSchemaNodeFromNamespace(final XmlElement element) throws NetconfDocumentedException {
+
+ try {
+ final Module module = schemaContext.getCurrentContext().findModuleByNamespaceAndRevision(new URI(element.getNamespace()), null);
+ DataSchemaNode dataSchemaNode = module.getDataChildByName(element.getName());
+ if (dataSchemaNode != null) {
+ return dataSchemaNode;
+ }
+ } catch (URISyntaxException e) {
+ LOG.debug("Error during parsing of element namespace, this should not happen since namespace of an xml " +
+ "element is valid and if the xml was parsed then the URI should be as well");
+ throw new IllegalArgumentException("Unable to parse element namespace, this should not happen since " +
+ "namespace of an xml element is valid and if the xml was parsed then the URI should be as well");
+ }
+ throw new NetconfDocumentedException("Unable to find node with namespace: " + element.getNamespace() + "in schema context: " + schemaContext.getCurrentContext().toString(),
+ ErrorType.application,
+ ErrorTag.unknown_namespace,
+ ErrorSeverity.error);
+ }
+
+ protected Element serializeNodeWithParentStructure(Document document, YangInstanceIdentifier dataRoot, NormalizedNode node) {
+ if (!dataRoot.equals(ROOT)) {
+ return (Element) transformNormalizedNode(document,
+ InstanceIdToNodes.serialize(schemaContext.getCurrentContext(), dataRoot, node),
+ ROOT);
+ }
+ return (Element) transformNormalizedNode(document, node, ROOT);
+ }
+
+ /**
+ *
+ * @param operationElement operation element
+ * @return if Filter is present and not empty returns Optional of the InstanceIdentifier to the read location in datastore.
+ * empty filter returns Optional.absent() which should equal an empty <data/> container in the response.
+ * if filter is not present we want to read the entire datastore - return ROOT.
+ * @throws NetconfDocumentedException
+ */
+ protected Optional<YangInstanceIdentifier> getDataRootFromFilter(XmlElement operationElement) throws NetconfDocumentedException {
+ Optional<XmlElement> filterElement = operationElement.getOnlyChildElementOptionally(FILTER);
+ if (filterElement.isPresent()) {
+ if (filterElement.get().getChildElements().size() == 0) {
+ return Optional.absent();
+ }
+ return Optional.of(getInstanceIdentifierFromFilter(filterElement.get()));
+ } else {
+ return Optional.of(ROOT);
+ }
+ }
+
+ @VisibleForTesting
+ protected YangInstanceIdentifier getInstanceIdentifierFromFilter(XmlElement filterElement) throws NetconfDocumentedException {
+
+ if (filterElement.getChildElements().size() != 1) {
+ throw new NetconfDocumentedException("Multiple filter roots not supported yet",
+ ErrorType.application, ErrorTag.operation_not_supported, ErrorSeverity.error);
+ }
+
+ XmlElement element = filterElement.getOnlyChildElement();
+ DataSchemaNode schemaNode = getSchemaNodeFromNamespace(element);
+
+ return getReadPointFromNode(YangInstanceIdentifier.builder().build(), filterToNormalizedNode(element, schemaNode));
+ }
+
+ private YangInstanceIdentifier getReadPointFromNode(final YangInstanceIdentifier pathArg, final NormalizedNode nNode) {
+ final YangInstanceIdentifier path = pathArg.node(nNode.getIdentifier());
+ if (nNode instanceof DataContainerNode) {
+ DataContainerNode node = (DataContainerNode) nNode;
+ if (node.getValue().size() == 1) {
+ return getReadPointFromNode(path, (NormalizedNode) Lists.newArrayList(node.getValue()).get(0));
+ }
+ }
+ return path;
+ }
+
+ private NormalizedNode filterToNormalizedNode(XmlElement element, DataSchemaNode schemaNode) throws NetconfDocumentedException {
+ DomToNormalizedNodeParserFactory parserFactory = DomToNormalizedNodeParserFactory
+ .getInstance(DomUtils.defaultValueCodecProvider(), schemaContext.getCurrentContext());
+
+ final NormalizedNode parsedNode;
+
+ if (schemaNode instanceof ContainerSchemaNode) {
+ parsedNode = parserFactory.getContainerNodeParser().parse(Collections.singletonList(element.getDomElement()), (ContainerSchemaNode) schemaNode);
+ } else if (schemaNode instanceof ListSchemaNode) {
+ parsedNode = parserFactory.getMapNodeParser().parse(Collections.singletonList(element.getDomElement()), (ListSchemaNode) schemaNode);
+ } else {
+ throw new NetconfDocumentedException("Schema node of the top level element is not an instance of container or list",
+ ErrorType.application, ErrorTag.unknown_element, ErrorSeverity.error);
+ }
+ return parsedNode;
+ }
+
protected static final class GetConfigExecution {
- private final Optional<Datastore> datastore;
+ private final Optional<Datastore> datastore;
public GetConfigExecution(final Optional<Datastore> datastore) {
this.datastore = datastore;
}
throw new NetconfDocumentedException("Get-config source attribute error: " + e.getMessage(), e.getErrorType(), e.getErrorTag(), e.getErrorSeverity(), e.getErrorInfo());
}
- // Add filter
-
return new GetConfigExecution(sourceDatastore);
}
xml.checkName(operationName);
xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
}
+
}
}
import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.mdsal.connector.CurrentSchemaContext;
import org.opendaylight.controller.netconf.mdsal.connector.TransactionProvider;
import org.opendaylight.controller.netconf.mdsal.connector.ops.Datastore;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.slf4j.Logger;
private static final Logger LOG = LoggerFactory.getLogger(Get.class);
private static final String OPERATION_NAME = "get";
-
private final TransactionProvider transactionProvider;
public Get(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext, final TransactionProvider transactionProvider) {
@Override
protected Element handleWithNoSubsequentOperations(Document document, XmlElement operationElement) throws NetconfDocumentedException {
- final YangInstanceIdentifier dataRoot = ROOT;
+ final Optional<YangInstanceIdentifier> dataRootOptional = getDataRootFromFilter(operationElement);
+ if (!dataRootOptional.isPresent()) {
+ return XmlUtil.createElement(document, XmlNetconfConstants.DATA_KEY, Optional.<String>absent());
+ }
+
+ final YangInstanceIdentifier dataRoot = dataRootOptional.get();
+
DOMDataReadWriteTransaction rwTx = getTransaction(Datastore.running);
try {
final Optional<NormalizedNode<?, ?>> normalizedNodeOptional = rwTx.read(LogicalDatastoreType.OPERATIONAL, dataRoot).checkedGet();
transactionProvider.abortRunningTransaction(rwTx);
- return (Element) transformNormalizedNode(document, normalizedNodeOptional.get(), dataRoot);
+
+ if (!normalizedNodeOptional.isPresent()) {
+ return XmlUtil.createElement(document, XmlNetconfConstants.DATA_KEY, Optional.<String>absent());
+ }
+
+ return serializeNodeWithParentStructure(document, dataRoot, normalizedNodeOptional.get());
} catch (ReadFailedException e) {
LOG.warn("Unable to read data: {}", dataRoot, e);
throw new IllegalStateException("Unable to read data " + dataRoot, e);
import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.mdsal.connector.CurrentSchemaContext;
import org.opendaylight.controller.netconf.mdsal.connector.TransactionProvider;
import org.opendaylight.controller.netconf.mdsal.connector.ops.Datastore;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.slf4j.Logger;
private static final Logger LOG = LoggerFactory.getLogger(GetConfig.class);
private static final String OPERATION_NAME = "get-config";
-
private final TransactionProvider transactionProvider;
public GetConfig(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext, final TransactionProvider transactionProvider) {
throw e;
}
- final YangInstanceIdentifier dataRoot = ROOT;
+ final Optional<YangInstanceIdentifier> dataRootOptional = getDataRootFromFilter(operationElement);
+ if (!dataRootOptional.isPresent()) {
+ return XmlUtil.createElement(document, XmlNetconfConstants.DATA_KEY, Optional.<String>absent());
+ }
+
+ final YangInstanceIdentifier dataRoot = dataRootOptional.get();
+
// Proper exception should be thrown
Preconditions.checkState(getConfigExecution.getDatastore().isPresent(), "Source element missing from request");
if (getConfigExecution.getDatastore().get() == Datastore.running) {
transactionProvider.abortRunningTransaction(rwTx);
}
- return (Element) transformNormalizedNode(document, normalizedNodeOptional.get(), dataRoot);
+
+ if (!normalizedNodeOptional.isPresent()) {
+ return XmlUtil.createElement(document, XmlNetconfConstants.DATA_KEY, Optional.<String>absent());
+ }
+
+ return serializeNodeWithParentStructure(document, dataRoot, normalizedNodeOptional.get());
} catch (ReadFailedException e) {
LOG.warn("Unable to read data: {}", dataRoot, e);
throw new IllegalStateException("Unable to read data " + dataRoot, e);
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.concurrent.ExecutorService;
import org.opendaylight.controller.netconf.mdsal.connector.ops.get.Get;
import org.opendaylight.controller.netconf.mdsal.connector.ops.get.GetConfig;
import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
import org.opendaylight.controller.sal.core.spi.data.DOMStore;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.util.concurrent.SpecialExecutors;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
private static final String RPC_REPLY_ELEMENT = "rpc-reply";
private static final String DATA_ELEMENT = "data";
+ private static final String FILTER_NODE = "filter";
+ private static final String GET_CONFIG = "get-config";
+ private static final QName TOP = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "top");
+ private static final QName USERS = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "users");
+ private static final QName USER = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "user");
+ private static final QName MODULES = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "modules");
+ private static final QName AUGMENTED_CONTAINER = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "augmented-container");
+ private static final QName AUGMENTED_STRING_IN_CONT = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "identifier");
+ private static final QName CHOICE_NODE = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "choice-node");
+ private static final QName AUGMENTED_CASE = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "augmented-case");
+ private static final QName CHOICE_WRAPPER = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "choice-wrapper");
+ private static final QName INNER_CHOICE = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "inner-choice");
+ private static final QName INNER_CHOICE_TEXT = QName.create("urn:opendaylight:mdsal:mapping:test", "2015-02-26", "text");
+
+ private static final YangInstanceIdentifier AUGMENTED_CONTAINER_IN_MODULES =
+ YangInstanceIdentifier.builder().node(TOP).node(MODULES).build().node(new AugmentationIdentifier(Collections.singleton(AUGMENTED_CONTAINER)));
private static Document RPC_REPLY_OK = null;
private TransactionProvider transactionProvider = null;
-
@Before
public void setUp() throws Exception {
this.schemaContext = parseSchemas(getYangSchemas());
schemaContext.getModules();
- SchemaService schemaService = createSchemaService();
+ final SchemaService schemaService = createSchemaService();
final DOMStore operStore = InMemoryDOMDataStoreFactory.create("DOM-OPER", schemaService);
final DOMStore configStore = InMemoryDOMDataStoreFactory.create("DOM-CFG", schemaService);
ExecutorService listenableFutureExecutor = SpecialExecutors.newBlockingBoundedCachedThreadPool(
16, 16, "CommitFutures");
- ConcurrentDOMDataBroker cdb = new ConcurrentDOMDataBroker(datastores, listenableFutureExecutor);
+ final ConcurrentDOMDataBroker cdb = new ConcurrentDOMDataBroker(datastores, listenableFutureExecutor);
this.transactionProvider = new TransactionProvider(cdb, sessionIdForReporting);
this.currentSchemaContext = new CurrentSchemaContext(schemaService);
@Test
public void testEmptyDatastore() throws Exception {
-
- Document response = getConfigRunning();
- assertEmptyDatastore(response);
-
- response = getConfigCandidate();
- assertEmptyDatastore(response);
-
- response = get();
- assertEmptyDatastore(response);
-
+ assertEmptyDatastore(get());
+ assertEmptyDatastore(getConfigCandidate());
+ assertEmptyDatastore(getConfigRunning());
}
@Test
public void testEditRunning() throws Exception {
try {
- edit("messages/mapping/editConfig_running.xml");
+ edit("messages/mapping/editConfigs/editConfig_running.xml");
fail("Should have failed - edit config on running datastore is not supported");
} catch (NetconfDocumentedException e) {
assertTrue(e.getErrorSeverity() == ErrorSeverity.error);
@Test
public void testCandidateTransaction() throws Exception {
- verifyResponse(edit("messages/mapping/editConfig_merge_n1.xml"), RPC_REPLY_OK);
- verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfig_merge_n1_control.xml"));
+ verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_n1.xml"), RPC_REPLY_OK);
+ verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_n1_control.xml"));
assertEmptyDatastore(getConfigRunning());
verifyResponse(discardChanges(), RPC_REPLY_OK);
@Test
public void testEditWithCommit() throws Exception {
- verifyResponse(edit("messages/mapping/editConfig_merge_n1.xml"), RPC_REPLY_OK);
- verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfig_merge_n1_control.xml"));
+ verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_n1.xml"), RPC_REPLY_OK);
+ verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_n1_control.xml"));
verifyResponse(commit(), RPC_REPLY_OK);
- verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfig_merge_n1_control.xml"));
+ verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_n1_control.xml"));
deleteDatastore();
@Test
public void testMultipleEditsWithMerge() throws Exception {
- verifyResponse(edit("messages/mapping/editConfig_merge_multiple_1.xml"), RPC_REPLY_OK);
- verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfig_merge_multiple_control_1.xml"));
- verifyResponse(edit("messages/mapping/editConfig_merge_single_1.xml"), RPC_REPLY_OK);
- verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfig_merge_multiple_control_2.xml"));
+ verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_1.xml"), RPC_REPLY_OK);
+ verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_control_1.xml"));
+ verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_single_1.xml"), RPC_REPLY_OK);
+ verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_control_2.xml"));
assertEmptyDatastore(getConfigRunning());
verifyResponse(commit(), RPC_REPLY_OK);
- verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfig_merge_multiple_control_2.xml"));
+ verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_control_2.xml"));
deleteDatastore();
@Test
public void testMoreComplexEditConfigs() throws Exception {
- verifyResponse(edit("messages/mapping/editConfig_merge_multiple_1.xml"), RPC_REPLY_OK);
- verifyResponse(edit("messages/mapping/editConfig_merge_single_1.xml"), RPC_REPLY_OK);
+ verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_1.xml"), RPC_REPLY_OK);
+ verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_single_1.xml"), RPC_REPLY_OK);
- verifyResponse(edit("messages/mapping/editConfig_merge_multiple_2.xml"), RPC_REPLY_OK);
- verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfig_merge_multiple_after_more_complex_merge.xml"));
+ verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_2.xml"), RPC_REPLY_OK);
+ verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_after_more_complex_merge.xml"));
- verifyResponse(edit("messages/mapping/editConfig_merge_multiple_3.xml"), RPC_REPLY_OK);
- verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfig_merge_multiple_after_more_complex_merge_2.xml"));
+ verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_3.xml"), RPC_REPLY_OK);
+ verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_after_more_complex_merge_2.xml"));
- verifyResponse(edit("messages/mapping/editConfig_merge_multiple_4_replace.xml"), RPC_REPLY_OK);
- verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfig_merge_multiple_after_replace.xml"));
+ verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_multiple_4_replace.xml"), RPC_REPLY_OK);
+ verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_after_replace.xml"));
verifyResponse(commit(), RPC_REPLY_OK);
- verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfig_merge_multiple_after_replace.xml"));
+ verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_multiple_after_replace.xml"));
- verifyResponse(edit("messages/mapping/editConfig_replace_default.xml"), RPC_REPLY_OK);
- verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfig_replace_default_control.xml"));
+ verifyResponse(edit("messages/mapping/editConfigs/editConfig_replace_default.xml"), RPC_REPLY_OK);
+ verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_replace_default_control.xml"));
verifyResponse(commit(), RPC_REPLY_OK);
- verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfig_replace_default_control.xml"));
+ verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_replace_default_control.xml"));
deleteDatastore();
@Test
public void testEditWithCreate() throws Exception {
- verifyResponse(edit("messages/mapping/editConfig_create.xml"), RPC_REPLY_OK);
+ verifyResponse(edit("messages/mapping/editConfigs/editConfig_create.xml"), RPC_REPLY_OK);
verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfig_create_n1_control.xml"));
try {
- edit("messages/mapping/editConfig_create.xml");
+ edit("messages/mapping/editConfigs/editConfig_create.xml");
fail("Create should have failed - data already exists");
} catch (NetconfDocumentedException e) {
assertTrue(e.getErrorSeverity() == ErrorSeverity.error);
assertEmptyDatastore(getConfigRunning());
try {
- edit("messages/mapping/editConfig_delete-root.xml");
+ edit("messages/mapping/editConfigs/editConfig_delete-root.xml");
fail("Delete should have failed - data is missing");
} catch (NetconfDocumentedException e) {
assertTrue(e.getErrorSeverity() == ErrorSeverity.error);
@Test
public void testEditMissingDefaultOperation() throws Exception {
- verifyResponse(edit("messages/mapping/editConfig_merge_missing_default-operation_1.xml"), RPC_REPLY_OK);
- verifyResponse(edit("messages/mapping/editConfig_merge_missing_default-operation_2.xml"), RPC_REPLY_OK);
- verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfig_merge_missing_default-operation_control.xml"));
+ verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_missing_default-operation_1.xml"), RPC_REPLY_OK);
+ verifyResponse(edit("messages/mapping/editConfigs/editConfig_merge_missing_default-operation_2.xml"), RPC_REPLY_OK);
+ verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_missing_default-operation_control.xml"));
verifyResponse(commit(), RPC_REPLY_OK);
- verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfig_merge_missing_default-operation_control.xml"));
+ verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/editConfigs/editConfig_merge_missing_default-operation_control.xml"));
deleteDatastore();
}
+ @Test
+ public void testFiltering() throws Exception {
+
+ assertEmptyDatastore(getConfigCandidate());
+ assertEmptyDatastore(getConfigRunning());
+
+ verifyResponse(getConfigCandidate(), XmlFileLoader.xmlFileToDocument("messages/mapping/get-empty-response.xml"));
+ verifyResponse(getConfigRunning(), XmlFileLoader.xmlFileToDocument("messages/mapping/get-empty-response.xml"));
+ verifyResponse(getConfigWithFilter("messages/mapping/filters/get-filter-users.xml"),
+ XmlFileLoader.xmlFileToDocument("messages/mapping/get-empty-response.xml"));
+
+ verifyResponse(edit("messages/mapping/editConfigs/editConfig-filtering-setup.xml"), RPC_REPLY_OK);
+ verifyResponse(commit(), RPC_REPLY_OK);
+
+ verifyFilterIdentifier("messages/mapping/filters/get-filter-alluser.xml",
+ YangInstanceIdentifier.builder().node(TOP).node(USERS).node(USER).build());
+ verifyFilterIdentifier("messages/mapping/filters/get-filter-company-info.xml",
+ YangInstanceIdentifier.builder().node(TOP).node(USERS).node(USER).build());
+ verifyFilterIdentifier("messages/mapping/filters/get-filter-modules-and-admin.xml",
+ YangInstanceIdentifier.builder().node(TOP).build());
+ verifyFilterIdentifier("messages/mapping/filters/get-filter-only-names-types.xml",
+ YangInstanceIdentifier.builder().node(TOP).node(USERS).node(USER).build());
+ verifyFilterIdentifier("messages/mapping/filters/get-filter-specific-module-type-and-user.xml",
+ YangInstanceIdentifier.builder().node(TOP).build());
+ verifyFilterIdentifier("messages/mapping/filters/get-filter-superuser.xml",
+ YangInstanceIdentifier.builder().node(TOP).node(USERS).node(USER).build());
+ verifyFilterIdentifier("messages/mapping/filters/get-filter-users.xml",
+ YangInstanceIdentifier.builder().node(TOP).node(USERS).build());
+
+ YangInstanceIdentifier ident = YangInstanceIdentifier.
+ builder(AUGMENTED_CONTAINER_IN_MODULES).
+ node(AUGMENTED_CONTAINER).
+ node(AUGMENTED_STRING_IN_CONT).build();
+
+ verifyFilterIdentifier("messages/mapping/filters/get-filter-augmented-string.xml", ident);
+ verifyFilterIdentifier("messages/mapping/filters/get-filter-augmented-case.xml",
+ YangInstanceIdentifier.builder().node(TOP).node(CHOICE_NODE).node(AUGMENTED_CASE).build());
+
+ verifyResponse(getConfigWithFilter("messages/mapping/filters/get-filter-augmented-case.xml"),
+ XmlFileLoader.xmlFileToDocument("messages/mapping/filters/response-augmented-case.xml"));
+ verifyResponse(edit("messages/mapping/editConfigs/editConfig-filtering-setup2.xml"), RPC_REPLY_OK);
+ verifyResponse(commit(), RPC_REPLY_OK);
+
+ verifyFilterIdentifier("messages/mapping/filters/get-filter-augmented-case-inner-choice.xml",
+ YangInstanceIdentifier.builder().node(TOP).node(CHOICE_NODE).node(CHOICE_WRAPPER).build());
+ verifyFilterIdentifier("messages/mapping/filters/get-filter-augmented-case-inner-case.xml",
+ YangInstanceIdentifier.builder().node(TOP).node(CHOICE_NODE).node(CHOICE_WRAPPER).node(INNER_CHOICE).node(INNER_CHOICE_TEXT).build());
+
+ verifyResponse(getConfigWithFilter("messages/mapping/filters/get-filter-augmented-string.xml"),
+ XmlFileLoader.xmlFileToDocument("messages/mapping/filters/response-augmented-string.xml"));
+ verifyResponse(getConfigWithFilter("messages/mapping/filters/get-filter-augmented-case-inner-choice.xml"),
+ XmlFileLoader.xmlFileToDocument("messages/mapping/filters/response-augmented-case-inner-choice.xml"));
+ verifyResponse(getConfigWithFilter("messages/mapping/filters/get-filter-augmented-case-inner-case.xml"),
+ XmlFileLoader.xmlFileToDocument("messages/mapping/filters/response-augmented-case-inner-choice.xml"));
+
+ verifyResponse(edit("messages/mapping/editConfigs/editConfig_delete-top.xml"), RPC_REPLY_OK);
+ verifyResponse(commit(), RPC_REPLY_OK);
+
+ }
+
+ private void verifyFilterIdentifier(String resource, YangInstanceIdentifier identifier) throws Exception{
+ TestingGetConfig getConfig = new TestingGetConfig(sessionIdForReporting, currentSchemaContext, transactionProvider);
+ Document request = XmlFileLoader.xmlFileToDocument(resource);
+ YangInstanceIdentifier iid = getConfig.getInstanceIdentifierFromDocument(request);
+ assertTrue(iid.equals(identifier));
+ }
+
+ private class TestingGetConfig extends GetConfig{
+ public TestingGetConfig(String sessionId, CurrentSchemaContext schemaContext, TransactionProvider transactionProvider) {
+ super(sessionId, schemaContext, transactionProvider);
+ }
+
+ public YangInstanceIdentifier getInstanceIdentifierFromDocument(Document request) throws NetconfDocumentedException {
+ XmlElement filterElement = XmlElement.fromDomDocument(request).getOnlyChildElement(GET_CONFIG).getOnlyChildElement(FILTER_NODE);
+ return getInstanceIdentifierFromFilter(filterElement);
+ }
+ }
+
private void deleteDatastore() throws Exception{
- verifyResponse(edit("messages/mapping/editConfig_delete-root.xml"), RPC_REPLY_OK);
+ verifyResponse(edit("messages/mapping/editConfigs/editConfig_delete-root.xml"), RPC_REPLY_OK);
assertEmptyDatastore(getConfigCandidate());
verifyResponse(commit(), RPC_REPLY_OK);
return executeOperation(getConfig, "messages/mapping/getConfig_candidate.xml");
}
+ private Document getConfigWithFilter(String resource) throws NetconfDocumentedException, ParserConfigurationException, SAXException, IOException {
+ GetConfig getConfig = new GetConfig(sessionIdForReporting, currentSchemaContext, transactionProvider);
+ return executeOperation(getConfig, resource);
+ }
+
private Document lock() throws NetconfDocumentedException, ParserConfigurationException, SAXException, IOException {
Lock lock = new Lock(sessionIdForReporting);
return executeOperation(lock, "messages/mapping/lock.xml");
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <edit-config>
+ <target>
+ <candidate/>
+ </target>
+ <test-option>
+ set
+ </test-option>
+ <default-operation>merge</default-operation>
+ <config>
+ <top xmlns="urn:opendaylight:mdsal:mapping:test">
+ <users>
+ <user>
+ <name>root</name>
+ <type>superuser</type>
+ <full-name>rooty root</full-name>
+ <company-info>
+ <dept>1</dept>
+ <id>1</id>
+ </company-info>
+ </user>
+ <user>
+ <name>admin</name>
+ <type>superuser</type>
+ <full-name>johny admin</full-name>
+ <company-info>
+ <dept>2</dept>
+ <id>2</id>
+ </company-info>
+ </user>
+ <user>
+ <name>regular</name>
+ <type>user</type>
+ <full-name>burt regular</full-name>
+ <company-info>
+ <dept>3</dept>
+ <id>3</id>
+ </company-info>
+ </user>
+ </users>
+ <modules>
+ <augmented-container>
+ <identifier>augmented container</identifier>
+ </augmented-container>
+ <module>
+ <id>module1</id>
+ <type>type1</type>
+ <desc>module1-desc</desc>
+ </module>
+ <module>
+ <id>module2</id>
+ <type>type1</type>
+ <desc>module2-desc</desc>
+ </module>
+ <module>
+ <id>module3</id>
+ <type>unknown</type>
+ <desc>module3-desc</desc>
+ </module>
+ </modules>
+ <augmented-case>augmented case</augmented-case>
+ </top>
+ </config>
+ </edit-config>
+</rpc>
\ No newline at end of file
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <edit-config>
+ <target>
+ <candidate/>
+ </target>
+ <test-option>
+ set
+ </test-option>
+ <default-operation>merge</default-operation>
+ <config>
+ <top xmlns="urn:opendaylight:mdsal:mapping:test">
+ <choice-wrapper>
+ <text>augmented nested choice text1</text>
+ </choice-wrapper>
+ </top>
+ </config>
+ </edit-config>
+</rpc>
\ No newline at end of file
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<edit-config>
+ <target>
+ <candidate/>
+ </target>
+ <test-option>
+ set
+ </test-option>
+ <default-operation>none</default-operation>
+ <config>
+ <top xmlns="urn:opendaylight:mdsal:mapping:test" xmlns:a="urn:ietf:params:xml:ns:netconf:base:1.0" a:operation="delete">
+ </top>
+ </config>
+</edit-config>
+</rpc>
\ No newline at end of file
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc id="a" a="64" xmlnx="a:b:c:d" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
+ <get-config>
+ <filter type="subtree">
+ </filter>
+ <source>
+ <running/>
+ </source>
+ </get-config>
+</rpc>
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc id="a" a="64" xmlnx="a:b:c:d" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
+ <get-config>
+ <filter type="subtree">
+ <top xmlns="urn:opendaylight:mdsal:mapping:test">
+ <users>
+ <user/>
+ </users>
+ </top>
+ </filter>
+ <source>
+ <running/>
+ </source>
+ </get-config>
+</rpc>
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc id="a" a="64" xmlnx="a:b:c:d" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
+ <get-config>
+ <filter type="subtree">
+ <top xmlns="urn:opendaylight:mdsal:mapping:test">
+ <choice-wrapper>
+ <text/>
+ </choice-wrapper>
+ </top>
+ </filter>
+ <source>
+ <running/>
+ </source>
+ </get-config>
+</rpc>
+
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc id="a" a="64" xmlnx="a:b:c:d" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
+ <get-config>
+ <filter type="subtree">
+ <top xmlns="urn:opendaylight:mdsal:mapping:test">
+ <choice-wrapper/>
+ </top>
+ </filter>
+ <source>
+ <running/>
+ </source>
+ </get-config>
+</rpc>
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc id="a" a="64" xmlnx="a:b:c:d" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
+ <get-config>
+ <filter type="subtree">
+ <top xmlns="urn:opendaylight:mdsal:mapping:test">
+ <augmented-case/>
+ </top>
+ </filter>
+ <source>
+ <running/>
+ </source>
+ </get-config>
+</rpc>
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc id="a" a="64" xmlnx="a:b:c:d" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
+ <get-config>
+ <filter type="subtree">
+ <top xmlns="urn:opendaylight:mdsal:mapping:test">
+ <modules>
+ <augmented-container>
+ <identifier/>
+ </augmented-container>
+ </modules>
+ </top>
+ </filter>
+ <source>
+ <running/>
+ </source>
+ </get-config>
+</rpc>
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc id="a" a="64" xmlnx="a:b:c:d" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
+ <get-config>
+ <filter type="subtree">
+ <top xmlns="urn:opendaylight:mdsal:mapping:test">
+ <users>
+ <user>
+ <name>root</name>
+ <company-info/>
+ </user>
+ <user>
+ <name>admin</name>
+ <company-info>
+ <id/>
+ </company-info>
+ </user>
+ <user>
+ <name>regular</name>
+ <company-info>
+ <dept/>
+ </company-info>
+ </user>
+ </users>
+ </top>
+ </filter>
+ <source>
+ <running/>
+ </source>
+ </get-config>
+</rpc>
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc id="a" a="64" xmlnx="a:b:c:d" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
+ <get-config>
+ <filter type="subtree">
+ <top xmlns="urn:opendaylight:mdsal:mapping:test">
+ <users>
+ <user>
+ <name>admin</name>
+ </user>
+ </users>
+ <modules/>
+ </top>
+ </filter>
+ <source>
+ <running/>
+ </source>
+ </get-config>
+</rpc>
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc id="a" a="64" xmlnx="a:b:c:d" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
+ <get-config>
+ <filter type="subtree">
+ <top xmlns="urn:opendaylight:mdsal:mapping:test">
+ <users>
+ <user>
+ <name/>
+ <type/>
+ </user>
+ </users>
+ </top>
+ </filter>
+ <source>
+ <running/>
+ </source>
+ </get-config>
+</rpc>
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc id="a" a="64" xmlnx="a:b:c:d" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
+ <get-config>
+ <filter type="subtree">
+ <top xmlns="urn:opendaylight:mdsal:mapping:test">
+ <users>
+ <user>
+ <type>superuser</type>
+ </user>
+ </users>
+ <modules>
+ <module>
+ <type>type1</type>
+ </module>
+ </modules>
+ </top>
+ </filter>
+ <source>
+ <running/>
+ </source>
+ </get-config>
+</rpc>
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc id="a" a="64" xmlnx="a:b:c:d" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
+ <get-config>
+ <filter type="subtree">
+ <top xmlns="urn:opendaylight:mdsal:mapping:test">
+ <users>
+ <user>
+ <type>superuser</type>
+ </user>
+ </users>
+ </top>
+ </filter>
+ <source>
+ <running/>
+ </source>
+ </get-config>
+</rpc>
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc id="a" a="64" xmlnx="a:b:c:d" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
+ <get-config>
+ <filter type="subtree">
+ <top xmlns="urn:opendaylight:mdsal:mapping:test">
+ <users/>
+ </top>
+ </filter>
+ <source>
+ <running/>
+ </source>
+ </get-config>
+</rpc>
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" a="64" id="a" message-id="101" xmlnx="a:b:c:d">
+ <data>
+ <top xmlns="urn:opendaylight:mdsal:mapping:test">
+ <choice-wrapper>
+ <text>augmented nested choice text1</text>
+ </choice-wrapper>
+ </top>
+ </data>
+</rpc-reply>
+
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" a="64" id="a" message-id="101" xmlnx="a:b:c:d">
+ <data>
+ <top xmlns="urn:opendaylight:mdsal:mapping:test">
+ <augmented-case>augmented case</augmented-case>
+ </top>
+ </data>
+</rpc-reply>
+
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" a="64" id="a" message-id="101" xmlnx="a:b:c:d">
+ <data>
+ <top xmlns="urn:opendaylight:mdsal:mapping:test">
+ <modules>
+ <augmented-container>
+ <identifier>augmented container</identifier>
+ </augmented-container>
+ </modules>
+ </top>
+ </data>
+</rpc-reply>
+
--- /dev/null
+<!--
+ ~ Copyright (c) 2015 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
+ -->
+
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" a="64" id="a" message-id="101" xmlnx="a:b:c:d">
+ <data/>
+</rpc-reply>
\ No newline at end of file
}
}
}
+
+ container top {
+
+ container users {
+
+ list user {
+
+ leaf name {
+ type string;
+ }
+
+ leaf type {
+ type string;
+ }
+
+ leaf full-name {
+ type string;
+ }
+
+ container company-info {
+
+ leaf dept {
+ type string;
+ }
+
+ leaf id {
+ type string;
+ }
+ }
+ }
+ }
+
+ container modules {
+
+ list module {
+
+ leaf id {
+ type string;
+ }
+
+ leaf type {
+ type string;
+ }
+
+ leaf desc {
+ type string;
+ }
+ }
+ }
+
+ choice choice-node {
+ case a {
+ leaf text {
+ type string;
+ }
+ }
+
+ case b {
+ container text-cont {
+ leaf text {
+ type string;
+ }
+ }
+ }
+ }
+
+ } //top
+
+ augment "/map:top/map:choice-node" {
+ case c {
+ leaf augmented-case {
+ type string;
+ }
+ }
+
+ case d {
+ container choice-wrapper {
+ choice inner-choice {
+ case ia {
+ leaf text {
+ type string;
+ }
+ }
+
+ case ib {
+ leaf text2 {
+ type string;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ augment "/map:top/map:modules/" {
+ container augmented-container{
+ leaf identifier {
+ type string;
+ }
+ }
+ }
}
\ No newline at end of file
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity1;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity2;
-import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
-import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
}
@Override
- protected CodecRegistry getCodecRegistry() {
- final IdentityCodec<?> codec = mock(IdentityCodec.class);
- doReturn(TestIdentity1.class).when(codec).deserialize(TestIdentity1.QNAME);
- doReturn(TestIdentity2.class).when(codec).deserialize(TestIdentity2.QNAME);
-
- final CodecRegistry ret = super.getCodecRegistry();
- doReturn(codec).when(ret).getIdentityCodec();
+ protected BindingRuntimeContext getBindingRuntimeContext() {
+ final BindingRuntimeContext ret = super.getBindingRuntimeContext();
+ doReturn(TestIdentity1.class).when(ret).getIdentityClass(TestIdentity1.QNAME);
+ doReturn(TestIdentity2.class).when(ret).getIdentityClass(TestIdentity2.QNAME);
return ret;
}
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.api.NetconfSessionListener;
import org.opendaylight.controller.netconf.api.NetconfSessionPreferences;
+import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.nettyutil.handler.FramingMechanismHandlerFactory;
import org.opendaylight.controller.netconf.nettyutil.handler.NetconfChunkAggregator;
import org.opendaylight.controller.netconf.nettyutil.handler.NetconfMessageToXMLEncoder;
}
private boolean containsBase11Capability(final Document doc) {
- final NodeList nList = doc.getElementsByTagName("capability");
+ final NodeList nList = doc.getElementsByTagName(XmlNetconfConstants.CAPABILITY);
for (int i = 0; i < nList.getLength(); i++) {
- if (nList.item(i).getTextContent().contains("base:1.1")) {
+ if (nList.item(i).getTextContent().contains(XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_1)) {
return true;
}
}
}
ret.setOutputProperty(OutputKeys.INDENT, "yes");
- ret.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+ ret.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
return ret;
};
package org.opendaylight.controller.netconf.notifications.impl.ops;
-import static org.junit.Assert.assertTrue;
-
import com.google.common.collect.Lists;
import java.io.IOException;
-import org.custommonkey.xmlunit.Diff;
-import org.custommonkey.xmlunit.XMLUnit;
import org.junit.Test;
-import org.opendaylight.controller.netconf.notifications.impl.ops.Get;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.StreamNameType;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netmod.notification.rev080714.netconf.Streams;
final Document response = getBlankResponse();
Get.serializeStreamsSubtree(response, streams);
- final Diff diff = XMLUnit.compareXML(XmlUtil.toString(response),
+ NotificationsTransformUtilTest.compareXml(XmlUtil.toString(response),
"<rpc-reply message-id=\"101\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n" +
- "<data>\n" +
- "<netconf xmlns=\"urn:ietf:params:xml:ns:netmod:notification\">\n" +
- "<streams>\n" +
- "<stream>\n" +
- "<name>base</name>\n" +
- "<description>description</description>\n" +
- "<replaySupport>false</replaySupport>\n" +
- "</stream>\n" +
- "</streams>\n" +
- "</netconf>\n" +
- "</data>\n" +
- "</rpc-reply>\n");
-
- assertTrue(diff.toString(), diff.identical());
+ "<data>\n" +
+ "<netconf xmlns=\"urn:ietf:params:xml:ns:netmod:notification\">\n" +
+ "<streams>\n" +
+ "<stream>\n" +
+ "<name>base</name>\n" +
+ "<description>description</description>\n" +
+ "<replaySupport>false</replaySupport>\n" +
+ "</stream>\n" +
+ "</streams>\n" +
+ "</netconf>\n" +
+ "</data>\n" +
+ "</rpc-reply>\n");
}
private Document getBlankResponse() throws IOException, SAXException {
package org.opendaylight.controller.netconf.notifications.impl.ops;
+import static org.junit.Assert.assertTrue;
+
import com.google.common.collect.Lists;
+import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
+import org.custommonkey.xmlunit.DetailedDiff;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.XMLUnit;
+import org.custommonkey.xmlunit.examples.RecursiveElementNameAndTextQualifier;
import org.junit.Test;
import org.opendaylight.controller.netconf.notifications.NetconfNotification;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.NetconfCapabilityChange;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.NetconfCapabilityChangeBuilder;
+import org.xml.sax.SAXException;
public class NotificationsTransformUtilTest {
private static final Date DATE = new Date();
private static final String innerNotification = "<netconf-capability-change xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-notifications\">" +
- "<deleted-capability>uri3</deleted-capability>" +
"<deleted-capability>uri4</deleted-capability>" +
+ "<deleted-capability>uri3</deleted-capability>" +
"<added-capability>uri1</added-capability>" +
"</netconf-capability-change>";
final NetconfCapabilityChangeBuilder netconfCapabilityChangeBuilder = new NetconfCapabilityChangeBuilder();
netconfCapabilityChangeBuilder.setAddedCapability(Lists.newArrayList(new Uri("uri1"), new Uri("uri1")));
- netconfCapabilityChangeBuilder.setDeletedCapability(Lists.newArrayList(new Uri("uri3"), new Uri("uri4")));
+ netconfCapabilityChangeBuilder.setDeletedCapability(Lists.newArrayList(new Uri("uri4"), new Uri("uri3")));
final NetconfCapabilityChange capabilityChange = netconfCapabilityChangeBuilder.build();
final NetconfNotification transform = NotificationsTransformUtil.transform(capabilityChange, DATE);
final String serialized = XmlUtil.toString(transform.getDocument());
+ compareXml(expectedNotification, serialized);
+ }
+
+ static void compareXml(final String expected, final String actual) throws SAXException, IOException {
XMLUnit.setIgnoreWhitespace(true);
- final Diff diff = XMLUnit.compareXML(expectedNotification, serialized);
- // FIXME the diff is unreliable, provide a proper comparison of XML
-// assertTrue(diff.toString(), diff.similar());
+ final Diff diff = new Diff(expected, actual);
+ final DetailedDiff detailedDiff = new DetailedDiff(diff);
+ detailedDiff.overrideElementQualifier(new RecursiveElementNameAndTextQualifier());
+ assertTrue(detailedDiff.toString(), detailedDiff.similar());
}
@Test
final NetconfNotification netconfNotification = new NetconfNotification(XmlUtil.readXmlToDocument(innerNotification), DATE);
XMLUnit.setIgnoreWhitespace(true);
- final Diff diff = XMLUnit.compareXML(expectedNotification, netconfNotification.toString());
- // FIXME the diff is unreliable, provide a proper comparison of XML
-// assertTrue(diff.toString(), diff.similar());
+ compareXml(expectedNotification, netconfNotification.toString());
}
}
\ No newline at end of file
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
import org.apache.commons.io.FilenameUtils;
import org.apache.sshd.common.util.ThreadUtils;
import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider;
private static final java.lang.String ALGORITHM = "RSA";
private static final int KEY_SIZE = 4096;
public static final int POOL_SIZE = 8;
- private static final int DEFAULT_IDLE_TIMEOUT = (int) TimeUnit.MINUTES.toMillis(20);
+ private static final int DEFAULT_IDLE_TIMEOUT = Integer.MAX_VALUE;
private ScheduledExecutorService minaTimerExecutor;
private NioEventLoopGroup clientGroup;