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>