import java.net.URI;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringInstanceIdentifierCodec;
+import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
final class JSONStringInstanceIdentifierCodec extends AbstractModuleStringInstanceIdentifierCodec implements JSONCodec<YangInstanceIdentifier> {
private final SchemaContext context;
+ private final DataSchemaContextTree dataContextTree;
JSONStringInstanceIdentifierCodec(final SchemaContext context) {
this.context = Preconditions.checkNotNull(context);
+ this.dataContextTree = DataSchemaContextTree.from(context);
}
@Override
return module == null ? null : module.getName();
}
+ @Override
+ protected DataSchemaContextTree getDataContextTree() {
+ return dataContextTree;
+ }
+
@Override
public boolean needQuotes() {
return true;
*/
package org.opendaylight.yangtools.yang.data.codec.gson;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.childArray;
+import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.childPrimitive;
+import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.loadModules;
+import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.resolveCont1;
+
import com.google.common.collect.Sets;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.URISyntaxException;
+import java.util.HashSet;
+import java.util.Iterator;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.net.URISyntaxException;
-import java.util.HashSet;
-import java.util.Iterator;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.childArray;
-import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.childPrimitive;
-import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.loadModules;
-import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.resolveCont1;
-
/**
* Each test tests whether json output obtained after transformation contains is corect. The transformation takes
* normalized node data structure and transform it to json output. To make it easier validate json output it is loaded
assertNotNull(lf111);
assertEquals("key111 value", key111.getAsString());
- assertEquals("/complexjson:cont1/complexjson:lflst11", lf112.getAsString());
+ assertEquals("/complexjson:cont1/complexjson:lflst11[.='foo']", lf112.getAsString());
assertEquals("lf113 value", lf113.getAsString());
assertEquals("lf111 value", lf111.getAsString());
}
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
+import java.util.HashMap;
+import java.util.Map;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.SimpleNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.InstanceIdentifierBuilder;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
-import java.util.HashMap;
-import java.util.Map;
-
public class TestingNormalizedNodeStructuresCreator {
static NormalizedNode<?, ?> cont1Node(
}
private static Object lf112Value() {
- InstanceIdentifierBuilder builder = YangInstanceIdentifier.builder();
- builder.node(QName.create("ns:complex:json", "2014-08-11", "cont1"));
- builder.node(QName.create("ns:complex:json", "2014-08-11", "lflst11"));
- return builder.build();
+ return YangInstanceIdentifier.create(
+ new NodeIdentifier(QName.create("ns:complex:json", "2014-08-11", "cont1")),
+ new NodeIdentifier(QName.create("ns:complex:json", "2014-08-11", "lflst11")),
+ new NodeWithValue(QName.create("ns:complex:json", "2014-08-11", "lflst11"),"foo")
+ );
}
private static DataContainerChild<? extends PathArgument, ?> childLflst11() {
public static NormalizedNode<?, ?> leafNodeInContainer() {
LeafNode<Object> lf11 = Builders.leafBuilder()
.withNodeIdentifier(new NodeIdentifier(QName.create("ns:complex:json", "2014-08-11", "lf11")))
- .withValue((int) 453).build();
+ .withValue(453).build();
return cont1Node(lf11);
}
"lst11":[
{
"key111":"key111 value",
- "lf112":"/complexjson:cont1/complexjson:lflst11",
+ "lf112":"/complexjson:cont1/complexjson:lflst11[.='foo']",
"lf113":"lf113 value",
"lf111":"lf111 value"
}
"lst11":[
{
"key111":"key111 value",
- "lf112":"/complexjson:cont1/complexjson:lflst11",
+ "lf112":"/complexjson:cont1/complexjson:lflst11[.='foo']",
"lf113":"lf113 value",
"lf111":"lf111 value"
}
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy;
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
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.util.EffectiveAugmentationSchema;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
for(final DataSchemaNode child : schema.getChildNodes()) {
realChildSchemas.add(((DataNodeContainer) parent).getDataChildByName(child.getQName()));
}
- final AugmentationSchema resolvedSchema = new AugmentationSchemaProxy(schema, realChildSchemas);
+ final AugmentationSchema resolvedSchema = new EffectiveAugmentationSchema(schema, realChildSchemas);
schemaStack.push(resolvedSchema);
return resolvedSchema;
}
package org.opendaylight.yangtools.yang.data.impl.codec.xml;
import com.google.common.base.Preconditions;
-
import java.net.URI;
-
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.util.AbstractStringInstanceIdentifierCodec;
+import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.w3c.dom.Element;
final class ElementInstanceIdentifierParser extends AbstractStringInstanceIdentifierCodec {
private final SchemaContext schema;
private final Element element;
+ private final DataSchemaContextTree dataContextTree;
ElementInstanceIdentifierParser(final SchemaContext schema, final Element element) {
this.element = Preconditions.checkNotNull(element);
this.schema = Preconditions.checkNotNull(schema);
+ this.dataContextTree = DataSchemaContextTree.from(schema);
}
@Override
return QName.create(module.getQNameModule(), localName);
}
+ @Override
+ protected DataSchemaContextTree getDataContextTree() {
+ return dataContextTree;
+ }
+
}
return codec.deserialize(element.getTextContent().trim());
}
- public static Element serialize(final YangInstanceIdentifier id, final Element element) {
- final RandomPrefixInstanceIdentifierSerializer codec = new RandomPrefixInstanceIdentifierSerializer();
+ public static Element serialize(final YangInstanceIdentifier id, final Element element, SchemaContext context) {
+ final RandomPrefixInstanceIdentifierSerializer codec = new RandomPrefixInstanceIdentifierSerializer(context);
final String str = codec.serialize(id);
for (Entry<URI, String> e : codec.getPrefixes()) {
return element;
}
+ /**
+ *
+ * @deprecated USe {@link #serialize(YangInstanceIdentifier, Element, SchemaContext)} instead.
+ */
+ @Deprecated
+ public static Element serialize(final YangInstanceIdentifier id, final Element element) {
+ throw new UnsupportedOperationException("Not supported, due to buggy API contract.");
+ }
+
private static String getIdAndPrefixAsStr(final String pathPart) {
int predicateStartIndex = pathPart.indexOf('[');
return predicateStartIndex == -1 ? pathPart : pathPart.substring(0, predicateStartIndex);
import java.net.URI;
import java.util.Map;
-
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.util.AbstractStringInstanceIdentifierCodec;
+import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
final class RandomPrefixInstanceIdentifierSerializer extends AbstractStringInstanceIdentifierCodec {
private final RandomPrefix prefixes = new RandomPrefix();
+ private final DataSchemaContextTree schemaTree;
+
+
+ RandomPrefixInstanceIdentifierSerializer(SchemaContext ctx) {
+ schemaTree = DataSchemaContextTree.from(ctx);
+ }
Iterable<Map.Entry<URI, String>> getPrefixes() {
return prefixes.getPrefixes();
throw new UnsupportedOperationException("Not implemented");
}
+ @Override
+ protected DataSchemaContextTree getDataContextTree() {
+ return schemaTree;
+ }
+
}
* @param writer XML Stream writer
* @param id InstanceIdentifier
* @throws XMLStreamException
+ *
+ * @deprecated Use {@link #writeInstanceIdentifier(XMLStreamWriter, YangInstanceIdentifier)} instead.
*/
+ @Deprecated
public static void write(final @Nonnull XMLStreamWriter writer, final @Nonnull YangInstanceIdentifier id) throws XMLStreamException {
Preconditions.checkNotNull(writer, "Writer may not be null");
Preconditions.checkNotNull(id, "Variable should contain instance of instance identifier and can't be null");
final RandomPrefix prefixes = new RandomPrefix();
final String str = XmlUtils.encodeIdentifier(prefixes, id);
-
- for (Entry<URI, String> e: prefixes.getPrefixes()) {
- final String ns = e.getKey().toString();
- final String p = e.getValue();
-
- writer.writeNamespace(p, ns);
- }
+ writeNamespaceDeclarations(writer,prefixes.getPrefixes());
writer.writeCharacters(str);
}
}
}
- private static void write(final @Nonnull XMLStreamWriter writer, final @Nonnull InstanceIdentifierTypeDefinition type, final @Nonnull Object value) throws XMLStreamException {
+ private void write(final @Nonnull XMLStreamWriter writer, final @Nonnull InstanceIdentifierTypeDefinition type, final @Nonnull Object value) throws XMLStreamException {
if (value instanceof YangInstanceIdentifier) {
- write(writer, (YangInstanceIdentifier)value);
+ writeInstanceIdentifier(writer, (YangInstanceIdentifier)value);
} else {
LOG.warn("Value of {}:{} is not an InstanceIdentifier but {}", type.getQName().getNamespace(), type.getQName().getLocalName(), value.getClass());
writer.writeCharacters(String.valueOf(value));
}
}
+ public void writeInstanceIdentifier(XMLStreamWriter writer, YangInstanceIdentifier value) throws XMLStreamException {
+ if(schemaContext.isPresent()) {
+ RandomPrefixInstanceIdentifierSerializer iiCodec = new RandomPrefixInstanceIdentifierSerializer(schemaContext.get());
+ String serializedValue = iiCodec.serialize(value);
+ writeNamespaceDeclarations(writer,iiCodec.getPrefixes());
+ writer.writeCharacters(serializedValue);
+ } else {
+ LOG.warn("Schema context not present in {}, serializing {} without schema.",this,value);
+ write(writer,value);
+ }
+ }
+
+ private static void writeNamespaceDeclarations(XMLStreamWriter writer, Iterable<Entry<URI, String>> prefixes) throws XMLStreamException {
+ for (Entry<URI, String> e: prefixes) {
+ final String ns = e.getKey().toString();
+ final String p = e.getValue();
+ writer.writeNamespace(p, ns);
+ }
+ }
+
public static XmlStreamUtils create(final XmlCodecProvider codecProvider, final SchemaContext schemaContext) {
return new XmlStreamUtils(codecProvider, schemaContext);
}
package org.opendaylight.yangtools.yang.data.impl.codec.xml;
import java.util.Map;
-
import javax.annotation.Nonnull;
-
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
return superType;
}
+ /**
+ *
+ * @deprecated Use {@link RandomPrefixInstanceIdentifierSerializer} instead.
+ */
+ @Deprecated
static String encodeIdentifier(final RandomPrefix prefixes, final YangInstanceIdentifier id) {
StringBuilder textContent = new StringBuilder();
for (PathArgument pathArgument : id.getPathArguments()) {
*/
package org.opendaylight.yangtools.yang.data.impl.schema.transform.base;
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableMap;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
import java.util.Set;
-
-import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
-import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
-import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.model.api.Status;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.UsesNode;
+import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
/**
* Proxy for AugmentationSchema. Child node schemas are replaced with actual schemas from parent.
+ *
+ * @deprecated Replaced with {@link EffectiveAugmentationSchema}.
*/
-public final class AugmentationSchemaProxy implements AugmentationSchema {
- private final AugmentationSchema delegate;
- private final Set<DataSchemaNode> realChildSchemas;
- private final Map<QName, DataSchemaNode> mappedChildSchemas;
-
- public AugmentationSchemaProxy(final AugmentationSchema augmentSchema, final Set<DataSchemaNode> realChildSchemas) {
- this.delegate = augmentSchema;
- this.realChildSchemas = realChildSchemas;
-
- final Map<QName, DataSchemaNode> m = new HashMap<>(realChildSchemas.size());
- for (DataSchemaNode realChildSchema : realChildSchemas) {
- m.put(realChildSchema.getQName(), realChildSchema);
- }
-
- this.mappedChildSchemas = ImmutableMap.copyOf(m);
- }
+@Deprecated
+public final class AugmentationSchemaProxy extends EffectiveAugmentationSchema {
- @Override
- public RevisionAwareXPath getWhenCondition() {
- return delegate.getWhenCondition();
- }
-
- @Override
- public String getDescription() {
- return delegate.getDescription();
- }
-
- @Override
- public String getReference() {
- return delegate.getReference();
- }
-
- @Override
- public Status getStatus() {
- return delegate.getStatus();
- }
- @Override
- public SchemaPath getTargetPath() {
- return delegate.getTargetPath();
- }
-
- @Override
- public List<UnknownSchemaNode> getUnknownSchemaNodes() {
- return delegate.getUnknownSchemaNodes();
- }
-
- @Override
- public Set<TypeDefinition<?>> getTypeDefinitions() {
- return delegate.getTypeDefinitions();
- }
-
- @Override
- public Set<DataSchemaNode> getChildNodes() {
- return realChildSchemas;
- }
-
- @Override
- public Set<GroupingDefinition> getGroupings() {
- return delegate.getGroupings();
- }
-
- @Override
- public DataSchemaNode getDataChildByName(final QName name) {
- return mappedChildSchemas.get(name);
- }
-
- @Override
- public DataSchemaNode getDataChildByName(final String name) {
- // Unused
- throw new UnsupportedOperationException("Unable to retrieve child node by name");
- }
-
- @Override
- public Set<UsesNode> getUses() {
- return delegate.getUses();
+ public AugmentationSchemaProxy(final AugmentationSchema augmentSchema, final Set<DataSchemaNode> realChildSchemas) {
+ super(augmentSchema,realChildSchemas);
}
- @Override
- public Optional<AugmentationSchema> getOriginalDefinition() {
- return delegate.getOriginalDefinition();
- }
}
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.AttributesBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
/**
* Abstract(base) Parser for DataContainerNodes e.g. ContainerNode, AugmentationNode.
for (AugmentationSchema augmentSchema : augmentsToElements.keySet()) {
Set<DataSchemaNode> realChildSchemas = getRealSchemasForAugment(schema, augmentSchema);
- AugmentationSchemaProxy augSchemaProxy = new AugmentationSchemaProxy(augmentSchema, realChildSchemas);
+ EffectiveAugmentationSchema augSchemaProxy = new EffectiveAugmentationSchema(augmentSchema, realChildSchemas);
containerBuilder.withChild(getDispatcher().dispatchChildElement(augSchemaProxy, augmentsToElements.get(augmentSchema)));
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
import java.util.List;
import java.util.Set;
-
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
+import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
/**
* Abstract(base) Serializer for DataContainerNodes e.g. ContainerNode, AugmentationNode.
AugmentationSchema augSchema = getAugmentedCase(schema, (AugmentationNode) choiceChild);
Set<DataSchemaNode> realChildSchemas = getRealSchemasForAugment(schema, augSchema);
- childSchema = new AugmentationSchemaProxy(augSchema, realChildSchemas);
+ childSchema = new EffectiveAugmentationSchema(augSchema, realChildSchemas);
} else {
childSchema = getSchemaForChild(schema, choiceChild);
import static com.google.common.base.Preconditions.checkArgument;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutionException;
-
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
+import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
/**
* Base strategy for applying changes to a ContainerNode, irrespective of its
return ImmutableAugmentationNodeBuilder.create((AugmentationNode) original);
}
-
private static AugmentationSchema createAugmentProxy(final AugmentationSchema schema, final DataNodeContainer resolved) {
Set<DataSchemaNode> realChildSchemas = new HashSet<>();
for(DataSchemaNode augChild : schema.getChildNodes()) {
realChildSchemas.add(resolved.getDataChildByName(augChild.getQName()));
}
- return new AugmentationSchemaProxy(schema, realChildSchemas);
+ return new EffectiveAugmentationSchema(schema, realChildSchemas);
}
}
public static final String XML_CONTENT = "<input xmlns=\"urn:opendaylight:controller:rpc:test\">\n" +
"<a>value</a>\n" +
- "<ref xmlns:ltha=\"urn:opendaylight:controller:rpc:test\">/ltha:cont/ltha:l[ltha:id='id']</ref>\n" +
+ "<ref xmlns:ltha=\"urn:opendaylight:controller:rpc:test\">"+
+ "/ltha:cont/ltha:l[ ltha:id='id/foo/bar' ]"+
+ "</ref>\n" +
"</input>";
public static final String RPC_REPLY = "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"m-1\">\n" +
<groupId>${project.groupId}</groupId>
<artifactId>yang-data-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>yang-model-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>yang-model-util</artifactId>
+ </dependency>
</dependencies>
</project>
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+abstract class AbstractInteriorContextNode<T extends PathArgument> extends
+ DataSchemaContextNode<T> {
+
+ protected AbstractInteriorContextNode(final T identifier, final DataSchemaNode schema) {
+ super(identifier, schema);
+ }
+
+ @Override
+ public boolean isLeaf() {
+ return false;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+abstract class AbstractLeafNodeContext<T extends PathArgument> extends DataSchemaContextNode<T> {
+
+ protected AbstractLeafNodeContext(final T identifier, final DataSchemaNode potential) {
+ super(identifier, potential);
+ }
+
+ @Override
+ public DataSchemaContextNode<?> getChild(final PathArgument child) {
+ return null;
+ }
+
+ @Override
+ public DataSchemaContextNode<?> getChild(final QName child) {
+ return null;
+ }
+
+ @Override
+ public boolean isLeaf() {
+ return true;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+abstract class AbstractMixinContextNode<T extends PathArgument> extends
+ AbstractInteriorContextNode<T> {
+
+ protected AbstractMixinContextNode(final T identifier, final DataSchemaNode schema) {
+ super(identifier, schema);
+ }
+
+ @Override
+ public final boolean isMixin() {
+ return true;
+ }
+
+}
\ No newline at end of file
import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
-import com.google.common.base.Splitter;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
*/
@Beta
public abstract class AbstractStringInstanceIdentifierCodec extends AbstractNamespaceCodec implements InstanceIdentifierCodec<String> {
- private static final Pattern PREDICATE_PATTERN = Pattern.compile("\\[(.*?)\\]");
- private static final Splitter SLASH_SPLITTER = Splitter.on('/');
@Override
public final String serialize(final YangInstanceIdentifier data) {
StringBuilder sb = new StringBuilder();
+ DataSchemaContextNode<?> current = getDataContextTree().getRoot();
for (PathArgument arg : data.getPathArguments()) {
- if(arg instanceof AugmentationIdentifier) {
+ current = current.getChild(arg);
+
+ if(current.isMixin()) {
/*
* XML/YANG instance identifier does not have concept
- * of augmentation identifier, which identifies
- * mixin (same as paretn element), so we can safely
- * ignore it if it is part of path (since child node)
- * is identified in same fashion.
+ * of augmentation identifier, or list as whole which
+ * identifies mixin (same as paretn element),
+ * so we can safely ignore it if it is part of path
+ * (since child node) is identified in same fashion.
*
*/
continue;
sb.append("']");
}
}
-
return sb.toString();
}
+ /**
+ *
+ * Returns DataSchemaContextTree associated with SchemaContext for which
+ * serialization / deserialization occurs.
+ *
+ * Implementations MUST provide non-null Data Tree context, in order
+ * for correct serialization / deserialization of PathArguments,
+ * since XML representation does not have Augmentation arguments
+ * and does not provide path arguments for cases.
+ *
+ * This effectively means same input XPath representation of Path Argument
+ * may result in different YangInstanceIdentifiers if models are different
+ * in uses of choices and cases.
+ *
+ * @return DataSchemaContextTree associated with SchemaContext for which
+ * serialization / deserialization occurs.
+ */
+ protected abstract @Nonnull DataSchemaContextTree getDataContextTree();
+
@Override
public final YangInstanceIdentifier deserialize(final String data) {
Preconditions.checkNotNull(data, "Data may not be null");
-
- final Iterator<String> xPathParts = SLASH_SPLITTER.split(data).iterator();
-
- // must be at least "/pr:node"
- if (!xPathParts.hasNext() || !xPathParts.next().isEmpty() || !xPathParts.hasNext()) {
- return null;
- }
-
- List<PathArgument> result = new ArrayList<>();
- while (xPathParts.hasNext()) {
- String xPathPartTrimmed = xPathParts.next().trim();
-
- PathArgument pathArgument = toPathArgument(xPathPartTrimmed);
- if (pathArgument != null) {
- result.add(pathArgument);
- }
- }
- return YangInstanceIdentifier.create(result);
+ XpathStringParsingPathArgumentBuilder builder = new XpathStringParsingPathArgumentBuilder(this, data);
+ return YangInstanceIdentifier.create(builder.build());
}
- private PathArgument toPathArgument(final String xPathArgument) {
- final QName mainQName = parseQName(xPathArgument);
-
- // predicates
- final Matcher matcher = PREDICATE_PATTERN.matcher(xPathArgument);
- final Map<QName, Object> predicates = new LinkedHashMap<>();
- QName currentQName = mainQName;
-
- while (matcher.find()) {
- final String predicateStr = matcher.group(1).trim();
- final int indexOfEqualityMark = predicateStr.indexOf('=');
- if (indexOfEqualityMark != -1) {
- final String predicateValue = toPredicateValue(predicateStr.substring(indexOfEqualityMark + 1));
- if (predicateValue == null) {
- return null;
- }
-
- if (predicateStr.charAt(0) != '.') {
- // target is not a leaf-list
- currentQName = parseQName(predicateStr.substring(0, indexOfEqualityMark));
- if (currentQName == null) {
- return null;
- }
- }
- predicates.put(currentQName, predicateValue);
- }
- }
-
- if (predicates.isEmpty()) {
- return new YangInstanceIdentifier.NodeIdentifier(mainQName);
- } else {
- return new YangInstanceIdentifier.NodeIdentifierWithPredicates(mainQName, predicates);
- }
- }
-
- private static String toPredicateValue(final String predicatedValue) {
- final String predicatedValueTrimmed = predicatedValue.trim();
- if (predicatedValue.isEmpty()) {
- return null;
- }
-
- switch (predicatedValueTrimmed.charAt(0)) {
- case '"':
- return trimIfEndIs(predicatedValueTrimmed, '"');
- case '\'':
- return trimIfEndIs(predicatedValueTrimmed, '\'');
- default:
- return null;
- }
- }
-
- private static String trimIfEndIs(final String str, final char end) {
- final int l = str.length() - 1;
- if (str.charAt(l) != end) {
- return null;
- }
-
- return str.substring(1, l);
- }
}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
+
+class AnyXmlContextNode extends DataSchemaContextNode<NodeIdentifier> {
+
+ protected AnyXmlContextNode(final AnyXmlSchemaNode schema) {
+ super(new NodeIdentifier(schema.getQName()), schema);
+ }
+
+ @Override
+ public DataSchemaContextNode<?> getChild(final PathArgument child) {
+ return null;
+ }
+
+ @Override
+ public DataSchemaContextNode<?> getChild(final QName child) {
+ return null;
+ }
+
+ @Override
+ public boolean isLeaf() {
+ return false;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import java.util.Set;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+final class AugmentationContextNode extends
+ DataContainerContextNode<AugmentationIdentifier> {
+
+ public AugmentationContextNode(final AugmentationSchema augmentation, final DataNodeContainer schema) {
+ // super();
+ super(augmentationIdentifierFrom(augmentation), augmentationProxy(augmentation, schema), null);
+ }
+
+ @Override
+ public boolean isMixin() {
+ return true;
+ }
+
+ @Override
+ protected DataSchemaContextNode<?> fromLocalSchemaAndQName(final DataNodeContainer schema, final QName child) {
+ DataSchemaNode result = findChildSchemaNode(schema, child);
+ // We try to look up if this node was added by augmentation
+ if ((schema instanceof DataSchemaNode) && result.isAugmenting()) {
+ return fromAugmentation(schema, (AugmentationTarget) schema, result);
+ }
+ return fromDataSchemaNode(result);
+ }
+
+ @Override
+ protected Set<QName> getQNameIdentifiers() {
+ return getIdentifier().getPossibleChildNames();
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import com.google.common.collect.ImmutableMap;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+class ChoiceNodeContextNode extends AbstractMixinContextNode<NodeIdentifier> {
+
+ private final ImmutableMap<QName, DataSchemaContextNode<?>> byQName;
+ private final ImmutableMap<PathArgument, DataSchemaContextNode<?>> byArg;
+
+ protected ChoiceNodeContextNode(final org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
+ super(new NodeIdentifier(schema.getQName()), schema);
+ ImmutableMap.Builder<QName, DataSchemaContextNode<?>> byQNameBuilder = ImmutableMap.builder();
+ ImmutableMap.Builder<PathArgument, DataSchemaContextNode<?>> byArgBuilder = ImmutableMap.builder();
+
+ for (ChoiceCaseNode caze : schema.getCases()) {
+ for (DataSchemaNode cazeChild : caze.getChildNodes()) {
+ DataSchemaContextNode<?> childOp = fromDataSchemaNode(cazeChild);
+ byArgBuilder.put(childOp.getIdentifier(), childOp);
+ for (QName qname : childOp.getQNameIdentifiers()) {
+ byQNameBuilder.put(qname, childOp);
+ }
+ }
+ }
+ byQName = byQNameBuilder.build();
+ byArg = byArgBuilder.build();
+ }
+
+ @Override
+ public DataSchemaContextNode<?> getChild(final PathArgument child) {
+ return byArg.get(child);
+ }
+
+ @Override
+ public DataSchemaContextNode<?> getChild(final QName child) {
+ return byQName.get(child);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+
+final class ContainerContextNode extends DataContainerContextNode<NodeIdentifier> {
+
+ protected ContainerContextNode(final ContainerSchemaNode schema) {
+ super(new NodeIdentifier(schema.getQName()), schema, schema);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+class DataContainerContextNode<T extends PathArgument> extends
+ AbstractInteriorContextNode<T> {
+
+ private final DataNodeContainer schema;
+ private final Map<QName, DataSchemaContextNode<?>> byQName;
+ private final Map<PathArgument, DataSchemaContextNode<?>> byArg;
+
+ protected DataContainerContextNode(final T identifier, final DataNodeContainer schema,
+ final DataSchemaNode node) {
+ super(identifier, node);
+ this.schema = schema;
+ this.byArg = new ConcurrentHashMap<>();
+ this.byQName = new ConcurrentHashMap<>();
+ }
+
+ @Override
+ public DataSchemaContextNode<?> getChild(final PathArgument child) {
+ DataSchemaContextNode<?> potential = byArg.get(child);
+ if (potential != null) {
+ return potential;
+ }
+ potential = fromLocalSchema(child);
+ return register(potential);
+ }
+
+ private DataSchemaContextNode<?> fromLocalSchema(final PathArgument child) {
+ if (child instanceof AugmentationIdentifier) {
+ return fromSchemaAndQNameChecked(schema, ((AugmentationIdentifier) child).getPossibleChildNames()
+ .iterator().next());
+ }
+ return fromSchemaAndQNameChecked(schema, child.getNodeType());
+ }
+
+ @Override
+ public DataSchemaContextNode<?> getChild(final QName child) {
+ DataSchemaContextNode<?> potential = byQName.get(child);
+ if (potential != null) {
+ return potential;
+ }
+ potential = fromLocalSchemaAndQName(schema, child);
+ return register(potential);
+ }
+
+ protected DataSchemaContextNode<?> fromLocalSchemaAndQName(final DataNodeContainer schema2, final QName child) {
+ return fromSchemaAndQNameChecked(schema2, child);
+ }
+
+ private DataSchemaContextNode<?> register(final DataSchemaContextNode<?> potential) {
+ if (potential != null) {
+ byArg.put(potential.getIdentifier(), potential);
+ for (QName qName : potential.getQNameIdentifiers()) {
+ byQName.put(qName, potential);
+ }
+ }
+ return potential;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableSet;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
+
+/**
+ * Schema derived data providing necessary information for mapping
+ * between {@link org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode}
+ * and serialization format defined in RFC6020, since the mapping
+ * is not one-to-one.
+ *
+ * @param <T> Path Argument type
+ *
+ */
+public abstract class DataSchemaContextNode<T extends PathArgument> implements Identifiable<T> {
+
+ private final T identifier;
+ private final DataSchemaNode dataSchemaNode;
+
+ @Override
+ public T getIdentifier() {
+ return identifier;
+ };
+
+ protected DataSchemaContextNode(final T identifier, final SchemaNode schema) {
+ super();
+ this.identifier = identifier;
+ if (schema instanceof DataSchemaNode) {
+ this.dataSchemaNode = (DataSchemaNode) schema;
+ } else {
+ this.dataSchemaNode = null;
+ }
+ }
+
+ public boolean isMixin() {
+ return false;
+ }
+
+ public boolean isKeyedEntry() {
+ return false;
+ }
+
+ protected Set<QName> getQNameIdentifiers() {
+ return Collections.singleton(identifier.getNodeType());
+ }
+
+ public abstract @Nullable DataSchemaContextNode<?> getChild(final PathArgument child);
+
+ public abstract @Nullable DataSchemaContextNode<?> getChild(QName child);
+
+ public abstract boolean isLeaf();
+
+
+ public @Nullable DataSchemaNode getDataSchemaNode() {
+ return dataSchemaNode;
+ }
+
+ static final DataSchemaNode findChildSchemaNode(final DataNodeContainer parent, final QName child) {
+ DataSchemaNode potential = parent.getDataChildByName(child);
+ if (potential == null) {
+ Iterable<org.opendaylight.yangtools.yang.model.api.ChoiceNode> choices = FluentIterable.from(
+ parent.getChildNodes()).filter(ChoiceNode.class);
+ potential = findChoice(choices, child);
+ }
+ return potential;
+ }
+
+ static DataSchemaContextNode<?> fromSchemaAndQNameChecked(final DataNodeContainer schema, final QName child) {
+ DataSchemaNode result = findChildSchemaNode(schema, child);
+ // We try to look up if this node was added by augmentation
+ if ((schema instanceof DataSchemaNode) && result.isAugmenting()) {
+ return fromAugmentation(schema, (AugmentationTarget) schema, result);
+ }
+ return fromDataSchemaNode(result);
+ }
+
+ private static org.opendaylight.yangtools.yang.model.api.ChoiceNode findChoice(
+ final Iterable<org.opendaylight.yangtools.yang.model.api.ChoiceNode> choices, final QName child) {
+ org.opendaylight.yangtools.yang.model.api.ChoiceNode foundChoice = null;
+ choiceLoop: for (org.opendaylight.yangtools.yang.model.api.ChoiceNode choice : choices) {
+ for (ChoiceCaseNode caze : choice.getCases()) {
+ if (findChildSchemaNode(caze, child) != null) {
+ foundChoice = choice;
+ break choiceLoop;
+ }
+ }
+ }
+ return foundChoice;
+ }
+
+ public static AugmentationIdentifier augmentationIdentifierFrom(final AugmentationSchema augmentation) {
+ ImmutableSet.Builder<QName> potentialChildren = ImmutableSet.builder();
+ for (DataSchemaNode child : augmentation.getChildNodes()) {
+ potentialChildren.add(child.getQName());
+ }
+ return new AugmentationIdentifier(potentialChildren.build());
+ }
+
+ static DataNodeContainer augmentationProxy(final AugmentationSchema augmentation,
+ final DataNodeContainer schema) {
+ Set<DataSchemaNode> children = new HashSet<>();
+ for (DataSchemaNode augNode : augmentation.getChildNodes()) {
+ children.add(schema.getDataChildByName(augNode.getQName()));
+ }
+ return new EffectiveAugmentationSchema(augmentation, children);
+ }
+
+ /**
+ * Returns a DataContextNodeOperation for provided child node
+ *
+ * If supplied child is added by Augmentation this operation returns a
+ * DataContextNodeOperation for augmentation, otherwise returns a
+ * DataContextNodeOperation for child as call for
+ * {@link #fromDataSchemaNode(DataSchemaNode)}.
+ *
+ *
+ * @param parent
+ * @param parentAug
+ * @param child
+ * @return
+ */
+ static @Nullable DataSchemaContextNode<?> fromAugmentation(final DataNodeContainer parent,
+ final AugmentationTarget parentAug, final DataSchemaNode child) {
+ AugmentationSchema augmentation = null;
+ for (AugmentationSchema aug : parentAug.getAvailableAugmentations()) {
+ DataSchemaNode potential = aug.getDataChildByName(child.getQName());
+ if (potential != null) {
+ augmentation = aug;
+ break;
+ }
+ }
+ if (augmentation != null) {
+ return new AugmentationContextNode(augmentation, parent);
+ }
+ return fromDataSchemaNode(child);
+ }
+
+ public static @Nullable DataSchemaContextNode<?> fromDataSchemaNode(final DataSchemaNode potential) {
+ if (potential instanceof ContainerSchemaNode) {
+ return new ContainerContextNode((ContainerSchemaNode) potential);
+ } else if (potential instanceof ListSchemaNode) {
+ return fromListSchemaNode((ListSchemaNode) potential);
+ } else if (potential instanceof LeafSchemaNode) {
+ return new LeafContextNode((LeafSchemaNode) potential);
+ } else if (potential instanceof org.opendaylight.yangtools.yang.model.api.ChoiceNode) {
+ return new ChoiceNodeContextNode((org.opendaylight.yangtools.yang.model.api.ChoiceNode) potential);
+ } else if (potential instanceof LeafListSchemaNode) {
+ return fromLeafListSchemaNode((LeafListSchemaNode) potential);
+ } else if (potential instanceof AnyXmlSchemaNode) {
+ return new AnyXmlContextNode((AnyXmlSchemaNode) potential);
+ }
+ return null;
+ }
+
+ private static DataSchemaContextNode<?> fromListSchemaNode(final ListSchemaNode potential) {
+ List<QName> keyDefinition = potential.getKeyDefinition();
+ if (keyDefinition == null || keyDefinition.isEmpty()) {
+ return new UnkeyedListMixinContextNode(potential);
+ }
+ if (potential.isUserOrdered()) {
+ return new OrderedMapMixinContextNode(potential);
+ }
+ return new UnorderedMapMixinContextNode(potential);
+ }
+
+ private static DataSchemaContextNode<?> fromLeafListSchemaNode(final LeafListSchemaNode potential) {
+ if (potential.isUserOrdered()) {
+ return new OrderedLeafListMixinContextNode(potential);
+ }
+ return new UnorderedLeafListMixinContextNode(potential);
+ }
+
+ public static DataSchemaContextNode<?> from(final SchemaContext ctx) {
+ return new ContainerContextNode(ctx);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import java.util.Iterator;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class DataSchemaContextTree {
+
+ private static final LoadingCache<SchemaContext, DataSchemaContextTree> TREES = CacheBuilder.newBuilder()
+ .weakKeys()
+ .build(new CacheLoader<SchemaContext, DataSchemaContextTree>() {
+
+ @Override
+ public DataSchemaContextTree load(SchemaContext key) throws Exception {
+ return new DataSchemaContextTree(key);
+ }
+
+ });
+
+ private final DataSchemaContextNode<?> root;
+
+ private DataSchemaContextTree(final SchemaContext ctx) {
+ root = DataSchemaContextNode.from(ctx);
+ }
+
+
+ public static DataSchemaContextTree from(SchemaContext ctx) {
+ return TREES.getUnchecked(ctx);
+ }
+
+ public DataSchemaContextNode<?> getChild(final YangInstanceIdentifier path) {
+ DataSchemaContextNode<?> currentOp = root;
+ Iterator<PathArgument> arguments = path.getPathArguments().iterator();
+ while (arguments.hasNext()) {
+ currentOp = currentOp.getChild(arguments.next());
+ }
+ return currentOp;
+ }
+
+ public DataSchemaContextNode<?> getRoot() {
+ return root;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+
+final class LeafContextNode extends AbstractLeafNodeContext<NodeIdentifier> {
+
+ protected LeafContextNode(final LeafSchemaNode potential) {
+ super(new NodeIdentifier(potential.getQName()), potential);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+final class LeafListEntryContextNode extends AbstractLeafNodeContext<NodeWithValue> {
+
+ public LeafListEntryContextNode(final LeafListSchemaNode potential) {
+ super(new NodeWithValue(potential.getQName(), null), potential);
+ }
+
+ @Override
+ public boolean isKeyedEntry() {
+ return true;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+final class ListItemContextNode extends
+ DataContainerContextNode<NodeIdentifierWithPredicates> {
+
+
+ protected ListItemContextNode(final NodeIdentifierWithPredicates identifier, final ListSchemaNode schema) {
+ super(identifier, schema, schema);
+ }
+
+ @Override
+ public boolean isKeyedEntry() {
+ return true;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+final class OrderedLeafListMixinContextNode extends UnorderedLeafListMixinContextNode {
+
+ public OrderedLeafListMixinContextNode(final LeafListSchemaNode potential) {
+ super(potential);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+final class OrderedMapMixinContextNode extends UnorderedMapMixinContextNode {
+
+ public OrderedMapMixinContextNode(final ListSchemaNode list) {
+ super(list);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+final class UnkeyedListItemContextNode extends DataContainerContextNode<NodeIdentifier> {
+
+ protected UnkeyedListItemContextNode(final ListSchemaNode schema) {
+ super(new NodeIdentifier(schema.getQName()), schema, schema);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+class UnkeyedListMixinContextNode extends AbstractMixinContextNode<NodeIdentifier> {
+
+ private final UnkeyedListItemContextNode innerNode;
+
+ public UnkeyedListMixinContextNode(final ListSchemaNode list) {
+ super(new NodeIdentifier(list.getQName()), list);
+ this.innerNode = new UnkeyedListItemContextNode(list);
+ }
+
+ @Override
+ public DataSchemaContextNode<?> getChild(final PathArgument child) {
+ if (child.getNodeType().equals(getIdentifier().getNodeType())) {
+ return innerNode;
+ }
+ return null;
+ }
+
+ @Override
+ public DataSchemaContextNode<?> getChild(final QName child) {
+ if (getIdentifier().getNodeType().equals(child)) {
+ return innerNode;
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+class UnorderedLeafListMixinContextNode extends AbstractMixinContextNode<NodeIdentifier> {
+
+ private final DataSchemaContextNode<?> innerOp;
+
+ public UnorderedLeafListMixinContextNode(final LeafListSchemaNode potential) {
+ super(new NodeIdentifier(potential.getQName()), potential);
+ innerOp = new LeafListEntryContextNode(potential);
+ }
+
+ @Override
+ public DataSchemaContextNode<?> getChild(final PathArgument child) {
+ if (child instanceof NodeWithValue) {
+ return innerOp;
+ }
+ return null;
+ }
+
+ @Override
+ public DataSchemaContextNode<?> getChild(final QName child) {
+ if (getIdentifier().getNodeType().equals(child)) {
+ return innerOp;
+ }
+ return null;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import java.util.Collections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+class UnorderedMapMixinContextNode extends AbstractMixinContextNode<NodeIdentifier> {
+
+ private final ListItemContextNode innerNode;
+
+ public UnorderedMapMixinContextNode(final ListSchemaNode list) {
+ super(new NodeIdentifier(list.getQName()), list);
+ this.innerNode = new ListItemContextNode(new NodeIdentifierWithPredicates(list.getQName(),
+ Collections.<QName, Object> emptyMap()), list);
+ }
+
+ @Override
+ public DataSchemaContextNode<?> getChild(final PathArgument child) {
+ if (child.getNodeType().equals(getIdentifier().getNodeType())) {
+ return innerNode;
+ }
+ return null;
+ }
+
+ @Override
+ public DataSchemaContextNode<?> getChild(final QName child) {
+ if (getIdentifier().getNodeType().equals(child)) {
+ return innerNode;
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.data.util;
+
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import java.util.LinkedList;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+/**
+ *
+ * Iterator which lazily parses {@link PathArgument} from string representation.
+ *
+ * Note that invocation of {@link #hasNext()} or {@link #next()} may result in
+ * throwing of {@link IllegalArgumentException} if underlying string represenation
+ * is not correctly serialized or does not represent instance identifier valid
+ * for associated schema context.
+ *
+ * In order to obtain {@link Iterable} or {@link java.util.Collection} please use
+ * {@link com.google.common.collect.ImmutableList#copyOf(java.util.Iterator)}
+ * with this Iterator, which will trigger computation of all path arguments.
+ *
+ */
+class XpathStringParsingPathArgumentBuilder implements Builder<Iterable<PathArgument>> {
+
+ /**
+ * Matcher matching WSP YANG ABNF token
+ *
+ */
+ private static final CharMatcher WSP = CharMatcher.anyOf(" \t");
+
+ /**
+ * Matcher matching IDENTIFIER first char token.
+ *
+ */
+ private static final CharMatcher IDENTIFIER_FIRST_CHAR =
+ CharMatcher.inRange('a', 'z')
+ .or(CharMatcher.inRange('A', 'Z'))
+ .or(CharMatcher.is('_')).precomputed();
+ /**
+ *
+ * Matcher matching IDENTIFIER token
+ *
+ */
+ private static final CharMatcher IDENTIFIER =
+ IDENTIFIER_FIRST_CHAR
+ .or(CharMatcher.inRange('0', '9'))
+ .or(CharMatcher.anyOf(".-")).precomputed();
+
+ private static final CharMatcher SQUOTE = CharMatcher.is('\'');
+ private static final CharMatcher DQUOTE = CharMatcher.is('"');
+
+ private static final char SLASH = '/';
+ private static final char COLON = ':';
+ private static final char DOT = '.';
+ private static final char EQUALS = '=';
+ private static final char PRECONDITION_START = '[';
+ private static final char PRECONDITION_END = ']';
+
+ private final AbstractStringInstanceIdentifierCodec codec;
+ private final String data;
+
+ private final LinkedList<PathArgument> product = new LinkedList<>();
+
+ private DataSchemaContextNode<?> current;
+ private int offset;
+
+ XpathStringParsingPathArgumentBuilder(AbstractStringInstanceIdentifierCodec codec, String data) {
+ this.codec = Preconditions.checkNotNull(codec);
+ this.data = Preconditions.checkNotNull(data);
+ this.current = codec.getDataContextTree().getRoot();
+ this.offset = 0;
+ }
+
+
+ @Override
+ public Iterable<PathArgument> build() {
+ while (!allCharactersConsumed()) {
+ product.add(computeNextArgument());
+ }
+ return ImmutableList.copyOf(product);
+ }
+
+ private PathArgument computeNextArgument() {
+ checkValid(SLASH == currentChar(),"Identifier must start with '/'.");
+ skipCurrentChar();
+
+ QName name = nextQName();
+ if(allCharactersConsumed() || SLASH == currentChar()) {
+ return computeIdentifier(name);
+ } else {
+ checkValid(PRECONDITION_START == currentChar(), "Last element must be identifier, predicate or '/'");
+ return computeIdentifierWithPredicate(name);
+ }
+ }
+
+
+ private DataSchemaContextNode<?> nextContextNode(QName name) {
+ current = current.getChild(name);
+ checkValid(current != null, "%s is not correct schema node identifier.",name);
+ while(current.isMixin()) {
+ product.add(current.getIdentifier());
+ current = current.getChild(name);
+ }
+ return current;
+ }
+
+
+ /**
+ *
+ * Creates path argument with predicates and sets offset
+ * to end of path argument.
+ *
+ * {@code
+ * predicate = "[" *WSP (predicate-expr / pos) *WSP "]"
+ * predicate-expr = (node-identifier / ".") *WSP "=" *WSP
+ * ((DQUOTE string DQUOTE) /
+ * (SQUOTE string SQUOTE))
+ * pos = non-negative-integer-value
+ * }
+ *
+ * @param name QName of node, for which predicates are computed.
+ * @return PathArgument representing node selection with predictes
+ */
+ private PathArgument computeIdentifierWithPredicate(QName name) {
+ DataSchemaContextNode<?> currentNode = nextContextNode(name);
+ checkValid(currentNode.isKeyedEntry(), "Entry %s does not allow specifying predicates.", name);
+
+ ImmutableMap.Builder<QName,Object> keyValues = ImmutableMap.builder();
+ while(!allCharactersConsumed() && PRECONDITION_START == currentChar()) {
+ skipCurrentChar();
+ skipWhitespaces();
+ final QName key;
+ if(DOT == currentChar()) {
+ key = null;
+ skipCurrentChar();
+ } else {
+ key = nextQName();
+ }
+ skipWhitespaces();
+ checkCurrentAndSkip(EQUALS, "Precondition must contain '='");
+ skipWhitespaces();
+ final Object value = deserializeValue(key,nextQuotedValue());
+ skipWhitespaces();
+ checkCurrentAndSkip(PRECONDITION_END, "Precondition must ends with ']'");
+
+ // Break-out from method for leaf-list case
+ if(key == null && currentNode.isLeaf()) {
+ checkValid(offset == data.length(), "Leaf argument must be last argument of instance identifier.");
+ return new YangInstanceIdentifier.NodeWithValue(name, value);
+ }
+ keyValues.put(key, value);
+ }
+ return new YangInstanceIdentifier.NodeIdentifierWithPredicates(name, keyValues.build());
+ }
+
+
+ private PathArgument computeIdentifier(QName name) {
+ DataSchemaContextNode<?> currentNode = nextContextNode(name);
+ checkValid(!currentNode.isKeyedEntry(), "Entry %s requires key or value predicate to be present", name);
+ return currentNode.getIdentifier();
+ }
+
+
+ /**
+ *
+ * Returns following QName and sets offset to end of QName.
+ *
+ * @return following QName.
+ */
+ private QName nextQName() {
+ // Consume prefix or identifie
+ final String maybePrefix = nextIdentifier();
+ final String prefix,localName;
+ if(COLON == currentChar()) {
+ // previous token is prefix;
+ prefix = maybePrefix;
+ skipCurrentChar();
+ localName = nextIdentifier();
+ } else {
+ prefix = "";
+ localName = maybePrefix;
+ }
+ return createQName(prefix, localName);
+ }
+
+ /**
+ * Returns true if all characters from input string
+ * were consumed.
+ *
+ * @return true if all characters from input string
+ * were consumed.
+ */
+ private boolean allCharactersConsumed() {
+ return offset == data.length();
+ }
+
+
+ private QName createQName(String prefix, String localName) {
+ return codec.createQName(prefix, localName);
+ }
+
+ /**
+ *
+ * Skips current char if it equals expected otherwise fails parsing.
+ *
+ * @param expected Expected character
+ * @param errorMsg Error message if {@link #currentChar()} does not match expected.
+ */
+ private void checkCurrentAndSkip(char expected, String errorMsg) {
+ checkValid(expected == currentChar(), errorMsg);
+ offset++;
+ }
+
+
+ /**
+ *
+ * Deserializes value for supplied key
+ *
+ * @param key Name of referenced key, If null, referenced leaf is previous encountered item.
+ * @param value Value to be checked and deserialized
+ * @return Object representing value in yang-data-api format.
+ */
+ private Object deserializeValue(@Nullable QName key, String value) {
+ // FIXME: Use codec to deserialize value to correct Java type
+ return value;
+ }
+
+ /**
+ *
+ * Fails parsing if condition is not met.
+ *
+ * In case of error provides pointer to failed instance identifier,
+ * offset on which failure occured with explanation.
+ *
+ * @param condition Fails parsing if {@code condition} is false
+ * @param errorMsg Error message which will be provided to user.
+ * @param attributes
+ */
+ private void checkValid(boolean condition, String errorMsg, Object... attributes) {
+ Preconditions.checkArgument(condition, "Could not parse Instance Identifier '%s'. Offset: %s : Reason: %s",
+ data,
+ offset,
+ String.format(errorMsg, attributes));
+ }
+
+ /**
+ *
+ * Returns following value of quoted literal (without qoutes)
+ * and sets offset after literal.
+ *
+ * @return String literal
+ */
+ private String nextQuotedValue() {
+ char quoteChar = currentChar();
+ checkValidQuotation(quoteChar);
+ skipCurrentChar();
+ int valueStart = offset;
+ int endQoute = data.indexOf(quoteChar, offset);
+ String value = data.substring(valueStart, endQoute);
+ offset = endQoute;
+ skipCurrentChar();
+ return value;
+ }
+
+ /**
+ * Returns character at current offset.
+ *
+ * @return character at current offset.
+ */
+ private char currentChar() {
+ return data.charAt(offset);
+ }
+
+ /**
+ * Increases processing offset by 1
+ */
+ private void skipCurrentChar() {
+ offset++;
+ }
+
+ /**
+ * Skip whitespace characters, sets offset to first following
+ * non-whitespace character.
+ */
+ private void skipWhitespaces() {
+ nextSequenceEnd(WSP);
+ }
+
+ /**
+ * Returns string which matches IDENTIFIER YANG ABNF token
+ * and sets processing offset after end of identifier.
+ *
+ * @return string which matches IDENTIFIER YANG ABNF token
+ */
+ private String nextIdentifier() {
+ int start = offset;
+ checkValid(IDENTIFIER_FIRST_CHAR.matches(currentChar()), "Identifier must start with character from set 'a-zA-Z_'");
+ nextSequenceEnd(IDENTIFIER);
+ return data.substring(start, offset);
+ }
+
+ private void nextSequenceEnd(CharMatcher matcher) {
+ while(!allCharactersConsumed() && matcher.matches(data.charAt(offset))) {
+ offset++;
+ }
+ }
+
+ private void checkValidQuotation(char quoteChar) {
+ checkValid(
+ SQUOTE.matches(quoteChar) || DQUOTE.matches(quoteChar),
+ "Value must be qoute escaped with ''' or '\"'.");
+
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yangtools.yang.model.util;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.UsesNode;
+
+/**
+ * Proxy for AugmentationSchema. Child node schemas are replaced with actual schemas from parent.
+ *
+ * FIXME: Make this class final, once derived deprecated class is removed.
+ */
+public class EffectiveAugmentationSchema implements AugmentationSchema {
+ private final AugmentationSchema delegate;
+ private final Set<DataSchemaNode> realChildSchemas;
+ private final Map<QName, DataSchemaNode> mappedChildSchemas;
+
+ public EffectiveAugmentationSchema(final AugmentationSchema augmentSchema, final Set<DataSchemaNode> realChildSchemas) {
+ this.delegate = augmentSchema;
+ this.realChildSchemas = realChildSchemas;
+
+ final Map<QName, DataSchemaNode> m = new HashMap<>(realChildSchemas.size());
+ for (DataSchemaNode realChildSchema : realChildSchemas) {
+ m.put(realChildSchema.getQName(), realChildSchema);
+ }
+
+ this.mappedChildSchemas = ImmutableMap.copyOf(m);
+ }
+
+ @Override
+ public RevisionAwareXPath getWhenCondition() {
+ return delegate.getWhenCondition();
+ }
+
+ @Override
+ public String getDescription() {
+ return delegate.getDescription();
+ }
+
+ @Override
+ public String getReference() {
+ return delegate.getReference();
+ }
+
+ @Override
+ public Status getStatus() {
+ return delegate.getStatus();
+ }
+
+ @Override
+ public SchemaPath getTargetPath() {
+ return delegate.getTargetPath();
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return delegate.getUnknownSchemaNodes();
+ }
+
+ @Override
+ public Set<TypeDefinition<?>> getTypeDefinitions() {
+ return delegate.getTypeDefinitions();
+ }
+
+ @Override
+ public Set<DataSchemaNode> getChildNodes() {
+ return realChildSchemas;
+ }
+
+ @Override
+ public Set<GroupingDefinition> getGroupings() {
+ return delegate.getGroupings();
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(final QName name) {
+ return mappedChildSchemas.get(name);
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(final String name) {
+ // Unused
+ throw new UnsupportedOperationException("Unable to retrieve child node by name");
+ }
+
+ @Override
+ public Set<UsesNode> getUses() {
+ return delegate.getUses();
+ }
+
+ @Override
+ public Optional<AugmentationSchema> getOriginalDefinition() {
+ return delegate.getOriginalDefinition();
+ }
+}