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
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 {
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
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);
}
-
}
<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.odlparent</groupId>
- <artifactId>bundle-parent</artifactId>
- <version>1.5.0-SNAPSHOT</version>
- <relativePath/>
- </parent>
+ <parent>
+ <groupId>org.opendaylight.odlparent</groupId>
+ <artifactId>bundle-parent</artifactId>
+ <version>1.5.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>binding-parent</artifactId>
- <version>0.7.0-SNAPSHOT</version>
- <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
- <properties>
- <yangtools.version>0.7.0-SNAPSHOT</yangtools.version>
- <salGeneratorPath>src/main/yang-gen-sal</salGeneratorPath>
- </properties>
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yangtools-artifacts</artifactId>
- <version>${yangtools.version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
- <build>
- <pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-maven-plugin</artifactId>
- <version>${yangtools.version}</version>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>maven-sal-api-gen-plugin</artifactId>
- <version>${yangtools.version}</version>
- <type>jar</type>
- </dependency>
- </dependencies>
- <executions>
- <execution>
- <id>binding</id>
- <goals>
- <goal>generate-sources</goal>
- </goals>
- <configuration>
- <codeGenerators>
- <generator>
- <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
- <outputBaseDir>${salGeneratorPath}</outputBaseDir>
- </generator>
- </codeGenerators>
- <inspectDependencies>true</inspectDependencies>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <artifactId>maven-clean-plugin</artifactId>
- <configuration>
- <filesets>
- <fileset>
- <directory>${salGeneratorPath}</directory>
- <includes>
- <include>**</include>
- </includes>
- </fileset>
- </filesets>
- </configuration>
- </plugin>
- </plugins>
- </pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-maven-plugin</artifactId>
- <version>${yangtools.version}</version>
- </plugin>
- </plugins>
- </build>
+ <properties>
+ <yangtools.version>0.7.0-SNAPSHOT</yangtools.version>
+ <salGeneratorPath>src/main/yang-gen-sal</salGeneratorPath>
+ </properties>
+ <profiles>
+ <profile>
+ <activation>
+ <file>
+ <exists>src/main/yang</exists>
+ </file>
+ </activation>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yangtools-artifacts</artifactId>
+ <version>${yangtools.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ </dependencies>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>${yangtools.version}</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>maven-sal-api-gen-plugin</artifactId>
+ <version>${yangtools.version}</version>
+ <type>jar</type>
+ </dependency>
+ </dependencies>
+ <executions>
+ <execution>
+ <id>binding</id>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+ <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>${salGeneratorPath}</directory>
+ <includes>
+ <include>**</include>
+ </includes>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>${yangtools.version}</version>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
</project>
+++ /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
-#
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;import java.lang.Override;import java.lang.String;import java.lang.UnsupportedOperationException;
+import com.google.common.base.Optional;
/**
* Concretization of AbstractTreeNode for leaf nodes which only contain data.
*/
package org.opendaylight.yangtools.yang.data.impl.schema.nodes;
-import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ImmutableMap;
-import java.util.Arrays;
import java.util.Map;
import org.opendaylight.yangtools.yang.common.QName;
+ 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);
}
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() {
// TODO Test yang files in transitive dependencies
@Test
- public void testYangRootNotExist() throws URISyntaxException {
- try {
- setUp("test-parent/YangRootNotExist/", false);
- } catch (VerificationException e) {
- assertVerificationException(e,
- "[ERROR] yang-to-sources: Unable to parse yang files from ");
- assertVerificationException(
- e,
- "Caused by: org.apache.maven.plugin.MojoExecutionException: yang-to-sources: Unable to parse yang files from ");
- return;
- }
-
- fail("Verification exception should have been thrown");
+ public void testYangRootNotExist() throws Exception {
+ Verifier v = setUp("test-parent/YangRootNotExist/", false);
+ v.verifyTextInLog("[WARNING] yang-to-sources: YANG source directory");
}
@Test
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
static Collection<File> listFiles(File root, File[] excludedFiles, Log log) throws FileNotFoundException {
if (!root.exists()) {
- throw new FileNotFoundException(root.toString());
+ if (log != null) {
+ log.warn(Util.message("YANG source directory %s not found. No code will be generated.", YangToSourcesProcessor.LOG_PREFIX, root.toString()));
+ }
+ return Collections.emptyList();
}
Collection<File> result = new ArrayList<>();
Collection<File> yangFiles = FileUtils.listFiles(root, new String[] { YANG_SUFFIX }, true);
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;