public static final String SERVICE_QNAME_KEY = "serviceQName";
public static final String INSTANCE_NAME_KEY = "instanceName";
public static final String TYPE_KEY = ConfigRegistryConstants.TYPE_KEY;
- public static final String TYPE_CONFIG_REGISTRY = ConfigRegistryConstants.TYPE_CONFIG_REGISTRY;
public static final String TYPE_CONFIG_TRANSACTION = "ConfigTransaction";
public static final String TYPE_MODULE = "Module";
public static final String TYPE_SERVICE_REFERENCE = "ServiceReference";
public static final String TRANSACTION_NAME_KEY = "TransactionName";
public static final String REF_NAME_KEY = "RefName";
private static final String REPLACED_QUOTATION_MARK = "\\?";
+ public static final String ON_WILDCARD = "*";
public static ObjectName createON(String on) {
try {
public static ObjectName createModulePattern(String moduleName,
String instanceName) {
- if (moduleName == null) {
- moduleName = "*";
- }
- if (instanceName == null) {
- instanceName = "*";
- }
+ moduleName = moduleName == null ? ON_WILDCARD : moduleName;
+ instanceName = instanceName == null ? ON_WILDCARD : instanceName;
+
// do not return object names containing transaction name
ObjectName namePattern = ObjectNameUtil
.createON(ObjectNameUtil.ON_DOMAIN + ":"
public static ObjectName createModulePattern(String ifcName,
String instanceName, String transactionName) {
+ ifcName = ifcName == null ? ON_WILDCARD : ifcName;
+ instanceName = instanceName == null ? ON_WILDCARD : instanceName;
+ transactionName = transactionName == null ? ON_WILDCARD : transactionName;
+
return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN
+ ":type=Module," + ObjectNameUtil.MODULE_FACTORY_NAME_KEY
+ "=" + ifcName + "," + ObjectNameUtil.INSTANCE_NAME_KEY + "="
public static ObjectName createRuntimeBeanPattern(String moduleName,
String instanceName) {
+ moduleName = moduleName == null ? ON_WILDCARD : moduleName;
+ instanceName = instanceName == null ? ON_WILDCARD : instanceName;
+
return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN + ":"
+ ObjectNameUtil.TYPE_KEY + "="
+ ObjectNameUtil.TYPE_RUNTIME_BEAN + ","
--- /dev/null
+package org.opendaylight.controller.config.api;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.collect.Lists;
+import org.junit.Before;
+import org.junit.Test;
+
+public class JmxAttributeValidationExceptionTest {
+
+ private JmxAttribute jmxAttribute = new JmxAttribute("attr1");
+ private JmxAttribute jmxAttribute2 = new JmxAttribute("attr2");
+
+ @Before
+ public void setUp() throws Exception {
+
+ }
+
+ @Test
+ public void testGetAttributeNames() throws Exception {
+
+ }
+
+ @Test
+ public void testCheckNotNull() throws Exception {
+ try {
+ JmxAttributeValidationException.checkNotNull(false, "message", jmxAttribute);
+ } catch (JmxAttributeValidationException e) {
+ assertJmxEx(e, jmxAttribute.getAttributeName() + " " + "message", jmxAttribute);
+ }
+ }
+
+ @Test
+ public void testWrap() throws Exception {
+
+ }
+
+ @Test
+ public void testCheckCondition() throws Exception {
+ try {
+ JmxAttributeValidationException.checkCondition(false, "message", jmxAttribute);
+ } catch (JmxAttributeValidationException e) {
+ assertJmxEx(e, jmxAttribute.getAttributeName() + " " + "message", jmxAttribute);
+ }
+ }
+
+ private void assertJmxEx(JmxAttributeValidationException e, String message, JmxAttribute... attrNames) {
+ assertEquals(message, e.getMessage());
+ assertEquals(Lists.newArrayList(attrNames), e.getAttributeNames());
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.config.api;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import com.google.common.collect.Lists;
+import java.util.Map;
+import org.junit.Test;
+
+public class ValidationExceptionTest {
+
+ private String instance = "instance";
+ private final ModuleIdentifier mi = new ModuleIdentifier("module", instance);
+ private String instance2 = "instance2";
+ private final ModuleIdentifier mi2 = new ModuleIdentifier("module", instance2);
+ private final String message = "ex message";
+ private final Exception e = new IllegalStateException(message);
+
+ @Test
+ public void testCreateFromCollectedValidationExceptions() throws Exception {
+ ValidationException single = ValidationException.createForSingleException(mi, e);
+ ValidationException single2 = ValidationException.createForSingleException(mi2, e);
+
+ ValidationException collected = ValidationException.createFromCollectedValidationExceptions(Lists.newArrayList(single, single2));
+
+ Map<String, Map<String, ValidationException.ExceptionMessageWithStackTrace>> failedMap = collected.getFailedValidations();
+ assertEquals(1, failedMap.size());
+ assertTrue(failedMap.containsKey("module"));
+
+ Map<String, ValidationException.ExceptionMessageWithStackTrace> failedModule = failedMap.get("module");
+ assertEquals(2, failedModule.size());
+ assertTrue(failedModule.containsKey(instance));
+ assertEquals(message, failedModule.get(instance).getMessage());
+ assertEquals(message, failedModule.get(instance2).getMessage());
+ assertEquals(failedModule.get(instance), failedModule.get(instance2));
+ }
+
+ @Test
+ public void testCreateFromCollectedValidationExceptionsWithDuplicate() throws Exception {
+ ValidationException single = ValidationException.createForSingleException(mi, e);
+ ValidationException single2 = ValidationException.createForSingleException(mi, e);
+ try {
+ ValidationException.createFromCollectedValidationExceptions(Lists.newArrayList(single, single2));
+ } catch (IllegalArgumentException ex) {
+ // Duplicate exception
+ assertThat(ex.getMessage(), containsString("Cannot merge"));
+ return;
+ }
+ fail("Duplicate exception should have failed");
+ }
+}
\ 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.config.api.jmx;
+
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.Maps;
+import java.util.Map;
+import javax.management.ObjectName;
+import junit.framework.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+
+public class ObjectNameUtilTest {
+
+ private String moduleName;
+ private String instanceName;
+
+ @Before
+ public void setUp() throws Exception {
+ moduleName = "module";
+ instanceName = "instance";
+ }
+
+ @Test
+ public void testServiceReferenceName() throws Exception {
+ String serviceQName = "(namespace?revision=r)qname";
+ String refName = "refName";
+ String transaction = "transaction";
+
+ ObjectName serviceReferenceON = ObjectNameUtil.createTransactionServiceON(transaction, serviceQName, refName);
+ ObjectNameUtil.checkType(serviceReferenceON, ObjectNameUtil.TYPE_SERVICE_REFERENCE);
+
+ assertFalse(serviceReferenceON.isPattern());
+ assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
+ assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
+ assertEquals(transaction, ObjectNameUtil.getTransactionName(serviceReferenceON));
+ assertEquals(ObjectNameUtil.createReadOnlyServiceON(serviceQName, refName), ObjectNameUtil.withoutTransactionName(serviceReferenceON));
+
+ serviceReferenceON = ObjectNameUtil.createReadOnlyServiceON(serviceQName, refName);
+ assertFalse(serviceReferenceON.isPattern());
+ assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
+ assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
+ assertEquals(null, ObjectNameUtil.getTransactionName(serviceReferenceON));
+ }
+
+ @Test
+ public void testModuleName() throws Exception {
+ String txName = "transaction";
+
+ ObjectName on = ObjectNameUtil.createTransactionModuleON(txName, moduleName, instanceName);
+
+ ObjectNameUtil.checkDomain(on);
+ ObjectNameUtil.checkType(on, ObjectNameUtil.TYPE_MODULE);
+
+ assertFalse(on.isPattern());
+ assertEquals(moduleName, ObjectNameUtil.getFactoryName(on));
+ assertEquals(instanceName, ObjectNameUtil.getInstanceName(on));
+ assertEquals(txName, ObjectNameUtil.getTransactionName(on));
+ assertEquals(4, ObjectNameUtil.getAdditionalProperties(on).size());
+
+ ObjectName withoutTx = ObjectNameUtil.withoutTransactionName(on);
+ assertEquals(ObjectNameUtil.createReadOnlyModuleON(moduleName, instanceName), withoutTx);
+ assertEquals(moduleName, ObjectNameUtil.getFactoryName(withoutTx));
+ assertEquals(instanceName, ObjectNameUtil.getInstanceName(withoutTx));
+ assertEquals(null, ObjectNameUtil.getTransactionName(withoutTx));
+ assertEquals(on, ObjectNameUtil.withTransactionName(withoutTx, txName));
+
+ ObjectName pattern = ObjectNameUtil.createModulePattern(moduleName, null);
+ assertPattern(withoutTx, pattern);
+ pattern = ObjectNameUtil.createModulePattern(moduleName, null, txName);
+ assertPattern(on, pattern);
+ }
+
+ private void assertPattern(ObjectName test, ObjectName pattern) {
+ assertTrue(pattern.isPattern());
+ assertTrue(pattern.apply(test));
+ }
+
+ @Test
+ public void testRuntimeBeanName() throws Exception {
+
+ Map<String, String> properties = Maps.newHashMap();
+ properties.put("p1", "value");
+ properties.put("p2", "value2");
+
+ ObjectName on = ObjectNameUtil.createRuntimeBeanName(moduleName, instanceName, properties);
+
+ ObjectNameUtil.checkDomain(on);
+ ObjectNameUtil.checkTypeOneOf(on, ObjectNameUtil.TYPE_RUNTIME_BEAN);
+
+ assertFalse(on.isPattern());
+ assertEquals(moduleName, ObjectNameUtil.getFactoryName(on));
+ assertEquals(instanceName, ObjectNameUtil.getInstanceName(on));
+ assertEquals(2, ObjectNameUtil.getAdditionalPropertiesOfRuntimeBeanName(on).size());
+ assertTrue(ObjectNameUtil.getAdditionalPropertiesOfRuntimeBeanName(on).containsKey("p1"));
+ assertEquals("value", ObjectNameUtil.getAdditionalPropertiesOfRuntimeBeanName(on).get("p1"));
+ assertTrue(ObjectNameUtil.getAdditionalProperties(on).containsKey("p2"));
+ assertEquals("value2", ObjectNameUtil.getAdditionalPropertiesOfRuntimeBeanName(on).get("p2"));
+
+ ObjectName pattern = ObjectNameUtil.createRuntimeBeanPattern(null, instanceName);
+ assertPattern(on, pattern);
+ }
+
+ @Test
+ public void testModuleIdentifier() throws Exception {
+ ModuleIdentifier mi = new ModuleIdentifier(moduleName, instanceName);
+ ObjectName on = ObjectNameUtil.createReadOnlyModuleON(mi);
+ assertEquals(moduleName, ObjectNameUtil.getFactoryName(on));
+ assertEquals(instanceName, ObjectNameUtil.getInstanceName(on));
+
+ assertEquals(mi, ObjectNameUtil.fromON(on, ObjectNameUtil.TYPE_MODULE));
+ }
+
+ @Test
+ public void testChecks() throws Exception {
+ final ObjectName on = ObjectNameUtil.createON("customDomain", ObjectNameUtil.TYPE_KEY, ObjectNameUtil.TYPE_MODULE);
+
+ assertFailure(new Runnable() {
+ @Override
+ public void run() {
+ ObjectNameUtil.checkTypeOneOf(on, ObjectNameUtil.TYPE_RUNTIME_BEAN, ObjectNameUtil.TYPE_CONFIG_TRANSACTION);
+ }
+ }, IllegalArgumentException.class);
+
+ assertFailure(new Runnable() {
+ @Override
+ public void run() {
+ ObjectNameUtil.checkType(on, ObjectNameUtil.TYPE_RUNTIME_BEAN);
+ }
+ }, IllegalArgumentException.class);
+
+ assertFailure(new Runnable() {
+ @Override
+ public void run() {
+ ObjectNameUtil.checkDomain(on);
+ }
+ }, IllegalArgumentException.class);
+ }
+
+ private void assertFailure(Runnable test, Class<? extends Exception> ex) {
+ try {
+ test.run();
+ } catch(Exception e) {
+ Assert.assertTrue("Failed with wrong exception: " + Throwables.getStackTraceAsString(e),
+ e.getClass().isAssignableFrom(ex));
+ return;
+ }
+
+ fail(test + " should have failed on " + ex);
+ }
+}
*/
package org.opendaylight.controller.config.manager.impl.osgi;
+import com.google.common.annotations.VisibleForTesting;
+import javax.management.ObjectName;
import org.opendaylight.controller.config.api.ConflictingVersionException;
import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.api.jmx.CommitStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.management.ObjectName;
-
/**
* Every time factory is added or removed, blank transaction is triggered to handle
* {@link org.opendaylight.controller.config.spi.ModuleFactory#getDefaultModules(org.opendaylight.controller.config.api.DependencyResolverFactory, org.osgi.framework.BundleContext)}
public class BlankTransactionServiceTracker implements ServiceTrackerCustomizer<ModuleFactory, Object> {
private static final Logger logger = LoggerFactory.getLogger(BlankTransactionServiceTracker.class);
- private final ConfigRegistryImpl configRegistry;
+ public static final int DEFAULT_MAX_ATTEMPTS = 10;
- public BlankTransactionServiceTracker(ConfigRegistryImpl configRegistry) {
- this.configRegistry = configRegistry;
+ private final BlankTransaction blankTransaction;
+ private int maxAttempts;
+
+ public BlankTransactionServiceTracker(final ConfigRegistryImpl configRegistry) {
+ this(new BlankTransaction() {
+ @Override
+ public CommitStatus hit() throws ValidationException, ConflictingVersionException {
+ ObjectName tx = configRegistry.beginConfig(true);
+ return configRegistry.commitConfig(tx);
+ }
+ });
+ }
+
+ public BlankTransactionServiceTracker(final BlankTransaction blankTransaction) {
+ this(blankTransaction, DEFAULT_MAX_ATTEMPTS);
+ }
+
+ @VisibleForTesting
+ BlankTransactionServiceTracker(final BlankTransaction blankTx, final int maxAttempts) {
+ this.blankTransaction = blankTx;
+ this.maxAttempts = maxAttempts;
}
@Override
synchronized void blankTransaction() {
// race condition check: config-persister might push new configuration while server is starting up.
ConflictingVersionException lastException = null;
- int maxAttempts = 10;
for (int i = 0; i < maxAttempts; i++) {
try {
// create transaction
- boolean blankTransaction = true;
- ObjectName tx = configRegistry.beginConfig(blankTransaction);
- CommitStatus commitStatus = configRegistry.commitConfig(tx);
+ CommitStatus commitStatus = blankTransaction.hit();
logger.debug("Committed blank transaction with status {}", commitStatus);
return;
} catch (ConflictingVersionException e) {
public void removedService(ServiceReference<ModuleFactory> moduleFactoryServiceReference, Object o) {
blankTransaction();
}
+
+ @VisibleForTesting
+ static interface BlankTransaction {
+ CommitStatus hit() throws ValidationException, ConflictingVersionException;
+ }
}
import static java.lang.String.format;
+import com.google.common.annotations.VisibleForTesting;
import java.io.InputStream;
import java.net.URL;
import java.util.List;
blankTransactionServiceTracker.blankTransaction();
}
- // TODO:test
- private static ServiceRegistration<?> registerFactory(String factoryClassName, Bundle bundle) {
+ @VisibleForTesting
+ protected static ServiceRegistration<?> registerFactory(String factoryClassName, Bundle bundle) {
String errorMessage;
+ Exception ex = null;
try {
Class<?> clazz = bundle.loadClass(factoryClassName);
if (ModuleFactory.class.isAssignableFrom(clazz)) {
errorMessage = logMessage(
"Could not instantiate {} in bundle {}, reason {}",
factoryClassName, bundle, e);
+ ex = e;
} catch (IllegalAccessException e) {
errorMessage = logMessage(
- "Illegal access during instatiation of class {} in bundle {}, reason {}",
+ "Illegal access during instantiation of class {} in bundle {}, reason {}",
factoryClassName, bundle, e);
+ ex = e;
}
} else {
errorMessage = logMessage(
}
} catch (ClassNotFoundException e) {
errorMessage = logMessage(
- "Could not find class {} in bunde {}, reason {}",
+ "Could not find class {} in bundle {}, reason {}",
factoryClassName, bundle, e);
+ ex = e;
}
- throw new IllegalStateException(errorMessage);
+
+ throw ex == null ? new IllegalStateException(errorMessage) : new IllegalStateException(errorMessage, ex);
}
public static String logMessage(String slfMessage, Object... params) {
*/
public static Set<Class<?>> getOsgiRegistrationTypes(
Class<? extends Module> configBeanClass) {
- // TODO test with service interface hierarchy
Set<Class<?>> serviceInterfaces = getServiceInterfaces(configBeanClass);
Set<Class<?>> result = new HashSet<>();
for (Class<?> clazz : serviceInterfaces) {
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.opendaylight.yangtools.yang.binding.annotations.ModuleQName;
+import org.opendaylight.yangtools.yang.common.QName;
import org.osgi.framework.BundleContext;
import java.util.HashSet;
inspected = inspected.getSuperclass();
}
if (annotation != null) {
- // FIXME
- String qName = "(" + annotation.namespace() + "?revision=" + annotation.revision() + ")" + annotation.name();
- result.add(qName);
+ result.add(QName.create(annotation.namespace(), annotation.revision(), annotation.name()).toString());
}
}
return result;
package org.opendaylight.controller.config.manager.impl.util;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.util.tracker.BundleTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ListIterator;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
public class OsgiRegistrationUtil {
private static final Logger logger = LoggerFactory.getLogger(OsgiRegistrationUtil.class);
--- /dev/null
+package org.opendaylight.controller.config.manager.impl.osgi;
+
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.Assert.fail;
+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.util.Collections;
+import javax.management.ObjectName;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.ServiceReference;
+
+public class BlankTransactionServiceTrackerTest {
+
+ @Mock
+ private BlankTransactionServiceTracker.BlankTransaction blankTx;
+ private BlankTransactionServiceTracker tracker;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ doReturn(new CommitStatus(Collections.<ObjectName>emptyList(), Collections.<ObjectName>emptyList(), Collections.<ObjectName>emptyList())).when(blankTx).hit();
+ tracker = new BlankTransactionServiceTracker(blankTx);
+ }
+
+ @Test
+ public void testBlankTransaction() throws Exception {
+ tracker.addingService(getMockServiceReference());
+ tracker.modifiedService(getMockServiceReference(), null);
+ tracker.removedService(getMockServiceReference(), null);
+ verify(blankTx, times(3)).hit();
+ }
+
+ @Test
+ public void testValidationException() throws Exception {
+ IllegalArgumentException argumentException = new IllegalArgumentException();
+ ValidationException validationException = ValidationException.createForSingleException(new ModuleIdentifier("m", "i"), argumentException);
+ doThrow(validationException).when(blankTx).hit();
+ try {
+ tracker.addingService(getMockServiceReference());
+ } catch (Exception e) {
+ verify(blankTx, times(1)).hit();
+ assertNotNull(e.getCause());
+ assertSame(validationException, e.getCause());
+ return;
+ }
+
+ fail("Exception should have occurred for validation exception");
+ }
+
+ @Test
+ public void testConflictingException() throws Exception {
+ int maxAttempts = 2;
+ tracker = new BlankTransactionServiceTracker(blankTx, maxAttempts);
+
+ final ConflictingVersionException ex = new ConflictingVersionException();
+ doThrow(ex).when(blankTx).hit();
+ try {
+ tracker.addingService(getMockServiceReference());
+ } catch (Exception e) {
+ verify(blankTx, times(maxAttempts)).hit();
+ return;
+ }
+
+ fail("Exception should have occurred for conflicting exception");
+ }
+
+ private ServiceReference<ModuleFactory> getMockServiceReference() {
+ return mock(ServiceReference.class);
+ }
+}
--- /dev/null
+package org.opendaylight.controller.config.manager.impl.osgi;
+
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import com.google.common.collect.Lists;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public class BundleContextBackedModuleFactoriesResolverTest {
+
+ @Mock
+ private BundleContext bundleContext;
+ private BundleContextBackedModuleFactoriesResolver resolver;
+ private ServiceReference s1;
+ private ServiceReference s2;
+ private ModuleFactory f1;
+ private ModuleFactory f2;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ s1 = getServiceRef();
+ s2 = getServiceRef();
+ doReturn(Lists.newArrayList(s1, s2)).when(bundleContext).getServiceReferences(ModuleFactory.class, null);
+ f1 = getMockFactory("f1");
+ doReturn(f1).when(bundleContext).getService(s1);
+ f2 = getMockFactory("f2");
+ doReturn(f2).when(bundleContext).getService(s2);
+ resolver = new BundleContextBackedModuleFactoriesResolver(bundleContext);
+ }
+
+ private ModuleFactory getMockFactory(String name) {
+ ModuleFactory mock = mock(ModuleFactory.class);
+ doReturn(name).when(mock).toString();
+ doReturn(name).when(mock).getImplementationName();
+ return mock;
+ }
+
+ private ServiceReference getServiceRef() {
+ ServiceReference mock = mock(ServiceReference.class);
+ doReturn("serviceRef").when(mock).toString();
+ final Bundle bundle = mock(Bundle.class);
+ doReturn(bundleContext).when(bundle).getBundleContext();
+ doReturn(bundle).when(mock).getBundle();
+ return mock;
+ }
+
+ @Test
+ public void testGetAllFactories() throws Exception {
+ Map<String, Map.Entry<ModuleFactory, BundleContext>> allFactories = resolver.getAllFactories();
+ assertEquals(2, allFactories.size());
+ assertTrue(allFactories.containsKey(f1.getImplementationName()));
+ assertEquals(f1, allFactories.get(f1.getImplementationName()).getKey());
+ assertEquals(bundleContext, allFactories.get(f1.getImplementationName()).getValue());
+ assertTrue(allFactories.containsKey(f2.getImplementationName()));
+ assertEquals(f2, allFactories.get(f2.getImplementationName()).getKey());
+ assertEquals(bundleContext, allFactories.get(f2.getImplementationName()).getValue());
+ }
+
+ @Test
+ public void testDuplicateFactories() throws Exception {
+ doReturn(f1).when(bundleContext).getService(s2);
+ try {
+ resolver.getAllFactories();
+ } catch (Exception e) {
+ assertThat(e.getMessage(), containsString(f1.getImplementationName()));
+ assertThat(e.getMessage(), containsString("unique"));
+ return;
+ }
+
+ fail("Should fail with duplicate factory name");
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNullFactory() throws Exception {
+ doReturn(null).when(bundleContext).getService(s2);
+ resolver.getAllFactories();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testNullFactoryName() throws Exception {
+ doReturn(null).when(f1).getImplementationName();
+ resolver.getAllFactories();
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNullBundleName() throws Exception {
+ doReturn(null).when(s1).getBundle();
+ resolver.getAllFactories();
+ }
+}
--- /dev/null
+package org.opendaylight.controller.config.manager.impl.osgi;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import com.google.common.util.concurrent.Futures;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+
+public class ExtensibleBundleTrackerTest {
+
+ @Mock
+ private BundleContext bundleContext;
+ @Mock
+ private Bundle bundle;
+ @Mock
+ private BundleEvent bundleEvent;
+
+ @Mock
+ private BundleTrackerCustomizer<Object> primaryTracker;
+ @Mock
+ private BundleTrackerCustomizer<?> additionalTracker;
+
+ private ExtensibleBundleTracker<Object> extensibleBundleTracker;
+ private Object primaryValue = new Object();
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ doReturn("bundle").when(bundle).toString();
+ doReturn("bundleEvent").when(bundleEvent).toString();
+
+ doReturn(primaryValue).when(primaryTracker).addingBundle(bundle, bundleEvent);
+ doNothing().when(primaryTracker).modifiedBundle(bundle, bundleEvent, primaryValue);
+ doNothing().when(primaryTracker).removedBundle(bundle, bundleEvent, primaryValue);
+
+ doReturn(new Object()).when(additionalTracker).addingBundle(bundle, bundleEvent);
+ doNothing().when(additionalTracker).modifiedBundle(bundle, bundleEvent, null);
+ doNothing().when(additionalTracker).removedBundle(bundle, bundleEvent, null);
+ extensibleBundleTracker = new ExtensibleBundleTracker<>(bundleContext, primaryTracker, additionalTracker);
+ }
+
+ @Test
+ public void testAddingBundle() throws Exception {
+ assertEquals(primaryValue, extensibleBundleTracker.addingBundle(bundle, bundleEvent).get());
+ InOrder inOrder = Mockito.inOrder(primaryTracker, additionalTracker);
+ inOrder.verify(primaryTracker).addingBundle(bundle, bundleEvent);
+ inOrder.verify(additionalTracker).addingBundle(bundle, bundleEvent);
+ }
+
+ @Test
+ public void testRemovedBundle() throws Exception {
+ extensibleBundleTracker.removedBundle(bundle, bundleEvent, Futures.immediateFuture(primaryValue));
+ InOrder inOrder = Mockito.inOrder(primaryTracker, additionalTracker);
+ inOrder.verify(primaryTracker).removedBundle(bundle, bundleEvent, primaryValue);
+ inOrder.verify(additionalTracker).removedBundle(bundle, bundleEvent, null);
+ }
+
+ @Test
+ public void testRemovedBundleWithEx() throws Exception {
+ IllegalStateException throwable = new IllegalStateException();
+ extensibleBundleTracker.removedBundle(bundle, bundleEvent, Futures.immediateFailedFuture(throwable));
+ verifyZeroInteractions(primaryTracker);
+ verifyZeroInteractions(additionalTracker);
+ }
+}
--- /dev/null
+package org.opendaylight.controller.config.manager.impl.osgi;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import java.util.Dictionary;
+import java.util.Set;
+
+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.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.DependencyResolverFactory;
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
+import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.controller.config.spi.Module;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.ServiceRegistration;
+
+public class ModuleFactoryBundleTrackerTest {
+
+ @Mock
+ private Bundle bundle;
+ @Mock
+ private BundleContext context;
+ @Mock
+ private ServiceRegistration<?> reg;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(final InvocationOnMock invocation) throws Throwable {
+ return getClass().getClassLoader().loadClass((String) invocation.getArguments()[0]);
+ }
+ }).when(bundle).loadClass(anyString());
+ doReturn("mockBundle").when(bundle).toString();
+ doReturn(context).when(bundle).getBundleContext();
+ doReturn(reg).when(context).registerService(anyString(), anyObject(), any(Dictionary.class));
+ }
+
+ @Test
+ public void testRegisterFactory() throws Exception {
+ ModuleFactoryBundleTracker.registerFactory(TestingFactory.class.getName(), bundle);
+ verify(context).registerService(ModuleFactory.class.getName(), TestingFactory.currentInstance, null);
+ }
+
+ @Test
+ public void testRegisterFactoryInstantiateEx() throws Exception {
+ try {
+ ModuleFactoryBundleTracker.registerFactory(WrongConstructorTestingFactory.class.getName(), bundle);
+ } catch (Exception e) {
+ verifyZeroInteractions(context);
+ assertNotNull(e.getCause());
+ assertEquals(InstantiationException.class, e.getCause().getClass());
+ return;
+ }
+
+ fail("Cannot register without proper constructor");
+ }
+
+ @Test
+ public void testRegisterFactoryInstantiateExAccess() throws Exception {
+ try {
+ ModuleFactoryBundleTracker.registerFactory(NoAccessConstructorTestingFactory.class.getName(), bundle);
+ } catch (Exception e) {
+ verifyZeroInteractions(context);
+ assertNotNull(e.getCause());
+ assertEquals(IllegalAccessException.class, e.getCause().getClass());
+ return;
+ }
+
+ fail("Cannot register without proper constructor");
+ }
+
+ @Test
+ public void testRegisterFactoryNotExtending() throws Exception {
+ try {
+ ModuleFactoryBundleTracker.registerFactory(NotExtendingTestingFactory.class.getName(), bundle);
+ } catch (Exception e) {
+ verifyZeroInteractions(context);
+ return;
+ }
+
+ fail("Cannot register without extend");
+ }
+
+ @Test
+ public void testRegisterFactoryNotExisting() throws Exception {
+ try {
+ ModuleFactoryBundleTracker.registerFactory("Unknown class", bundle);
+ } catch (Exception e) {
+ verifyZeroInteractions(context);
+ assertNotNull(e.getCause());
+ assertEquals(ClassNotFoundException.class, e.getCause().getClass());
+ return;
+ }
+
+ fail("Cannot register without extend");
+ }
+
+ @Mock
+ private BlankTransactionServiceTracker blankTxTracker;
+
+ @Test
+ public void testAddingBundle() throws Exception {
+ final ModuleFactoryBundleTracker tracker = new ModuleFactoryBundleTracker(blankTxTracker);
+ doReturn(getClass().getResource("/module-factories/module-factory-ok")).when(bundle).getEntry(anyString());
+ tracker.addingBundle(bundle, mock(BundleEvent.class));
+ verify(context).registerService(ModuleFactory.class.getName(), TestingFactory.currentInstance, null);
+ }
+
+ @Test
+ public void testAddingBundleError() throws Exception {
+ final ModuleFactoryBundleTracker tracker = new ModuleFactoryBundleTracker(blankTxTracker);
+ doReturn(getClass().getResource("/module-factories/module-factory-fail")).when(bundle).getEntry(anyString());
+ try {
+ tracker.addingBundle(bundle, mock(BundleEvent.class));
+ } catch (Exception e) {
+ verifyZeroInteractions(context);
+ return;
+ }
+
+ fail("Cannot register");
+ }
+
+ static class WrongConstructorTestingFactory extends TestingFactory {
+ WrongConstructorTestingFactory(String randomParam) {
+ }
+ }
+
+ static class NotExtendingTestingFactory {}
+
+ static class NoAccessConstructorTestingFactory extends TestingFactory {
+ private NoAccessConstructorTestingFactory() {
+ }
+ }
+
+ static class TestingFactory implements ModuleFactory {
+
+ static TestingFactory currentInstance;
+
+ TestingFactory() {
+ currentInstance = this;
+ }
+
+ @Override
+ public String getImplementationName() {
+ return "Testing";
+ }
+
+ @Override
+ public Module createModule(final String instanceName, final DependencyResolver dependencyResolver, final BundleContext bundleContext) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Module createModule(final String instanceName, final DependencyResolver dependencyResolver, final DynamicMBeanWithInstance old, final BundleContext bundleContext) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isModuleImplementingServiceInterface(final Class<? extends AbstractServiceInterface> serviceInterface) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Set<Class<? extends AbstractServiceInterface>> getImplementedServiceIntefaces() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Set<? extends Module> getDefaultModules(final DependencyResolverFactory dependencyResolverFactory, final BundleContext bundleContext) {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
import static org.junit.Assert.assertEquals;
+import com.google.common.collect.Sets;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
-
import javax.management.MXBean;
-
import org.junit.Test;
import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingScheduledThreadPoolServiceInterface;
import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingThreadPoolServiceInterface;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.yangtools.concepts.Identifiable;
-import com.google.common.collect.Sets;
-
public class InterfacesHelperTest {
interface SuperA {
}
+ @ServiceInterfaceAnnotation(value = "a", osgiRegistrationType = SuperA.class, namespace = "n", revision = "r", localName = "l")
+ interface Service extends AbstractServiceInterface{}
+ @ServiceInterfaceAnnotation(value = "b", osgiRegistrationType = SuperC.class, namespace = "n", revision = "r", localName = "l")
+ interface SubService extends Service{}
+
abstract class SubClass extends SuperClass implements SubA, Module {
}
+ abstract class SubClassWithService implements SubService, Module {
+
+ }
+
@Test
public void testGetAllInterfaces() {
Set<Class<?>> expected = Sets.<Class<?>> newHashSet(SuperA.class, SuperBMXBean.class, SuperC.class,
InterfacesHelper.getAllInterfaces(SubClass.class));
}
+ @Test
+ public void testGetServiceInterfaces() throws Exception {
+ assertEquals(Collections.<Class<?>>emptySet(), InterfacesHelper.getServiceInterfaces(SubClass.class));
+ assertEquals(Sets.<Class<?>>newHashSet(Service.class, SubService.class), InterfacesHelper.getServiceInterfaces(SubClassWithService.class));
+ }
+
+ @Test
+ public void testGetOsgiRegistrationTypes() throws Exception {
+ assertEquals(Collections.<Class<?>>emptySet(), InterfacesHelper.getOsgiRegistrationTypes(SubClass.class));
+ assertEquals(Sets.<Class<?>>newHashSet(SuperA.class, SuperC.class),
+ InterfacesHelper.getOsgiRegistrationTypes(SubClassWithService.class));
+ }
+
@Test
public void testGetMXInterfaces() {
Set<Class<?>> expected = Sets.<Class<?>> newHashSet(SuperBMXBean.class, SubA.class);
+++ /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.util;
-
-import com.google.common.base.Throwables;
-import com.google.common.collect.Sets;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-import org.opendaylight.controller.config.manager.impl.AbstractLockedPlatformMBeanServerTest;
-
-import javax.management.ObjectName;
-import java.util.Set;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-
-public class ObjectNameUtilTest extends AbstractLockedPlatformMBeanServerTest {
- private Set<ObjectName> unregisterONs;
-
- @Before
- public void initUnregisterList() {
- unregisterONs = Sets.newHashSet();
- }
-
- @After
- public void unregisterONs() {
- Exception lastException = null;
- for (ObjectName on : unregisterONs) {
- try {
- platformMBeanServer.unregisterMBean(on);
- } catch (Exception e) {
- lastException = e;
- }
- }
- if (lastException != null) {
- throw Throwables.propagate(lastException);
- }
- }
-
- @Test
- public void testQuotation() throws Exception {
- String serviceQName = "(namespace?revision=r)qname";
- String refName = "refName";
- String transaction = "transaction";
- ObjectName serviceReferenceON = ObjectNameUtil.createTransactionServiceON(transaction, serviceQName, refName);
- assertFalse(serviceReferenceON.isPattern());
- assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
- assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
- assertEquals(transaction, ObjectNameUtil.getTransactionName(serviceReferenceON));
-
- serviceReferenceON = ObjectNameUtil.createReadOnlyServiceON(serviceQName, refName);
- assertFalse(serviceReferenceON.isPattern());
- assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
- assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
- assertEquals(null, ObjectNameUtil.getTransactionName(serviceReferenceON));
-
- }
-}
--- /dev/null
+package org.opendaylight.controller.config.manager.impl.util;
+
+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 org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class OsgiRegistrationUtilTest {
+
+ @Test
+ public void testRegisterService() throws Exception {
+ final BundleContext bundleContext = mock(BundleContext.class);
+ ServiceRegistration<?> registration = mockServiceRegistration();
+ doReturn(registration).when(bundleContext).registerService(String.class, "string", null);
+ ServiceRegistration<?> registration2 = mockServiceRegistration();
+ doReturn(registration2).when(bundleContext).registerService(Object.class, "string", null);
+
+ AutoCloseable aggregatedRegister = OsgiRegistrationUtil.registerService(bundleContext, "string", String.class, Object.class);
+ aggregatedRegister.close();
+
+ InOrder inOrder = Mockito.inOrder(registration, registration2);
+ inOrder.verify(registration2).unregister();
+ inOrder.verify(registration).unregister();
+ }
+
+ @Test
+ public void testWrap() throws Exception {
+ final ServiceRegistration<?> serviceReg = mockServiceRegistration();
+ OsgiRegistrationUtil.wrap(serviceReg).close();
+ verify(serviceReg).unregister();
+
+ final BundleTracker tracker = mock(BundleTracker.class);
+ doNothing().when(tracker).close();
+ OsgiRegistrationUtil.wrap(tracker).close();
+ verify(tracker).close();
+
+ final ServiceTracker<?, ?> sTracker = mock(ServiceTracker.class);
+ doNothing().when(sTracker).close();
+ OsgiRegistrationUtil.wrap(sTracker).close();
+ verify(sTracker).close();
+ }
+
+ private ServiceRegistration<?> mockServiceRegistration() {
+ ServiceRegistration mock = mock(ServiceRegistration.class);
+ doNothing().when(mock).unregister();
+ return mock;
+ }
+
+ @Test
+ public void testAggregate() throws Exception {
+
+ }
+}
\ No newline at end of file
import org.opendaylight.yangtools.yang.binding.annotations.ModuleQName;
-@ModuleQName(namespace = "namespace", revision = "revision", name = "name")
+@ModuleQName(namespace = "namespace", revision = "2012-12-12", name = "name")
public abstract class AbstractTestingFixedThreadPoolModuleFactory {
}
@Test
public void testQNames() {
Set<String> availableModuleFactoryQNames = configRegistryClient.getAvailableModuleFactoryQNames();
- String expected = "(namespace?revision=revision)name";
+ String expected = "(namespace?revision=2012-12-12)name";
+
assertEquals(Sets.newHashSet(expected), availableModuleFactoryQNames);
}
--- /dev/null
+org.opendaylight.controller.config.manager.impl.osgi.ModuleFactoryBundleTrackerTest$NotExtendingTestingFactory
\ No newline at end of file
--- /dev/null
+org.opendaylight.controller.config.manager.impl.osgi.ModuleFactoryBundleTrackerTest$TestingFactory
\ No newline at end of file
<groupId>${project.groupId}</groupId>
<artifactId>netconf-client</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>config-manager</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>config-manager</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>config-util</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netty-threadgroup-config</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netty-timer-config</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>mockito-configuration</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
--- /dev/null
+package org.opendaylight.controller.config.yang.config.netconf.client.dispatcher;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import org.opendaylight.controller.config.yang.netty.threadgroup.NettyThreadgroupModuleFactory;
+import org.opendaylight.controller.config.yang.netty.threadgroup.NettyThreadgroupModuleMXBean;
+import org.opendaylight.controller.config.yang.netty.timer.HashedWheelTimerModuleFactory;
+
+public class NetconfClientDispatcherModuleTest extends AbstractConfigTest{
+
+ private NetconfClientDispatcherModuleFactory factory;
+ private final String instanceName = "dispatch";
+
+ @Before
+ public void setUp() {
+ factory = new NetconfClientDispatcherModuleFactory();
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory,
+ new NettyThreadgroupModuleFactory(),
+ new HashedWheelTimerModuleFactory()));
+ }
+
+ @Test
+ public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException, ConflictingVersionException {
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+ createInstance(transaction, instanceName, "timer", "thGroup");
+ createInstance(transaction, instanceName + 2, "timer2", "thGroup2");
+ transaction.validateConfig();
+ CommitStatus status = transaction.commit();
+
+ assertBeanCount(2, factory.getImplementationName());
+ assertStatus(status, 2 + 4, 0, 0);
+ }
+
+ @Test
+ public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException, ValidationException {
+
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+ createInstance(transaction, instanceName, "timer", "thGroup");
+
+ transaction.commit();
+
+ transaction = configRegistryClient.createTransaction();
+ assertBeanCount(1, factory.getImplementationName());
+ CommitStatus status = transaction.commit();
+
+ assertBeanCount(1, factory.getImplementationName());
+ assertStatus(status, 0, 0, 3);
+ }
+
+ @Test
+ public void testReconfigure() throws InstanceAlreadyExistsException, ConflictingVersionException,
+ ValidationException, InstanceNotFoundException {
+
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+ createInstance(transaction, instanceName, "timer", "thGroup");
+
+ transaction.commit();
+
+ transaction = configRegistryClient.createTransaction();
+ assertBeanCount(1, factory.getImplementationName());
+ NetconfClientDispatcherModuleMXBean mxBean = transaction.newMBeanProxy(
+ transaction.lookupConfigBean(NetconfClientDispatcherModuleFactory.NAME, instanceName),
+ NetconfClientDispatcherModuleMXBean.class);
+ mxBean.setBossThreadGroup(getThreadGroup(transaction, "group2"));
+ CommitStatus status = transaction.commit();
+
+ assertBeanCount(1, factory.getImplementationName());
+ assertStatus(status, 1, 1, 2);
+ }
+
+ private ObjectName createInstance(ConfigTransactionJMXClient transaction, String instanceName, String timerName, String threadGroupName)
+ throws InstanceAlreadyExistsException {
+ ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);
+ NetconfClientDispatcherModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated, NetconfClientDispatcherModuleMXBean.class);
+ ObjectName thGroup = getThreadGroup(transaction, threadGroupName);
+ mxBean.setBossThreadGroup(thGroup);
+ mxBean.setWorkerThreadGroup(thGroup);
+ mxBean.setTimer(getTimer(transaction, timerName));
+ return nameCreated;
+ }
+
+ private ObjectName getTimer(ConfigTransactionJMXClient transaction, String name) throws InstanceAlreadyExistsException {
+ return transaction.createModule(HashedWheelTimerModuleFactory.NAME, name);
+ }
+
+ private ObjectName getThreadGroup(ConfigTransactionJMXClient transaction, String name) throws InstanceAlreadyExistsException {
+ ObjectName nameCreated = transaction.createModule(NettyThreadgroupModuleFactory.NAME, name);
+ NettyThreadgroupModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, NettyThreadgroupModuleMXBean.class);
+ mxBean.setThreadCount(1);
+ return nameCreated;
+ }
+}
--- /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.yang.netty.eventexecutor;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+
+public class ImmediateEventExecutorModuleTest extends AbstractConfigTest {
+
+ private GlobalEventExecutorModuleFactory factory;
+ private final String instanceName = ImmediateEventExecutorModuleFactory.SINGLETON_NAME;
+
+ @Before
+ public void setUp() {
+ factory = new GlobalEventExecutorModuleFactory();
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory));
+ }
+
+ @Test
+ public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,
+ ConflictingVersionException {
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+ createInstance(transaction, instanceName);
+
+ transaction.validateConfig();
+ CommitStatus status = transaction.commit();
+
+ assertBeanCount(1, factory.getImplementationName());
+ assertStatus(status, 1, 0, 0);
+ }
+
+ @Test
+ public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,
+ ValidationException {
+
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+ createInstance(transaction, instanceName);
+
+ transaction.commit();
+
+ transaction = configRegistryClient.createTransaction();
+ assertBeanCount(1, factory.getImplementationName());
+ CommitStatus status = transaction.commit();
+
+ assertBeanCount(1, factory.getImplementationName());
+ assertStatus(status, 0, 0, 1);
+ }
+
+ private ObjectName createInstance(ConfigTransactionJMXClient transaction, String instanceName)
+ throws InstanceAlreadyExistsException {
+ ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);
+ transaction.newMBeanProxy(nameCreated, ImmediateEventExecutorModuleMXBean.class);
+ return nameCreated;
+ }
+
+}
public void setUp() {
factory = new HashedWheelTimerModuleFactory();
threadFactory = new NamingThreadFactoryModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory, threadFactory));
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, factory, threadFactory));
}
public void testValidationExceptionTickDuration() throws InstanceAlreadyExistsException {
LOG.debug("Processed {} operations, submitting transaction {}", ops, tx.getIdentifier());
final CheckedFuture<Void, TransactionCommitFailedException> result = tx.submit();
- Futures.addCallback(result, new FutureCallback<Object>() {
+ Futures.addCallback(result, new FutureCallback<Void>() {
@Override
- public void onSuccess(Object o) {
+ public void onSuccess(Void aVoid) {
+ //NOOP
}
@Override
*/
package org.opendaylight.controller.md.inventory.manager;
+import com.google.common.base.Optional;
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 org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
import org.slf4j.Logger;
LOG.debug("Node updated notification received.");
manager.enqueue(new InventoryOperation() {
@Override
- public void applyOperation(final ReadWriteTransaction tx) {
+ public void applyOperation(ReadWriteTransaction tx) {
final NodeRef ref = node.getNodeRef();
+ @SuppressWarnings("unchecked")
+ InstanceIdentifierBuilder<Node> builder = ((InstanceIdentifier<Node>) ref.getValue()).builder();
+ InstanceIdentifierBuilder<FlowCapableNode> augmentation = builder.augmentation(FlowCapableNode.class);
+ final InstanceIdentifier<FlowCapableNode> path = augmentation.build();
+ CheckedFuture readFuture = tx.read(LogicalDatastoreType.OPERATIONAL, path);
+ Futures.addCallback(readFuture, new FutureCallback<Optional<? extends DataObject>>() {
+ @Override
+ public void onSuccess(Optional<? extends DataObject> optional) {
+ enqueueWriteNodeDataTx(node, flowNode, path);
+ if (!optional.isPresent()) {
+ enqueuePutTable0Tx(ref);
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ LOG.debug(String.format("Can't retrieve node data for node %s. Writing node data with table0.", node));
+ enqueueWriteNodeDataTx(node, flowNode, path);
+ enqueuePutTable0Tx(ref);
+ }
+ });
+ }
+ });
+ }
+
+ private void enqueueWriteNodeDataTx(final NodeUpdated node, final FlowCapableNodeUpdated flowNode, final InstanceIdentifier<FlowCapableNode> path) {
+ manager.enqueue(new InventoryOperation() {
+ @Override
+ public void applyOperation(final ReadWriteTransaction tx) {
final NodeBuilder nodeBuilder = new NodeBuilder(node);
nodeBuilder.setKey(new NodeKey(node.getId()));
final FlowCapableNode augment = InventoryMapping.toInventoryAugment(flowNode);
nodeBuilder.addAugmentation(FlowCapableNode.class, augment);
-
- @SuppressWarnings("unchecked")
- InstanceIdentifierBuilder<Node> builder = ((InstanceIdentifier<Node>) ref.getValue()).builder();
- InstanceIdentifierBuilder<FlowCapableNode> augmentation = builder.augmentation(FlowCapableNode.class);
- final InstanceIdentifier<FlowCapableNode> path = augmentation.build();
LOG.debug("updating node :{} ", path);
tx.put(LogicalDatastoreType.OPERATIONAL, path, augment);
}
});
}
+
+ private void enqueuePutTable0Tx(final NodeRef ref) {
+ manager.enqueue(new InventoryOperation() {
+ @Override
+ public void applyOperation(ReadWriteTransaction tx) {
+ final TableKey tKey = new TableKey((short) 0);
+ final InstanceIdentifier<Table> tableIdentifier =
+ ((InstanceIdentifier<Node>) ref.getValue()).augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tKey));
+ TableBuilder tableBuilder = new TableBuilder();
+ Table table0 = tableBuilder.setId((short) 0).build();
+ LOG.debug("writing table :{} ", tableIdentifier);
+ tx.put(LogicalDatastoreType.OPERATIONAL, tableIdentifier, table0, true);
+ }
+ });
+ }
}
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-generator-impl</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>binding-data-codec</artifactId>
- <version>0.6.2-SNAPSHOT</version>
- </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-impl</artifactId>
import java.util.Collection;
import java.util.Collections;
-import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+
import org.opendaylight.controller.md.sal.binding.impl.ForwardedBindingDataBroker;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
import org.opendaylight.controller.sal.core.api.Broker;
import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
import org.opendaylight.controller.sal.core.api.Provider;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
public class BindingAsyncDataBrokerImplModule extends
org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractBindingAsyncDataBrokerImplModule implements
@Override
public java.lang.AutoCloseable createInstance() {
Broker domBroker = getDomAsyncBrokerDependency();
- BindingToNormalizedNodeCodec mappingService = getBindingMappingServiceDependency();
+ BindingIndependentMappingService mappingService = getBindingMappingServiceDependency();
// FIXME: Switch this to DOM Broker registration which would not require
// BundleContext when API are updated.
--- /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.binding.impl;
+
+import java.util.concurrent.ExecutorService;
+
+import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
+import org.opendaylight.controller.sal.binding.impl.RootDataBrokerImpl;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingDomConnectorDeployer;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
+import org.opendaylight.controller.sal.binding.impl.forward.DomForwardedDataBrokerImpl;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+
+/**
+*
+*/
+public final class DataBrokerImplModule extends
+ org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractDataBrokerImplModule {
+
+ public DataBrokerImplModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+ final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public DataBrokerImplModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+ final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+ final DataBrokerImplModule oldModule, final java.lang.AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public void validate() {
+ super.validate();
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ RootDataBrokerImpl dataBindingBroker;
+
+
+ ExecutorService listeningExecutor = SingletonHolder.getDefaultCommitExecutor();
+ BindingIndependentMappingService potentialMapping = getMappingServiceDependency();
+ if (getDomBrokerDependency() != null && potentialMapping != null) {
+
+ dataBindingBroker = createDomConnectedBroker(listeningExecutor,potentialMapping);
+ } else {
+ dataBindingBroker = createStandAloneBroker(listeningExecutor);
+ }
+ dataBindingBroker.registerRuntimeBean(getRootRuntimeBeanRegistratorWrapper());
+ dataBindingBroker.setNotificationExecutor(SingletonHolder.getDefaultChangeEventExecutor());
+ return dataBindingBroker;
+ }
+
+
+ private RootDataBrokerImpl createStandAloneBroker(final ExecutorService listeningExecutor) {
+ RootDataBrokerImpl broker = new RootDataBrokerImpl();
+ broker.setExecutor(listeningExecutor);
+ return broker;
+ }
+
+ private RootDataBrokerImpl createDomConnectedBroker(final ExecutorService listeningExecutor, final BindingIndependentMappingService mappingService) {
+ DomForwardedDataBrokerImpl forwardedBroker = new DomForwardedDataBrokerImpl();
+ forwardedBroker.setExecutor(listeningExecutor);
+ BindingIndependentConnector connector = BindingDomConnectorDeployer.createConnector(mappingService);
+ getDomBrokerDependency().registerProvider(forwardedBroker, null);
+ ProviderSession domContext = forwardedBroker.getDomProviderContext();
+ forwardedBroker.setConnector(connector);
+ forwardedBroker.setDomProviderContext(domContext);
+ forwardedBroker.startForwarding();
+ return forwardedBroker;
+ }
+
+}
--- /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.binding.impl;
+
+
+/**
+*
+*/
+public class DataBrokerImplModuleFactory extends
+ org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractDataBrokerImplModuleFactory {
+
+}
*/
package org.opendaylight.controller.config.yang.md.sal.binding.impl;
-import com.google.common.util.concurrent.ListeningExecutorService;
import java.util.Collection;
import java.util.Collections;
-import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+
import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
import org.opendaylight.controller.sal.core.api.Provider;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+
+import com.google.common.util.concurrent.ListeningExecutorService;
/**
*
@Override
public java.lang.AutoCloseable createInstance() {
ListeningExecutorService listeningExecutor = SingletonHolder.getDefaultCommitExecutor();
- BindingToNormalizedNodeCodec mappingService = getBindingMappingServiceDependency();
+ BindingIndependentMappingService mappingService = getBindingMappingServiceDependency();
Broker domBroker = getDomAsyncBrokerDependency();
ProviderSession session = domBroker.registerProvider(this, null);
ForwardedBackwardsCompatibleDataBroker dataBroker = new ForwardedBackwardsCompatibleDataBroker(domDataBroker,
mappingService, schemaService,listeningExecutor);
- dataBroker.setConnector(BindingDomConnectorDeployer.createConnector(mappingService.getLegacy()));
+ dataBroker.setConnector(BindingDomConnectorDeployer.createConnector(getBindingMappingServiceDependency()));
dataBroker.setDomProviderContext(session);
return dataBroker;
}
*/
package org.opendaylight.controller.config.yang.md.sal.binding.impl;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
import java.util.Hashtable;
import java.util.Map.Entry;
import java.util.Set;
-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.concepts.Delegator;
-import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
/**
*
*/
private BundleContext bundleContext;
- public RuntimeMappingModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
- final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ public RuntimeMappingModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+ org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
super(identifier, dependencyResolver);
}
- public RuntimeMappingModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
- final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
- final RuntimeMappingModule oldModule, final java.lang.AutoCloseable oldInstance) {
+ public RuntimeMappingModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+ org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+ RuntimeMappingModule oldModule, java.lang.AutoCloseable oldInstance) {
super(identifier, dependencyResolver, oldModule, oldInstance);
}
}
@Override
- public boolean canReuseInstance(final AbstractRuntimeMappingModule oldModule) {
+ public boolean canReuseInstance(AbstractRuntimeMappingModule oldModule) {
return true;
}
@Override
public java.lang.AutoCloseable createInstance() {
- final GeneratedClassLoadingStrategy classLoading = getGlobalClassLoadingStrategy();
- final BindingIndependentMappingService legacyMapping = getGlobalLegacyMappingService(classLoading);
- BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(new StreamWriterGenerator(SingletonHolder.JAVASSIST));
- BindingToNormalizedNodeCodec instance = new BindingToNormalizedNodeCodec(classLoading, legacyMapping, 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>());
+ RuntimeGeneratedMappingServiceProxy potential = tryToReuseGlobalInstance();
+ if(potential != null) {
+ return potential;
}
- return potential;
- }
- private GeneratedClassLoadingStrategy getGlobalClassLoadingStrategy() {
- ServiceReference<GeneratedClassLoadingStrategy> ref = bundleContext.getServiceReference(GeneratedClassLoadingStrategy.class);
- return bundleContext.getService(ref);
+ final RuntimeGeneratedMappingServiceImpl service = new RuntimeGeneratedMappingServiceImpl(SingletonHolder.CLASS_POOL);
+ bundleContext.registerService(SchemaContextListener.class, service, new Hashtable<String,String>());
+ return service;
}
- private BindingIndependentMappingService tryToReuseGlobalMappingServiceInstance() {
+ private RuntimeGeneratedMappingServiceProxy tryToReuseGlobalInstance() {
ServiceReference<BindingIndependentMappingService> serviceRef = getBundleContext().getServiceReference(BindingIndependentMappingService.class);
if(serviceRef == null) {
return null;
}
- return bundleContext.getService(serviceRef);
+ BindingIndependentMappingService delegate = bundleContext.getService(serviceRef);
+ if (delegate == null) {
+ return null;
+ }
+ return new RuntimeGeneratedMappingServiceProxy(getBundleContext(),serviceRef,delegate);
}
private BundleContext getBundleContext() {
return bundleContext;
}
- public void setBundleContext(final BundleContext bundleContext) {
+ public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
private ServiceReference<BindingIndependentMappingService> reference;
private BundleContext bundleContext;
- public RuntimeGeneratedMappingServiceProxy(final BundleContext bundleContext,
- final ServiceReference<BindingIndependentMappingService> serviceRef,
- final BindingIndependentMappingService delegate) {
+ public RuntimeGeneratedMappingServiceProxy(BundleContext bundleContext,
+ ServiceReference<BindingIndependentMappingService> serviceRef,
+ BindingIndependentMappingService delegate) {
this.bundleContext = Preconditions.checkNotNull(bundleContext);
this.reference = Preconditions.checkNotNull(serviceRef);
this.delegate = Preconditions.checkNotNull(delegate);
}
@Override
- public CompositeNode toDataDom(final DataObject data) {
+ public CompositeNode toDataDom(DataObject data) {
return delegate.toDataDom(data);
}
@Override
public Entry<YangInstanceIdentifier, CompositeNode> toDataDom(
- final Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> entry) {
+ Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> entry) {
return delegate.toDataDom(entry);
}
@Override
public YangInstanceIdentifier toDataDom(
- final org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> path) {
+ org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> path) {
return delegate.toDataDom(path);
}
@Override
public DataObject dataObjectFromDataDom(
- final org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> path,
- final CompositeNode result) throws DeserializationException {
+ org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> path,
+ CompositeNode result) throws DeserializationException {
return delegate.dataObjectFromDataDom(path, result);
}
@Override
- public org.opendaylight.yangtools.yang.binding.InstanceIdentifier<?> fromDataDom(final YangInstanceIdentifier entry)
+ public org.opendaylight.yangtools.yang.binding.InstanceIdentifier<?> fromDataDom(YangInstanceIdentifier entry)
throws DeserializationException {
return delegate.fromDataDom(entry);
}
@Override
- public Set<QName> getRpcQNamesFor(final Class<? extends RpcService> service) {
+ public Set<QName> getRpcQNamesFor(Class<? extends RpcService> service) {
return delegate.getRpcQNamesFor(service);
}
@Override
- public Optional<Class<? extends RpcService>> getRpcServiceClassFor(final String namespace, final String revision) {
+ public Optional<Class<? extends RpcService>> getRpcServiceClassFor(String namespace, String revision) {
return delegate.getRpcServiceClassFor(namespace,revision);
}
@Override
- public DataContainer dataObjectFromDataDom(final Class<? extends DataContainer> inputClass, final CompositeNode domInput) {
+ public DataContainer dataObjectFromDataDom(Class<? extends DataContainer> inputClass, CompositeNode domInput) {
return delegate.dataObjectFromDataDom(inputClass, domInput);
}
import com.google.common.base.Objects;
import com.google.common.base.Optional;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
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.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBroker>, DomForwardedBroker,
- SchemaContextListener, AutoCloseable {
+public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBroker>, DomForwardedBroker, SchemaContextListener, AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(AbstractForwardedDataBroker.class);
// The Broker to whom we do all forwarding
private final DOMDataBroker domDataBroker;
+ // Mapper to convert from Binding Independent objects to Binding Aware
+ // objects
+ private final BindingIndependentMappingService mappingService;
+
private final BindingToNormalizedNodeCodec codec;
private BindingIndependentConnector connector;
private ProviderSession context;
private final ListenerRegistration<SchemaContextListener> schemaListenerRegistration;
- protected AbstractForwardedDataBroker(final DOMDataBroker domDataBroker, final BindingToNormalizedNodeCodec codec,
- final SchemaService schemaService) {
+ protected AbstractForwardedDataBroker(final DOMDataBroker domDataBroker,
+ final BindingIndependentMappingService mappingService,final SchemaService schemaService) {
this.domDataBroker = domDataBroker;
- this.codec = codec;
+ this.mappingService = mappingService;
+ this.codec = new BindingToNormalizedNodeCodec(mappingService);
this.schemaListenerRegistration = schemaService.registerSchemaContextListener(this);
}
return codec;
}
+ protected BindingIndependentMappingService getMappingService() {
+ return mappingService;
+ }
+
@Override
public DOMDataBroker getDelegate() {
return domDataBroker;
@Override
public void onGlobalContextUpdated(final SchemaContext ctx) {
- // NOOP
+ codec.onGlobalContextUpdated(ctx);
}
public ListenerRegistration<DataChangeListener> registerDataChangeListener(final LogicalDatastoreType store,
- final InstanceIdentifier<?> path, final DataChangeListener listener, final DataChangeScope triggeringScope) {
+ final InstanceIdentifier<?> path, final DataChangeListener listener,
+ final DataChangeScope triggeringScope) {
DOMDataChangeListener domDataChangeListener = new TranslatingDataChangeInvoker(store, path, listener,
triggeringScope);
YangInstanceIdentifier domPath = codec.toNormalized(path);
return new ListenerRegistrationImpl(listener, domRegistration);
}
- protected Map<InstanceIdentifier<?>, DataObject> toBinding(final InstanceIdentifier<?> path,
+ protected Map<InstanceIdentifier<?>, DataObject> toBinding(
+ InstanceIdentifier<?> path,
final Map<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized) {
Map<InstanceIdentifier<?>, DataObject> newMap = new HashMap<>();
for (Map.Entry<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : sortedEntries(normalized)) {
try {
- Optional<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> potential = getCodec().toBinding(entry);
+ Optional<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> potential = getCodec().toBinding(
+ entry);
if (potential.isPresent()) {
Entry<InstanceIdentifier<? extends DataObject>, DataObject> binding = potential.get();
newMap.put(binding.getKey(), binding.getValue());
+ } else if (entry.getKey().getLastPathArgument() instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+ DataObject bindingDataObject = getCodec().toBinding(path, entry.getValue());
+ if (bindingDataObject != null) {
+ newMap.put(path, bindingDataObject);
+ }
}
} catch (DeserializationException e) {
LOG.warn("Failed to transform {}, omitting it", entry, e);
private static final Comparator<Entry<YangInstanceIdentifier, ?>> MAP_ENTRY_COMPARATOR = new Comparator<Entry<YangInstanceIdentifier, ?>>() {
@Override
- public int compare(final Entry<YangInstanceIdentifier, ?> left, final Entry<YangInstanceIdentifier, ?> right) {
+ public int compare(final Entry<YangInstanceIdentifier, ?> left,
+ final Entry<YangInstanceIdentifier, ?> right) {
final Iterator<?> li = left.getKey().getPathArguments().iterator();
final Iterator<?> ri = right.getKey().getPathArguments().iterator();
}
};
- private static <T> Iterable<Entry<YangInstanceIdentifier, T>> sortedEntries(final Map<YangInstanceIdentifier, T> map) {
+ private static <T> Iterable<Entry<YangInstanceIdentifier,T>> sortedEntries(final Map<YangInstanceIdentifier, T> map) {
if (!map.isEmpty()) {
ArrayList<Entry<YangInstanceIdentifier, T>> entries = new ArrayList<>(map.entrySet());
Collections.sort(entries, MAP_ENTRY_COMPARATOR);
}
}
- protected Set<InstanceIdentifier<?>> toBinding(final InstanceIdentifier<?> path,
+ protected Set<InstanceIdentifier<?>> toBinding(InstanceIdentifier<?> path,
final Set<YangInstanceIdentifier> normalized) {
Set<InstanceIdentifier<?>> hashSet = new HashSet<>();
for (YangInstanceIdentifier normalizedPath : normalized) {
if (path.isWildcarded()) {
return Optional.absent();
}
- return (Optional) getCodec().deserializeFunction(path).apply(Optional.<NormalizedNode<?, ?>> of(data));
+
+ try {
+ return Optional.fromNullable(getCodec().toBinding(path, data));
+ } catch (DeserializationException e) {
+ return Optional.absent();
+ }
}
private class TranslatingDataChangeInvoker implements DOMDataChangeListener {
}
@Override
- public void onDataChanged(final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
+ public void onDataChanged(
+ final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
bindingDataChangeListener.onDataChanged(new TranslatedDataChangeEvent(change, path));
}
}
@Override
public DataObject getOriginalSubtree() {
if (originalDataCache == null) {
- if (domEvent.getOriginalSubtree() != null) {
+ if(domEvent.getOriginalSubtree() != null) {
originalDataCache = toBindingData(path, domEvent.getOriginalSubtree());
} else {
originalDataCache = Optional.absent();
@Override
public DataObject getUpdatedSubtree() {
if (updatedDataCache == null) {
- if (domEvent.getUpdatedSubtree() != null) {
+ if(domEvent.getUpdatedSubtree() != null) {
updatedDataCache = toBindingData(path, domEvent.getUpdatedSubtree());
} else {
updatedDataCache = Optional.absent();
*/
package org.opendaylight.controller.md.sal.binding.impl;
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
+import java.lang.reflect.Method;
import java.util.AbstractMap.SimpleEntry;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
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.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.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+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.QNameModule;
+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.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.DataContainerNode;
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.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class BindingToNormalizedNodeCodec implements SchemaContextListener,AutoCloseable {
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+public class BindingToNormalizedNodeCodec implements SchemaContextListener {
private static final Logger LOG = LoggerFactory.getLogger(BindingToNormalizedNodeCodec.class);
private final BindingIndependentMappingService bindingToLegacy;
- private final BindingNormalizedNodeCodecRegistry codecRegistry;
private DataNormalizer legacyToNormalized;
- private final GeneratedClassLoadingStrategy classLoadingStrategy;
- public BindingToNormalizedNodeCodec(final GeneratedClassLoadingStrategy classLoadingStrategy, final BindingIndependentMappingService mappingService, final BindingNormalizedNodeCodecRegistry codecRegistry) {
+ public BindingToNormalizedNodeCodec(final BindingIndependentMappingService mappingService) {
super();
this.bindingToLegacy = mappingService;
- this.classLoadingStrategy = classLoadingStrategy;
- this.codecRegistry = codecRegistry;
-
}
public org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier toNormalized(
final InstanceIdentifier<? extends DataObject> binding) {
- return codecRegistry.toYangInstanceIdentifier(binding);
+
+ // Used instance-identifier codec do not support serialization of last
+ // path
+ // argument if it is Augmentation (behaviour expected by old datastore)
+ // in this case, we explicitly check if last argument is augmentation
+ // to process it separately
+ if (isAugmentationIdentifier(binding)) {
+ return toNormalizedAugmented(binding);
+ }
+ return toNormalizedImpl(binding);
}
- @SuppressWarnings({ "unchecked", "rawtypes" })
public Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
final InstanceIdentifier<? extends DataObject> bindingPath, final DataObject bindingObject) {
- return codecRegistry.toNormalizedNode((InstanceIdentifier) bindingPath, bindingObject);
+ return toNormalizedNode(toBindingEntry(bindingPath, bindingObject));
}
public Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
final Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> binding) {
- return toNormalizedNode(binding.getKey(),binding.getValue());
+ Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> legacyEntry = bindingToLegacy
+ .toDataDom(binding);
+ Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedEntry = legacyToNormalized
+ .toNormalized(legacyEntry);
+ LOG.trace("Serialization of {}, Legacy Representation: {}, Normalized Representation: {}", binding,
+ legacyEntry, normalizedEntry);
+ if (isAugmentation(binding.getKey().getTargetType())) {
+
+ for (DataContainerChild<? extends PathArgument, ?> child : ((DataContainerNode<?>) normalizedEntry
+ .getValue()).getValue()) {
+ if (child instanceof AugmentationNode) {
+ ImmutableList<PathArgument> childArgs = ImmutableList.<PathArgument> builder()
+ .addAll(normalizedEntry.getKey().getPathArguments()).add(child.getIdentifier()).build();
+ org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier childPath = org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier
+ .create(childArgs);
+ return toDOMEntry(childPath, child);
+ }
+ }
+
+ }
+ return normalizedEntry;
+
}
/**
public Optional<InstanceIdentifier<? extends DataObject>> toBinding(
final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
throws DeserializationException {
+
+ PathArgument lastArgument = Iterables.getLast(normalized.getPathArguments());
+ // Used instance-identifier codec do not support serialization of last
+ // path
+ // argument if it is AugmentationIdentifier (behaviour expected by old
+ // datastore)
+ // in this case, we explicitly check if last argument is augmentation
+ // to process it separately
+ if (lastArgument instanceof AugmentationIdentifier) {
+ return toBindingAugmented(normalized);
+ }
+ return toBindingImpl(normalized);
+ }
+
+ private Optional<InstanceIdentifier<? extends DataObject>> toBindingAugmented(
+ final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
+ throws DeserializationException {
+ Optional<InstanceIdentifier<? extends DataObject>> potential = toBindingImpl(normalized);
+ // Shorthand check, if codec already supports deserialization
+ // of AugmentationIdentifier we will return
+ if (potential.isPresent() && isAugmentationIdentifier(potential.get())) {
+ return potential;
+ }
+
+ int normalizedCount = getAugmentationCount(normalized);
+ AugmentationIdentifier lastArgument = (AugmentationIdentifier) Iterables.getLast(normalized.getPathArguments());
+
+ // Here we employ small trick - Binding-aware Codec injects an pointer
+ // to augmentation class
+ // if child is referenced - so we will reference child and then shorten
+ // path.
+ LOG.trace("Looking for candidates to match {}", normalized);
+ for (QName child : lastArgument.getPossibleChildNames()) {
+ org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier childPath = normalized.node(child);
+ try {
+ if (isNotRepresentable(childPath)) {
+ LOG.trace("Path {} is not BI-representable, skipping it", childPath);
+ continue;
+ }
+ } catch (DataNormalizationException e) {
+ LOG.warn("Failed to denormalize path {}, skipping it", childPath, e);
+ continue;
+ }
+
+ Optional<InstanceIdentifier<? extends DataObject>> baId = toBindingImpl(childPath);
+ if (!baId.isPresent()) {
+ LOG.debug("No binding-aware identifier found for path {}, skipping it", childPath);
+ continue;
+ }
+
+ InstanceIdentifier<? extends DataObject> potentialPath = shortenToLastAugment(baId.get());
+ int potentialAugmentCount = getAugmentationCount(potentialPath);
+ if (potentialAugmentCount == normalizedCount) {
+ LOG.trace("Found matching path {}", potentialPath);
+ return Optional.<InstanceIdentifier<? extends DataObject>> of(potentialPath);
+ }
+
+ LOG.trace("Skipping mis-matched potential path {}", potentialPath);
+ }
+
+ LOG.trace("Failed to find augmentation matching {}", normalized);
+ return Optional.absent();
+ }
+
+ private Optional<InstanceIdentifier<? extends DataObject>> toBindingImpl(
+ final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
+ throws DeserializationException {
+ org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier legacyPath;
+
try {
- return Optional.<InstanceIdentifier<? extends DataObject>>of(codecRegistry.fromYangInstanceIdentifier(normalized));
- } catch (IllegalArgumentException e) {
- return Optional.absent();
+ if (isNotRepresentable(normalized)) {
+ return Optional.absent();
+ }
+ legacyPath = legacyToNormalized.toLegacy(normalized);
+ } catch (DataNormalizationException e) {
+ throw new IllegalStateException("Could not denormalize path.", e);
+ }
+ LOG.trace("InstanceIdentifier Path Deserialization: Legacy representation {}, Normalized representation: {}",
+ legacyPath, normalized);
+ return Optional.<InstanceIdentifier<? extends DataObject>> of(bindingToLegacy.fromDataDom(legacyPath));
+ }
+
+ private boolean isNotRepresentable(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
+ throws DataNormalizationException {
+ DataNormalizationOperation<?> op = findNormalizationOperation(normalized);
+ if (op.isMixin() && op.getIdentifier() instanceof NodeIdentifier) {
+ return true;
+ }
+ if (op.isLeaf()) {
+ return true;
}
+ return false;
}
+ private DataNormalizationOperation<?> findNormalizationOperation(
+ final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
+ throws DataNormalizationException {
+ DataNormalizationOperation<?> current = legacyToNormalized.getRootOperation();
+ for (PathArgument arg : normalized.getPathArguments()) {
+ current = current.getChild(arg);
+ }
+ return current;
+ }
private static final Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> toBindingEntry(
final org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> key,
key, value);
}
+ private static final Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>> toDOMEntry(
+ final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier key, final NormalizedNode<?, ?> value) {
+ return new SimpleEntry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>>(key,
+ value);
+ }
+
+ public DataObject toBinding(final InstanceIdentifier<?> path, final NormalizedNode<?, ?> normalizedNode)
+ throws DeserializationException {
+ CompositeNode legacy = null;
+ if (isAugmentationIdentifier(path) && normalizedNode instanceof AugmentationNode) {
+ QName augIdentifier = BindingReflections.findQName(path.getTargetType());
+ ContainerNode virtualNode = Builders.containerBuilder() //
+ .withNodeIdentifier(new NodeIdentifier(augIdentifier)) //
+ .withChild((DataContainerChild<?, ?>) normalizedNode) //
+ .build();
+ legacy = (CompositeNode) DataNormalizer.toLegacy(virtualNode);
+ } else {
+ legacy = (CompositeNode) DataNormalizer.toLegacy(normalizedNode);
+ }
+
+ return bindingToLegacy.dataObjectFromDataDom(path, legacy);
+ }
+
public DataNormalizer getDataNormalizer() {
return legacyToNormalized;
}
- @SuppressWarnings("unchecked")
public Optional<Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject>> toBinding(
final Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized)
throws DeserializationException {
- try {
- @SuppressWarnings("rawtypes")
- Entry binding = codecRegistry.fromNormalizedNode(normalized.getKey(), normalized.getValue());
- return Optional.<Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject>>fromNullable(binding);
- } catch (IllegalArgumentException e) {
+ Optional<InstanceIdentifier<? extends DataObject>> potentialPath = toBinding(normalized.getKey());
+ if (potentialPath.isPresent()) {
+ InstanceIdentifier<? extends DataObject> bindingPath = potentialPath.get();
+ DataObject bindingData = toBinding(bindingPath, normalized.getValue());
+ if (bindingData == null) {
+ LOG.warn("Failed to deserialize {} to Binding format. Binding path is: {}", normalized, bindingPath);
+ }
+ return Optional.of(toBindingEntry(bindingPath, bindingData));
+ } else {
return Optional.absent();
}
}
@Override
public void onGlobalContextUpdated(final SchemaContext arg0) {
legacyToNormalized = new DataNormalizer(arg0);
- codecRegistry.onBindingRuntimeContextUpdated(BindingRuntimeContext.create(classLoadingStrategy, arg0));
}
+ private org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier toNormalizedAugmented(
+ final InstanceIdentifier<?> augPath) {
+ org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier processed = toNormalizedImpl(augPath);
+ // If used instance identifier codec added supports for deserialization
+ // of last AugmentationIdentifier we will just reuse it
+ if (isAugmentationIdentifier(processed)) {
+ return processed;
+ }
+ Optional<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier> additionalSerialized;
+ additionalSerialized = toNormalizedAugmentedUsingChildContainers(augPath, processed);
+
+ if (additionalSerialized.isPresent()) {
+ return additionalSerialized.get();
+ }
+ additionalSerialized = toNormalizedAugmentedUsingChildLeafs(augPath, processed);
+ if (additionalSerialized.isPresent()) {
+ return additionalSerialized.get();
+ }
+ throw new IllegalStateException("Unabled to construct augmentation identfier for " + augPath);
+ }
+
+ /**
+ * Tries to find correct augmentation identifier using children leafs
+ *
+ * This method uses normalized Instance Identifier of parent node to fetch
+ * schema and {@link BindingReflections#getModuleInfo(Class)} to learn about
+ * augmentation namespace, specificly, in which module it was defined.
+ *
+ * Then it uses it to filter all available augmentations for parent by
+ * module. After that it walks augmentations in particular module and
+ * pick-up first which at least one leaf name matches supplied augmentation.
+ * We could do this safely since YANG explicitly states that no any existing
+ * augmentations must differ in leaf fully qualified names.
+ *
+ *
+ * @param augPath
+ * Binding Aware Path which ends with augment
+ * @param parentPath
+ * Processed path
+ * @return
+ */
+ private Optional<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier> toNormalizedAugmentedUsingChildLeafs(
+ final InstanceIdentifier<?> augPath,
+ final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier parentPath) {
+ try {
+ DataNormalizationOperation<?> parentOp = legacyToNormalized.getOperation(parentPath);
+ if(!parentOp.getDataSchemaNode().isPresent()) {
+ return Optional.absent();
+ }
+ DataSchemaNode parentSchema = parentOp.getDataSchemaNode().get();
+ if (parentSchema instanceof AugmentationTarget) {
+ Set<AugmentationSchema> augmentations = ((AugmentationTarget) parentSchema).getAvailableAugmentations();
+ LOG.info("Augmentations for {}, {}", augPath, augmentations);
+ Optional<AugmentationSchema> schema = findAugmentation(augPath.getTargetType(), augmentations);
+ if (schema.isPresent()) {
+ AugmentationIdentifier augmentationIdentifier = DataNormalizationOperation
+ .augmentationIdentifierFrom(schema.get());
+ return Optional.of(parentPath.node(augmentationIdentifier));
+ }
+ }
+ } catch (DataNormalizationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ return Optional.absent();
+ }
+
+ /**
+ * Creates instance identifier for augmentation child, tries to serialize it
+ * Instance Identifier is then shortened to last augmentation.
+ *
+ * This is for situations, where underlying codec is implementing hydrogen
+ * style DOM APIs (which did not supported {@link AugmentationIdentifier}.)
+ *
+ * @param augPath
+ * @param parentPath
+ * Path to parent node
+ * @return
+ */
+ @SuppressWarnings("rawtypes")
+ private Optional<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier> toNormalizedAugmentedUsingChildContainers(
+ final InstanceIdentifier<?> augPath,
+ final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier parentPath) {
+ for (Class augChild : BindingReflections.getChildrenClasses(augPath.getTargetType())) {
+ @SuppressWarnings("unchecked")
+ InstanceIdentifier<?> childPath = augPath.child(augChild);
+ org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized = toNormalizedImpl(childPath);
+ org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier potentialDiscovered = shortenToLastAugmentation(
+ normalized, parentPath);
+ if (potentialDiscovered != null) {
+ return Optional.of(potentialDiscovered);
+ }
+ }
+ return Optional.absent();
+ }
+
+ private Optional<AugmentationSchema> findAugmentation(final Class<?> targetType,
+ final Set<AugmentationSchema> augmentations) {
+ YangModuleInfo moduleInfo;
+ try {
+ moduleInfo = BindingReflections.getModuleInfo(targetType);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ Iterable<AugmentationSchema> filtered = filteredByModuleInfo(augmentations,
+ BindingReflections.getModuleQName(moduleInfo).getModule());
+ filtered.toString();
+ Set<String> targetTypeGetters = getYangModeledGetters(targetType);
+ for (AugmentationSchema schema : filtered) {
+ for (DataSchemaNode child : schema.getChildNodes()) {
+ String getterName = "get" + BindingMapping.getClassName(child.getQName());
+ if (targetTypeGetters.contains(getterName)) {
+ return Optional.of(schema);
+ }
+ }
+ }
+ return Optional.absent();
+ }
+
+ private static Iterable<AugmentationSchema> filteredByModuleInfo(final Iterable<AugmentationSchema> augmentations,
+ final QNameModule module) {
+ return Iterables.filter(augmentations, new Predicate<AugmentationSchema>() {
+ @Override
+ public boolean apply(final AugmentationSchema schema) {
+ final Collection<DataSchemaNode> childNodes = schema.getChildNodes();
+ return !childNodes.isEmpty() && module.equals(Iterables.get(childNodes, 0).getQName().getModule());
+ }
+ });
+ }
+
+ public static final Set<String> getYangModeledGetters(final Class<?> targetType) {
+ HashSet<String> ret = new HashSet<String>();
+ for (Method method : targetType.getMethods()) {
+ if (isYangModeledGetter(method)) {
+ ret.add(method.getName());
+ }
+ }
+ return ret;
+ }
+
+ /**
+ *
+ * Returns true if supplied method represent getter for YANG modeled value
+ *
+ * @param method
+ * Method to be tested
+ * @return true if method represent getter for YANG Modeled value.
+ */
+ private static final boolean isYangModeledGetter(final Method method) {
+ return !method.getName().equals("getClass") && !method.getName().equals("getImplementedInterface")
+ && method.getName().startsWith("get") && method.getParameterTypes().length == 0;
+ }
+
+ private org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier shortenToLastAugmentation(
+ final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized,
+ final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier parentPath) {
+ int parentSize = Iterables.size(parentPath.getPathArguments());
+ int position = 0;
+ int foundPosition = -1;
+ for (PathArgument arg : normalized.getPathArguments()) {
+ position++;
+ if (arg instanceof AugmentationIdentifier) {
+ foundPosition = position;
+ }
+ }
+ if (foundPosition > 0 && foundPosition > parentSize) {
+ Iterable<PathArgument> shortened = Iterables.limit(normalized.getPathArguments(), foundPosition);
+ return org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.create(shortened);
+ }
+ return null;
+ }
+
+ private InstanceIdentifier<? extends DataObject> shortenToLastAugment(
+ final InstanceIdentifier<? extends DataObject> binding) {
+ int position = 0;
+ int foundPosition = -1;
+ for (org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument arg : binding.getPathArguments()) {
+ position++;
+ if (isAugmentation(arg.getType())) {
+ foundPosition = position;
+ }
+ }
+ return InstanceIdentifier.create(Iterables.limit(binding.getPathArguments(), foundPosition));
+ }
+
+ private org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier toNormalizedImpl(
+ final InstanceIdentifier<? extends DataObject> binding) {
+ final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier legacyPath = bindingToLegacy
+ .toDataDom(binding);
+ final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized = legacyToNormalized
+ .toNormalized(legacyPath);
+ return normalized;
+ }
+
+ private static boolean isAugmentation(final Class<? extends DataObject> type) {
+ return Augmentation.class.isAssignableFrom(type);
+ }
+
+ private static boolean isAugmentationIdentifier(final InstanceIdentifier<?> potential) {
+ return Augmentation.class.isAssignableFrom(potential.getTargetType());
+ }
+
+ private boolean isAugmentationIdentifier(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier processed) {
+ return Iterables.getLast(processed.getPathArguments()) instanceof AugmentationIdentifier;
+ }
+
+ private static int getAugmentationCount(final InstanceIdentifier<?> potential) {
+ int count = 0;
+ for (org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument arg : potential.getPathArguments()) {
+ if (isAugmentation(arg.getType())) {
+ count++;
+ }
+
+ }
+ return count;
+ }
+
+ private static int getAugmentationCount(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier potential) {
+ int count = 0;
+ for (PathArgument arg : potential.getPathArguments()) {
+ if (arg instanceof AugmentationIdentifier) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
public <T extends DataObject> Function<Optional<NormalizedNode<?, ?>>, Optional<T>> deserializeFunction(final InstanceIdentifier<T> path) {
- return codecRegistry.deserializeFunction(path);
+ return new DeserializeFunction(this, path);
+ }
+
+ private static class DeserializeFunction<T extends DataObject> implements Function<Optional<NormalizedNode<?, ?>>, Optional<T>> {
+
+ private final BindingToNormalizedNodeCodec codec;
+ private final InstanceIdentifier<?> path;
+
+ public DeserializeFunction(final BindingToNormalizedNodeCodec codec, final InstanceIdentifier<?> path) {
+ super();
+ this.codec = Preconditions.checkNotNull(codec, "Codec must not be null");
+ this.path = Preconditions.checkNotNull(path, "Path must not be null");
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Nullable
+ @Override
+ public Optional apply(@Nullable final Optional<NormalizedNode<?, ?>> normalizedNode) {
+ if (normalizedNode.isPresent()) {
+ final DataObject dataObject;
+ try {
+ dataObject = codec.toBinding(path, normalizedNode.get());
+ } catch (DeserializationException e) {
+ LOG.warn("Failed to create dataobject from node {}", normalizedNode.get(), e);
+ throw new IllegalStateException("Failed to create dataobject", e);
+ }
+
+ if (dataObject != null) {
+ return Optional.of(dataObject);
+ }
+ }
+ return Optional.absent();
+ }
}
/**
}
return currentOp.createDefault(path.getLastPathArgument());
}
-
- public BindingIndependentMappingService getLegacy() {
- return bindingToLegacy;
- }
-
- @Override
- public void close() throws Exception {
- // NOOP Intentionally
- }
}
*/
package org.opendaylight.controller.md.sal.binding.impl;
-import com.google.common.base.Function;
-import com.google.common.util.concurrent.AsyncFunction;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
+
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.AsyncDataBroker.DataChangeScope;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
@SuppressWarnings("deprecation")
public class ForwardedBackwardsCompatibleDataBroker extends AbstractForwardedDataBroker implements DataProviderService, AutoCloseable {
private final ListeningExecutorService executorService;
public ForwardedBackwardsCompatibleDataBroker(final DOMDataBroker domDataBroker,
- final BindingToNormalizedNodeCodec mappingService, final SchemaService schemaService,final ListeningExecutorService executor) {
+ final BindingIndependentMappingService mappingService, final SchemaService schemaService,final ListeningExecutorService executor) {
super(domDataBroker, mappingService,schemaService);
executorService = executor;
LOG.info("ForwardedBackwardsCompatibleBroker started.");
import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
/**
* The DataBrokerImpl simply defers to the DOMDataBroker for all its operations.
*/
public class ForwardedBindingDataBroker extends AbstractForwardedDataBroker implements DataBroker {
- public ForwardedBindingDataBroker(final DOMDataBroker domDataBroker, final BindingToNormalizedNodeCodec codec, final SchemaService schemaService) {
- super(domDataBroker, codec,schemaService);
+ public ForwardedBindingDataBroker(final DOMDataBroker domDataBroker, final BindingIndependentMappingService mappingService, final SchemaService schemaService) {
+ super(domDataBroker, mappingService,schemaService);
}
@Override
*/
package org.opendaylight.controller.sal.binding.codegen.impl;
-import com.google.common.util.concurrent.ForwardingBlockingQueue;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+
import javassist.ClassPool;
+
import org.apache.commons.lang3.StringUtils;
import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator;
import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory;
-import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.util.concurrent.ForwardingBlockingQueue;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
public class SingletonHolder {
private static final Logger logger = LoggerFactory.getLogger(SingletonHolder.class);
public static final ClassPool CLASS_POOL = ClassPool.getDefault();
- public static final JavassistUtils JAVASSIST = JavassistUtils.forClassPool(CLASS_POOL);
public static final org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator RPC_GENERATOR_IMPL = new org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator(
CLASS_POOL);
public static final RuntimeCodeGenerator RPC_GENERATOR = RPC_GENERATOR_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.binding.impl;\r
+\r
+import org.opendaylight.controller.config.yang.md.sal.binding.impl.Data;\r
+import org.opendaylight.controller.config.yang.md.sal.binding.impl.DataBrokerImplRuntimeMXBean;\r
+import org.opendaylight.controller.config.yang.md.sal.binding.impl.DataBrokerImplRuntimeRegistration;\r
+import org.opendaylight.controller.config.yang.md.sal.binding.impl.DataBrokerImplRuntimeRegistrator;\r
+import org.opendaylight.controller.config.yang.md.sal.binding.impl.Transactions;\r
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;\r
+\r
+public class RootDataBrokerImpl extends DataBrokerImpl implements DataBrokerImplRuntimeMXBean {\r
+\r
+ private final Transactions transactions = new Transactions();\r
+ private final Data data = new Data();\r
+ private BindingIndependentConnector bindingIndependentConnector;\r
+ private DataBrokerImplRuntimeRegistration runtimeBeanRegistration;\r
+\r
+ public BindingIndependentConnector getBindingIndependentConnector() {\r
+ return bindingIndependentConnector;\r
+ }\r
+\r
+ public Transactions getTransactions() {\r
+ transactions.setCreated(getCreatedTransactionsCount().get());\r
+ transactions.setSubmitted(getSubmittedTransactionsCount().get());\r
+ transactions.setSuccessful(getFinishedTransactionsCount().get());\r
+ transactions.setFailed(getFailedTransactionsCount().get());\r
+ return transactions;\r
+ }\r
+\r
+ @Override\r
+ public Data getData() {\r
+ data.setTransactions(getTransactions());\r
+ return data;\r
+ }\r
+\r
+ public void setBindingIndependentConnector(BindingIndependentConnector runtimeMapping) {\r
+ this.bindingIndependentConnector = runtimeMapping;\r
+ }\r
+\r
+ public void registerRuntimeBean(DataBrokerImplRuntimeRegistrator rootRegistrator) {\r
+ runtimeBeanRegistration = rootRegistrator.register(this);\r
+ }\r
+\r
+}\r
--- /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.impl.forward;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.opendaylight.controller.sal.binding.impl.RootDataBrokerImpl;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingDomConnectorDeployer;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+
+public class DomForwardedDataBrokerImpl extends RootDataBrokerImpl implements Provider, DomForwardedBroker {
+
+ private BindingIndependentConnector connector;
+ private ProviderSession domProviderContext;
+
+ public void setConnector(BindingIndependentConnector connector) {
+ this.connector = connector;
+ }
+
+ @Override
+ public void onSessionInitiated(ProviderSession session) {
+ this.setDomProviderContext(session);
+ }
+
+ @Override
+ public Collection<ProviderFunctionality> getProviderFunctionality() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public BindingIndependentConnector getConnector() {
+ return connector;
+ }
+
+ @Override
+ public ProviderSession getDomProviderContext() {
+ return domProviderContext;
+ }
+
+ public void setDomProviderContext(ProviderSession domProviderContext) {
+ this.domProviderContext = domProviderContext;
+ }
+
+ @Override
+ public void startForwarding() {
+ BindingDomConnectorDeployer.startDataForwarding(getConnector(), this, getDomProviderContext());
+ }
+}
identity binding-dom-mapping-service {
base config:service-type;
- config:java-class "org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec";
+ config:java-class "org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService";
}
+
identity binding-broker-impl {
base config:module-type;
config:provided-service sal:binding-broker-osgi-registry;
config:java-name-prefix BindingBrokerImpl;
}
+ identity binding-data-broker {
+ base config:module-type;
+ config:provided-service sal:binding-data-broker;
+ config:provided-service sal:binding-data-consumer-broker;
+ config:java-name-prefix DataBrokerImpl;
+ }
+
identity binding-data-compatible-broker {
base config:module-type;
config:provided-service sal:binding-data-broker;
}
}
+ augment "/config:modules/config:module/config:configuration" {
+ case binding-data-broker {
+ when "/config:modules/config:module/config:type = 'binding-data-broker'";
+ container dom-broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity dom:dom-broker-osgi-registry;
+ }
+ }
+ }
+
+ container mapping-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity binding-dom-mapping-service;
+ }
+ }
+ }
+ }
+ }
+
augment "/config:modules/config:module/config:configuration" {
case binding-data-compatible-broker {
when "/config:modules/config:module/config:type = 'binding-data-compatible-broker'";
}
}
+ augment "/config:modules/config:module/config:state" {
+ case binding-data-broker {
+ when "/config:modules/config:module/config:type = 'binding-data-broker'";
+ container data {
+ uses common:data-state;
+ }
+ }
+ }
augment "/config:modules/config:module/config:state" {
case binding-rpc-broker {
when "/config:modules/config:module/config:type = 'binding-rpc-broker'";
package org.opendaylight.controller.md.sal.binding.impl.test;
import static org.junit.Assert.assertTrue;
-
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.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.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;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
@Override
protected void setupWithSchema(final SchemaContext context) {
mappingService = new RuntimeGeneratedMappingServiceImpl(ClassPool.getDefault());
- StreamWriterGenerator streamWriter = new StreamWriterGenerator(JavassistUtils.forClassPool(ClassPool.getDefault()));
- BindingNormalizedNodeCodecRegistry registry = new BindingNormalizedNodeCodecRegistry(streamWriter);
- codec = new BindingToNormalizedNodeCodec(GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy(), mappingService, registry);
+ codec = new BindingToNormalizedNodeCodec(mappingService);
mappingService.onGlobalContextUpdated(context);
codec.onGlobalContextUpdated(context);
};
*/
package org.opendaylight.controller.md.sal.binding.test;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-
import javassist.ClassPool;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker;
import org.opendaylight.controller.md.sal.binding.impl.ForwardedBindingDataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.sal.binding.test.util.MockSchemaService;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
import org.opendaylight.controller.sal.core.spi.data.DOMStore;
-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.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.data.impl.codec.BindingIndependentMappingService;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
public class DataBrokerTestCustomizer {
private DOMDataBroker domDataBroker;
private final RuntimeGeneratedMappingServiceImpl mappingService;
private final MockSchemaService schemaService;
private ImmutableMap<LogicalDatastoreType, DOMStore> datastores;
- private final BindingToNormalizedNodeCodec bindingToNormalized ;
public ImmutableMap<LogicalDatastoreType, DOMStore> createDatastores() {
return ImmutableMap.<LogicalDatastoreType, DOMStore>builder()
public DataBrokerTestCustomizer() {
schemaService = new MockSchemaService();
- ClassPool pool = ClassPool.getDefault();
- mappingService = new RuntimeGeneratedMappingServiceImpl(pool);
- DataObjectSerializerGenerator generator = StreamWriterGenerator.create(JavassistUtils.forClassPool(pool));
- BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(generator);
- GeneratedClassLoadingStrategy loading = GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy();
- bindingToNormalized = new BindingToNormalizedNodeCodec(loading, mappingService, codecRegistry);
- schemaService.registerSchemaContextListener(bindingToNormalized);
+ mappingService = new RuntimeGeneratedMappingServiceImpl(ClassPool.getDefault());
}
public DOMStore createConfigurationDatastore() {
}
public DataBroker createDataBroker() {
- return new ForwardedBindingDataBroker(getDOMDataBroker(), bindingToNormalized, schemaService );
+ return new ForwardedBindingDataBroker(getDOMDataBroker(), getMappingService(), getSchemaService());
}
public ForwardedBackwardsCompatibleDataBroker createBackwardsCompatibleDataBroker() {
- return new ForwardedBackwardsCompatibleDataBroker(getDOMDataBroker(), bindingToNormalized, getSchemaService(), MoreExecutors.sameThreadExecutor());
+ return new ForwardedBackwardsCompatibleDataBroker(getDOMDataBroker(), getMappingService(), getSchemaService(), MoreExecutors.sameThreadExecutor());
}
+
private SchemaService getSchemaService() {
return schemaService;
}
import java.util.Collections;
import java.util.List;
import java.util.Map;
+
import org.junit.Test;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
*
* @throws Exception
*/
- @Test()
+ @Test( timeout = 15000)
public void testAugmentSerialization() throws Exception {
baDataService.registerDataChangeListener(NODES_INSTANCE_ID_BA, this);
testNodeRemove();
}
- private <T extends Augmentation<Node>> Node createTestNode(final Class<T> augmentationClass, final T augmentation) {
+ private <T extends Augmentation<Node>> Node createTestNode(Class<T> augmentationClass, T augmentation) {
NodeBuilder nodeBuilder = new NodeBuilder();
nodeBuilder.setId(new NodeId(NODE_ID));
nodeBuilder.setKey(NODE_KEY);
return nodeBuilder.build();
}
- private DataModificationTransaction commitNodeAndVerifyTransaction(final Node original) throws Exception {
+ private DataModificationTransaction commitNodeAndVerifyTransaction(Node original) throws Exception {
DataModificationTransaction transaction = baDataService.beginTransaction();
transaction.putOperationalData(NODE_INSTANCE_ID_BA, original);
RpcResult<TransactionStatus> result = transaction.commit().get();
assertNull(node);
}
- private AugmentationVerifier<Node> verifyNode(final Nodes nodes, final Node original) {
+ private AugmentationVerifier<Node> verifyNode(Nodes nodes, Node original) {
assertNotNull(nodes);
assertNotNull(nodes.getNode());
assertEquals(1, nodes.getNode().size());
return new AugmentationVerifier<Node>(readedNode);
}
- private void assertBindingIndependentVersion(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier nodeId) {
+ private void assertBindingIndependentVersion(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier nodeId) {
CompositeNode node = biDataService.readOperationalData(nodeId);
assertNotNull(node);
}
return nodeMeterStatistics(10, false);
}
- private NodeMeterStatistics nodeMeterStatistics(final int count, final boolean setDuration) {
+ private NodeMeterStatistics nodeMeterStatistics(int count, boolean setDuration) {
NodeMeterStatisticsBuilder nmsb = new NodeMeterStatisticsBuilder();
MeterStatisticsBuilder meterStats = new MeterStatisticsBuilder();
}
@Override
- public void onDataChanged(final DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ public void onDataChanged(DataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
receivedChangeEvent = change;
}
import static com.google.common.base.Preconditions.checkState;
-import com.google.common.annotations.Beta;
-import com.google.common.collect.ClassToInstanceMap;
-import com.google.common.collect.ImmutableClassToInstanceMap;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-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.impl.BindingToNormalizedNodeCodec;
import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker;
import org.opendaylight.controller.md.sal.binding.impl.ForwardedBindingDataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.sal.dom.broker.BrokerImpl;
import org.opendaylight.controller.sal.dom.broker.MountPointManagerImpl;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ClassToInstanceMap;
+import com.google.common.collect.ImmutableClassToInstanceMap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.MutableClassToInstanceMap;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
@Beta
public class BindingTestContext implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(BindingTestContext.class);
private RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
- private BindingToNormalizedNodeCodec codec;
private DomForwardedBindingBrokerImpl baBrokerImpl;
private DataBrokerImpl baDataImpl;
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, mockSchemaService);
+ dataBroker = new ForwardedBindingDataBroker(newDOMDataBroker, mappingServiceImpl, mockSchemaService);
}
public void startNewDomDataBroker() {
checkState(classPool != null, "ClassPool needs to be present");
mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl(classPool);
mockSchemaService.registerSchemaContextListener(mappingServiceImpl);
-
- DataObjectSerializerGenerator generator = StreamWriterGenerator.create(JavassistUtils.forClassPool(classPool));
- BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(generator);
- GeneratedClassLoadingStrategy loading = GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy();
- codec = new BindingToNormalizedNodeCodec(loading, mappingServiceImpl, codecRegistry);
- mockSchemaService.registerSchemaContextListener(codec);
}
private void updateYangSchema(final ImmutableSet<YangModuleInfo> moduleInfos) {
}
public void startNewBindingDataBroker() {
- ForwardedBackwardsCompatibleDataBroker forwarded = new ForwardedBackwardsCompatibleDataBroker(newDOMDataBroker, codec,mockSchemaService, executor);
+ ForwardedBackwardsCompatibleDataBroker forwarded = new ForwardedBackwardsCompatibleDataBroker(newDOMDataBroker, mappingServiceImpl,mockSchemaService, executor);
baData = forwarded;
}
mavenBundle(YANGTOOLS, "binding-generator-api").versionAsInProject(), mavenBundle(YANGTOOLS,
"binding-generator-spi").versionAsInProject(), //
mavenBundle(YANGTOOLS, "binding-generator-impl").versionAsInProject(),
- mavenBundle(YANGTOOLS, "binding-data-codec").versionAsInProject(),
mavenBundle(YANGTOOLS + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), // //
mavenBundle(CONTROLLER, "sal-core-api").versionAsInProject().update(), //
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
-import com.google.inject.Inject;
import java.util.concurrent.Future;
+
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.controller.sal.core.api.Broker;
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.NodeBuilder;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import com.google.inject.Inject;
+
public class DataServiceTest extends AbstractTest {
protected DataBrokerService consumerDataService;
public void setUp() throws Exception {
}
- /*
- *
- * Ignored this, because classes here are constructed from
- * very different class loader as MD-SAL is run into,
- * this is code is run from different classloader.
- *
- */
@Test
- @Ignore
public void test() throws Exception {
BindingAwareConsumer consumer1 = new BindingAwareConsumer() {
@Override
- public void onSessionInitialized(final ConsumerContext session) {
+ public void onSessionInitialized(ConsumerContext session) {
consumerDataService = session.getSALService(DataBrokerService.class);
}
};
DataModificationTransaction transaction = consumerDataService.beginTransaction();
assertNotNull(transaction);
- InstanceIdentifier<Node> node1 = createNodeRef("0");
- DataObject node = consumerDataService.readConfigurationData(node1);
+ NodeRef node1 = createNodeRef("0");
+ DataObject node = consumerDataService.readConfigurationData(node1.getValue());
assertNull(node);
Node nodeData1 = createNode("0");
- transaction.putConfigurationData(node1, nodeData1);
+ transaction.putConfigurationData(node1.getValue(), nodeData1);
Future<RpcResult<TransactionStatus>> commitResult = transaction.commit();
assertNotNull(commitResult);
assertNotNull(result.getResult());
assertEquals(TransactionStatus.COMMITED, result.getResult());
- Node readedData = (Node) consumerDataService.readConfigurationData(node1);
+ Node readedData = (Node) consumerDataService.readConfigurationData(node1.getValue());
assertNotNull(readedData);
assertEquals(nodeData1.getKey(), readedData.getKey());
DataModificationTransaction transaction2 = consumerDataService.beginTransaction();
assertNotNull(transaction);
- transaction2.removeConfigurationData(node1);
+ transaction2.removeConfigurationData(node1.getValue());
Future<RpcResult<TransactionStatus>> commitResult2 = transaction2.commit();
assertNotNull(commitResult2);
assertNotNull(result2.getResult());
assertEquals(TransactionStatus.COMMITED, result2.getResult());
- DataObject readedData2 = consumerDataService.readConfigurationData(node1);
+ DataObject readedData2 = consumerDataService.readConfigurationData(node1.getValue());
assertNull(readedData2);
}
- private static InstanceIdentifier<Node> createNodeRef(final String string) {
+ private static NodeRef createNodeRef(String string) {
NodeKey key = new NodeKey(new NodeId(string));
- return InstanceIdentifier.builder(Nodes.class).child(Node.class, key).build();
+ InstanceIdentifier<Node> path = InstanceIdentifier.builder(Nodes.class).child(Node.class, key).build();
+
+ return new NodeRef(path);
}
- private static Node createNode(final String string) {
+ private static Node createNode(String string) {
NodeBuilder ret = new NodeBuilder();
NodeId id = new NodeId(string);
ret.setKey(new NodeKey(id));
<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:schema-service-singleton</type>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
+ prefix:schema-service-singleton
+ </type>
<name>yang-schema-service</name>
</module>
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:runtime-generated-mapping</type>
- <name>runtime-mapping-singleton</name>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
+ prefix:hash-map-data-store
+ </type>
+ <name>hash-map-data-store</name>
</module>
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-notification-broker</type>
- <name>binding-notification-broker</name>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
+ prefix:dom-broker-impl
+ </type>
+ <name>dom-broker</name>
+ <data-store xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
+ dom:dom-data-store
+ </type>
+ <name>ref_hash-map-data-store</name>
+ </data-store>
</module>
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</type>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ prefix:binding-broker-impl
+ </type>
<name>binding-broker-impl</name>
- <notification-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
- <name>binding-notification-broker</name>
+ <notification-service
+ xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+ binding:binding-notification-service
+ </type>
+ <name>ref_binding-notification-broker</name>
</notification-service>
<data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
- <name>binding-data-broker</name>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+ binding:binding-data-broker
+ </type>
+ <name>ref_binding-data-broker</name>
</data-broker>
</module>
- <!--
- Tree-based in-memory data store. This is the data store which is currently
- recommended for single-node deployments.
- -->
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-inmemory-data-broker</type>
- <name>inmemory-data-broker</name>
- <schema-service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
- <name>yang-schema-service</name>
- </schema-service>
- </module>
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</type>
- <name>inmemory-dom-broker</name>
- <async-data-broker>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
- <name>inmemory-data-broker</name>
- </async-data-broker>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ prefix:runtime-generated-mapping
+ </type>
+ <name>runtime-mapping-singleton</name>
</module>
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-data-compatible-broker</type>
- <name>inmemory-binding-data-broker</name>
- <dom-async-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding: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-async-broker>
- <binding-mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
- <name>runtime-mapping-singleton</name>
- </binding-mapping-service>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ prefix:binding-notification-broker
+ </type>
+ <name>binding-notification-broker</name>
</module>
<module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-forwarded-data-broker</type>
- <name>binding-async-data-broker</name>
- <binding-forwarded-data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- <dom-async-broker>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
- <name>dom-broker</name>
- </dom-async-broker>
- <binding-mapping-service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
- <name>runtime-mapping-singleton</name>
- </binding-mapping-service>
- </binding-forwarded-data-broker>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ prefix:binding-data-broker
+ </type>
+ <name>binding-data-broker</name>
+ <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
+ dom:dom-broker-osgi-registry
+ </type>
+ <name>ref_dom-broker</name>
+ </dom-broker>
+ <mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ binding:binding-dom-mapping-service
+ </type>
+ <name>ref_runtime-mapping-singleton</name>
+ </mapping-service>
</module>
</modules>
<services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
<service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
+ dom:schema-service
+ </type>
<instance>
- <name>yang-schema-service</name>
- <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
+ <name>ref_yang-schema-service</name>
+ <provider>
+ /config/modules/module[name='schema-service-singleton']/instance[name='yang-schema-service']
+ </provider>
</instance>
</service>
<service>
- <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+ binding:binding-notification-service
+ </type>
<instance>
- <name>runtime-mapping-singleton</name>
- <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
+ <name>ref_binding-notification-broker</name>
+ <provider>
+ /config/modules/module[name='binding-notification-broker']/instance[name='binding-notification-broker']
+ </provider>
</instance>
</service>
<service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
+ dom:dom-data-store
+ </type>
<instance>
- <name>binding-notification-broker</name>
- <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
+ <name>ref_hash-map-data-store</name>
+ <provider>
+ /config/modules/module[name='hash-map-data-store']/instance[name='hash-map-data-store']
+ </provider>
</instance>
</service>
+
<service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+ binding:binding-broker-osgi-registry
+ </type>
<instance>
- <name>binding-osgi-broker</name>
- <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
+ <name>ref_binding-broker-impl</name>
+ <provider>
+ /config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl']
+ </provider>
</instance>
</service>
<service>
<provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
</instance>
</service>
-
- <service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
- <instance>
- <name>dom-broker</name>
- <provider>/modules/module[type='dom-broker-impl'][name='inmemory-dom-broker']</provider>
- </instance>
- </service>
-
<service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+ <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ binding-impl:binding-dom-mapping-service
+ </type>
<instance>
- <name>binding-data-broker</name>
- <provider>/modules/module[type='binding-data-compatible-broker'][name='inmemory-binding-data-broker']</provider>
+ <name>ref_runtime-mapping-singleton</name>
+ <provider>
+ /config/modules/module[name='runtime-generated-mapping']/instance[name='runtime-mapping-singleton']
+ </provider>
</instance>
</service>
-
<service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
+ dom:dom-broker-osgi-registry
+ </type>
<instance>
- <name>binding-data-broker</name>
- <provider>/modules/module[type='binding-forwarded-data-broker'][name='binding-async-data-broker']</provider>
+ <name>ref_dom-broker</name>
+ <provider>/config/modules/module[name='dom-broker-impl']/instance[name='dom-broker']
+ </provider>
</instance>
</service>
-
<service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+ binding:binding-data-broker
+ </type>
<instance>
- <name>inmemory-data-broker</name>
- <provider>/modules/module[type='dom-inmemory-data-broker'][name='inmemory-data-broker']</provider>
+ <name>ref_binding-data-broker</name>
+ <provider>
+ /config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker']
+ </provider>
</instance>
</service>
</services>
package org.opendaylight.md.controller.topology.manager;
import java.util.concurrent.ExecutionException;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
final String name = "flow:1";
final TopologyKey key = new TopologyKey(new TopologyId(name));
final InstanceIdentifier<Topology> path = InstanceIdentifier
- .builder(NetworkTopology.class)
- .child(Topology.class, key)
- .build();
+ .create(NetworkTopology.class)
+ .child(Topology.class, key);
final OperationProcessor processor = new OperationProcessor(dataBroker);
final FlowCapableTopologyExporter listener = new FlowCapableTopologyExporter(processor, path);
this.listenerRegistration = notificationService.registerNotificationListener(listener);
final ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
- tx.put(LogicalDatastoreType.OPERATIONAL, path, new TopologyBuilder().setKey(key).build());
+ tx.put(LogicalDatastoreType.OPERATIONAL, path, new TopologyBuilder().setKey(key).build(), true);
try {
tx.submit().get();
} catch (InterruptedException | ExecutionException e) {