-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
- <artifactId>concepts</artifactId>
- <version>${opendaylight.yangtools.version}</version>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
</dependency>
</dependencies>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Import-Package>
- javax.management,
- org.opendaylight.yangtools.concepts,
- org.osgi.framework,
- </Import-Package>
<Export-Package>
org.opendaylight.controller.config.api,
org.opendaylight.controller.config.api.annotations,
org.opendaylight.controller.config.api.jmx,
org.opendaylight.controller.config.api.jmx.constants,
org.opendaylight.controller.config.api.runtime,
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.rpc.context.rev130617.*,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.*,
</Export-Package>
</instructions>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ </plugin>
</plugins>
</build>
</project>
org.opendaylight.controller.config.manager.*,
javax.annotation.*,
</Private-Package>
- <Import-Package>
- org.opendaylight.controller.config.api.*,
- org.opendaylight.controller.config.spi.*,
- org.slf4j,
- javax.management,
- org.osgi.framework,
- org.opendaylight.yangtools.concepts.*,
- org.apache.commons.io,
- org.osgi.util.tracker,
- </Import-Package>
<Export-Package>
</Export-Package>
</instructions>
*/
package org.opendaylight.controller.config.manager.impl.osgi;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
import org.opendaylight.controller.config.api.jmx.CommitStatus;
import org.opendaylight.controller.config.manager.impl.ConfigRegistryImpl;
import org.opendaylight.controller.config.spi.ModuleFactory;
/**
* 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)}
+ * {@link org.opendaylight.controller.config.spi.ModuleFactory#getDefaultModules(org.opendaylight.controller.config.api.DependencyResolverFactory, org.osgi.framework.BundleContext)}
* functionality.
*/
public class BlankTransactionServiceTracker implements ServiceTrackerCustomizer<ModuleFactory, Object> {
}
private synchronized void blankTransaction() {
- // create transaction
- ObjectName tx = configRegistry.beginConfig();
- CommitStatus commitStatus = configRegistry.commitConfig(tx);
- logger.debug("Committed blank transaction with status {}", commitStatus);
+ // race condition check: config-persister might push new configuration while server is starting up.
+ ConflictingVersionException lastException = null;
+ for (int i = 0; i < 10; i++) {
+ try {
+ // create transaction
+ ObjectName tx = configRegistry.beginConfig();
+ CommitStatus commitStatus = configRegistry.commitConfig(tx);
+ logger.debug("Committed blank transaction with status {}", commitStatus);
+ return;
+ } catch (ConflictingVersionException e) {
+ lastException = e;
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException interruptedException) {
+ Thread.currentThread().interrupt();
+ throw new IllegalStateException(interruptedException);
+ }
+ }
+ }
+ throw lastException;
}
@Override
- public void modifiedService(ServiceReference<ModuleFactory> moduleFactoryServiceReference, Object o) {
+ public void modifiedService(ServiceReference <ModuleFactory> moduleFactoryServiceReference, Object o) {
blankTransaction();
}
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Import-Package>
- com.google.common.base,
- org.w3c.dom,
- org.osgi.framework,
- </Import-Package>
<Export-Package>
org.opendaylight.controller.config.persist.api,
org.opendaylight.controller.config.persist.api.storage,
</Fragment-Host>
<Provide-Capability>org.opendaylight.controller.config.persister.storage.adapter
</Provide-Capability>
- <Import-Package>
- org.osgi.framework,
- com.google.common.base,
- com.google.common.collect,
- com.google.common.io,
- javax.xml.parsers,
- javax.xml.transform,
- javax.xml.transform.dom,
- javax.xml.transform.stream,
- org.apache.commons.lang3,
- org.opendaylight.controller.config.persist.api,
- org.slf4j,
- org.w3c.dom,
- org.xml.sax,
- </Import-Package>
</instructions>
</configuration>
</plugin>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-subsystem</artifactId>
+ <version>0.2.3-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>config-plugin-parent</artifactId>
+ <name>${project.artifactId}</name>
+ <packaging>pom</packaging>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <properties>
+ <jmxGeneratorPath>${project.build.directory}/generated-sources/config</jmxGeneratorPath>
+ </properties>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>config</id>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ </codeGeneratorClass>
+ <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
+ <additionalConfiguration>
+ <namespaceToPackage1>
+ urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
+ </namespaceToPackage1>
+ </additionalConfiguration>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-jmx-generator-plugin</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+
+ <!-- tell eclipse about generated source folders -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.8</version>
+ <executions>
+ <execution>
+ <id>add-source</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>add-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>${jmxGeneratorPath}</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>config-subsystem</artifactId>
+ <artifactId>config-plugin-parent</artifactId>
<version>0.2.3-SNAPSHOT</version>
+ <relativePath>../config-plugin-parent</relativePath>
</parent>
<artifactId>logback-config</artifactId>
<name>${project.artifactId}</name>
<instructions>
<Private-Package>
</Private-Package>
- <Import-Package>
- ch.qos.logback.classic,
- ch.qos.logback.classic.encoder,
- ch.qos.logback.classic.filter,
- ch.qos.logback.classic.spi,
- ch.qos.logback.core,
- ch.qos.logback.core.status,
- ch.qos.logback.core.encoder,
- ch.qos.logback.core.rolling,
- org.opendaylight.controller.config.api,
- org.opendaylight.controller.config.api.runtime,
- org.opendaylight.controller.config.api.annotations,
- org.opendaylight.controller.config.spi,
- com.google.common.base,
- com.google.common.collect,
- org.apache.commons.lang3,
- org.slf4j,
- org.osgi.framework
- </Import-Package>
<Export-Package>
org.opendaylight.controller.config.yang.logback.config,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.logback.config.rev130716.*,
</Export-Package>
</instructions>
</configuration>
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>config-subsystem</artifactId>
- <version>0.2.3-SNAPSHOT</version>
+ <artifactId>config-plugin-parent</artifactId>
+ <version>0.2.3-SNAPSHOT</version>
+ <relativePath>../config-plugin-parent</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>netty-config-api</artifactId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Import-Package>
- org.opendaylight.controller.config.api.*,
- io.netty.channel,
- io.netty.util,
- io.netty.util.concurrent
- </Import-Package>
<Export-Package>
- org.opendaylight.controller.config.yang.netty
+ org.opendaylight.controller.config.yang.netty,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.netty.rev131119.*,
</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
-</project>
\ No newline at end of file
+</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>config-subsystem</artifactId>
- <version>0.2.3-SNAPSHOT</version>
+ <artifactId>config-plugin-parent</artifactId>
+ <version>0.2.3-SNAPSHOT</version>
+ <relativePath>../config-plugin-parent</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>netty-event-executor-config</artifactId>
<instructions>
<Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
<Export-Package>
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.netty.eventexecutor.rev131112.*,
</Export-Package>
- <Import-Package>
- com.google.common.base,
- org.opendaylight.controller.config.yang.netty,
- io.netty.util.concurrent,
- org.opendaylight.controller.config.api,
- org.opendaylight.controller.config.api.annotations,
- org.opendaylight.controller.config.api.runtime,
- org.opendaylight.controller.config.spi,
- org.slf4j,
- org.osgi.framework
- </Import-Package>
</instructions>
</configuration>
</plugin>
</site>
</distributionManagement>
-</project>
\ No newline at end of file
+</project>
<parent>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>config-subsystem</artifactId>
+ <artifactId>config-plugin-parent</artifactId>
<version>0.2.3-SNAPSHOT</version>
+ <relativePath>../config-plugin-parent</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<instructions>
<Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
<Export-Package>
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.netty.threadgroup.rev131107.*,
</Export-Package>
- <Import-Package>
- com.google.common.base,
- io.netty.channel.nio,
- org.opendaylight.controller.config.yang.netty,
- io.netty.util.concurrent,
- org.opendaylight.controller.config.api,
- org.opendaylight.controller.config.api.annotations,
- org.opendaylight.controller.config.api.runtime,
- org.opendaylight.controller.config.spi,
- org.slf4j,
- org.osgi.framework
- </Import-Package>
</instructions>
</configuration>
</plugin>
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>config-subsystem</artifactId>
- <version>0.2.3-SNAPSHOT</version>
+ <artifactId>config-plugin-parent</artifactId>
+ <version>0.2.3-SNAPSHOT</version>
+ <relativePath>../config-plugin-parent</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>netty-timer-config</artifactId>
<instructions>
<Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
<Export-Package>
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.netty.timer.rev131119.*,
</Export-Package>
- <Import-Package>
- javax.management,
- com.google.common.base,
- org.opendaylight.controller.config.yang.netty,
- org.opendaylight.controller.config.yang.threadpool,
- io.netty.util,
- org.opendaylight.controller.config.api,
- org.opendaylight.controller.config.api.annotations,
- org.opendaylight.controller.config.api.runtime,
- org.opendaylight.controller.config.spi,
- org.slf4j,
- org.osgi.framework
- </Import-Package>
</instructions>
</configuration>
</plugin>
<url>${basedir}/target/site/${project.artifactId}</url>
</site>
</distributionManagement>
-</project>
\ No newline at end of file
+</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<modules>
<module>config-api</module>
<module>config-manager</module>
+ <module>config-plugin-parent</module>
<module>config-util</module>
<module>config-persister-api</module>
<module>config-persister-file-adapter</module>
<opendaylight.yang.version>0.5.9-SNAPSHOT</opendaylight.yang.version>
<opendaylight.binding.version>0.6.0-SNAPSHOT</opendaylight.binding.version>
<opendaylight.yangtools.version>0.1.1-SNAPSHOT</opendaylight.yangtools.version>
- <jmxGeneratorPath>${project.build.directory}/generated-sources/config</jmxGeneratorPath>
</properties>
<dependencies>
<artifactId>yang-store-api</artifactId>
<version>${config.version}</version>
</dependency>
+
+ <!-- MD-SAL -->
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ <version>${opendaylight.binding.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ <version>${opendaylight.yang.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>concepts</artifactId>
+ <version>${opendaylight.yangtools.version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>
</plugin>
</plugins>
-
-
<pluginManagement>
<plugins>
<plugin>
<version>${opendaylight.yang.version}</version>
<executions>
<execution>
+ <id>sal</id>
<goals>
<goal>generate-sources</goal>
</goals>
<configuration>
+ <yangFilesRootDir>src/main/yang</yangFilesRootDir>
<codeGenerators>
<generator>
<codeGeneratorClass>
- org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
</codeGeneratorClass>
- <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
- <additionalConfiguration>
- <namespaceToPackage1>
- urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
- </namespaceToPackage1>
- </additionalConfiguration>
+ <outputBaseDir>
+ target/generated-sources/sal
+ </outputBaseDir>
+ </generator>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
+ <outputBaseDir>target/site</outputBaseDir>
</generator>
</codeGenerators>
<inspectDependencies>true</inspectDependencies>
</executions>
<dependencies>
<dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>yang-jmx-generator-plugin</artifactId>
- <version>${config.version}</version>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>maven-sal-api-gen-plugin</artifactId>
+ <version>${opendaylight.binding.version}</version>
+ <type>jar</type>
</dependency>
</dependencies>
</plugin>
- <!-- tell eclipse about generated source folders -->
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <version>1.8</version>
- <executions>
- <execution>
- <id>add-source</id>
- <phase>generate-sources</phase>
- <goals>
- <goal>add-source</goal>
- </goals>
- <configuration>
- <sources>
- <source>${jmxGeneratorPath}</source>
- </sources>
- </configuration>
- </execution>
- </executions>
- </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>config-subsystem</artifactId>
- <version>0.2.3-SNAPSHOT</version>
+ <artifactId>config-plugin-parent</artifactId>
+ <version>0.2.3-SNAPSHOT</version>
+ <relativePath>../config-plugin-parent</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>threadpool-config-api</artifactId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Import-Package>
- org.opendaylight.controller.config.api.*,
- com.google.common.eventbus,
- </Import-Package>
<Export-Package>
org.opendaylight.controller.config.threadpool,
- org.opendaylight.controller.config.yang.threadpool
+ org.opendaylight.controller.config.yang.threadpool,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.threadpool.rev130409.*,
</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
-</project>
\ No newline at end of file
+</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>config-subsystem</artifactId>
- <version>0.2.3-SNAPSHOT</version>
+ <artifactId>config-plugin-parent</artifactId>
+ <version>0.2.3-SNAPSHOT</version>
+ <relativePath>../config-plugin-parent</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>threadpool-config-impl</artifactId>
javax.annotation.*,
org.opendaylight.controller.config.yang.threadpool.impl,
</Private-Package>
- <Import-Package>
- org.opendaylight.controller.config.api.*,
- org.opendaylight.controller.config.spi.*,
- org.opendaylight.controller.config.threadpool,
- org.opendaylight.controller.config.yang.threadpool,
- javax.management,
- org.osgi.framework,
- org.slf4j,
- com.google.common.*
- </Import-Package>
<Export-Package>
- org.opendaylight.controller.config.threadpool.util
+ org.opendaylight.controller.config.threadpool.util,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.threadpool.impl.rev130405.*,
</Export-Package>
</instructions>
</configuration>
public String getDefinition() {
return definition;
}
+
+ public boolean isArray() {
+ return type.endsWith("[]");
+ }
}
dependencyResolver.validateDependency(${field.dependency.sie.fullyQualifiedName}.class, ${field.name}, ${field.name}JmxAttribute);
</#if>
</#list>
+ customValidation();
+ }
+
+ protected void customValidation(){
+
}
// caches of resolved dependencies
public boolean canReuseInstance(${typeDeclaration.name} oldModule){
// allow reusing of old instance if no parameters was changed
- return equals(oldModule);
+ return isSame(oldModule);
}
public ${instanceType} reuseInstance(${instanceType} oldInstance){
public abstract ${instanceType} createInstance();
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- ${typeDeclaration.name} other = (${typeDeclaration.name}) obj;
-
-
+ public boolean isSame(${typeDeclaration.name} other) {
+ if (other == null) {
+ throw new IllegalArgumentException("Parameter 'other' is null");
+ }
<#list moduleFields as field>
<#if field.dependent==true>
if (${field.name}Dependency == null) {
if (other.${field.name}Dependency != null)
return false;
- } else if (!${field.name}Dependency.equals(other.${field.name}Dependency))
+ } else if (!${field.name}Dependency.equals(other.${field.name}Dependency)) {
return false;
+ }
<#else>
if (${field.name} == null) {
- if (other.${field.name} != null)
+ if (other.${field.name} != null) {
return false;
- } else if (!${field.name}.equals(other.${field.name}))
+ }
+ } else if
+ <#if field.array == false>
+ (${field.name}.equals(other.${field.name}) == false)
+ <#else>
+ (java.util.Arrays.equals(${field.name},other.${field.name}) == false)
+ </#if>
+ {
return false;
+ }
</#if>
</#list>
return true;
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ${typeDeclaration.name} that = (${typeDeclaration.name}) o;
+
+ return identifier.equals(that.identifier);
+ }
+
+ @Override
+ public int hashCode() {
+ return identifier.hashCode();
+ }
}
package ${packageName};
<@javadocD object=javadoc/>
-<@typeDeclarationD object=typeDeclaration/>
-{
+<@typeDeclarationD object=typeDeclaration/> {
public ${typeDeclaration.name}(${moduleNameType} identifier, ${dependencyResolverType} dependencyResolver) {
super(identifier, dependencyResolver);
}
- public ${typeDeclaration.name}(${moduleNameType} identifier, ${dependencyResolverType} dependencyResolver, ${typeDeclaration.name} oldModule, ${instanceType} oldInstance) {
+ public ${typeDeclaration.name}(${moduleNameType} identifier, ${dependencyResolverType} dependencyResolver,
+ ${typeDeclaration.name} oldModule, ${instanceType} oldInstance) {
+
super(identifier, dependencyResolver, oldModule, oldInstance);
}
@Override
- public void validate(){
- super.validate();
+ protected void customValidation(){
// Add custom validation for module attributes here.
}
assertContains(reqIfc, PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
+ ".threads.ThreadFactoryServiceInterface");
- assertEquals("Incorrenct number of generated methods", 24,
+ assertEquals("Incorrenct number of generated methods", 27,
visitor.methods.size());
assertEquals("Incorrenct number of generated method descriptions", 3,
visitor.methodDescriptions.size());
<Private-Package>
org.opendaylight.controller.config.yangjmxgenerator.plugin.util,
</Private-Package>
- <Import-Package>
- org.slf4j,
- com.google.common.base,
- com.google.common.collect,
- javax.management.*,
- <!-- YANGTOOLS -->
- org.opendaylight.yangtools.binding.generator.util,
- org.opendaylight.yangtools.sal.binding.generator.spi,
- org.opendaylight.yangtools.sal.binding.model.api,
- org.opendaylight.yangtools.yang.common,
- org.opendaylight.yangtools.yang.model.api
- </Import-Package>
<Export-Package>
org.opendaylight.controller.config.yangjmxgenerator,
org.opendaylight.controller.config.yangjmxgenerator.attribute,
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Import-Package>
- org.opendaylight.controller.config.yangjmxgenerator,
- org.opendaylight.yangtools.yang.model.api
- </Import-Package>
<Export-Package>
org.opendaylight.controller.config.yang.store.api,
</Export-Package>
<configuration>
<instructions>
<Bundle-Activator>org.opendaylight.controller.config.yang.store.impl.YangStoreActivator</Bundle-Activator>
- <Import-Package>
- org.opendaylight.controller.config.yang.store.api,
- org.opendaylight.controller.config.yangjmxgenerator,
- com.google.common.base,
- com.google.common.collect,
- com.google.common.primitives,
- org.apache.commons.io,
- org.osgi.framework,
- org.osgi.util.tracker,
- org.slf4j,
- <!-- YANGTOOLS -->
- org.opendaylight.yangtools.sal.binding.yang.types,
- org.opendaylight.yangtools.yang.common,
- org.opendaylight.yangtools.yang.model.api,
- org.opendaylight.yangtools.sal.binding.generator.spi,
- org.opendaylight.yangtools.yang.parser.impl,
- </Import-Package>
<Export-Package>
</Export-Package>
</instructions>
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>config-subsystem</artifactId>
+ <artifactId>config-plugin-parent</artifactId>
<version>0.2.3-SNAPSHOT</version>
+ <relativePath>../config-plugin-parent</relativePath>
</parent>
<artifactId>yang-test</artifactId>
-/**
- * Generated file
-
- * Generated from: yang module name: config-test-impl yang module local name: impl-dep
- * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
- * Generated at: Fri Sep 27 13:02:28 CEST 2013
- *
- * Do not modify this file unless it is present under src/main directory
- */
package org.opendaylight.controller.config.yang.test.impl;
-
/**
*
*/
-public final class DepTestImplModule
- extends
- org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModule {
+public final class DepTestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModule
+ {
- public DepTestImplModule(
- org.opendaylight.controller.config.api.ModuleIdentifier name,
- org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
- super(name, dependencyResolver);
+ public DepTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
}
- public DepTestImplModule(
- org.opendaylight.controller.config.api.ModuleIdentifier name,
- org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+ public DepTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
DepTestImplModule oldModule, java.lang.AutoCloseable oldInstance) {
- super(name, dependencyResolver, oldModule, oldInstance);
+
+ super(identifier, dependencyResolver, oldModule, oldInstance);
}
@Override
- public void validate() {
- super.validate();
+ protected void customValidation(){
// Add custom validation for module attributes here.
}
}
};
}
-
}
-/**
- * Generated file
-
- * Generated from: yang module name: config-test-impl yang module local name: impl-dep
- * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
- * Generated at: Fri Sep 27 13:02:28 CEST 2013
- *
- * Do not modify this file unless it is present under src/main directory
- */
package org.opendaylight.controller.config.yang.test.impl;
/**
*
*/
-public class DepTestImplModuleFactory
- extends
- org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModuleFactory {
+public class DepTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractDepTestImplModuleFactory
+{
+
}
--- /dev/null
+ return new AutoCloseable() {
+ @Override
+ public void close() throws Exception {
+ }
+ };
-/**
- * Generated file
-
- * Generated from: yang module name: config-test-impl yang module local name: impl-netconf
- * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
- * Generated at: Fri Sep 27 13:02:28 CEST 2013
- *
- * Do not modify this file unless it is present under src/main directory
- */
package org.opendaylight.controller.config.yang.test.impl;
-
-import com.google.common.collect.Lists;
-
-import java.util.List;
-
/**
*
*/
-public final class NetconfTestImplModule
- extends
- org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModule {
+public final class NetconfTestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModule
+ {
- public NetconfTestImplModule(
- org.opendaylight.controller.config.api.ModuleIdentifier name,
- org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
- super(name, dependencyResolver);
+ public NetconfTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
}
- public NetconfTestImplModule(
- org.opendaylight.controller.config.api.ModuleIdentifier name,
- org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+ public NetconfTestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
NetconfTestImplModule oldModule, java.lang.AutoCloseable oldInstance) {
- super(name, dependencyResolver, oldModule, oldInstance);
+
+ super(identifier, dependencyResolver, oldModule, oldInstance);
}
@Override
- public void validate() {
- super.validate();
+ protected void customValidation(){
// Add custom validation for module attributes here.
}
@Override
public java.lang.AutoCloseable createInstance() {
- return registerRuntimeBeans();
+ return NetconfTestImplModuleUtil.registerRuntimeBeans(this);
}
-
- private NetconfTestImplRuntimeRegistration registerRuntimeBeans() {
- NetconfTestImplRuntimeRegistration reg = getRootRuntimeBeanRegistratorWrapper().register(new NetconfTestImplRuntimeMXBean() {
-
- @Override
- public Long getCreatedSessions() {
- return getSimpleLong();
- }
-
- @Override
- public Asdf getAsdf() {
- final Asdf asdf = new Asdf();
- asdf.setSimpleString("asdf");
- return asdf;
- }
-
- @Override
- public String noArg(final String arg1) {
- return arg1.toUpperCase();
- }
-
- });
-
- for (int i = 0; i < getSimpleShort(); i++) {
- final int finalI = i;
-
- reg.register(new InnerRunningDataAdditionalRuntimeMXBean() {
- @Override
- public Integer getSimpleInt3() {
- return getSimpleTest();
- }
-
- @Override
- public Deep4 getDeep4() {
- final Deep4 d = new Deep4();
- d.setBoool(false);
- return d;
- }
-
- @Override
- public String getSimpleString() {
- return Integer.toString(finalI);
- }
-
- @Override
- public void noArgInner() {
- }
- });
-
- InnerRunningDataRuntimeRegistration innerReg = reg.register(new InnerRunningDataRuntimeMXBean() {
- @Override
- public Integer getSimpleInt3() {
- return finalI;
- }
-
- @Override
- public Deep2 getDeep2() {
- return new Deep2();
- }
- });
-
- for (int j = 0; j < getSimpleShort(); j++) {
- final int finalJ = j;
- innerReg.register(new InnerInnerRunningDataRuntimeMXBean() {
- @Override
- public List<NotStateBean> getNotStateBean() {
- NotStateBean b1 = new NotStateBean();
- b1.setElement("not state");
- return Lists.newArrayList(b1);
- }
-
- @Override
- public Integer getSimpleInt3() {
- return finalJ;
- }
-
- @Override
- public Deep3 getDeep3() {
- return new Deep3();
- }
-
- @Override
- public List<String> getListOfStrings() {
- return Lists.newArrayList("l1", "l2");
- }
-
- @Override
- public List<RetValList> listOutput() {
- return Lists.newArrayList(new RetValList());
- }
-
- @Override
- public Boolean noArgInnerInner(Integer integer, Boolean aBoolean) {
- return aBoolean;
- }
-
- @Override
- public RetValContainer containerOutput() {
- return new RetValContainer();
- }
-
- @Override
- public List<String> leafListOutput() {
- return Lists.newArrayList("1", "2");
- }
- });
- }
- }
-
- return reg;
- }
-
}
-/**
- * Generated file
-
- * Generated from: yang module name: config-test-impl yang module local name: impl-netconf
- * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
- * Generated at: Fri Sep 27 13:02:28 CEST 2013
- *
- * Do not modify this file unless it is present under src/main directory
- */
package org.opendaylight.controller.config.yang.test.impl;
/**
*
*/
-public class NetconfTestImplModuleFactory
- extends
- org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModuleFactory {
+public class NetconfTestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractNetconfTestImplModuleFactory
+{
+
}
--- /dev/null
+return NetconfTestImplModuleUtil.registerRuntimeBeans(this);
--- /dev/null
+/**
+ * @author Tomas Olvecky
+ *
+ * 11 2013
+ *
+ * Copyright (c) 2013 by Cisco Systems, Inc.
+ * All rights reserved.
+ */
+package org.opendaylight.controller.config.yang.test.impl;
+
+import com.google.common.collect.Lists;
+
+import java.util.List;
+
+public class NetconfTestImplModuleUtil {
+ static NetconfTestImplRuntimeRegistration registerRuntimeBeans(final NetconfTestImplModule module) {
+ NetconfTestImplRuntimeRegistration reg = module.getRootRuntimeBeanRegistratorWrapper().register(new NetconfTestImplRuntimeMXBean() {
+
+ @Override
+ public Long getCreatedSessions() {
+ return module.getSimpleLong();
+ }
+
+ @Override
+ public Asdf getAsdf() {
+ final Asdf asdf = new Asdf();
+ asdf.setSimpleString("asdf");
+ return asdf;
+ }
+
+ @Override
+ public String noArg(final String arg1) {
+ return arg1.toUpperCase();
+ }
+
+ });
+
+ for (int i = 0; i < module.getSimpleShort(); i++) {
+ final int finalI = i;
+
+ reg.register(new InnerRunningDataAdditionalRuntimeMXBean() {
+ @Override
+ public Integer getSimpleInt3() {
+ return module.getSimpleTest();
+ }
+
+ @Override
+ public Deep4 getDeep4() {
+ final Deep4 d = new Deep4();
+ d.setBoool(false);
+ return d;
+ }
+
+ @Override
+ public String getSimpleString() {
+ return Integer.toString(finalI);
+ }
+
+ @Override
+ public void noArgInner() {
+ }
+ });
+
+ InnerRunningDataRuntimeRegistration innerReg = reg.register(new InnerRunningDataRuntimeMXBean() {
+ @Override
+ public Integer getSimpleInt3() {
+ return finalI;
+ }
+
+ @Override
+ public Deep2 getDeep2() {
+ return new Deep2();
+ }
+ });
+
+ for (int j = 0; j < module.getSimpleShort(); j++) {
+ final int finalJ = j;
+ innerReg.register(new InnerInnerRunningDataRuntimeMXBean() {
+ @Override
+ public List<NotStateBean> getNotStateBean() {
+ NotStateBean b1 = new NotStateBean();
+ b1.setElement("not state");
+ return Lists.newArrayList(b1);
+ }
+
+ @Override
+ public Integer getSimpleInt3() {
+ return finalJ;
+ }
+
+ @Override
+ public Deep3 getDeep3() {
+ return new Deep3();
+ }
+
+ @Override
+ public List<String> getListOfStrings() {
+ return Lists.newArrayList("l1", "l2");
+ }
+
+ @Override
+ public List<RetValList> listOutput() {
+ return Lists.newArrayList(new RetValList());
+ }
+
+ @Override
+ public Boolean noArgInnerInner(Integer integer, Boolean aBoolean) {
+ return aBoolean;
+ }
+
+ @Override
+ public RetValContainer containerOutput() {
+ return new RetValContainer();
+ }
+
+ @Override
+ public List<String> leafListOutput() {
+ return Lists.newArrayList("1", "2");
+ }
+ });
+ }
+ }
+
+ return reg;
+ }
+}
-/**
- * Generated file
-
- * Generated from: yang module name: config-test-impl yang module local name: impl
- * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
- * Generated at: Fri Sep 27 13:02:28 CEST 2013
- *
- * Do not modify this file unless it is present under src/main directory
- */
package org.opendaylight.controller.config.yang.test.impl;
-
/**
*
*/
-public final class TestImplModule
- extends
- org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModule {
+public final class TestImplModule extends org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModule
+ {
- public TestImplModule(
- org.opendaylight.controller.config.api.ModuleIdentifier name,
- org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
- super(name, dependencyResolver);
+ public TestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
}
- public TestImplModule(
- org.opendaylight.controller.config.api.ModuleIdentifier name,
- org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+ public TestImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
TestImplModule oldModule, java.lang.AutoCloseable oldInstance) {
- super(name, dependencyResolver, oldModule, oldInstance);
+
+ super(identifier, dependencyResolver, oldModule, oldInstance);
}
@Override
- public void validate() {
- super.validate();
+ protected void customValidation(){
// Add custom validation for module attributes here.
}
}
};
}
-
}
-/**
- * Generated file
-
- * Generated from: yang module name: config-test-impl yang module local name: impl
- * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
- * Generated at: Fri Sep 27 13:02:28 CEST 2013
- *
- * Do not modify this file unless it is present under src/main directory
- */
package org.opendaylight.controller.config.yang.test.impl;
/**
*
*/
-public class TestImplModuleFactory
- extends
- org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModuleFactory {
+public class TestImplModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractTestImplModuleFactory
+{
+
}
--- /dev/null
+ return new AutoCloseable() {
+ @Override
+ public void close() throws Exception {
+ }
+ };
private void addFlow(InstanceIdentifier<?> path, Flow dataObject) {
AddFlowInputBuilder input = new AddFlowInputBuilder();
+
List<Instruction> inst = (dataObject).getInstructions().getInstruction();
input.setNode((dataObject).getNode());
input.setPriority((dataObject).getPriority());
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupRemoved;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupUpdated;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInputBuilder;
-
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes.GroupType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.config.rev131024.meters.Meter;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
return new Status(StatusCode.BADREQUEST, "Group record does not exist");
}*/
- if (!(group.getGroupType().getIntValue() >= GroupType.GroupAll.getIntValue() && group.getGroupType()
- .getIntValue() <= GroupType.GroupFf.getIntValue())) {
+ if (!(group.getGroupType().getIntValue() >= GroupTypes.GroupAll.getIntValue() && group.getGroupType()
+ .getIntValue() <= GroupTypes.GroupFf.getIntValue())) {
logger.error("Invalid Group type %d" + group.getGroupType().getIntValue());
return new Status(StatusCode.BADREQUEST, "Invalid Group type");
}
type uint32;
}
- grouping group-types {
- leaf group-type {
- type enumeration {
- enum group-all;
- enum group-select;
- enum group-indirect;
- enum group-ff;
- }
- }
+ typedef group-types {
+ type enumeration {
+ enum group-all;
+ enum group-select;
+ enum group-indirect;
+ enum group-ff;
+ }
}
typedef group-capabilities {
- type enumeration {
- enum select-weight;
- enum select-liveness;
- enum chaining;
- enum chaining-checks;
- }
- }
+ type enumeration {
+ enum select-weight;
+ enum select-liveness;
+ enum chaining;
+ enum chaining-checks;
+ }
+ }
grouping group {
- uses group-types;
+ leaf group-type {
+ type group-types;
+ }
leaf group-id {
type group-id;
type uint32;
}
- grouping meter-flags {
- leaf flags {
- type bits {
- bit meter-kbps;
- bit meter-pktps;
- bit meter-burst;
- bit meter-stats;
- }
- }
+ // field types
+ identity meter-flags {
+ description "Base identity for match Fields";
}
- grouping meter-band-type {
- leaf flags {
- type bits {
- bit ofpmbt-drop;
- bit ofpmbt-dscp-remark;
- bit ofpmbt-experimenter;
- }
+ typedef meter-flags {
+ type bits {
+ bit meter-kbps;
+ bit meter-pktps;
+ bit meter-burst;
+ bit meter-stats;
+ }
+ }
+
+ typedef meter-band-type {
+ type bits {
+ bit ofpmbt-drop;
+ bit ofpmbt-dscp-remark;
+ bit ofpmbt-experimenter;
}
}
grouping meter {
- uses meter-flags;
+ leaf flags {
+ type meter-flags;
+ }
leaf meter-id {
type meter-id;
}
container meter-band-types {
- uses meter-band-type;
+ leaf flags {
+ type meter-band-type;
+ }
}
leaf rate {
checkNotNull(parent);
checkNotNull(parentSchema);
- List<String> longestPathToElementViaChoiceCase = new ArrayList<>();
for (Node<?> child : parent.getChildren()) {
- Deque<String> choiceCasePathStack = new ArrayDeque<>(longestPathToElementViaChoiceCase);
- SchemaLocation schemaLocation = findFirstSchemaForNode(child, parentSchema.getChildNodes(),
- choiceCasePathStack);
-
- if (schemaLocation == null) {
- if (!choiceCasePathStack.isEmpty()) {
- throw new UnsupportedDataTypeException("On choice-case path " + choiceCasePathStack
- + " wasn't found data schema for " + child.getNodeType().getLocalName());
- } else {
- throw new UnsupportedDataTypeException("Probably the data node \""
- + child.getNodeType().getLocalName() + "\" is not conform to schema");
- }
- }
-
- longestPathToElementViaChoiceCase = resolveLongerPath(longestPathToElementViaChoiceCase,
- schemaLocation.getLocation());
+ DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchema.getChildNodes());
- DataSchemaNode childSchema = schemaLocation.getSchema();
+ if (childSchema == null) {
+ throw new UnsupportedDataTypeException("Probably the data node \"" + child.getNodeType().getLocalName()
+ + "\" is not conform to schema");
+ }
if (childSchema instanceof ContainerSchemaNode) {
Preconditions.checkState(child instanceof CompositeNode,
}
for (Node<?> child : parent.getChildren()) {
- SchemaLocation schemaLocation = findFirstSchemaForNode(child, parentSchema.getChildNodes(),
- new ArrayDeque<>(longestPathToElementViaChoiceCase));
-
- DataSchemaNode childSchema = schemaLocation.getSchema();
+ DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchema.getChildNodes());
if (childSchema instanceof LeafListSchemaNode) {
foundLeafLists.remove((LeafListSchemaNode) childSchema);
} else if (childSchema instanceof ListSchemaNode) {
}
}
- private List<String> resolveLongerPath(List<String> l1, List<String> l2) {
- return l1.size() > l2.size() ? l1 : l2;
- }
-
- private SchemaLocation findFirstSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode,
- Deque<String> pathIterator) {
- Map<String, ChoiceNode> choiceSubnodes = new HashMap<>();
+ private DataSchemaNode findFirstSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
for (DataSchemaNode dsn : dataSchemaNode) {
- if (dsn instanceof ChoiceNode) {
- choiceSubnodes.put(dsn.getQName().getLocalName(), (ChoiceNode) dsn);
- } else if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
- return new SchemaLocation(dsn);
- }
- }
-
- for (ChoiceNode choiceSubnode : choiceSubnodes.values()) {
- if ((!pathIterator.isEmpty() && pathIterator.peekLast().equals(choiceSubnode.getQName().getLocalName()))
- || pathIterator.isEmpty()) {
- String pathPartChoice = pathIterator.pollLast();
- for (ChoiceCaseNode concreteCase : choiceSubnode.getCases()) {
- if ((!pathIterator.isEmpty() && pathIterator.peekLast().equals(
- concreteCase.getQName().getLocalName()))
- || pathIterator.isEmpty()) {
- String pathPartCase = pathIterator.pollLast();
- SchemaLocation schemaLocation = findFirstSchemaForNode(node, concreteCase.getChildNodes(),
- pathIterator);
- if (schemaLocation != null) {
- schemaLocation.addPathPart(concreteCase.getQName().getLocalName());
- schemaLocation.addPathPart(choiceSubnode.getQName().getLocalName());
- return schemaLocation;
- }
- if (pathPartCase != null) {
- pathIterator.addLast(pathPartCase);
- }
+ if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
+ return dsn;
+ } else if (dsn instanceof ChoiceNode) {
+ for (ChoiceCaseNode choiceCase : ((ChoiceNode) dsn).getCases()) {
+ DataSchemaNode foundDsn = findFirstSchemaForNode(node, choiceCase.getChildNodes());
+ if (foundDsn != null) {
+ return foundDsn;
}
}
- if (pathPartChoice != null) {
- pathIterator.addLast(pathPartChoice);
- }
}
}
return null;
+++ /dev/null
-package org.opendaylight.controller.sal.rest.impl;
-
-import java.util.*;
-
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-
-class SchemaLocation {
- final private List<String> location = new ArrayList<>();
- final private DataSchemaNode schema;
-
- public SchemaLocation(DataSchemaNode schema) {
- this.schema = schema;
- }
-
- DataSchemaNode getSchema() {
- return schema;
- }
-
- List<String> getLocation() {
- return location;
- }
-
- SchemaLocation addPathPart(String partOfPath) {
- location.add(partOfPath);
- return this;
- }
-
-}
package org.opendaylight.controller.sal.restconf.impl
-import javax.ws.rs.WebApplicationException
import javax.ws.rs.core.Response
import org.opendaylight.controller.md.sal.common.api.data.DataReader
import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession
private String localName;
private URI namespace;
+ private QName name;
private List<NodeWrapper<?>> values = new ArrayList<>();
public CompositeNodeWrapper(String localName) {
this(localName);
this.namespace = namespace;
}
+
+ @Override
+ public void setQname(QName name) {
+ Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies.");
+ this.name = name;
+ }
@Override
public String getLocalName() {
@Override
public CompositeNode unwrap(CompositeNode parent) {
if (compositeNode == null) {
- Preconditions.checkNotNull(namespace);
- compositeNode = NodeFactory.createMutableCompositeNode(new QName(namespace, localName),
- parent, new ArrayList<Node<?>>(), ModifyAction.CREATE, null);
+ if (name == null) {
+ Preconditions.checkNotNull(namespace);
+ name = new QName(namespace, localName);
+ }
+ compositeNode = NodeFactory.createMutableCompositeNode(name, parent, new ArrayList<Node<?>>(), null, null);
List<Node<?>> nodeValues = new ArrayList<>();
for (NodeWrapper<?> nodeWrapper : values) {
values = null;
namespace = null;
localName = null;
+ name = null;
}
return compositeNode;
}
private def dispatch CharSequence toRestconfIdentifier(PathArgument argument, DataSchemaNode node) {
throw new IllegalArgumentException("Conversion of generic path argument is not supported");
}
+
+ def findModuleByNamespace(URI namespace) {
+ checkPreconditions
+ var module = uriToModuleName.get(namespace)
+ if (module === null) {
+ val moduleSchemas = schemas.findModuleByNamespace(namespace);
+ if(moduleSchemas === null) throw new IllegalArgumentException()
+ var latestModule = moduleSchemas.head
+ for (m : moduleSchemas) {
+ if (m.revision.after(latestModule.revision)) {
+ latestModule = m
+ }
+ }
+ if(latestModule === null) throw new IllegalArgumentException()
+ uriToModuleName.put(namespace, latestModule.name)
+ module = latestModule.name;
+ }
+ return module
+ }
def CharSequence toRestconfIdentifier(QName qname) {
checkPreconditions
import java.net.URI;
+import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.Node;
public interface NodeWrapper<T extends Node<?>> {
+ void setQname(QName name);
+
T unwrap(CompositeNode parent);
URI getNamespace();
package org.opendaylight.controller.sal.restconf.impl
import java.util.List
+import java.util.Set
import javax.ws.rs.core.Response
import org.opendaylight.controller.md.sal.common.api.TransactionStatus
import org.opendaylight.controller.sal.rest.api.RestconfService
import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
override readConfigurationData(String identifier) {
val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
- val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
+ val data = broker.readConfigurationData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
}
}
private def void addNamespaceToNodeFromSchemaRecursively(NodeWrapper<?> nodeBuilder, DataSchemaNode schema) {
- if (nodeBuilder.namespace === null) {
- nodeBuilder.namespace = schema.QName.namespace
+ if (schema === null) {
+ throw new ResponseException(Response.Status.BAD_REQUEST,
+ "Data has bad format\n" + nodeBuilder.localName + " does not exist in yang schema.");
+ }
+ val moduleName = controllerContext.findModuleByNamespace(schema.QName.namespace);
+ if (nodeBuilder.namespace === null || nodeBuilder.namespace == schema.QName.namespace ||
+ nodeBuilder.namespace.path == moduleName) {
+ nodeBuilder.qname = schema.QName
+ } else {
+ throw new ResponseException(Response.Status.BAD_REQUEST,
+ "Data has bad format\nIf data is in XML format then namespace for " + nodeBuilder.localName +
+ " should be " + schema.QName.namespace + ".\n If data is in Json format then module name for " +
+ nodeBuilder.localName + " should be " + moduleName + ".");
}
if (nodeBuilder instanceof CompositeNodeWrapper) {
val List<NodeWrapper<?>> children = (nodeBuilder as CompositeNodeWrapper).getValues
for (child : children) {
addNamespaceToNodeFromSchemaRecursively(child,
- (schema as DataNodeContainer).childNodes.findFirst[n|n.QName.localName.equals(child.localName)])
+ findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes))
+ }
+ }
+ }
+
+ private def DataSchemaNode findFirstSchemaByLocalName(String localName, Set<DataSchemaNode> schemas) {
+ for (schema : schemas) {
+ if (schema instanceof ChoiceNode) {
+ for (caze : (schema as ChoiceNode).cases) {
+ val result = findFirstSchemaByLocalName(localName, caze.childNodes)
+ if (result !== null) {
+ return result
+ }
+ }
+ } else {
+ return schemas.findFirst[n|n.QName.localName.equals(localName)]
}
}
+ return null
}
}
private String localName;
private String value;
private URI namespace;
+ private QName name;
public SimpleNodeWrapper(String localName, String value) {
this.localName = Preconditions.checkNotNull(localName);
this.namespace = namespace;
}
+ @Override
+ public void setQname(QName name) {
+ Preconditions.checkState(simpleNode == null, "Cannot change the object, due to data inconsistencies.");
+ this.name = name;
+ }
+
@Override
public String getLocalName() {
if (simpleNode != null) {
@Override
public SimpleNode<String> unwrap(CompositeNode parent) {
if (simpleNode == null) {
- Preconditions.checkNotNull(namespace);
- simpleNode = NodeFactory.createImmutableSimpleNode(new QName(namespace, localName), parent, value);
+ if (name == null) {
+ Preconditions.checkNotNull(namespace);
+ name = new QName(namespace, localName);
+ }
+ simpleNode = NodeFactory.createImmutableSimpleNode(name, parent, value);
value = null;
namespace = null;
localName = null;
+ name = null;
}
return simpleNode;
}
}
/**
- * Test when some data are in one case node and other in another. Exception
- * expected!!
+ * Test when some data are in one case node and other in another. This isn't
+ * correct. Next Json validator should return error because nodes has to be
+ * from one case below concrete choice.
+ *
*/
@Test
- public void compNodeDataOnVariousChoiceCasePathTest() {
- boolean exceptionCatched = false;
+ public void nodeSchemasOnVariousChoiceCasePathTest() {
try {
TestUtils.writeCompNodeWithSchemaContextToJson(
- TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_various_path.xml"),
+ TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_various_path_err.xml"),
"/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
- } catch (UnsupportedDataTypeException e) {
- exceptionCatched = true;
-
} catch (WebApplicationException | IOException e) {
// shouldn't end here
assertTrue(false);
}
+ }
- assertTrue(exceptionCatched);
-
+ /**
+ * Test when some data are in one case node and other in another.
+ * Additionally data are loadef from various choices. This isn't
+ * correct. Next Json validator should return error because nodes has to be
+ * from one case below concrete choice.
+ *
+ */
+ @Test
+ public void nodeSchemasOnVariousChoiceCasePathAndMultipleChoicesTest() {
+ try {
+ TestUtils
+ .writeCompNodeWithSchemaContextToJson(
+ TestUtils
+ .loadCompositeNode("/yang-to-json-conversion/choice/xml/data_more_choices_same_level_various_paths_err.xml"),
+ "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
+ } catch (WebApplicationException | IOException e) {
+ // shouldn't end here
+ assertTrue(false);
+ }
}
/**
* Test when second level data are red first, then first and at the end
* third level. Level represents pass through couple choice-case
*/
- @Ignore
+
@Test
- public void compNodeDataWithRandomOrderAccordingLevel() {
+ public void nodeSchemasWithRandomOrderAccordingLevel() {
try {
- String jsonOutput = TestUtils.writeCompNodeWithSchemaContextToJson(
+ TestUtils.writeCompNodeWithSchemaContextToJson(
TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_random_level.xml"),
"/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
+
} catch (WebApplicationException | IOException e) {
// shouldn't end here
assertTrue(false);
/**
* Test when element from no first case is used
*/
- @Ignore
@Test
- public void compNodeDataNoFirstCase() {
+ public void nodeSchemasNotInFirstCase() {
try {
- String jsonOutput = TestUtils.writeCompNodeWithSchemaContextToJson(
+ TestUtils.writeCompNodeWithSchemaContextToJson(
TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_no_first_case.xml"),
"/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
} catch (WebApplicationException | IOException e) {
/**
* Test when element in case is list
*/
- @Ignore
@Test
- public void compNodeDataAsList() {
+ public void nodeSchemaAsList() {
try {
- String jsonOutput = TestUtils.writeCompNodeWithSchemaContextToJson(
+ TestUtils.writeCompNodeWithSchemaContextToJson(
TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_list.xml"),
"/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
} catch (WebApplicationException | IOException e) {
/**
* Test when element in case is container
*/
- @Ignore
@Test
- public void compNodeDataAsContainer() {
+ public void nodeSchemaAsContainer() {
try {
- String jsonOutput = TestUtils.writeCompNodeWithSchemaContextToJson(
+ TestUtils.writeCompNodeWithSchemaContextToJson(
TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_container.xml"),
"/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
} catch (WebApplicationException | IOException e) {
}
/**
- * Test when element in case is container
+ * Test when element in case is leaflist
*/
- @Ignore
@Test
- public void compNodeDataAsLeafList() {
+ public void nodeSchemaAsLeafList() {
try {
- String jsonOutput = TestUtils.writeCompNodeWithSchemaContextToJson(
+ TestUtils.writeCompNodeWithSchemaContextToJson(
TestUtils.loadCompositeNode("/yang-to-json-conversion/choice/xml/data_leaflist.xml"),
"/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
} catch (WebApplicationException | IOException e) {
}
}
+ /**
+ *
+ */
+ @Test
+ public void nodeSchemasInMultipleChoicesTest() {
+ try {
+ TestUtils
+ .writeCompNodeWithSchemaContextToJson(TestUtils
+ .loadCompositeNode("/yang-to-json-conversion/choice/xml/data_more_choices_same_level.xml"),
+ "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
+ } catch (WebApplicationException | IOException e) {
+ // shouldn't end here
+ assertTrue(false);
+ }
+ }
+
+ /**
+ * Test whether is possible to find data schema for node which is specified
+ * as dirrect subnode of choice (case without CASE key word)
+ */
+ @Test
+ public void nodeSchemasInCaseNotDefinedWithCaseKeyword() {
+ try {
+ TestUtils.writeCompNodeWithSchemaContextToJson(TestUtils
+ .loadCompositeNode("/yang-to-json-conversion/choice/xml/data_case_defined_without_case.xml"),
+ "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
+ } catch (WebApplicationException | IOException e) {
+ // shouldn't end here
+ assertTrue(false);
+ }
+ }
+
+ /**
+ * Test of multiple use of choices
+ */
+ @Test
+ public void nodeSchemasInThreeChoicesAtSameLevel() {
+ try {
+ TestUtils.writeCompNodeWithSchemaContextToJson(TestUtils
+ .loadCompositeNode("/yang-to-json-conversion/choice/xml/data_three_choices_same_level.xml"),
+ "/yang-to-json-conversion/choice/xml", modules, dataSchemaNode);
+ } catch (WebApplicationException | IOException e) {
+ // shouldn't end here
+ assertTrue(false);
+ }
+ }
}
type string;
}
- choice choi1 {
+ choice choi1 {
case a1 {
leaf lf1a {
type uint16;
type string;
}
}
+ leaf e1 {
+ type uint32;
+ }
}
choice choi2 {
}
}
}
+
+ choice choi4 {
+ case a4 {
+ list lst4a {
+ choice choi4aa {
+ case aa1 {
+ leaf lf4aa {
+ type string;
+ }
+ }
+ case ab2 {
+ leaf lf4ab {
+ type int16;
+ }
+ }
+ }
+ }
+ }
+ case b4 {
+ leaf-list lflst4b {
+ type uint32;
+ }
+ }
+
+ }
/* equal identifiers in various cases are illegal 7.9.2 rfc6020 */
/*
--- /dev/null
+<cont>
+ <e1>45</e1>
+ <lf2b>lf2b val</lf2b>
+</cont>
\ No newline at end of file
<cont1c>
<lf11c>lf11c val</lf11c>
</cont1c>
+ <lf2b>lf2b value</lf2b>
</cont>
\ No newline at end of file
--- /dev/null
+<cont>
+ <cont1c>
+ <lf11c>lf11c val</lf11c>
+ </cont1c>
+ <lf2b>lf2b value</lf2b>
+ <lf2a>lf2b value</lf2a>
+</cont>
\ No newline at end of file
--- /dev/null
+<cont>
+ <lf1aaa>lf1aaa value</lf1aaa>
+ <lf2b>lf2b value</lf2b>
+ <lst4a>
+ <lf4ab>33</lf4ab>
+ </lst4a>
+ <lst4a>
+ <lf4ab>33</lf4ab>
+ </lst4a>
+ <lst4a>
+ <lf4ab>37</lf4ab>
+ </lst4a>
+</cont>
\ No newline at end of file
org.slf4j,
org.w3c.dom,
org.xml.sax,
+ javax.xml.namespace,
+ javax.xml.xpath,
+ org.opendaylight.controller.config.api
</Import-Package>
<Export-Package>
</Export-Package>
import com.google.common.collect.Sets;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
import org.opendaylight.controller.config.persist.api.Persister;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.api.jmx.NetconfJMXNotification;
import org.opendaylight.controller.netconf.client.NetconfClient;
import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.controller.netconf.util.xml.XMLNetconfUtil;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.net.ssl.SSLContext;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
private final Persister persister;
private final MBeanServerConnection mbeanServer;
- private Long currentSessionId;
+
private final ObjectName on = DefaultCommitOperationMXBean.objectName;
if (maybeConfig.isPresent()) {
logger.debug("Last config found {}", persister);
+ ConflictingVersionException lastException = null;
+ pushLastConfigWithRetries(maybeConfig, lastException);
+
+ } else {
+ // this ensures that netconf is initialized, this is first
+ // connection
+ // this means we can register as listener for commit
+ registerToNetconf(Collections.<String>emptySet());
+ logger.info("No last config provided by backend storage {}", persister);
+ }
+ registerAsJMXListener();
+ }
+
+ private void pushLastConfigWithRetries(Optional<ConfigSnapshotHolder> maybeConfig, ConflictingVersionException lastException) throws InterruptedException {
+ int maxAttempts = 30;
+ for(int i = 0 ; i < maxAttempts; i++) {
registerToNetconf(maybeConfig.get().getCapabilities());
final String configSnapshot = maybeConfig.get().getConfigSnapshot();
logger.trace("Pushing following xml to netconf {}", configSnapshot);
try {
pushLastConfig(XmlUtil.readXmlToElement(configSnapshot));
+ return;
+ } catch(ConflictingVersionException e) {
+ closeClientAndDispatcher(netconfClient, netconfClientDispatcher);
+ lastException = e;
+ Thread.sleep(1000);
} catch (SAXException | IOException e) {
throw new IllegalStateException("Unable to load last config", e);
}
-
- } else {
- // this ensures that netconf is initialized, this is first
- // connection
- // this means we can register as listener for commit
- registerToNetconf(Collections.<String>emptySet());
-
- logger.info("No last config provided by backend storage {}", persister);
}
- registerAsJMXListener();
+ throw new IllegalStateException("Failed to push configuration, maximum attempt count has been reached: "
+ + maxAttempts, lastException);
}
private synchronized long registerToNetconf(Set<String> expectedCaps) throws InterruptedException {
int attempt = 0;
- while (true) {
+ long deadline = pollingStart + timeout;
+ while (System.currentTimeMillis() < deadline) {
attempt++;
-
netconfClientDispatcher = new NetconfClientDispatcher(Optional.<SSLContext>absent(), nettyThreadgroup, nettyThreadgroup);
try {
netconfClient = new NetconfClient(this.toString(), address, delay, netconfClientDispatcher);
if (isSubset(currentCapabilities, expectedCaps)) {
logger.debug("Hello from netconf stable with {} capabilities", currentCapabilities);
- currentSessionId = netconfClient.getSessionId();
+ long currentSessionId = netconfClient.getSessionId();
logger.info("Session id received from netconf server: {}", currentSessionId);
return currentSessionId;
}
- if (System.currentTimeMillis() > pollingStart + timeout) {
- break;
- }
+
logger.debug("Polling hello from netconf, attempt {}, capabilities {}", attempt, currentCapabilities);
}
private void registerAsJMXListener() {
+ logger.trace("Called registerAsJMXListener");
try {
mbeanServer.addNotificationListener(on, this, null, null);
} catch (InstanceNotFoundException | IOException e) {
return maybeConfigElement;
}
- private synchronized void pushLastConfig(Element xmlToBePersisted) {
+ private synchronized void pushLastConfig(Element xmlToBePersisted) throws ConflictingVersionException {
logger.info("Pushing last configuration to netconf");
StringBuilder response = new StringBuilder("editConfig response = {");
logger.trace("Detailed message {}", response);
}
- private void checkIsOk(XmlElement element, NetconfMessage responseMessage) {
+ static void checkIsOk(XmlElement element, NetconfMessage responseMessage) throws ConflictingVersionException {
if (element.getName().equals(XmlNetconfConstants.OK)) {
return;
- } else {
- if (element.getName().equals(XmlNetconfConstants.RPC_ERROR)) {
- logger.warn("Can not load last configuration, operation failed");
- throw new IllegalStateException("Can not load last configuration, operation failed: "
- + XmlUtil.toString(responseMessage.getDocument()));
+ }
+
+ if (element.getName().equals(XmlNetconfConstants.RPC_ERROR)) {
+ logger.warn("Can not load last configuration, operation failed");
+ // is it ConflictingVersionException ?
+ XPathExpression xPathExpression = XMLNetconfUtil.compileXPath("/netconf:rpc-reply/netconf:rpc-error/netconf:error-info/netconf:error");
+ String error = (String) XmlUtil.evaluateXPath(xPathExpression, element.getDomElement(), XPathConstants.STRING);
+ if (error!=null && error.contains(ConflictingVersionException.class.getCanonicalName())) {
+ throw new ConflictingVersionException(error);
}
- logger.warn("Can not load last configuration. Operation failed.");
- throw new IllegalStateException("Can not load last configuration. Operation failed: "
+ throw new IllegalStateException("Can not load last configuration, operation failed: "
+ XmlUtil.toString(responseMessage.getDocument()));
}
+
+ logger.warn("Can not load last configuration. Operation failed.");
+ throw new IllegalStateException("Can not load last configuration. Operation failed: "
+ + XmlUtil.toString(responseMessage.getDocument()));
}
private static NetconfMessage createEditConfigMessage(Element dataElement, String editConfigResourcename) {
--- /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.netconf.persist.impl;
+
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.w3c.dom.Document;
+
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+public class ConfigPersisterNotificationHandlerTest {
+
+ @Test
+ public void testConflictingVersionDetection() throws Exception {
+ Document document = XmlUtil.readXmlToDocument(getClass().getResourceAsStream("/conflictingVersionResponse.xml"));
+ try{
+ ConfigPersisterNotificationHandler.checkIsOk(XmlElement.fromDomDocument(document).getOnlyChildElement(), new NetconfMessage(document));
+ fail();
+ }catch(ConflictingVersionException e){
+ assertThat(e.getMessage(), containsString("Optimistic lock failed. Expected parent version 21, was 18"));
+ }
+ }
+
+}
--- /dev/null
+<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="persister_commit">
+ <rpc-error>
+ <error-type>application</error-type>
+ <error-tag>operation-failed</error-tag>
+ <error-severity>error</error-severity>
+
+
+
+ <error-info>
+ <error>org.opendaylight.controller.config.api.ConflictingVersionException: Optimistic lock failed. Expected parent version 21, was 18</error>
+ </error-info>
+ </rpc-error>
+</rpc-reply>