import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-class BindingCodecContext implements CodecContextFactory, Immutable {
+final class BindingCodecContext implements CodecContextFactory, Immutable {
private static final Logger LOG = LoggerFactory.getLogger(BindingCodecContext.class);
private static final String GETTER_PREFIX = "get";
- private final SchemaRootCodecContext root;
- private final BindingRuntimeContext context;
private final Codec<YangInstanceIdentifier, InstanceIdentifier<?>> instanceIdentifierCodec =
new InstanceIdentifierCodec();
- private final Codec<QName, Class<?>> identityCodec = new IdentityCodec();
+ private final Codec<QName, Class<?>> identityCodec;
+ private final BindingRuntimeContext context;
+ private final SchemaRootCodecContext root;
public BindingCodecContext(final BindingRuntimeContext context) {
this.context = Preconditions.checkNotNull(context, "Binding Runtime Context is required.");
this.root = SchemaRootCodecContext.create(this);
+ this.identityCodec = new IdentityCodec(context);
}
@Override
}
}
- private class IdentityCodec implements Codec<QName, Class<?>> {
+ private static class IdentityCodec implements Codec<QName, Class<?>> {
+ private final BindingRuntimeContext context;
+
+ IdentityCodec(final BindingRuntimeContext context) {
+ this.context = Preconditions.checkNotNull(context);
+ }
@Override
public Class<?> deserialize(final QName input) {
import org.opendaylight.yangtools.yang.binding.DataRoot;
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
class SchemaRootCodecContext extends DataContainerCodecContext<SchemaContext> {
- private final LoadingCache<Class<?>, DataContainerCodecContext<?>> children = CacheBuilder.newBuilder().build(
+ private final LoadingCache<Class<?>, DataContainerCodecContext<?>> childrenByClass = CacheBuilder.newBuilder().build(
new CacheLoader<Class<?>, DataContainerCodecContext<?>>() {
@Override
public DataContainerCodecContext<?> load(final Class<?> key) {
}
});
+ private final LoadingCache<QName, DataContainerCodecContext<?>> childrenByQName = CacheBuilder.newBuilder().build(
+ new CacheLoader<QName, DataContainerCodecContext<?>>() {
+ @Override
+ public DataContainerCodecContext<?> load(final QName qname) {
+ final DataSchemaNode childSchema = schema().getDataChildByName(qname);
+ Preconditions.checkArgument(childSchema != null, "Argument %s is not valid child of %s", qname, schema());
+
+ if (childSchema instanceof DataNodeContainer || childSchema instanceof ChoiceNode) {
+ final Class<?> childCls = factory().getRuntimeContext().getClassForSchema(childSchema);
+ return getStreamChild(childCls);
+ } else {
+ throw new UnsupportedOperationException("Unsupported child type " + childSchema.getClass());
+ }
+ }
+ });
+
private SchemaRootCodecContext(final DataContainerCodecPrototype<SchemaContext> dataPrototype) {
super(dataPrototype);
}
@Override
protected DataContainerCodecContext<?> getStreamChild(final Class<?> childClass) {
- return children.getUnchecked(childClass);
+ return childrenByClass.getUnchecked(childClass);
}
@Override
}
@Override
- protected YangInstanceIdentifier.PathArgument getDomPathArgument() {
+ protected PathArgument getDomPathArgument() {
throw new UnsupportedOperationException();
}
@Override
- protected NodeCodecContext getYangIdentifierChild(final YangInstanceIdentifier.PathArgument arg) {
- // FIXME: Optimize this
- QName childQName = arg.getNodeType();
- DataSchemaNode childSchema = schema().getDataChildByName(childQName);
- Preconditions.checkArgument(childSchema != null, "Argument %s is not valid child of %s", arg, schema());
- if (childSchema instanceof DataNodeContainer || childSchema instanceof ChoiceNode) {
- Class<?> childCls = factory().getRuntimeContext().getClassForSchema(childSchema);
- DataContainerCodecContext<?> childNode = getStreamChild(childCls);
- return childNode;
- } else {
- throw new UnsupportedOperationException();
- }
+ protected NodeCodecContext getYangIdentifierChild(final PathArgument arg) {
+ return childrenByQName.getUnchecked(arg.getNodeType());
}
@Override
<modelVersion>4.0.0</modelVersion>
<artifactId>binding-generator-impl</artifactId>
+ <packaging>bundle</packaging>
<dependencies>
<dependency>
<build>
<plugins>
- <plugin>
- <artifactId>maven-jar-plugin</artifactId>
- </plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
org.opendaylight.yangtools.sal.binding.generator.impl.*,
org.opendaylight.yangtools.sal.binding.generator.util.*
</Export-Package>
+ <Embed-Dependency>
+ org.eclipse.xtend.lib;inline=true,
+ org.eclipse.xtend.lib.macro;inline=true,
+ org.eclipse.xtext.xbase.lib;inline=true,
+ </Embed-Dependency>
+ <Embed-Transitive>true</Embed-Transitive>
</instructions>
</configuration>
</plugin>
import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
-import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
+import org.opendaylight.yangtools.util.ClassLoaderUtils;
public abstract class GeneratedClassLoadingStrategy implements ClassLoadingStrategy {
package org.opendaylight.yangtools.sal.binding.generator.impl
import com.google.common.base.Joiner
+import com.google.common.base.Supplier
import java.io.File
import java.security.ProtectionDomain
import java.util.AbstractMap.SimpleEntry
if (cl === null) {
cl = Thread.currentThread.contextClassLoader
}
- ClassLoaderUtils.withClassLoader(cl,
- [ |
- if (!(node instanceof DataNodeContainer)) {
- return null
- }
- var InstanceIdentifier<?> bindingId = getBindingIdentifierByPath(node.path)
- if (bindingId != null) {
- return null
- }
- val ref = Types.typeForClass(inputType)
- var typeSpecBuilder = getDefinition(ref)
- if (typeSpecBuilder == null) {
- typeSpecBuilder = getTypeBuilder(node.path);
- }
- checkState(typeSpecBuilder !== null, "Could not find type definition for %s, $s", inputType.name, node);
- val typeSpec = typeSpecBuilder.toInstance();
- var InstanceIdentifier<?> parent
- if (parentId == null) {
- bindingId = InstanceIdentifier.create(inputType as Class)
- parent = bindingId
- putPathToBindingIdentifier(node.path, bindingId)
- } else {
- parent = putPathToBindingIdentifier(node.path, parentId, inputType)
- }
- val Map<String, Type> properties = typeSpec.allProperties
- if (node instanceof DataNodeContainer) {
- mappingForNodes((node as DataNodeContainer).childNodes, properties, parent)
- } else if (node instanceof ChoiceNode) {
- mappingForNodes((node as ChoiceNode).cases, properties, parent)
- }
- return null;
- ])
+
+ val Supplier<?> sup = [ |
+ if (!(node instanceof DataNodeContainer)) {
+ return null
+ }
+ var InstanceIdentifier<?> bindingId = getBindingIdentifierByPath(node.path)
+ if (bindingId != null) {
+ return null
+ }
+ val ref = Types.typeForClass(inputType)
+ var typeSpecBuilder = getDefinition(ref)
+ if (typeSpecBuilder == null) {
+ typeSpecBuilder = getTypeBuilder(node.path);
+ }
+ checkState(typeSpecBuilder !== null, "Could not find type definition for %s, $s", inputType.name, node);
+ val typeSpec = typeSpecBuilder.toInstance();
+ var InstanceIdentifier<?> parent
+ if (parentId == null) {
+ bindingId = InstanceIdentifier.create(inputType as Class)
+ parent = bindingId
+ putPathToBindingIdentifier(node.path, bindingId)
+ } else {
+ parent = putPathToBindingIdentifier(node.path, parentId, inputType)
+ }
+ val Map<String, Type> properties = typeSpec.allProperties
+ if (node instanceof DataNodeContainer) {
+ mappingForNodes((node as DataNodeContainer).childNodes, properties, parent)
+ } else if (node instanceof ChoiceNode) {
+ mappingForNodes((node as ChoiceNode).cases, properties, parent)
+ }
+ return null ]
+ ClassLoaderUtils.withClassLoader(cl, sup)
}
private def void mappingForNodes(Collection<? extends DataSchemaNode> childNodes, Map<String, Type> properties,
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
import com.google.common.collect.BiMap;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.HashBiMap;
private final Multimap<Type, Type> choiceToCases = HashMultimap.create();
private final Map<QName, Type> identities = new HashMap<>();
+ private final LoadingCache<QName, Class<?>> identityClasses = CacheBuilder.newBuilder().weakValues().build(
+ new CacheLoader<QName, Class<?>>() {
+ @Override
+ public Class<?> load(final QName key) {
+ final Type identityType = identities.get(key);
+ Preconditions.checkArgument(identityType != null, "Supplied QName %s is not a valid identity", key);
+ try {
+ return strategy.loadClass(identityType);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Required class " + identityType + "was not found.", e);
+ }
+ }
+ });
+
private BindingRuntimeContext(final ClassLoadingStrategy strategy, final SchemaContext schema) {
this.strategy = strategy;
this.schemaContext = schema;
}
public Class<?> getIdentityClass(final QName input) {
- Type identityType = identities.get(input);
- Preconditions.checkArgument(identityType != null, "Supplied QName %s is not a valid identity", input);
- try {
- return strategy.loadClass(identityType);
- } catch (ClassNotFoundException e) {
- throw new IllegalArgumentException("Required class " + identityType + "was not found.",e);
- }
+ return identityClasses.getUnchecked(input);
}
-
}
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testAugmentation;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
-
+import com.google.common.collect.ImmutableSet;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
-import java.util.HashSet;
import java.util.List;
import org.junit.Test;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
final List<File> sourceFiles = getSourceFiles("/compilation/augment-uses-to-augment");
final SchemaContext context = parser.parseFiles(sourceFiles);
final List<Type> types = bindingGenerator.generateTypes(context);
- final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+ final GeneratorJavaFile generator = new GeneratorJavaFile(ImmutableSet.copyOf(types));
generator.generateToFile(sourcesOutputDir);
// Test if all sources are generated from 'module foo'
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
-
+import com.google.common.collect.ImmutableSet;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
-import java.util.HashSet;
import java.util.List;
import org.junit.Test;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
cleanUp(sourcesOutputDir, compiledOutputDir);
}
- private void generateTestSources(String resourceDirPath, File sourcesOutputDir) throws Exception {
+ private void generateTestSources(final String resourceDirPath, final File sourcesOutputDir) throws Exception {
final List<File> sourceFiles = getSourceFiles(resourceDirPath);
final SchemaContext context = parser.parseFiles(sourceFiles);
final List<Type> types = bindingGenerator.generateTypes(context);
- final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+ final GeneratorJavaFile generator = new GeneratorJavaFile(ImmutableSet.copyOf(types));
generator.generateToFile(sourcesOutputDir);
}
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
-
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import java.io.File;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.net.URLClassLoader;
-import java.util.HashSet;
import java.util.List;
import org.junit.Test;
import org.mockito.Mockito;
cleanUp(sourcesOutputDir, compiledOutputDir);
}
- private void generateTestSources(String resourceDirPath, File sourcesOutputDir) throws Exception {
+ private void generateTestSources(final String resourceDirPath, final File sourcesOutputDir) throws Exception {
final List<File> sourceFiles = getSourceFiles(resourceDirPath);
final SchemaContext context = parser.parseFiles(sourceFiles);
final List<Type> types = bindingGenerator.generateTypes(context);
- final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+ final GeneratorJavaFile generator = new GeneratorJavaFile(ImmutableSet.copyOf(types));
generator.generateToFile(sourcesOutputDir);
}
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
-
+import com.google.common.collect.ImmutableSet;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
-import java.util.HashSet;
import java.util.List;
import org.junit.Test;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
final List<File> sourceFiles = getSourceFiles("/compilation/cascade-uses");
final SchemaContext context = parser.parseFiles(sourceFiles);
final List<Type> types = bindingGenerator.generateTypes(context);
- final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+ final GeneratorJavaFile generator = new GeneratorJavaFile(ImmutableSet.copyOf(types));
generator.generateToFile(sourcesOutputDir);
// Test if all sources are generated from module foo
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
-
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Range;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.WildcardType;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
-import java.util.HashSet;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import org.junit.Test;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
*/
public class CompilationTest extends BaseCompilationTest {
+ /*
+ * Java 8 allows JaCoCo to hook onto interfaces, as well as
+ * generating a default implementation. We only want to check
+ * abstract methods.
+ */
+ private static Collection<Method> abstractMethods(final Class<?> clazz) {
+ // Filter out
+ return Collections2.filter(Arrays.asList(clazz.getDeclaredMethods()), new Predicate<Method>() {
+ @Override
+ public boolean apply(final Method input) {
+ return Modifier.isAbstract(input.getModifiers());
+ }
+ });
+ }
+
@Test
public void testListGeneration() throws Exception {
final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "list-gen");
// Test generated 'grouping key-args'
assertTrue(keyArgsClass.isInterface());
- assertEquals(2, keyArgsClass.getDeclaredMethods().length);
assertContainsMethod(keyArgsClass, String.class, "getName");
assertContainsMethod(keyArgsClass, Integer.class, "getSize");
+ assertEquals(2, abstractMethods(keyArgsClass).size());
// Test generated 'list links'
assertTrue(linksClass.isInterface());
- // TODO: anyxml
- assertEquals(6, linksClass.getDeclaredMethods().length);
assertImplementsIfc(linksClass, keyArgsClass);
+ // TODO: anyxml
+ assertEquals(6, abstractMethods(linksClass).size());
// Test list key constructor arguments ordering
assertContainsConstructor(linksKeyClass, Byte.class, String.class, Integer.class);
cleanUp(sourcesOutputDir, compiledOutputDir);
}
- private void generateTestSources(String resourceDirPath, File sourcesOutputDir) throws Exception {
+ private void generateTestSources(final String resourceDirPath, final File sourcesOutputDir) throws Exception {
final List<File> sourceFiles = getSourceFiles(resourceDirPath);
final SchemaContext context = parser.parseFiles(sourceFiles);
final List<Type> types = bindingGenerator.generateTypes(context);
- final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+ Collections.sort(types, new Comparator<Type>() {
+ @Override
+ public int compare(final Type o1, final Type o2) {
+ return o2.getName().compareTo(o1.getName());
+ }
+ });
+ final GeneratorJavaFile generator = new GeneratorJavaFile(ImmutableSet.copyOf(types));
generator.generateToFile(sourcesOutputDir);
}
- private void testReturnTypeIdentityref(Class<?> clazz, String methodName, String returnTypeStr) throws Exception {
+ private void testReturnTypeIdentityref(final Class<?> clazz, final String methodName, final String returnTypeStr) throws Exception {
Method method;
java.lang.reflect.Type returnType;
try {
}
}
- private void testReturnTypeInstanceIdentitifer(ClassLoader loader, Class<?> clazz, String methodName)
+ private void testReturnTypeInstanceIdentitifer(final ClassLoader loader, final Class<?> clazz, final String methodName)
throws Exception {
Method method;
Class<?> rawReturnType;
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(filesList);
Iterable<String> options = Arrays.asList("-d", compiledOutputDir.getAbsolutePath());
boolean compiled = compiler.getTask(null, null, null, options, null, compilationUnits).call();
- assertTrue(compiled);
+ assertTrue("Compilation failed", compiled);
}
/**
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
-
+import com.google.common.collect.ImmutableSet;
import java.io.File;
-import java.util.HashSet;
import java.util.List;
import org.junit.Test;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
final List<File> sourceFiles = getSourceFiles("/compilation/encoding-javadoc");
final SchemaContext context = parser.parseFiles(sourceFiles);
final List<Type> types = bindingGenerator.generateTypes(context);
- final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+ final GeneratorJavaFile generator = new GeneratorJavaFile(ImmutableSet.copyOf(types));
generator.generateToFile(sourcesOutputDir);
// Test if sources are compilable
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
-
+import com.google.common.collect.ImmutableSet;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
-import java.util.HashSet;
import java.util.List;
import org.junit.Test;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
cleanUp(sourcesOutputDir, compiledOutputDir);
}
- private void generateTestSources(String resourceDirPath, File sourcesOutputDir) throws Exception {
+ private void generateTestSources(final String resourceDirPath, final File sourcesOutputDir) throws Exception {
final List<File> sourceFiles = getSourceFiles(resourceDirPath);
final SchemaContext context = parser.parseFiles(sourceFiles);
final List<Type> types = bindingGenerator.generateTypes(context);
- final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+ final GeneratorJavaFile generator = new GeneratorJavaFile(ImmutableSet.copyOf(types));
generator.generateToFile(sourcesOutputDir);
}
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Range;
import java.io.File;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
import org.junit.Test;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
final List<File> sourceFiles = getSourceFiles("/compilation/typedef");
final SchemaContext context = parser.parseFiles(sourceFiles);
final List<Type> types = bindingGenerator.generateTypes(context);
- final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+ final GeneratorJavaFile generator = new GeneratorJavaFile(ImmutableSet.copyOf(types));
generator.generateToFile(sourcesOutputDir);
File parent = new File(sourcesOutputDir, NS_FOO);
</dependency>
</dependencies>
</dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ </dependencies>
<build>
<pluginManagement>
<plugins>
<artifactId>antlr4-runtime-osgi-nohead</artifactId>
<version>4.0</version>
</dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools.thirdparty</groupId>
- <artifactId>xtend-lib-osgi</artifactId>
- <version>2.4.3</version>
- </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>concepts</artifactId>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-data-codec</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools.thirdparty</groupId>
- <artifactId>xtend-lib-osgi</artifactId>
- <scope>compile</scope>
- </dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<bundle>mvn:org.opendaylight.yangtools/binding-model-api/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.yangtools/binding-type-provider/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.yangtools/binding-data-codec/{{VERSION}}</bundle>
- <bundle>mvn:org.opendaylight.yangtools.thirdparty/xtend-lib-osgi/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.yangtools/yang-model-api/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.yangtools/yang-model-util/{{VERSION}}</bundle>
<bundle>mvn:org.opendaylight.yangtools/yang-parser-api/{{VERSION}}</bundle>
<dependency>
<groupId>org.eclipse.xtend</groupId>
<artifactId>org.eclipse.xtend.lib</artifactId>
- <version>2.4.3</version>
+ <version>2.7.3</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<plugin>
<groupId>org.eclipse.xtend</groupId>
<artifactId>xtend-maven-plugin</artifactId>
- <version>${xtend.version}</version>
+ <version>2.7.3</version>
<executions>
<execution>
<goals>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
- <dependency>
- <groupId>org.sonatype.plexus</groupId>
- <artifactId>plexus-build-api</artifactId>
- </dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-slf4j-logging</artifactId>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
- <artifactId>maven-sal-api-gen-plugin</artifactId>
+ <artifactId>binding-generator-impl</artifactId>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools.thirdparty</groupId>
<artifactId>antlr4-runtime-osgi-nohead</artifactId>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools.thirdparty</groupId>
- <artifactId>xtend-lib-osgi</artifactId>
- <scope>test</scope>
- </dependency>
</dependencies>
<build>
options.add(mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject());
options.add(mavenBundle("org.opendaylight.yangtools.thirdparty", "antlr4-runtime-osgi-nohead")
.versionAsInProject());
- options.add(mavenBundle("org.opendaylight.yangtools.thirdparty", "xtend-lib-osgi").versionAsInProject());
- options.add(mavenBundle("org.sonatype.plexus", "plexus-build-api").versionAsInProject());
- options.add(mavenBundle("org.codehaus.plexus", "plexus-slf4j-logging").versionAsInProject());
options.add(mavenBundle("org.javassist", "javassist").versionAsInProject());
options.add(mavenBundle(GROUP, "concepts").versionAsInProject());
options.add(mavenBundle(GROUP, "binding-generator-impl").versionAsInProject());
options.add(mavenBundle(GROUP, "binding-generator-spi").versionAsInProject());
options.add(mavenBundle(GROUP, "binding-generator-util").versionAsInProject());
- options.add(mavenBundle(GROUP, "binding-java-api-generator").versionAsInProject());
options.add(mavenBundle(GROUP, "binding-model-api").versionAsInProject());
options.add(mavenBundle(GROUP, "binding-type-provider").versionAsInProject());
- options.add(mavenBundle(GROUP, "maven-sal-api-gen-plugin").versionAsInProject());
options.add(junitBundles());
return options;
testBundle("binding-generator-spi");
testBundle("binding-generator-util");
testBundle("binding-model-api");
- testBundle("binding-java-api-generator");
testBundle("binding-type-provider");
- testBundle("maven-sal-api-gen-plugin");
}
private void testBundle(String name) throws BundleException {
<packaging>pom</packaging>
<modules>
- <module>xtend-lib-osgi</module>
<module>antlr4-runtime-osgi</module>
</modules>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
- 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
--->
-<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>
- <parent>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>third-party-parent</artifactId>
- <version>0.7.0-SNAPSHOT</version>
- <relativePath>../pom.xml</relativePath>
- </parent>
-
- <artifactId>xtend-lib-osgi</artifactId>
- <version>2.4.3</version>
- <packaging>bundle</packaging>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <extensions>true</extensions>
- <configuration>
- <instructions>
- <Bundle-Name>Xtend Runtime Library</Bundle-Name>
- <Bundle-SymbolicName>org.eclipse.xtend.lib</Bundle-SymbolicName>
- <Import-Package>
- com.google.common.base;version="[10.0.1,16)",
- com.google.common.collect;version="[10.0.1,16)",
- com.google.common.primitives;version="[10.0.1,16)"
- </Import-Package>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
- <dependencies>
- <dependency>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>org.eclipse.xtend.lib</artifactId>
- <version>2.4.3</version>
- </dependency>
- <dependency>
- <groupId>org.eclipse.xtext</groupId>
- <artifactId>org.eclipse.xtext.xbase.lib</artifactId>
- <version>2.4.3</version>
- </dependency>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- <version>[10.0.1,15.0)</version>
- <scope>provided</scope>
- </dependency>
- </dependencies>
-</project>
* and {@link StoreMetadataNode} which represents original state {@link #getOriginal()}.
*/
@NotThreadSafe
-final class ModifiedNode implements StoreTreeNode<ModifiedNode>, Identifiable<PathArgument>, NodeModification {
+final class ModifiedNode extends NodeModification implements StoreTreeNode<ModifiedNode> {
public static final Predicate<ModifiedNode> IS_TERMINAL_PREDICATE = new Predicate<ModifiedNode>() {
@Override
* @return original store metadata
*/
@Override
- public Optional<TreeNode> getOriginal() {
+ Optional<TreeNode> getOriginal() {
return original;
}
* @return modification type
*/
@Override
- public ModificationType getType() {
+ ModificationType getType() {
return modificationType;
}
* @return all recorded direct child modifications
*/
@Override
- public Iterable<ModifiedNode> getChildren() {
+ Iterable<ModifiedNode> getChildren() {
return children.values();
}
+ modificationType + ", childModification=" + children + "]";
}
+ /**
+ * Create a node which will reflect the state of this node, except it will behave as newly-written
+ * value. This is useful only for merge validation.
+ *
+ * @param value Value associated with the node
+ * @return An isolated node. This node should never reach a datatree.
+ */
+ ModifiedNode asNewlyWritten(final NormalizedNode<?, ?> value) {
+ final ModifiedNode ret = new ModifiedNode(getIdentifier(), Optional.<TreeNode>absent(), false);
+ ret.write(value);
+ return ret;
+ }
+
public static ModifiedNode createUnmodified(final TreeNode metadataTree, final boolean isOrdered) {
return new ModifiedNode(metadataTree.getIdentifier(), Optional.of(metadataTree), isOrdered);
}
* It is used by the validation code to allow for a read-only view of the
* modification tree as we should never modify that during validation.
*/
-interface NodeModification extends Identifiable<PathArgument> {
+abstract class NodeModification implements Identifiable<PathArgument> {
/**
* Get the type of modification.
*
* @return Modification type.
*/
- ModificationType getType();
+ abstract ModificationType getType();
/**
* Get the original tree node to which the modification is to be applied.
* @return The original node, or {@link Optional#absent()} if the node is
* a new node.
*/
- Optional<TreeNode> getOriginal();
+ abstract Optional<TreeNode> getOriginal();
/**
* Get a read-only view of children nodes.
*
* @return Iterable of all children nodes.
*/
- Iterable<? extends NodeModification> getChildren();
+ abstract Iterable<? extends NodeModification> getChildren();
}
applyOperation.verifyStructure(modification);
}
- private void mergeImpl(final NormalizedNode<?,?> data) {
+ private void recursiveMerge(final NormalizedNode<?,?> data) {
if (data instanceof NormalizedNodeContainer<?,?,?>) {
@SuppressWarnings({ "rawtypes", "unchecked" })
NormalizedNodeContainer<?,?,NormalizedNode<PathArgument, ?>> dataContainer = (NormalizedNodeContainer) data;
for (NormalizedNode<PathArgument, ?> child : dataContainer.getValue()) {
PathArgument childId = child.getIdentifier();
- forChild(childId).mergeImpl(child);
+ forChild(childId).recursiveMerge(child);
}
}
}
void merge(final NormalizedNode<?, ?> data) {
- mergeImpl(data);
- applyOperation.verifyStructure(modification);
+ /*
+ * A merge operation will end up overwriting parts of the tree, retaining others.
+ * We want to make sure we do not validate the complete resulting structure, but
+ * rather just what was written. In order to do that, we first pretend the data
+ * was written, run verification and then perform the merge -- with the explicit
+ * assumption that adding the newly-validated data with the previously-validated
+ * data will not result in invalid data.
+ */
+ applyOperation.verifyStructure(modification.asNewlyWritten(data));
+ recursiveMerge(data);
}
void delete() {