With implementation for dom <-> normalized nodes.
Change-Id: Ic2c08d2955177bc335d6493d64076a77d2cc7d62
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
Signed-off-by: Jozef Gloncak <jgloncak@cisco.com>
Signed-off-by: Ladislav Borak <lborak@cisco.com>
Signed-off-by: Robert Varga <rovarga@cisco.com>
<!-- Build Plugin Versions -->
<maven.bundle.version>2.4.0</maven.bundle.version>
- <maven.jar.version>2.4</maven.jar.version>
+ <maven.jar.version>2.3.2</maven.jar.version>
<maven.javadoc.version>2.9.1</maven.javadoc.version>
<maven.release.version>2.4.2</maven.release.version>
<maven.source.version>2.2.1</maven.source.version>
return childNames;
}
+ @Override
+ public String toString() {
+ final StringBuffer sb = new StringBuffer("AugmentationIdentifier{");
+ sb.append("childNames=").append(childNames);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof AugmentationIdentifier)) return false;
+
+ AugmentationIdentifier that = (AugmentationIdentifier) o;
+
+ if (childNames != null ? !childNames.equals(that.childNames) : that.childNames != null) return false;
+ if (nodeType != null ? !nodeType.equals(that.nodeType) : that.nodeType != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = nodeType != null ? nodeType.hashCode() : 0;
+ result = 31 * result + (childNames != null ? childNames.hashCode() : 0);
+ return result;
+ }
}
private static class BuilderImpl implements InstanceIdentifierBuilder {
import com.google.common.io.BaseEncoding;
public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> implements DataStringCodec<J> {
-
+
private static final Pattern intPattern = Pattern.compile("[+-]?[1-9][0-9]*$");
private static final Pattern hexPattern = Pattern.compile("[+-]?0[xX][0-9a-fA-F]+");
private static final Pattern octalPattern = Pattern.compile("[+-]?0[1-7][0-7]*$");
-
+
private final Optional<T> typeDefinition;
private final Class<J> inputClass;
-
+
private static final int provideBase(final String integer) {
if (integer == null) {
throw new IllegalArgumentException("String representing integer number cannot be NULL!");
}
-
+
if ((integer.length() == 1) && (integer.charAt(0) == '0')) {
return 10;
}
-
+
final Matcher intMatcher = intPattern.matcher(integer);
if (intMatcher.matches()) {
return 10;
if (octMatcher.matches()) {
return 8;
} else {
- throw new NumberFormatException("Incorrect lexical representation of Integer value!"
+ throw new NumberFormatException("Incorrect lexical representation of Integer value: " + integer
+ "The Integer value can be defined as Integer Number, Hexadecimal Number or"
+ "Octal Number. The sign vlues are allowed. "
+ "Spaces between digits are NOT allowed!");
}
}
}
-
+
private static String normalizeHexadecimal(final String hexInt) {
if (hexInt == null) {
throw new IllegalArgumentException(
}
return normalizedString;
}
-
+
public static final BinaryCodecStringImpl BINARY_DEFAULT_CODEC = new BinaryCodecStringImpl(
Optional.<BinaryTypeDefinition> absent());
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
-import com.google.common.collect.Maps;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.ModifyAction;
import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.w3c.dom.*;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
import com.google.common.base.Function;
import com.google.common.base.Objects;
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.Sets;
public class ImmutableAugmentationNodeSchemaAwareBuilder extends ImmutableAugmentationNodeBuilder {
final Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children) {
super(ImmutableMap.copyOf(children), nodeIdentifier);
}
-
}
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
+import com.google.common.base.Supplier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataNodeContainerValidator;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils;
import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-
-import com.google.common.base.Preconditions;
public class ImmutableChoiceNodeSchemaAwareBuilder extends ImmutableChoiceNodeBuilder {
}
@Override
- public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> withChild(DataContainerChild<?, ?> child) {
+ public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> withChild(final DataContainerChild<?, ?> child) {
if(detectedCase == null) {
- detectedCase = detectCase(child);
+ detectedCase = SchemaUtils.detectCase(schema, child).or(new Supplier<ChoiceCaseNode>() {
+ @Override
+ public ChoiceCaseNode get() {
+ throw new IllegalArgumentException(String.format("Unknown child node: %s, for choice: %s", child.getNodeType(),
+ schema.getQName()));
+ }
+ });
validator = new DataNodeContainerValidator(detectedCase);
}
return super.build();
}
- private ChoiceCaseNode detectCase(DataContainerChild<?, ?> child) {
- for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
- for (DataSchemaNode childFromCase : choiceCaseNode.getChildNodes()) {
- if (childFromCase.getQName().equals(child.getNodeType())) {
- return choiceCaseNode;
- }
- }
- }
-
- throw new IllegalArgumentException(String.format("Unknown child node: %s, for choice: %s", child.getNodeType(),
- schema.getQName()));
- }
-
public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> create(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
return new ImmutableChoiceNodeSchemaAwareBuilder(schema);
}
super(nodeIdentifier, value);
}
- @Override
- public String toString() {
- final StringBuffer sb = new StringBuffer("ImmutableLeafNode{");
- sb.append("nodeIdentifier=").append(nodeIdentifier);
- sb.append(", value=").append(value);
- sb.append('}');
- return sb.toString();
- }
}
}
"Node identifier contains different value: %s than value itself: %s", nodeIdentifier, value);
}
- @Override
- public String toString() {
- final StringBuffer sb = new StringBuffer("ImmutableLeafSetEntryNode{");
- sb.append("nodeIdentifier=").append(nodeIdentifier);
- sb.append(", value=").append(value);
- sb.append('}');
- return sb.toString();
- }
}
}
import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
public class ImmutableLeafSetNodeBuilder<T> implements ListNodeBuilder<T, LeafSetEntryNode<T>> {
ImmutableLeafSetNode(final InstanceIdentifier.NodeIdentifier nodeIdentifier,
final Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> children) {
- super(nodeIdentifier, children.values());
+ super(nodeIdentifier, ImmutableList.copyOf(children.values()));
this.mappedChildren = children;
}
return Optional.fromNullable(mappedChildren.get(child));
}
- @Override
- public String toString() {
- final StringBuffer sb = new StringBuffer("ImmutableLeafSetNode{");
- sb.append("nodeIdentifier=").append(nodeIdentifier);
- sb.append(", children=").append(value);
- sb.append('}');
- return sb.toString();
- }
}
@Override
@Override
public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> withValue(final List<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> value) {
for (DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> childId : value) {
- this.childrenQNamesToPaths.put(childId.getNodeType(), childId.getIdentifier());
+ InstanceIdentifier.PathArgument identifier = childId.getIdentifier();
+
+ // Augmentation nodes cannot be keys, and do not have to be present in childrenQNamesToPaths map
+ if(identifier instanceof InstanceIdentifier.AugmentationIdentifier) {
+ continue;
+ }
+
+ this.childrenQNamesToPaths.put(childId.getNodeType(), identifier);
}
return super.withValue(value);
}
@Override
public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> withChild(final DataContainerChild<?, ?> child) {
- childrenQNamesToPaths.put(child.getNodeType(), child.getIdentifier());
+ // Augmentation nodes cannot be keys, and do not have to be present in childrenQNamesToPaths map
+ if(child.getIdentifier() instanceof InstanceIdentifier.AugmentationIdentifier == false) {
+ childrenQNamesToPaths.put(child.getNodeType(), child.getIdentifier());
+ }
return super.withChild(child);
}
keysToValues.put(key, valueForKey.getValue());
}
+
return new InstanceIdentifier.NodeIdentifierWithPredicates(schema.getQName(), keysToValues);
}
import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
public class ImmutableMapNodeBuilder
ImmutableMapNode(final InstanceIdentifier.NodeIdentifier nodeIdentifier,
final Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> children) {
- super(nodeIdentifier, children.values());
+ super(nodeIdentifier, ImmutableList.copyOf(children.values()));
this.mappedChildren = children;
}
return Optional.fromNullable(mappedChildren.get(child));
}
- @Override
- public String toString() {
- final StringBuffer sb = new StringBuffer("ImmutableMapNode{");
- sb.append("nodeIdentifier=").append(nodeIdentifier);
- sb.append(", children=").append(mappedChildren);
- sb.append('}');
- return sb.toString();
- }
}
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
+import java.util.Collection;
+import java.util.Collections;
+
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeSchemaAwareBuilder;
-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.*;
-import java.util.Collection;
-import java.util.Collections;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
/**
* General validator for container like statements, e.g. container, list-entry, choice, augment
return true;
}
}
- // check regular child node
+ // check regular child node (also in child cases)
+ } else if(schema.getDataChildByName(child.getNodeType()) == null) {
+ for (DataSchemaNode dataSchemaNode : schema.getChildNodes()) {
+ if(dataSchemaNode instanceof ChoiceCaseNode) {
+ if(((ChoiceCaseNode) dataSchemaNode).getDataChildByName(child.getNodeType()) != null) {
+ return true;
+ }
+ }
+ }
} else {
- return schema.getDataChildByName(child.getNodeType()) != null;
+ return true;
}
return false;
// FIXME, need to compare Set of QNames(AugmentationIdentifier) with Set of DataSchemaNodes(AugmentationSchema)
// throw away set is created just to compare
// Or if augmentationSchemaNode had a QName, we would just compare a QName
- private boolean equalAugments(AugmentationSchema augmentationSchema, InstanceIdentifier.AugmentationIdentifier identifier) {
+ public static boolean equalAugments(AugmentationSchema augmentationSchema, InstanceIdentifier.AugmentationIdentifier identifier) {
return identifier.getPossibleChildNames().equals(ImmutableAugmentationNodeSchemaAwareBuilder.getChildQNames(augmentationSchema));
}
public void validateChild(InstanceIdentifier.PathArgument child) {
- Preconditions.checkArgument(isKnownChild(child), "Unknown child node: %s, does not belong to: %s", child.getNodeType(), schema);
+ Preconditions.checkArgument(isKnownChild(child), "Unknown child node: %s, does not belong to: %s", child, schema);
// FIXME make a cache for augmentation child sets in constructor
Optional<AugmentationSchema> augmentChild = isAugmentChild(child);
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
public abstract class AbstractImmutableDataContainerNode<K extends PathArgument> //
extends AbstractImmutableNormalizedNode<K, Iterable<DataContainerChild<? extends PathArgument, ?>>> //
protected final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> children;
+
public AbstractImmutableDataContainerNode(
final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> children, final K nodeIdentifier) {
- super(nodeIdentifier, children.values());
+ super(nodeIdentifier, ImmutableList.copyOf(children.values()));
this.children = children;
}
return Optional.<DataContainerChild<? extends PathArgument, ?>> fromNullable(children.get(child));
}
- @Override
- public String toString() {
- final StringBuffer sb = new StringBuffer("ImmutableContainerNode{");
- sb.append("nodeIdentifier=").append(nodeIdentifier);
- sb.append(", children=").append(children);
- sb.append('}');
- return sb.toString();
- }
}
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
public abstract class AbstractImmutableNormalizedNode<K extends InstanceIdentifier.PathArgument,V>
implements NormalizedNode<K, V>, Immutable {
protected final K nodeIdentifier;
- protected V value;
+ protected final V value;
protected AbstractImmutableNormalizedNode(K nodeIdentifier, V value) {
this.nodeIdentifier = Preconditions.checkNotNull(nodeIdentifier, "nodeIdentifier");
}
@Override
- public QName getNodeType() {
+ public final QName getNodeType() {
return getIdentifier().getNodeType();
}
@Override
- public K getIdentifier() {
+ public final K getIdentifier() {
return nodeIdentifier;
}
@Override
- public CompositeNode getParent() {
+ public final CompositeNode getParent() {
throw new UnsupportedOperationException("Deprecated");
}
@Override
- public QName getKey() {
+ public final QName getKey() {
return getNodeType();
}
@Override
- public V getValue() {
+ public final V getValue() {
return value;
}
@Override
- public V setValue(V value) {
+ public final V setValue(V value) {
throw new UnsupportedOperationException("Immutable");
}
+ @Override
+ public final String toString() {
+ return Objects.toStringHelper(this)
+ .add("nodeIdentifier", nodeIdentifier)
+ .add("value", value)
+ .toString();
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AbstractImmutableNormalizedNode)) return false;
- AbstractImmutableNormalizedNode that = (AbstractImmutableNormalizedNode) o;
+ AbstractImmutableNormalizedNode<?, ?> that = (AbstractImmutableNormalizedNode<?, ?>) o;
if (!nodeIdentifier.equals(that.nodeIdentifier)) return false;
if (!value.equals(that.value)) return false;
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform;
+
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ *
+ * Generic serializer for normalized nodes. NormalizedNodes can be serialized
+ * e.g. to Dom APIs.
+ *
+ * @param <E>
+ * type of resulting/serialized element from NormalizedNode
+ * @param <N>
+ * type of NormalizedNode to be serialized
+ * @param <S>
+ * schema belonging to the type N of NormalizedNode
+ */
+public interface FromNormalizedNodeSerializer<E, N extends NormalizedNode<?, ?>, S> {
+
+ /**
+ *
+ * Serialize one node of type N as a list of E elements. If the serialization
+ * process creates only one E element as a result e.g. container node, the
+ * result element is expected to be wrapped in a list.
+ *
+ * @param schema
+ * @param node
+ * @return Serialized N node as a list of E elements
+ */
+ Iterable<E> serialize(S schema, N node);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform;
+
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ *
+ * Generic parser for normalized nodes. NormalizedNodes can be parsed
+ * e.g. from Dom APIs.
+ *
+ * @param <E>
+ * type of element to be parsed into NormalizedNode
+ * @param <N>
+ * type of NormalizedNode to be the result of parsing
+ * @param <S>
+ * schema belonging to the type N of NormalizedNode
+ */
+public interface ToNormalizedNodeParser<E, N extends NormalizedNode<?, ?>, S> {
+
+ /**
+ *
+ * Parse a list of E elements as a NormalizedNode of type N. If the parsing
+ * process expects only one E element as input e.g. container node, the
+ * input element will be wrapped in a list.
+ *
+ * @param xmlDom
+ * @param schema
+ * @return NormalizedNode as a result of parsing list of E elements with schema S
+ */
+ N parse(Iterable<E> xmlDom, S schema);
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.common.collect.Maps;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.*;
+
+/**
+ * Proxy for AugmentationSchema. Child node schemas are replaced with actual schemas from parent.
+ */
+public final class AugmentationSchemaProxy implements AugmentationSchema {
+ private final AugmentationSchema delegate;
+ private final Set<DataSchemaNode> realChildSchemas;
+ private final Map<QName, DataSchemaNode> mappedChildSchemas;
+
+ public AugmentationSchemaProxy(AugmentationSchema augmentSchema, Set<DataSchemaNode> realChildSchemas) {
+ this.delegate = augmentSchema;
+ this.realChildSchemas = realChildSchemas;
+
+ this.mappedChildSchemas = Maps.newHashMap();
+ for (DataSchemaNode realChildSchema : realChildSchemas) {
+ mappedChildSchemas.put(realChildSchema.getQName(), realChildSchema);
+ }
+ }
+
+ @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(QName name) {
+ if(mappedChildSchemas.containsKey(name)) {
+ return mappedChildSchemas.get(name);
+ }
+
+ throw new IllegalArgumentException("Unknown child: " + name + " in: " + delegate);
+ }
+
+ @Override
+ public DataSchemaNode getDataChildByName(String name) {
+ // Unused
+ throw new UnsupportedOperationException("Unable to retrieve child node by name");
+ }
+
+ @Override
+ public Set<UsesNode> getUses() {
+ return delegate.getUses();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.model.api.*;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public final class SchemaUtils {
+
+ private SchemaUtils() {
+ }
+
+ public static DataSchemaNode findSchemaForChild(DataNodeContainer schema, QName qname) {
+ Set<DataSchemaNode> childNodes = schema.getChildNodes();
+ return findSchemaForChild(schema, qname, childNodes);
+ }
+
+ public static DataSchemaNode findSchemaForChild(DataNodeContainer schema, QName qname, Set<DataSchemaNode> childNodes) {
+ Optional<DataSchemaNode> childSchema = XmlDocumentUtils.findFirstSchema(qname, childNodes);
+ Preconditions.checkState(childSchema.isPresent(),
+ "Unknown child(ren) node(s) detected, identified by: %s, in: %s", qname, schema);
+ return childSchema.get();
+ }
+
+ public static AugmentationSchema findSchemaForAugment(AugmentationTarget schema, Set<QName> qNames) {
+ Optional<AugmentationSchema> schemaForAugment = findAugment(schema, qNames);
+ Preconditions.checkState(schemaForAugment.isPresent(), "Unknown augmentation node detected, identified by: %s, in: %s",
+ qNames, schema);
+ return schemaForAugment.get();
+ }
+
+ public static AugmentationSchema findSchemaForAugment(ChoiceNode schema, Set<QName> qNames) {
+ Optional<AugmentationSchema> schemaForAugment = Optional.absent();
+
+ for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+ schemaForAugment = findAugment(choiceCaseNode, qNames);
+ if(schemaForAugment.isPresent()) {
+ break;
+ }
+ }
+
+ Preconditions.checkState(schemaForAugment.isPresent(), "Unknown augmentation node detected, identified by: %s, in: %s",
+ qNames, schema);
+ return schemaForAugment.get();
+ }
+
+ private static Optional<AugmentationSchema> findAugment(AugmentationTarget schema, Set<QName> qNames) {
+ for (AugmentationSchema augment : schema.getAvailableAugmentations()) {
+
+ HashSet<QName> qNamesFromAugment = Sets.newHashSet(Collections2.transform(augment.getChildNodes(), new Function<DataSchemaNode, QName>() {
+ @Override
+ public QName apply(DataSchemaNode input) {
+ return input.getQName();
+ }
+ }));
+
+ if(qNamesFromAugment.equals(qNames)) {
+ return Optional.of(augment);
+ }
+ }
+
+ return Optional.absent();
+ }
+
+ public static DataSchemaNode findSchemaForChild(ChoiceNode schema, QName childPartialQName) {
+ for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+ Optional<DataSchemaNode> childSchema = XmlDocumentUtils.findFirstSchema(childPartialQName,
+ choiceCaseNode.getChildNodes());
+ if (childSchema.isPresent()) {
+ return childSchema.get();
+ }
+ }
+
+
+ throw new IllegalStateException(String.format("Unknown child(ren) node(s) detected, identified by: %s, in: %s",
+ childPartialQName, schema));
+ }
+
+ /**
+ * Recursively find all child nodes that come from choices in augment.
+ *
+ * @return Map with all child nodes, to their most top augmentation
+ */
+ public static Map<QName,ChoiceNode> mapChildElementsFromChoicesInAugment(AugmentationSchema schema, Set<DataSchemaNode> realChildSchemas) {
+ Map<QName, ChoiceNode> mappedChoices = Maps.newLinkedHashMap();
+
+ for (DataSchemaNode realChildSchema : realChildSchemas) {
+ if(realChildSchema instanceof ChoiceNode)
+ mappedChoices.putAll(mapChildElementsFromChoices(schema, realChildSchemas));
+ }
+
+ return mappedChoices;
+ }
+
+ /**
+ * Recursively find all child nodes that come from choices.
+ *
+ * @return Map with all child nodes, to their most top augmentation
+ */
+ public static Map<QName, ChoiceNode> mapChildElementsFromChoices(DataNodeContainer schema) {
+ Set<DataSchemaNode> childNodes = schema.getChildNodes();
+
+ return mapChildElementsFromChoices(schema, childNodes);
+ }
+
+ private static Map<QName, ChoiceNode> mapChildElementsFromChoices(DataNodeContainer schema, Set<DataSchemaNode> childNodes) {
+ Map<QName, ChoiceNode> mappedChoices = Maps.newLinkedHashMap();
+
+ for (final DataSchemaNode childSchema : childNodes) {
+ if(childSchema instanceof ChoiceNode) {
+ for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) childSchema).getCases()) {
+
+ for (QName qName : getChildNodes(choiceCaseNode)) {
+ mappedChoices.put(qName, (ChoiceNode) childSchema);
+ }
+ }
+ }
+ }
+
+ // Remove augmented choices
+ // TODO ineffective, mapping augments one more time is not necessary, the map could be injected
+ if(schema instanceof AugmentationTarget) {
+ final Map<QName, AugmentationSchema> augments = mapChildElementsFromAugments((AugmentationTarget) schema);
+
+ return Maps.filterKeys(mappedChoices, new Predicate<QName>() {
+ @Override
+ public boolean apply(QName input) {
+ return augments.containsKey(input) == false;
+ }
+ });
+ }
+
+ return mappedChoices;
+ }
+
+ /**
+ * Recursively find all child nodes that come from augmentations.
+ *
+ * @return Map with all child nodes, to their most top augmentation
+ */
+ public static Map<QName, AugmentationSchema> mapChildElementsFromAugments(AugmentationTarget schema) {
+
+ Map<QName, AugmentationSchema> childNodesToAugmentation = Maps.newLinkedHashMap();
+
+ // Find QNames of augmented child nodes
+ Map<QName, AugmentationSchema> augments = Maps.newHashMap();
+ for (final AugmentationSchema augmentationSchema : schema.getAvailableAugmentations()) {
+ for (DataSchemaNode dataSchemaNode : augmentationSchema.getChildNodes()) {
+ augments.put(dataSchemaNode.getQName(), augmentationSchema);
+ }
+ }
+
+ // Augmented nodes have to be looked up directly in augmentationTarget
+ // because nodes from augment do not contain nodes from other augmentations
+ if (schema instanceof DataNodeContainer) {
+
+ for (DataSchemaNode child : ((DataNodeContainer) schema).getChildNodes()) {
+ // If is not augmented child, continue
+ if (augments.containsKey(child.getQName()) == false)
+ continue;
+
+ AugmentationSchema mostTopAugmentation = augments.get(child.getQName());
+
+ // recursively add all child nodes in case of augment, case and choice
+ if (child instanceof AugmentationSchema || child instanceof ChoiceCaseNode) {
+ for (QName qName : getChildNodes((DataNodeContainer) child)) {
+ childNodesToAugmentation.put(qName, mostTopAugmentation);
+ }
+ } else if (child instanceof ChoiceNode) {
+ for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) child).getCases()) {
+ for (QName qName : getChildNodes(choiceCaseNode)) {
+ childNodesToAugmentation.put(qName, mostTopAugmentation);
+ }
+ }
+ } else {
+ childNodesToAugmentation.put(child.getQName(), mostTopAugmentation);
+ }
+ }
+ }
+
+ // Choice Node has to map child nodes from all its cases
+ if (schema instanceof ChoiceNode) {
+ for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) schema).getCases()) {
+ if (augments.containsKey(choiceCaseNode.getQName()) == false) {
+ continue;
+ }
+
+ for (QName qName : getChildNodes(choiceCaseNode)) {
+ childNodesToAugmentation.put(qName, augments.get(choiceCaseNode.getQName()));
+ }
+ }
+ }
+
+ return childNodesToAugmentation;
+ }
+
+ /**
+ * Recursively list all child nodes.
+ *
+ * In case of choice, augment and cases, step in.
+ */
+ public static Set<QName> getChildNodes(DataNodeContainer nodeContainer) {
+ Set<QName> allChildNodes = Sets.newHashSet();
+
+ for (DataSchemaNode childSchema : nodeContainer.getChildNodes()) {
+ if(childSchema instanceof ChoiceNode) {
+ for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) childSchema).getCases()) {
+ allChildNodes.addAll(getChildNodes(choiceCaseNode));
+ }
+ } else if(childSchema instanceof AugmentationSchema || childSchema instanceof ChoiceCaseNode) {
+ allChildNodes.addAll(getChildNodes((DataNodeContainer) childSchema));
+ }
+ else {
+ allChildNodes.add(childSchema.getQName());
+ }
+ }
+
+ return allChildNodes;
+ }
+
+ /**
+ * Retrieves real schemas for augmented child node.
+ *
+ * Schema of the same child node from augment, and directly from target is not the same.
+ * Schema of child node from augment is incomplete, therefore its useless for xml <-> normalizedNode translation.
+ *
+ */
+ public static Set<DataSchemaNode> getRealSchemasForAugment(AugmentationTarget targetSchema, AugmentationSchema augmentSchema) {
+ if(targetSchema.getAvailableAugmentations().contains(augmentSchema) == false) {
+ return Collections.emptySet();
+ }
+
+ Set<DataSchemaNode> realChildNodes = Sets.newHashSet();
+
+ if(targetSchema instanceof DataNodeContainer) {
+ realChildNodes = getRealSchemasForAugment((DataNodeContainer)targetSchema, augmentSchema);
+ } else if(targetSchema instanceof ChoiceNode) {
+ for (DataSchemaNode dataSchemaNode : augmentSchema.getChildNodes()) {
+ for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) targetSchema).getCases()) {
+ if(getChildNodes(choiceCaseNode).contains(dataSchemaNode.getQName())) {
+ realChildNodes.add(choiceCaseNode.getDataChildByName(dataSchemaNode.getQName()));
+ }
+ }
+ }
+ }
+
+ return realChildNodes;
+ }
+
+ public static Set<DataSchemaNode> getRealSchemasForAugment(DataNodeContainer targetSchema,
+ AugmentationSchema augmentSchema) {
+ Set<DataSchemaNode> realChildNodes = Sets.newHashSet();
+ for (DataSchemaNode dataSchemaNode : augmentSchema.getChildNodes()) {
+ DataSchemaNode realChild = ((DataNodeContainer) targetSchema).getDataChildByName(dataSchemaNode.getQName());
+ realChildNodes.add(realChild);
+ }
+
+ return realChildNodes;
+ }
+
+ public static Optional<ChoiceCaseNode> detectCase(ChoiceNode schema, DataContainerChild<?, ?> child) {
+ for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+ for (DataSchemaNode childFromCase : choiceCaseNode.getChildNodes()) {
+ if (childFromCase.getQName().equals(child.getNodeType())) {
+ return Optional.of(choiceCaseNode);
+ }
+ }
+ }
+
+ return Optional.absent();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+/**
+ * Abstract(base) parser for AugmentationNode, parses elements of type E.
+ *
+ * @param <E> type of elements to be parsed
+ */
+public abstract class AugmentationNodeBaseParser<E> extends
+ BaseDispatcherParser<E,AugmentationNode, AugmentationSchema> {
+
+ @Override
+ protected final DataContainerNodeBuilder<InstanceIdentifier.AugmentationIdentifier, AugmentationNode> getBuilder(AugmentationSchema schema) {
+ return Builders.augmentationBuilder(schema);
+ }
+
+ @Override
+ protected final Set<DataSchemaNode> getRealSchemasForAugment(AugmentationSchema schema, AugmentationSchema augmentSchema) {
+ return SchemaUtils.getRealSchemasForAugment(schema, augmentSchema);
+ }
+
+
+ @Override
+ protected final DataSchemaNode getSchemaForChild(AugmentationSchema schema, QName childQName) {
+ return SchemaUtils.findSchemaForChild(schema, childQName);
+ }
+
+ @Override
+ protected final Map<QName, ChoiceNode> mapChildElementsFromChoices(AugmentationSchema schema) {
+ return SchemaUtils.mapChildElementsFromChoices(schema);
+ }
+
+ @Override
+ protected final Map<QName, AugmentationSchema> mapChildElementsFromAugments(AugmentationSchema schema) {
+ return Collections.emptyMap();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+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.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 com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.LinkedListMultimap;
+
+/**
+ * Abstract(base) Parser for DataContainerNodes e.g. ContainerNode, AugmentationNode.
+ */
+public abstract class BaseDispatcherParser<E, N extends DataContainerNode<?>, S>
+ implements ToNormalizedNodeParser<E, N, S> {
+
+ /**
+ *
+ * @param schema
+ * @return New(empty) instance of a builder to build node identified by schema.
+ */
+ protected abstract DataContainerNodeBuilder<?, N> getBuilder(S schema);
+
+ /**
+ *
+ * @param schema
+ * @param childQName QName of a child being parsed, QName does not continue revision date
+ * @return schema object for child identified by parent schema: schema and QName childQName
+ */
+ protected abstract DataSchemaNode getSchemaForChild(S schema, QName childQName);
+
+ /**
+ *
+ * @param xml
+ * @return map from QName to child elements. Multiple elements are allowed under QName.
+ */
+ protected abstract LinkedListMultimap<QName, E> mapChildElements(Iterable<E> xml);
+
+ /**
+ *
+ * @param schema
+ * @return map from QName to ChoiceNode schema of child nodes that are
+ * contained within a choice statement under current schema.
+ */
+ protected abstract Map<QName, ChoiceNode> mapChildElementsFromChoices(S schema);
+
+ /**
+ *
+ * @param schema
+ * @return map from QName to child elements that are added by augmentation
+ * that targets current schema.
+ */
+ protected abstract Map<QName, AugmentationSchema> mapChildElementsFromAugments(S schema);
+
+ /**
+ *
+ * @param schema
+ * @param augmentSchema
+ * @return Set of real schema objects that represent child nodes of an
+ * augmentation. Augmentation schema child nodes, if further
+ * augmented, do not contain further augmented, that are crucial for
+ * parsing. The real schema object can be retrieved from parent schema: schema.
+ */
+ protected abstract Set<DataSchemaNode> getRealSchemasForAugment(S schema, AugmentationSchema augmentSchema);
+
+ /**
+ *
+ * @return dispatcher object to dispatch parsing of child elements, might be
+ * the same instance if provided parsers are immutable.
+ */
+ protected abstract NodeParserDispatcher<E> getDispatcher();
+
+ @Override
+ public N parse(Iterable<E> element, S schema) {
+
+ checkAtLeastOneNode(schema, element);
+
+ DataContainerNodeBuilder<?, N> containerBuilder = getBuilder(schema);
+
+ // Map child nodes to QName
+ LinkedListMultimap<QName, E> mappedChildElements = mapChildElements(element);
+
+ // Map child nodes from Augments
+ Map<QName, AugmentationSchema> mappedAugmentChildNodes = mapChildElementsFromAugments(schema);
+ LinkedListMultimap<AugmentationSchema, E> augmentsToElements = LinkedListMultimap.create();
+
+ // Map child nodes from choices
+ Map<QName, ChoiceNode> mappedChoiceChildNodes = mapChildElementsFromChoices(schema);
+ LinkedListMultimap<ChoiceNode, E> choicesToElements = LinkedListMultimap.create();
+
+ // process Child nodes
+ for (QName childPartialQName : mappedChildElements.keySet()) {
+ DataSchemaNode childSchema = getSchemaForChild(schema, childPartialQName);
+ List<E> childrenForQName = mappedChildElements.get(childPartialQName);
+
+ // Augment
+ if (isMarkedAs(mappedAugmentChildNodes, childSchema.getQName())) {
+ AugmentationSchema augmentationSchema = mappedAugmentChildNodes.get(childSchema.getQName());
+ augmentsToElements.putAll(augmentationSchema, childrenForQName);
+ // Choices
+ } else if (isMarkedAs(mappedChoiceChildNodes, childSchema.getQName())) {
+ ChoiceNode choiceSchema = mappedChoiceChildNodes.get(childSchema.getQName());
+ choicesToElements.putAll(choiceSchema, childrenForQName);
+ // Regular child nodes
+ } else {
+ DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> builtChildNode = getDispatcher()
+ .dispatchChildElement(childSchema, childrenForQName);
+ containerBuilder.withChild(builtChildNode);
+ }
+ }
+
+ // TODO ordering is not preserved for choice and augment elements
+ for (ChoiceNode choiceSchema : choicesToElements.keySet()) {
+ containerBuilder.withChild(getDispatcher().dispatchChildElement(choiceSchema,
+ choicesToElements.get(choiceSchema)));
+ }
+
+ for (AugmentationSchema augmentSchema : augmentsToElements.keySet()) {
+ Set<DataSchemaNode> realChildSchemas = getRealSchemasForAugment(schema, augmentSchema);
+ AugmentationSchemaProxy augSchemaProxy = new AugmentationSchemaProxy(augmentSchema, realChildSchemas);
+ containerBuilder.withChild(getDispatcher().dispatchChildElement(augSchemaProxy, augmentsToElements.get(augmentSchema)));
+ }
+
+ return containerBuilder.build();
+ }
+
+ private boolean isMarkedAs(Map<QName, ?> mappedAugmentChildNodes, QName qName) {
+ return mappedAugmentChildNodes.containsKey(qName);
+ }
+
+ protected void checkOnlyOneNode(S schema, Iterable<E> childNodes) {
+ final int size = Iterables.size(childNodes);
+ Preconditions.checkArgument(size == 1,
+ "Node detected multiple times, should be 1, identified by: %s, found: %s", schema, childNodes);
+ }
+
+ private void checkAtLeastOneNode(S schema, Iterable<E> childNodes) {
+ Preconditions.checkArgument(Iterables.isEmpty(childNodes) == false,
+ "Node detected 0 times, should be at least 1, identified by: %s, found: %s", schema, childNodes);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils;
+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.DataSchemaNode;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+/**
+ * Abstract(base) parser for ChoiceNodes, parses elements of type E.
+ *
+ * @param <E> type of elements to be parsed
+ */
+public abstract class ChoiceNodeBaseParser<E> extends
+ BaseDispatcherParser<E, ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> {
+
+ @Override
+ protected final DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> getBuilder(
+ org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
+ return Builders.choiceBuilder(schema);
+ }
+
+ @Override
+ protected final Set<DataSchemaNode> getRealSchemasForAugment(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema,
+ AugmentationSchema augmentSchema) {
+ Set<DataSchemaNode> fromAllCases = Sets.newHashSet();
+
+ fromAllCases.addAll(SchemaUtils.getRealSchemasForAugment(schema, augmentSchema));
+
+ for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+ fromAllCases.addAll(SchemaUtils.getRealSchemasForAugment((AugmentationTarget) choiceCaseNode, augmentSchema));
+ }
+
+ return fromAllCases;
+ }
+
+ @Override
+ protected final DataSchemaNode getSchemaForChild(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema,
+ QName childQName) {
+ return SchemaUtils.findSchemaForChild(schema, childQName);
+ }
+
+ @Override
+ protected final Map<QName, org.opendaylight.yangtools.yang.model.api.ChoiceNode> mapChildElementsFromChoices(
+ org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
+ Map<QName, org.opendaylight.yangtools.yang.model.api.ChoiceNode> mappedChoices = Maps.newLinkedHashMap();
+
+ for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+ mappedChoices.putAll(SchemaUtils.mapChildElementsFromChoices(choiceCaseNode));
+ }
+
+ return mappedChoices;
+ }
+
+ @Override
+ protected final Map<QName, AugmentationSchema> mapChildElementsFromAugments(
+ org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
+ Map<QName, AugmentationSchema> mappedAugments = Maps.newLinkedHashMap();
+
+ for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+ mappedAugments.putAll(SchemaUtils.mapChildElementsFromAugments(choiceCaseNode));
+ }
+ return mappedAugments;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+/**
+ * Abstract(base) parser for ContainerNodes, parses elements of type E.
+ *
+ * @param <E> type of elements to be parsed
+ */
+public abstract class ContainerNodeBaseParser<E> extends
+ BaseDispatcherParser<E, ContainerNode, ContainerSchemaNode> {
+
+ @Override
+ protected final DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> getBuilder(
+ ContainerSchemaNode schema) {
+ return Builders.containerBuilder(schema);
+ }
+
+ @Override
+ public final ContainerNode parse(Iterable<E> elements, ContainerSchemaNode schema) {
+ checkOnlyOneNode(schema, elements);
+ return super.parse(elements, schema);
+ }
+
+ @Override
+ protected final Set<DataSchemaNode> getRealSchemasForAugment(ContainerSchemaNode schema, AugmentationSchema augmentSchema) {
+ return SchemaUtils.getRealSchemasForAugment((AugmentationTarget) schema, augmentSchema);
+ }
+
+ @Override
+ protected final DataSchemaNode getSchemaForChild(ContainerSchemaNode schema, QName childQName) {
+ return SchemaUtils.findSchemaForChild(schema, childQName);
+ }
+
+ @Override
+ protected final Map<QName, ChoiceNode> mapChildElementsFromChoices(ContainerSchemaNode schema) {
+ return SchemaUtils.mapChildElementsFromChoices(schema);
+ }
+
+ @Override
+ protected final Map<QName, AugmentationSchema> mapChildElementsFromAugments(ContainerSchemaNode schema) {
+ return SchemaUtils.mapChildElementsFromAugments(schema);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+/**
+ * Abstract(base) parser for LeafNodes, parses elements of type E.
+ *
+ * @param <E> type of elements to be parsed
+ */
+public abstract class LeafNodeBaseParser<E> implements
+ ToNormalizedNodeParser<E, LeafNode<?>, LeafSchemaNode> {
+
+ @Override
+ public final LeafNode<?> parse(Iterable<E> elements, LeafSchemaNode schema) {
+ final int size = Iterables.size(elements);
+ Preconditions.checkArgument(size == 1, "Elements mapped to leaf node illegal count: %s", size);
+ Object value = parseLeaf(elements.iterator().next(), schema);
+ return Builders.leafBuilder(schema).withValue(value).build();
+ }
+
+ /**
+ *
+ * Parse the inner value of a LeafNode from element of type E.
+ *
+ * @param element to be parsed
+ * @param schema schema for leaf
+ * @return parsed element as an Object
+ */
+ protected abstract Object parseLeaf(E element, LeafSchemaNode schema);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+/**
+ * Abstract(base) parser for LeafSetEntryNodes, parses elements of type E.
+ *
+ * @param <E> type of elements to be parsed
+ */
+public abstract class LeafSetEntryNodeBaseParser<E> implements
+ ToNormalizedNodeParser<E, LeafSetEntryNode<?>, LeafListSchemaNode> {
+
+ @Override
+ public final LeafSetEntryNode<Object> parse(Iterable<E> elements, LeafListSchemaNode schema) {
+ final int size = Iterables.size(elements);
+ Preconditions.checkArgument(size == 1, "Xml elements mapped to leaf node illegal count: %s", size);
+ Object value = parseLeafListEntry(elements.iterator().next(),schema);
+ return Builders.leafSetEntryBuilder(schema).withValue(value).build();
+ }
+
+ /**
+ *
+ * Parse the inner value of a LeafSetEntryNode from element of type E.
+ *
+ * @param element to be parsed
+ * @param schema schema for leaf-list
+ * @return parsed element as an Object
+ */
+ protected abstract Object parseLeafListEntry(E element, LeafListSchemaNode schema);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
+
+import java.util.Collections;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+/**
+ * Abstract(base) parser for LeafSetNodes, parses elements of type E.
+ *
+ * @param <E> type of elements to be parsed
+ */
+public abstract class LeafSetNodeBaseParser<E> implements
+ ToNormalizedNodeParser<E, LeafSetNode<?>, LeafListSchemaNode> {
+
+ @Override
+ public final LeafSetNode<?> parse(Iterable<E> childNodes, LeafListSchemaNode schema) {
+
+ ListNodeBuilder<Object, LeafSetEntryNode<Object>> leafListBuilder = Builders.leafSetBuilder(schema);
+ for (E childNode : childNodes) {
+ LeafSetEntryNode<?> builtChild = getLeafSetEntryNodeBaseParser().parse(
+ Collections.singletonList(childNode), schema);
+
+ // TODO: can we get rid of this cast/SuppressWarnings somehow?
+ @SuppressWarnings("unchecked")
+ final LeafSetEntryNode<Object> child = (LeafSetEntryNode<Object>) builtChild;
+ leafListBuilder.withChild(child);
+ }
+
+ return leafListBuilder.build();
+ }
+
+ /**
+ *
+ * @return parser for inner LeafSetEntryNodes used to parse every entry of LeafSetNode, might be the same instance in case its immutable
+ */
+ protected abstract ToNormalizedNodeParser<E, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeBaseParser();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+/**
+ * Abstract(base) parser for MapEntryNodes, parses elements of type E.
+ *
+ * @param <E> type of elements to be parsed
+ */
+public abstract class MapEntryNodeBaseParser<E> extends BaseDispatcherParser<E, MapEntryNode, ListSchemaNode> {
+
+ @Override
+ protected final DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> getBuilder(
+ ListSchemaNode schema) {
+ return Builders.mapEntryBuilder(schema);
+ }
+
+ @Override
+ public final MapEntryNode parse(Iterable<E> elements, ListSchemaNode schema) {
+ checkOnlyOneNode(schema, elements);
+ return super.parse(elements, schema);
+ }
+
+ @Override
+ protected final Set<DataSchemaNode> getRealSchemasForAugment(ListSchemaNode schema, AugmentationSchema augmentSchema) {
+ return SchemaUtils.getRealSchemasForAugment((AugmentationTarget) schema, augmentSchema);
+ }
+
+ @Override
+ protected final DataSchemaNode getSchemaForChild(ListSchemaNode schema, QName childQName) {
+ return SchemaUtils.findSchemaForChild(schema, childQName);
+ }
+
+ @Override
+ protected final Map<QName, ChoiceNode> mapChildElementsFromChoices(ListSchemaNode schema) {
+ return SchemaUtils.mapChildElementsFromChoices(schema);
+ }
+
+ @Override
+ protected final Map<QName, AugmentationSchema> mapChildElementsFromAugments(ListSchemaNode schema) {
+ return SchemaUtils.mapChildElementsFromAugments(schema);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
+
+import java.util.Collections;
+
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+/**
+ * Abstract(base) parser for MapNodes, parses elements of type E.
+ *
+ * @param <E> type of elements to be parsed
+ */
+public abstract class MapNodeBaseParser<E> implements ToNormalizedNodeParser<E, MapNode, ListSchemaNode> {
+
+ @Override
+ public final MapNode parse(Iterable<E> childNodes, ListSchemaNode schema) {
+ CollectionNodeBuilder<MapEntryNode, MapNode> listBuilder = Builders.mapBuilder(schema);
+
+ for (E childNode : childNodes) {
+ MapEntryNode listChild = getMapEntryNodeDomParser().parse(Collections.singletonList(childNode), schema);
+ listBuilder.withChild(listChild);
+ }
+
+ return listBuilder.build();
+ }
+
+ /**
+ *
+ * @return parser for inner MapEntryNodes used to parse every entry of MapNode, might be the same instance in case its immutable
+ */
+ protected abstract ToNormalizedNodeParser<E, MapEntryNode, ListSchemaNode> getMapEntryNodeDomParser();
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+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 com.google.common.base.Preconditions;
+
+/**
+ *
+ * Dispatches the parsing process of elements according to schema and returns the parsed Node.
+ *
+ * @param <E> type of elements parsed
+ */
+public interface NodeParserDispatcher<E> {
+
+ DataContainerChild<?, ?> dispatchChildElement(Object schema, List<E> childNodes);
+
+ /**
+ * Abstract implementation that implements the dispatch conditions. Only requires parsers to be provided.
+ * The same instance of parser can be provided in case it is immutable.
+ */
+ public static abstract class BaseNodeParserDispatcher<E> implements NodeParserDispatcher<E> {
+
+ @Override
+ public final DataContainerChild<?, ?> dispatchChildElement(Object schema, List<E> childNodes) {
+ Preconditions.checkArgument(childNodes.isEmpty() == false);
+
+ if (schema instanceof ContainerSchemaNode) {
+ return getContainerNodeParser().parse(childNodes, (ContainerSchemaNode) schema);
+ } else if (schema instanceof LeafSchemaNode) {
+ return getLeafNodeParser().parse(childNodes, (LeafSchemaNode) schema);
+ } else if (schema instanceof LeafListSchemaNode) {
+ return getLeafSetNodeParser().parse(childNodes, (LeafListSchemaNode) schema);
+ } else if (schema instanceof ListSchemaNode) {
+ return getMapNodeParser().parse(childNodes, (ListSchemaNode) schema);
+ } else if (schema instanceof ChoiceNode) {
+ return getChoiceNodeParser().parse(childNodes, (ChoiceNode) schema);
+ } else if (schema instanceof AugmentationSchema) {
+ return getAugmentationNodeParser().parse(childNodes, (AugmentationSchema) schema);
+ }
+
+ throw new IllegalArgumentException("Unable to parse node, unknown schema type: " + schema.getClass());
+ }
+
+ protected abstract ToNormalizedNodeParser<E, ContainerNode, ContainerSchemaNode> getContainerNodeParser();
+
+ protected abstract ToNormalizedNodeParser<E, LeafNode<?>, LeafSchemaNode> getLeafNodeParser();
+
+ protected abstract ToNormalizedNodeParser<E, LeafSetNode<?>, LeafListSchemaNode> getLeafSetNodeParser();
+
+ protected abstract ToNormalizedNodeParser<E, MapNode, ListSchemaNode> getMapNodeParser();
+
+ protected abstract ToNormalizedNodeParser<E, org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode, ChoiceNode> getChoiceNodeParser();
+
+ protected abstract ToNormalizedNodeParser<E, AugmentationNode, AugmentationSchema> getAugmentationNodeParser();
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer;
+
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+/**
+ * Abstract(base) serializer for AugmentationNode, serializes elements of type E.
+ *
+ * @param <E> type of serialized elements
+ */
+public abstract class AugmentationNodeBaseSerializer<E> extends
+ BaseDispatcherSerializer<E, AugmentationNode, AugmentationSchema> {
+
+ @Override
+ protected Set<DataSchemaNode> getRealSchemasForAugment(AugmentationSchema schema, AugmentationSchema augmentationSchema) {
+ return SchemaUtils.getRealSchemasForAugment(schema, augmentationSchema);
+ }
+
+ @Override
+ protected DataSchemaNode getSchemaForChild(AugmentationSchema schema,
+ DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> childNode) {
+ return SchemaUtils.findSchemaForChild(schema, childNode.getNodeType());
+ }
+
+ @Override
+ protected AugmentationSchema getAugmentedCase(AugmentationSchema schema, AugmentationNode augmentationNode) {
+ throw new UnsupportedOperationException("");
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer;
+
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+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;
+
+/**
+ * Abstract(base) Serializer for DataContainerNodes e.g. ContainerNode, AugmentationNode.
+ */
+public abstract class BaseDispatcherSerializer<E, N extends DataContainerNode<?>, S> implements
+ FromNormalizedNodeSerializer<E, N, S> {
+
+ /**
+ *
+ * @param schema
+ * @param augmentationSchema
+ * @return Set of real schema objects that represent child nodes of an
+ * augmentation. Augmentation schema child nodes, if further
+ * augmented, do not contain further augmented, that are crucial for
+ * parsing. The real schema object can be retrieved from parent schema: schema.
+ */
+ protected abstract Set<DataSchemaNode> getRealSchemasForAugment(S schema, AugmentationSchema augmentationSchema);
+
+ /**
+ *
+ * @param schema
+ * @param childNode
+ * @return Schema object associated with child node identified as: childNode.
+ * Schema should be retrieved from parent schema: schema.
+ */
+ protected abstract DataSchemaNode getSchemaForChild(S schema,
+ DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> childNode);
+
+ /**
+ *
+ * @param schema
+ * @param augmentationNode
+ * @return Schema object associated with augmentation child node identified as: augmentationNode.
+ * Schema should be retrieved from parent schema: schema.
+ */
+ protected abstract AugmentationSchema getAugmentedCase(S schema, AugmentationNode augmentationNode);
+
+ /**
+ *
+ * @return Dispatcher object to dispatch serialization of child elements, might be
+ * the same instance if provided serializers are immutable.
+ */
+ protected abstract NodeSerializerDispatcher<E> getNodeDispatcher();
+
+ @Override
+ public Iterable<E> serialize(S schema, N node) {
+ List<Iterable<E>> choiceChildren = Lists.newArrayList();
+
+ for (DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> choiceChild : node.getValue()) {
+
+ Object childSchema;
+
+ if (choiceChild instanceof AugmentationNode) {
+
+ AugmentationSchema augSchema = getAugmentedCase(schema, (AugmentationNode) choiceChild);
+ Set<DataSchemaNode> realChildSchemas = getRealSchemasForAugment(schema, augSchema);
+ childSchema = new AugmentationSchemaProxy(augSchema, realChildSchemas);
+
+ } else {
+ childSchema = getSchemaForChild(schema, choiceChild);
+ }
+
+ Iterable<E> childElements = getNodeDispatcher().dispatchChildElement(childSchema, choiceChild);
+ choiceChildren.add(Preconditions.checkNotNull(childElements));
+ }
+
+ return Iterables.concat(choiceChildren);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer;
+
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils;
+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.DataSchemaNode;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Abstract(base) serializer for ChoiceNodes, serializes elements of type E.
+ *
+ * @param <E> type of serialized elements
+ */
+public abstract class ChoiceNodeBaseSerializer<E>
+ extends
+ BaseDispatcherSerializer<E, ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> {
+
+ @Override
+ protected final DataSchemaNode getSchemaForChild(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema,
+ DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> childNode) {
+ return SchemaUtils.findSchemaForChild(schema, childNode.getNodeType());
+ }
+
+ @Override
+ protected final AugmentationSchema getAugmentedCase(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema,
+ AugmentationNode augmentationNode) {
+ return SchemaUtils.findSchemaForAugment(schema, augmentationNode.getIdentifier().getPossibleChildNames());
+ }
+
+ @Override
+ protected final Set<DataSchemaNode> getRealSchemasForAugment(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema, AugmentationSchema augmentationSchema) {
+ Set<DataSchemaNode> aggregatedSchemas = Sets.newHashSet();
+
+ aggregatedSchemas.addAll(SchemaUtils.getRealSchemasForAugment(schema, augmentationSchema));
+
+ for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+ aggregatedSchemas.addAll(SchemaUtils.getRealSchemasForAugment((AugmentationTarget) choiceCaseNode, augmentationSchema));
+ }
+
+ return aggregatedSchemas;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer;
+
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils;
+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.DataSchemaNode;
+
+/**
+ * Abstract(base) serializer for ContainerNodes, serializes elements of type E.
+ *
+ * @param <E> type of serialized elements
+ */
+public abstract class ContainerNodeBaseSerializer<E> extends
+ BaseDispatcherSerializer<E, ContainerNode, ContainerSchemaNode> {
+
+ @Override
+ protected final DataSchemaNode getSchemaForChild(ContainerSchemaNode schema,
+ DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> childNode) {
+ return SchemaUtils.findSchemaForChild(schema, childNode.getNodeType());
+ }
+
+ @Override
+ protected final AugmentationSchema getAugmentedCase(ContainerSchemaNode schema, AugmentationNode augmentationNode) {
+ return SchemaUtils.findSchemaForAugment(schema, augmentationNode.getIdentifier().getPossibleChildNames());
+ }
+
+ @Override
+ protected final Set<DataSchemaNode> getRealSchemasForAugment(ContainerSchemaNode schema, AugmentationSchema augmentationSchema) {
+ return SchemaUtils.getRealSchemasForAugment((AugmentationTarget) schema, augmentationSchema);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer;
+
+import java.util.Collections;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+
+/**
+ * Abstract(base) serializer for LeafNodes, serializes elements of type E.
+ *
+ * @param <E> type of serialized elements
+ */
+public abstract class LeafNodeBaseSerializer<E> implements
+ FromNormalizedNodeSerializer<E, LeafNode<?>, LeafSchemaNode> {
+
+ @Override
+ public final Iterable<E> serialize(LeafSchemaNode schema, LeafNode<?> node) {
+ return Collections.singletonList(serializeLeaf(schema, node));
+ }
+
+ /**
+ *
+ * Serialize the inner value of a LeafNode into element of type E.
+ *
+ * @param node to be serialized
+ * @param schema schema for leaf
+ * @return serialized inner value as an Element
+ */
+ protected abstract E serializeLeaf(LeafSchemaNode schema, LeafNode<?> node);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer;
+
+import java.util.Collections;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+/**
+ * Abstract(base) serializer for LeafSetEntryNodes, serializes elements of type E.
+ *
+ * @param <E> type of serialized elements
+ */
+public abstract class LeafSetEntryNodeBaseSerializer<E> implements
+ FromNormalizedNodeSerializer<E, LeafSetEntryNode<?>, LeafListSchemaNode> {
+
+ @Override
+ public final Iterable<E> serialize(LeafListSchemaNode schema, LeafSetEntryNode<?> node) {
+ return Collections.singletonList(serializeLeaf(schema, node));
+ }
+
+ /**
+ *
+ * Serialize the inner value of a LeafSetEntryNode into element of type E.
+ *
+ * @param node to be serialized
+ * @param schema schema for leaf-list
+ * @return serialized inner value as an Element
+ */
+ protected abstract E serializeLeaf(LeafListSchemaNode schema, LeafSetEntryNode<?> node);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+/**
+ * Abstract(base) serializer for LeafSetNodes, serializes elements of type E.
+ *
+ * @param <E> type of serialized elements
+ */
+public abstract class LeafSetNodeBaseSerializer<E> implements
+ FromNormalizedNodeSerializer<E, LeafSetNode<?>, LeafListSchemaNode> {
+
+ @Override
+ public final Iterable<E> serialize(final LeafListSchemaNode schema, final LeafSetNode<?> node) {
+ return Iterables.concat(Iterables.transform(node.getValue(), new Function<LeafSetEntryNode<?>, Iterable<E>>() {
+ @Override
+ public Iterable<E> apply(final LeafSetEntryNode<?> input) {
+ final Iterable<E> serializedChild = getLeafSetEntryNodeSerializer().serialize(schema, input);
+ final int size = Iterables.size(serializedChild);
+ Preconditions.checkState(size == 1,
+ "Unexpected count of elements for leaf-list entry serialized from: %s, should be 1, was: %s",
+ input, size);
+ return serializedChild;
+ }
+ }));
+ }
+
+ /**
+ *
+ * @return serializer for inner LeafSetEntryNodes used to serialize every entry of LeafSetNode, might be the same instance in case its immutable
+ */
+ protected abstract FromNormalizedNodeSerializer<E, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeSerializer();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer;
+
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+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.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+/**
+ * Abstract(base) serializer for MapEntryNodes, serializes elements of type E.
+ *
+ * @param <E> type of serialized elements
+ */
+public abstract class MapEntryNodeBaseSerializer<E> extends
+ BaseDispatcherSerializer<E, MapEntryNode, ListSchemaNode> {
+
+ @Override
+ protected final DataSchemaNode getSchemaForChild(ListSchemaNode schema,
+ DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> childNode) {
+ return SchemaUtils.findSchemaForChild(schema, childNode.getNodeType());
+ }
+
+ @Override
+ protected final AugmentationSchema getAugmentedCase(ListSchemaNode schema, AugmentationNode augmentationNode) {
+ return SchemaUtils.findSchemaForAugment(schema, augmentationNode.getIdentifier().getPossibleChildNames());
+ }
+
+ @Override
+ protected final Set<DataSchemaNode> getRealSchemasForAugment(ListSchemaNode schema, AugmentationSchema augmentationSchema) {
+ return SchemaUtils.getRealSchemasForAugment((AugmentationTarget) schema, augmentationSchema);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer;
+
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+/**
+ * Abstract(base) serializer for MapNodes, serializes elements of type E.
+ *
+ * @param <E> type of serialized elements
+ */
+public abstract class MapNodeBaseSerializer<E> implements FromNormalizedNodeSerializer<E, MapNode, ListSchemaNode> {
+
+ @Override
+ public final Iterable<E> serialize(final ListSchemaNode schema, final MapNode node) {
+ return Iterables.concat(Iterables.transform(node.getValue(), new Function<MapEntryNode, Iterable<E>>() {
+ @Override
+ public Iterable<E> apply(MapEntryNode input) {
+ final Iterable<E> serializedChild = getMapEntryNodeDomSerializer().serialize(schema, input);
+ final int size = Iterables.size(serializedChild);
+
+ Preconditions.checkState(size == 1,
+ "Unexpected count of entries for list serialized from: %s, should be 1, was: %s",
+ input, size);
+ return serializedChild;
+ }
+ }));
+ }
+
+ /**
+ *
+ * @return serializer for inner MapEntryNodes used to serialize every entry of MapNode, might be the same instance in case its immutable
+ */
+ protected abstract FromNormalizedNodeSerializer<E, MapEntryNode, ListSchemaNode> getMapEntryNodeDomSerializer();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MixinNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+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 com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+
+/**
+ *
+ * Dispatches the serialization process of nodes according to schema and returns the serialized elements.
+ *
+ * @param <E> type of serialized elements
+ */
+public interface NodeSerializerDispatcher<E> {
+
+ Iterable<E> dispatchChildElement(Object childSchema,
+ DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild);
+
+ /**
+ * Abstract implementation that implements the dispatch conditions. Only requires serializers to be provided.
+ * The same instance of serializer can be provided in case it is immutable.
+ */
+ public static abstract class BaseNodeSerializerDispatcher<E> implements NodeSerializerDispatcher<E> {
+
+ @Override
+ public final Iterable<E> dispatchChildElement(Object childSchema,
+ DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+ if (dataContainerChild instanceof ContainerNode) {
+ return onContainerNode(childSchema, dataContainerChild);
+ } else if (dataContainerChild instanceof LeafNode<?>) {
+ return onLeafNode(childSchema, dataContainerChild);
+ } else if (dataContainerChild instanceof MixinNode) {
+ if (dataContainerChild instanceof LeafSetNode<?>) {
+ return onLeafListNode(childSchema, dataContainerChild);
+ } else if (dataContainerChild instanceof MapNode) {
+ return onListNode(childSchema, dataContainerChild);
+ } else if (dataContainerChild instanceof ChoiceNode) {
+ return onChoiceNode(childSchema, dataContainerChild);
+ } else if (dataContainerChild instanceof AugmentationNode) {
+ return onAugmentationSchema(childSchema, dataContainerChild);
+ }
+ }
+ throw new IllegalArgumentException("Unable to serialize " + childSchema);
+ }
+
+ private Iterable<E> onAugmentationSchema(Object childSchema,
+ DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+ checkSchemaCompatibility(childSchema, AugmentationSchema.class, dataContainerChild);
+ return getAugmentationNodeSerializer().serialize((AugmentationSchema) childSchema,
+ (AugmentationNode) dataContainerChild);
+ }
+
+ private Iterable<E> onChoiceNode(Object childSchema,
+ DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+ checkSchemaCompatibility(childSchema, org.opendaylight.yangtools.yang.model.api.ChoiceNode.class,
+ dataContainerChild);
+ return getChoiceNodeSerializer()
+ .serialize((org.opendaylight.yangtools.yang.model.api.ChoiceNode) childSchema,
+ (ChoiceNode) dataContainerChild);
+ }
+
+ private Iterable<E> onListNode(Object childSchema,
+ DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+ checkSchemaCompatibility(childSchema, ListSchemaNode.class, dataContainerChild);
+ return getMapNodeSerializer().serialize((ListSchemaNode) childSchema, (MapNode) dataContainerChild);
+ }
+
+ private Iterable<E> onLeafListNode(Object childSchema,
+ DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+ checkSchemaCompatibility(childSchema, LeafListSchemaNode.class, dataContainerChild);
+ return getLeafSetNodeSerializer().serialize((LeafListSchemaNode) childSchema,
+ (LeafSetNode<?>) dataContainerChild);
+ }
+
+ private Iterable<E> onLeafNode(Object childSchema,
+ DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+ checkSchemaCompatibility(childSchema, LeafSchemaNode.class, dataContainerChild);
+ Iterable<E> elements = getLeafNodeSerializer().serialize((LeafSchemaNode) childSchema,
+ (LeafNode<?>) dataContainerChild);
+ checkOnlyOneSerializedElement(elements, dataContainerChild);
+ return elements;
+ }
+
+ private static void checkOnlyOneSerializedElement(Iterable<?> elements,
+ DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+ final int size = Iterables.size(elements);
+ Preconditions.checkArgument(size == 1,
+ "Unexpected count of elements for entry serialized from: %s, should be 1, was: %s",
+ dataContainerChild, size);
+ }
+
+ private Iterable<E> onContainerNode(Object childSchema,
+ DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+ checkSchemaCompatibility(childSchema, ContainerSchemaNode.class, dataContainerChild);
+
+ Iterable<E> elements = getContainerNodeSerializer().serialize((ContainerSchemaNode) childSchema,
+ (ContainerNode) dataContainerChild);
+ checkOnlyOneSerializedElement(elements, dataContainerChild);
+ return elements;
+ }
+
+ private static void checkSchemaCompatibility(Object childSchema, Class<?> containerSchemaNodeClass,
+ DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+ Preconditions.checkArgument(containerSchemaNodeClass.isAssignableFrom(childSchema.getClass()),
+ "Incompatible schema: %s with node: %s, expected: %s", childSchema, dataContainerChild,
+ containerSchemaNodeClass);
+ }
+
+ protected abstract FromNormalizedNodeSerializer<E, ContainerNode, ContainerSchemaNode> getContainerNodeSerializer();
+
+ protected abstract FromNormalizedNodeSerializer<E, LeafNode<?>, LeafSchemaNode> getLeafNodeSerializer();
+
+ protected abstract FromNormalizedNodeSerializer<E, LeafSetNode<?>, LeafListSchemaNode> getLeafSetNodeSerializer();
+
+ protected abstract FromNormalizedNodeSerializer<E, MapNode, ListSchemaNode> getMapNodeSerializer();
+
+ protected abstract FromNormalizedNodeSerializer<E, org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> getChoiceNodeSerializer();
+
+ protected abstract FromNormalizedNodeSerializer<E, AugmentationNode, AugmentationSchema> getAugmentationNodeSerializer();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import com.google.common.collect.LinkedListMultimap;
+import com.google.common.collect.Lists;
+
+public class DomUtils {
+
+ private DomUtils() {
+ }
+
+ private static final XmlCodecProvider DEFAULT_XML_VALUE_CODEC_PROVIDER = new XmlCodecProvider() {
+
+ @Override
+ public TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codecFor(TypeDefinition<?> baseType) {
+ return TypeDefinitionAwareCodec.from(baseType);
+ }
+ };
+
+ public static XmlCodecProvider defaultValueCodecProvider() {
+ return DEFAULT_XML_VALUE_CODEC_PROVIDER;
+ }
+
+ public static Object parseXmlValue(Element xml, XmlCodecProvider codecProvider, TypeDefinition<?> type) {
+ TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codec = codecProvider.codecFor(type);
+
+ String text = xml.getTextContent();
+ text = text.trim();
+
+ Object value;
+ if (codec != null) {
+ value = codec.deserialize(text);
+ } else {
+ value = text;
+ }
+
+ return value;
+ }
+
+ public static void serializeXmlValue(Element itemEl, TypeDefinition<? extends TypeDefinition<?>> type, XmlCodecProvider codecProvider, Object value) {
+ XmlDocumentUtils.writeValueByType(itemEl, type, codecProvider, value);
+ }
+
+ public static LinkedListMultimap<QName, Element> mapChildElementsForSingletonNode(Element node) {
+ List<Element> childNodesCollection = Lists.newArrayList();
+ NodeList childNodes = node.getChildNodes();
+ for (int i = 0; i < childNodes.getLength(); i++) {
+ if(childNodes.item(i) instanceof Element) {
+ childNodesCollection.add((Element) childNodes.item(i));
+ }
+ }
+
+ return mapChildElements(childNodesCollection);
+ }
+
+ public static LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> childNodesCollection) {
+ LinkedListMultimap<QName, Element> mappedChildElements = LinkedListMultimap.create();
+
+ for (Element element : childNodesCollection) {
+ QName childQName = XmlDocumentUtils.qNameFromElement(element);
+ mappedChildElements.put(childQName, element);
+ }
+
+ return mappedChildElements;
+ }
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.AugmentationNodeBaseParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
+
+public final class AugmentationNodeDomParser extends AugmentationNodeBaseParser<Element> {
+
+ private final XmlCodecProvider codecProvider;
+
+ public AugmentationNodeDomParser(XmlCodecProvider codecProvider) {
+ this.codecProvider = Preconditions.checkNotNull(codecProvider);
+ }
+
+ @Override
+ protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> elements) {
+ return DomUtils.mapChildElements(elements);
+ }
+
+ @Override
+ protected NodeParserDispatcher<Element> getDispatcher() {
+ return DomNodeDispatcher.getInstance(codecProvider);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ChoiceNodeBaseParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
+
+public final class ChoiceNodeDomParser extends ChoiceNodeBaseParser<Element> {
+
+ private final XmlCodecProvider codecProvider;
+
+ public ChoiceNodeDomParser(XmlCodecProvider codecProvider) {
+ this.codecProvider = Preconditions.checkNotNull(codecProvider);
+ }
+
+ @Override
+ protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> xml) {
+ return DomUtils.mapChildElements(xml);
+ }
+
+ @Override
+ protected NodeParserDispatcher<Element> getDispatcher() {
+ return DomNodeDispatcher.getInstance(codecProvider);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ContainerNodeBaseParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
+
+public final class ContainerNodeDomParser extends ContainerNodeBaseParser<Element> {
+
+ private final XmlCodecProvider codecProvider;
+
+ public ContainerNodeDomParser(XmlCodecProvider codecProvider) {
+ this.codecProvider = Preconditions.checkNotNull(codecProvider);
+ }
+
+ @Override
+ protected NodeParserDispatcher<Element> getDispatcher() {
+ return DomNodeDispatcher.getInstance(codecProvider);
+ }
+
+ @Override
+ protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> elements) {
+ return DomUtils.mapChildElementsForSingletonNode(elements.iterator().next());
+ }
+
+}
--- /dev/null
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+
+import org.opendaylight.yangtools.yang.data.api.schema.*;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
+import org.opendaylight.yangtools.yang.model.api.*;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.w3c.dom.Element;
+
+public class DomNodeDispatcher extends NodeParserDispatcher.BaseNodeParserDispatcher<Element> {
+
+ private final ContainerNodeDomParser containerNodeDomParser;
+ private final LeafNodeDomParser leafNodeDomParser;
+ private final LeafSetNodeDomParser leafSetNodeDomParser;
+ private final MapNodeDomParser mapNodeDomParser;
+ private final ChoiceNodeDomParser choiceNodeDomParser;
+ private final AugmentationNodeDomParser augmentationNodeDomParser;
+
+ private static DomNodeDispatcher instance = null;
+
+ private DomNodeDispatcher(XmlCodecProvider codecProvider) {
+ leafNodeDomParser = new LeafNodeDomParser(codecProvider);
+ containerNodeDomParser = new ContainerNodeDomParser(codecProvider);
+ leafSetNodeDomParser = new LeafSetNodeDomParser(new LeafSetEntryNodeDomParser(codecProvider));
+ mapNodeDomParser = new MapNodeDomParser(new MapEntryNodeDomParser(codecProvider));
+ choiceNodeDomParser = new ChoiceNodeDomParser(codecProvider);
+ augmentationNodeDomParser = new AugmentationNodeDomParser(codecProvider);
+ }
+
+ @Override
+ protected ToNormalizedNodeParser<Element, ContainerNode, ContainerSchemaNode> getContainerNodeParser() {
+ return containerNodeDomParser;
+ }
+
+ @Override
+ protected ToNormalizedNodeParser<Element, LeafNode<?>, LeafSchemaNode> getLeafNodeParser() {
+ return leafNodeDomParser;
+ }
+
+ @Override
+ protected ToNormalizedNodeParser<Element, LeafSetNode<?>, LeafListSchemaNode> getLeafSetNodeParser() {
+ return leafSetNodeDomParser;
+ }
+
+ @Override
+ protected ToNormalizedNodeParser<Element, MapNode, ListSchemaNode> getMapNodeParser() {
+ return mapNodeDomParser;
+ }
+
+ @Override
+ protected ToNormalizedNodeParser<Element, org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode, ChoiceNode> getChoiceNodeParser() {
+ return choiceNodeDomParser;
+ }
+
+ @Override
+ protected ToNormalizedNodeParser<Element, AugmentationNode, AugmentationSchema> getAugmentationNodeParser() {
+ return augmentationNodeDomParser;
+ }
+
+ public static NodeParserDispatcher<Element> getInstance(XmlCodecProvider codecProvider) {
+ if (instance == null) {
+ instance = new DomNodeDispatcher(codecProvider);
+ }
+ return instance;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.LeafNodeBaseParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.w3c.dom.Element;
+
+public class LeafNodeDomParser extends LeafNodeBaseParser<Element> {
+
+ private final XmlCodecProvider codecProvider;
+
+ public LeafNodeDomParser(XmlCodecProvider codecProvider) {
+ this.codecProvider = Preconditions.checkNotNull(codecProvider);
+ }
+
+ @Override
+ protected Object parseLeaf(Element xmlElement, LeafSchemaNode schema) {
+ return DomUtils.parseXmlValue(xmlElement, codecProvider, schema.getType());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.LeafSetEntryNodeBaseParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.w3c.dom.Element;
+
+public class LeafSetEntryNodeDomParser extends LeafSetEntryNodeBaseParser<Element> {
+
+ private final XmlCodecProvider codecProvider;
+
+ public LeafSetEntryNodeDomParser(XmlCodecProvider codecProvider) {
+ this.codecProvider = Preconditions.checkNotNull(codecProvider);
+ }
+
+ @Override
+ protected Object parseLeafListEntry(Element xmlElement, LeafListSchemaNode schema) {
+ return DomUtils.parseXmlValue(xmlElement, codecProvider, schema.getType());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.LeafSetNodeBaseParser;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.w3c.dom.Element;
+
+public class LeafSetNodeDomParser extends LeafSetNodeBaseParser<Element> {
+
+ private final LeafSetEntryNodeDomParser leafSetEntryNodeBaseParser;
+
+ public LeafSetNodeDomParser(LeafSetEntryNodeDomParser leafSetEntryNodeBaseParser) {
+ this.leafSetEntryNodeBaseParser = leafSetEntryNodeBaseParser;
+ }
+
+ @Override
+ protected ToNormalizedNodeParser<Element, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeBaseParser() {
+ return leafSetEntryNodeBaseParser;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.MapEntryNodeBaseParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
+
+public final class MapEntryNodeDomParser extends MapEntryNodeBaseParser<Element> {
+
+ private final XmlCodecProvider codecProvider;
+
+ public MapEntryNodeDomParser(XmlCodecProvider codecProvider) {
+ this.codecProvider = Preconditions.checkNotNull(codecProvider);
+ }
+
+ @Override
+ protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> elements) {
+ return DomUtils.mapChildElementsForSingletonNode(elements.iterator().next());
+ }
+
+ @Override
+ protected NodeParserDispatcher<Element> getDispatcher() {
+ return DomNodeDispatcher.getInstance(codecProvider);
+ }
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.MapNodeBaseParser;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.w3c.dom.Element;
+
+public final class MapNodeDomParser extends MapNodeBaseParser<Element> {
+
+ private final MapEntryNodeDomParser mapEntryParser;
+
+ public MapNodeDomParser(MapEntryNodeDomParser mapEntryParser) {
+ this.mapEntryParser = mapEntryParser;
+ }
+
+ @Override
+ protected ToNormalizedNodeParser<Element, MapEntryNode, ListSchemaNode> getMapEntryNodeDomParser() {
+ return mapEntryParser;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer;
+
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.AugmentationNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+
+public class AugmentationNodeDomSerializer extends
+ AugmentationNodeBaseSerializer<Element> {
+
+ private final NodeSerializerDispatcher<Element> dispatcher;
+
+ public AugmentationNodeDomSerializer(NodeSerializerDispatcher<Element> dispatcher) {
+ this.dispatcher = Preconditions.checkNotNull(dispatcher);
+ }
+
+ @Override
+ protected NodeSerializerDispatcher<Element> getNodeDispatcher() {
+ return dispatcher;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer;
+
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.ChoiceNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+
+public class ChoiceNodeDomSerializer extends ChoiceNodeBaseSerializer<Element> {
+ private final NodeSerializerDispatcher<Element> dispatcher;
+
+ public ChoiceNodeDomSerializer(final NodeSerializerDispatcher<Element> dispatcher) {
+ this.dispatcher = Preconditions.checkNotNull(dispatcher);
+ }
+
+ @Override
+ protected NodeSerializerDispatcher<Element> getNodeDispatcher() {
+ return dispatcher;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer;
+
+import java.util.Collections;
+
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.ContainerNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+
+public class ContainerNodeDomSerializer extends
+ ContainerNodeBaseSerializer<Element> {
+
+ private final Document doc;
+ private final NodeSerializerDispatcher<Element> dispatcher;
+
+ public ContainerNodeDomSerializer(final Document doc, final NodeSerializerDispatcher<Element> dispatcher) {
+ this.doc = Preconditions.checkNotNull(doc);
+ this.dispatcher = Preconditions.checkNotNull(dispatcher);
+ }
+
+ @Override
+ public Iterable<Element> serialize(ContainerSchemaNode schema, ContainerNode containerNode) {
+ Element itemEl = XmlDocumentUtils.createElementFor(doc, containerNode);
+
+ for (Element element : super.serialize(schema, containerNode)) {
+ itemEl.appendChild(element);
+ }
+ return Collections.singletonList(itemEl);
+ }
+
+ @Override
+ protected NodeSerializerDispatcher<Element> getNodeDispatcher() {
+ return dispatcher;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+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.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+
+final class DomNodeSerializerDispatcher extends NodeSerializerDispatcher.BaseNodeSerializerDispatcher<Element> {
+ private static final Cache<Document, DomNodeSerializerDispatcher> dispatcherCache =
+ CacheBuilder.newBuilder().weakKeys().build();
+
+ private final FromNormalizedNodeSerializer<Element, ContainerNode, ContainerSchemaNode> containerSerializer;
+ private final FromNormalizedNodeSerializer<Element, ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> choiceSerializer;
+ private final FromNormalizedNodeSerializer<Element, AugmentationNode, AugmentationSchema> augmentSerializer;
+ private final FromNormalizedNodeSerializer<Element, LeafNode<?>, LeafSchemaNode> leafNodeSerializer;
+ private final FromNormalizedNodeSerializer<Element, LeafSetNode<?>, LeafListSchemaNode> leafSetSerializer;
+ private final FromNormalizedNodeSerializer<Element, MapNode, ListSchemaNode> mapNodeSerializer;
+
+ DomNodeSerializerDispatcher(Document doc, XmlCodecProvider codecProvider) {
+ containerSerializer = new ContainerNodeDomSerializer(doc, this);
+ choiceSerializer = new ChoiceNodeDomSerializer(this);
+ augmentSerializer = new AugmentationNodeDomSerializer(this);
+ leafNodeSerializer = new LeafNodeDomSerializer(doc, codecProvider);
+ leafSetSerializer = new LeafSetNodeDomSerializer(new LeafSetEntryNodeDomSerializer(doc, codecProvider));
+ mapNodeSerializer = new MapNodeDomSerializer(new MapEntryNodeDomSerializer(doc, this));
+ }
+
+ // FIXME: Callers should really grow a proper (per-document) lifecycle and not rely on this
+ @Deprecated
+ static DomNodeSerializerDispatcher getInstance(final Document doc, final XmlCodecProvider codecProvider) {
+ // DOM does not allow to add elements to one document from another, so maintain a cache
+ // on a per-document case.
+ try {
+ return dispatcherCache.get(doc, new Callable<DomNodeSerializerDispatcher>() {
+ @Override
+ public DomNodeSerializerDispatcher call() {
+ return new DomNodeSerializerDispatcher(doc, codecProvider);
+ }
+ });
+ } catch (ExecutionException e) {
+ throw new IllegalStateException("Failed to instantiated a dispatcher", e);
+ }
+ }
+
+ @Override
+ protected FromNormalizedNodeSerializer<Element, ContainerNode, ContainerSchemaNode> getContainerNodeSerializer() {
+ return containerSerializer;
+ }
+
+ @Override
+ protected FromNormalizedNodeSerializer<Element, LeafNode<?>, LeafSchemaNode> getLeafNodeSerializer() {
+ return leafNodeSerializer;
+ }
+
+ @Override
+ protected FromNormalizedNodeSerializer<Element, LeafSetNode<?>, LeafListSchemaNode> getLeafSetNodeSerializer() {
+ return leafSetSerializer;
+ }
+
+ @Override
+ protected FromNormalizedNodeSerializer<Element, MapNode, ListSchemaNode> getMapNodeSerializer() {
+ return mapNodeSerializer;
+ }
+
+ @Override
+ protected FromNormalizedNodeSerializer<Element, ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> getChoiceNodeSerializer() {
+ return choiceSerializer;
+ }
+
+ @Override
+ protected FromNormalizedNodeSerializer<Element, AugmentationNode, AugmentationSchema> getAugmentationNodeSerializer() {
+ return augmentSerializer;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.LeafNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class LeafNodeDomSerializer extends LeafNodeBaseSerializer<Element> {
+
+ private final Document doc;
+ private final XmlCodecProvider codecProvider;
+
+ public LeafNodeDomSerializer(Document doc, XmlCodecProvider codecProvider) {
+ this.doc = Preconditions.checkNotNull(doc);
+ this.codecProvider = Preconditions.checkNotNull(codecProvider);
+ }
+
+ @Override
+ protected Element serializeLeaf(LeafSchemaNode schema, LeafNode<?> node) {
+ Element itemEl = XmlDocumentUtils.createElementFor(doc, node);
+ DomUtils.serializeXmlValue(itemEl, schema.getType(), codecProvider, node.getValue());
+
+ return itemEl;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.LeafSetEntryNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class LeafSetEntryNodeDomSerializer extends
+ LeafSetEntryNodeBaseSerializer<Element> {
+
+ private final Document doc;
+ private final XmlCodecProvider codecProvider;
+
+ public LeafSetEntryNodeDomSerializer(Document doc, XmlCodecProvider codecProvider) {
+ this.doc = Preconditions.checkNotNull(doc);
+ this.codecProvider = Preconditions.checkNotNull(codecProvider);
+ }
+
+ @Override
+ protected Element serializeLeaf(LeafListSchemaNode schema, LeafSetEntryNode<?> node) {
+ Element itemEl = XmlDocumentUtils.createElementFor(doc, node);
+
+ DomUtils.serializeXmlValue(itemEl, schema.getType(), codecProvider, node.getValue());
+
+ return itemEl;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.LeafSetNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.w3c.dom.Element;
+
+public class LeafSetNodeDomSerializer extends
+ LeafSetNodeBaseSerializer<Element> {
+
+ private final FromNormalizedNodeSerializer<Element, LeafSetEntryNode<?>, LeafListSchemaNode> leafSetEntryNodeSerializer;
+
+ public LeafSetNodeDomSerializer(LeafSetEntryNodeDomSerializer leafSetEntryNodeSerializer) {
+ this.leafSetEntryNodeSerializer = leafSetEntryNodeSerializer;
+ }
+
+ @Override
+ protected FromNormalizedNodeSerializer<Element, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeSerializer() {
+ return leafSetEntryNodeSerializer;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer;
+
+import java.util.Collections;
+
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.MapEntryNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+
+public class MapEntryNodeDomSerializer extends
+ MapEntryNodeBaseSerializer<Element> {
+
+ private final Document doc;
+ private final NodeSerializerDispatcher<Element> dispatcher;
+
+ public MapEntryNodeDomSerializer(final Document doc, final NodeSerializerDispatcher<Element> dispatcher) {
+ this.doc = Preconditions.checkNotNull(doc);
+ this.dispatcher = Preconditions.checkNotNull(dispatcher);
+ }
+
+ @Override
+ public Iterable<Element> serialize(ListSchemaNode schema, MapEntryNode node) {
+ Element itemEl = XmlDocumentUtils.createElementFor(doc, node);
+
+ for (Element element : super.serialize(schema, node)) {
+ itemEl.appendChild(element);
+ }
+
+ return Collections.singletonList(itemEl);
+ }
+
+ @Override
+ protected NodeSerializerDispatcher<Element> getNodeDispatcher() {
+ return dispatcher;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer;
+
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.MapNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.w3c.dom.Element;
+
+public class MapNodeDomSerializer extends MapNodeBaseSerializer<Element> {
+
+ private final FromNormalizedNodeSerializer<Element, MapEntryNode, ListSchemaNode> mapEntrySerializer;
+
+ public MapNodeDomSerializer(MapEntryNodeDomSerializer mapEntrySerializer) {
+ this.mapEntrySerializer = mapEntrySerializer;
+ }
+
+ @Override
+ protected FromNormalizedNodeSerializer<Element, MapEntryNode, ListSchemaNode> getMapEntryNodeDomSerializer() {
+ return mapEntrySerializer;
+ }
+}
*/
package org.opendaylight.yangtools.yang.data.impl.schema;
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.*;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeSchemaAwareBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeSchemaAwareBuilder;
-import org.opendaylight.yangtools.yang.model.api.*;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
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.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.*;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringWriter;
-import java.net.URI;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
public class NormalizedDataBuilderTest {
private ContainerSchemaNode containerNode;
private SchemaContext schema;
- SchemaContext parseTestSchema() {
+ SchemaContext parseTestSchema(String... yangPath) {
YangParserImpl yangParserImpl = new YangParserImpl();
- Set<Module> modules = yangParserImpl.parseYangModelsFromStreams(getTestYangs());
+ Set<Module> modules = yangParserImpl.parseYangModelsFromStreams(getTestYangs(yangPath));
return yangParserImpl.resolveSchemaContext(modules);
}
- List<InputStream> getTestYangs() {
+ List<InputStream> getTestYangs(String... yangPaths) {
- return Lists.newArrayList(Collections2.transform(Lists.newArrayList("test.yang"),
+ return Lists.newArrayList(Collections2.transform(Lists.newArrayList(yangPaths),
new Function<String, InputStream>() {
@Override
public InputStream apply(String input) {
@Before
public void setUp() throws Exception {
- schema = parseTestSchema();
+ schema = parseTestSchema("test.yang");
containerNode = (ContainerSchemaNode) getSchemaNode(schema, "test", "container");
}
@Test
public void testSchemaUnaware() throws Exception {
// Container
- DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> builder = Builders.containerBuilder().withNodeIdentifier(
- getNodeIdentifier("container"));
+ DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> builder = Builders
+ .containerBuilder().withNodeIdentifier(getNodeIdentifier("container"));
// leaf
- LeafNode<String> leafChild = Builders.<String>leafBuilder()
- .withNodeIdentifier(getNodeIdentifier("leaf")).withValue("String").build();
+ LeafNode<String> leafChild = Builders.<String> leafBuilder().withNodeIdentifier(getNodeIdentifier("leaf"))
+ .withValue("String").build();
builder.withChild(leafChild);
// leafList
- LeafSetNode<Integer> leafList = Builders.<Integer>leafSetBuilder()
+ LeafSetNode<Integer> leafList = Builders
+ .<Integer> leafSetBuilder()
.withNodeIdentifier(getNodeIdentifier("leaf"))
.withChildValue(1)
- .withChild(Builders.<Integer>leafSetEntryBuilder().withNodeIdentifier(getNodeWithValueIdentifier("leaf", 3)).withValue(3).build())
+ .withChild(
+ Builders.<Integer> leafSetEntryBuilder()
+ .withNodeIdentifier(getNodeWithValueIdentifier("leaf", 3)).withValue(3).build())
.build();
builder.withChild(leafList);
// list
- MapEntryNode listChild1 = Builders.mapEntryBuilder()
- .withChild(
- Builders.<Integer>leafBuilder()
- .withNodeIdentifier(getNodeIdentifier("uint32InList")).withValue(1).build())
+ MapEntryNode listChild1 = Builders
+ .mapEntryBuilder()
.withChild(
- Builders.containerBuilder().withNodeIdentifier(
- getNodeIdentifier("containerInList"))
- .build())
+ Builders.<Integer> leafBuilder().withNodeIdentifier(getNodeIdentifier("uint32InList"))
+ .withValue(1).build())
+ .withChild(Builders.containerBuilder().withNodeIdentifier(getNodeIdentifier("containerInList")).build())
.withNodeIdentifier(
new InstanceIdentifier.NodeIdentifierWithPredicates(getNodeIdentifier("list").getNodeType(),
Collections.singletonMap(getNodeIdentifier("uint32InList").getNodeType(), (Object) 1)))
.build();
- MapNode list = Builders.mapBuilder().withChild(listChild1).withNodeIdentifier(getNodeIdentifier("list")).build();
+ MapNode list = Builders.mapBuilder().withChild(listChild1).withNodeIdentifier(getNodeIdentifier("list"))
+ .build();
builder.withChild(list);
- AugmentationNode augmentation = Builders.augmentationBuilder()
- .withNodeIdentifier(new InstanceIdentifier.AugmentationIdentifier(null, Sets.newHashSet(getQName("augmentUint32"))))
+ AugmentationNode augmentation = Builders
+ .augmentationBuilder()
+ .withNodeIdentifier(
+ new InstanceIdentifier.AugmentationIdentifier(null, Sets.newHashSet(getQName("augmentUint32"))))
.withChild(
- Builders.<Integer>leafBuilder().withNodeIdentifier(getNodeIdentifier("augmentUint32")).withValue(11).build())
- .build();
+ Builders.<Integer> leafBuilder().withNodeIdentifier(getNodeIdentifier("augmentUint32"))
+ .withValue(11).build()).build();
builder.withChild(augmentation);
- // This works without schema (adding child from augment as a direct child)
- builder.withChild(Builders.<Integer>leafBuilder().withNodeIdentifier(getNodeIdentifier("augmentUint32")).withValue(11).build());
-
- System.out.println(builder.build());
+ // This works without schema (adding child from augment as a direct
+ // child)
+ builder.withChild(Builders.<Integer> leafBuilder().withNodeIdentifier(getNodeIdentifier("augmentUint32"))
+ .withValue(11).build());
}
@Test
public void testSchemaAware() throws Exception {
- DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> builder = Builders.containerBuilder(containerNode);
+ DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> builder = Builders
+ .containerBuilder(containerNode);
LeafSchemaNode schemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "uint32");
- LeafNode<String> leafChild = Builders.<String>leafBuilder(schemaNode)
- .withValue("String").build();
+ LeafNode<String> leafChild = Builders.<String> leafBuilder(schemaNode).withValue("String").build();
builder.withChild(leafChild);
LeafListSchemaNode leafListSchemaNode = (LeafListSchemaNode) getSchemaNode(schema, "test", "leafList");
- LeafSetNode<Integer> leafList = Builders.<Integer>leafSetBuilder(leafListSchemaNode)
- .withChildValue(1)
- .withChild(Builders.<Integer>leafSetEntryBuilder(leafListSchemaNode).withValue(3).build())
- .build();
+ LeafSetNode<Integer> leafList = Builders.<Integer> leafSetBuilder(leafListSchemaNode).withChildValue(1)
+ .withChild(Builders.<Integer> leafSetEntryBuilder(leafListSchemaNode).withValue(3).build()).build();
builder.withChild(leafList);
ListSchemaNode listSchema = (ListSchemaNode) getSchemaNode(schema, "test", "list");
LeafSchemaNode uint32InListSchemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "uint32InList");
- ContainerSchemaNode containerInListSchemaNode = (ContainerSchemaNode) getSchemaNode(schema, "test", "containerInList");
+ ContainerSchemaNode containerInListSchemaNode = (ContainerSchemaNode) getSchemaNode(schema, "test",
+ "containerInList");
MapEntryNode listChild1 = Builders.mapEntryBuilder(listSchema)
- .withChild(
- Builders.<Integer>leafBuilder(uint32InListSchemaNode).withValue(1).build())
- .withChild(
- Builders.containerBuilder(containerInListSchemaNode).build())
- .build();
+ .withChild(Builders.<Integer> leafBuilder(uint32InListSchemaNode).withValue(1).build())
+ .withChild(Builders.containerBuilder(containerInListSchemaNode).build()).build();
MapNode list = ImmutableMapNodeSchemaAwareBuilder.create(listSchema).withChild(listChild1).build();
builder.withChild(list);
LeafSchemaNode augmentUint32SchemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "augmentUint32");
- AugmentationSchema augmentationSchema = getAugmentationSchemaForChild(containerNode, augmentUint32SchemaNode.getQName());
+ AugmentationSchema augmentationSchema = getAugmentationSchemaForChild(containerNode,
+ augmentUint32SchemaNode.getQName());
- AugmentationNode augmentation = Builders.augmentationBuilder(augmentationSchema).withChild(
- Builders.<Integer>leafBuilder(augmentUint32SchemaNode).withValue(11).build())
- .build();
+ AugmentationNode augmentation = Builders.augmentationBuilder(augmentationSchema)
+ .withChild(Builders.<Integer>leafBuilder(augmentUint32SchemaNode).withValue(11).build()).build();
builder.withChild(augmentation);
// This should fail with schema, since the leaf comes from augmentation
-// builder.withChild(ImmutableLeafNodeSchemaAwareBuilder.<Integer>get(augmentUint32SchemaNode).withValue(11).build());
+ // builder.withChild(ImmutableLeafNodeSchemaAwareBuilder.<Integer>get(augmentUint32SchemaNode).withValue(11).build());
LeafSchemaNode augumentString1SchemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "augmentString1");
LeafSchemaNode augumentString2SchemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "augmentString2");
ChoiceNode choice1SchemaNode = (ChoiceNode) getSchemaNode(schema, "test", "choice");
- org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode choice = ImmutableChoiceNodeSchemaAwareBuilder.create(choice1SchemaNode)
- .withChild(Builders.<String>leafBuilder(augumentString1SchemaNode).withValue("case1")
- .build())
- // This should fail, since child node belongs to different case
-// .withChild(Builders.<String>leafBuilder(augumentString2SchemaNode).withValue("case2")
-// .build())
+ org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode choice = ImmutableChoiceNodeSchemaAwareBuilder
+ .create(choice1SchemaNode)
+ .withChild(Builders.<String> leafBuilder(augumentString1SchemaNode).withValue("case1").build())
+ // This should fail, since child node belongs to different case
+ // .withChild(Builders.<String>leafBuilder(augumentString2SchemaNode).withValue("case2")
+ // .build())
.build();
-; builder.withChild(choice);
+ ;
+ builder.withChild(choice);
// This should fail, child from case
-// builder.withChild(Builders.<String>leafBuilder(augumentString1SchemaNode).withValue("case1")
-// .build());
-
- System.out.println(builder.build());
+ // builder.withChild(Builders.<String>leafBuilder(augumentString1SchemaNode).withValue("case1")
+ // .build());
}
private AugmentationSchema getAugmentationSchemaForChild(ContainerSchemaNode containerNode, QName qName) {
for (AugmentationSchema augmentationSchema : containerNode.getAvailableAugmentations()) {
- if(augmentationSchema.getDataChildByName(qName) != null) {
+ if (augmentationSchema.getDataChildByName(qName) != null) {
return augmentationSchema;
}
}
return new QName(URI.create(namespace), localName);
}
- private InstanceIdentifier.NodeWithValue getNodeWithValueIdentifier(QName q, Object value) {
- return new InstanceIdentifier.NodeWithValue(q, value);
- }
-
private InstanceIdentifier.NodeIdentifier getNodeIdentifier(String localName) {
return new InstanceIdentifier.NodeIdentifier(getQName(localName));
}
- private InstanceIdentifier.NodeIdentifier getNodeIdentifier(QName q) {
- return new InstanceIdentifier.NodeIdentifier(q);
- }
-
- private Document loadDocument(String xmlPath) throws Exception {
- InputStream resourceAsStream = getClass().getResourceAsStream(xmlPath);
-
- Document currentConfigElement = readXmlToDocument(resourceAsStream);
- Preconditions.checkNotNull(currentConfigElement);
- return currentConfigElement;
- }
-
- private static final DocumentBuilderFactory BUILDERFACTORY;
-
- static {
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- factory.setNamespaceAware(true);
- factory.setCoalescing(true);
- factory.setIgnoringElementContentWhitespace(true);
- factory.setIgnoringComments(true);
- BUILDERFACTORY = factory;
- }
-
- private Document readXmlToDocument(InputStream xmlContent) throws IOException, SAXException {
- DocumentBuilder dBuilder;
- try {
- dBuilder = BUILDERFACTORY.newDocumentBuilder();
- } catch (ParserConfigurationException e) {
- throw new RuntimeException("Failed to parse XML document", e);
- }
- Document doc = dBuilder.parse(xmlContent);
-
- doc.getDocumentElement().normalize();
- return doc;
- }
-
- public static String toString(Element xml) {
- try {
- Transformer transformer = TransformerFactory.newInstance().newTransformer();
- transformer.setOutputProperty(OutputKeys.INDENT, "yes");
-
- StreamResult result = new StreamResult(new StringWriter());
- DOMSource source = new DOMSource(xml);
- transformer.transform(source, result);
-
- return result.getWriter().toString();
- } catch (IllegalArgumentException | TransformerFactoryConfigurationError | TransformerException e) {
- throw new RuntimeException("Unable to serialize xml element " + xml, e);
- }
- }
-
- DataSchemaNode getSchemaNode(SchemaContext context, String moduleName, String childNodeName) {
+ public static DataSchemaNode getSchemaNode(SchemaContext context, String moduleName, String childNodeName) {
for (Module module : context.getModules()) {
if (module.getName().equals(moduleName)) {
DataSchemaNode found = findChildNode(module.getChildNodes(), childNodeName);
- Preconditions.checkState(found!=null, "Unable to find %s", childNodeName);
+ Preconditions.checkState(found != null, "Unable to find %s", childNodeName);
return found;
}
}
throw new IllegalStateException("Unable to find child node " + childNodeName);
}
- DataSchemaNode findChildNode(Set<DataSchemaNode> children, String name) {
+ static DataSchemaNode findChildNode(Set<DataSchemaNode> children, String name) {
List<DataNodeContainer> containers = Lists.newArrayList();
for (DataSchemaNode dataSchemaNode : children) {
if (dataSchemaNode.getQName().getLocalName().equals(name))
return dataSchemaNode;
- if(dataSchemaNode instanceof DataNodeContainer) {
+ if (dataSchemaNode instanceof DataNodeContainer) {
containers.add((DataNodeContainer) dataSchemaNode);
- } else if(dataSchemaNode instanceof ChoiceNode) {
+ } else if (dataSchemaNode instanceof ChoiceNode) {
containers.addAll(((ChoiceNode) dataSchemaNode).getCases());
}
}
for (DataNodeContainer container : containers) {
DataSchemaNode retVal = findChildNode(container.getChildNodes(), name);
- if(retVal != null) {
+ if (retVal != null) {
return retVal;
}
}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.net.URI;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedDataBuilderTest;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.ContainerNodeDomParser;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+@RunWith(Parameterized.class)
+public class NormalizedNodeXmlTranslationTest {
+ private static final Logger logger = LoggerFactory.getLogger(NormalizedNodeXmlTranslationTest.class);
+
+ @Parameterized.Parameters()
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[][]{
+ {"augment_choice_hell.yang", "augment_choice_hell_ok.xml", augmentChoiceHell()},
+ {"augment_choice_hell.yang", "augment_choice_hell_ok2.xml", null},
+ {"test.yang", "simple.xml", null},
+ {"test.yang", "simple2.xml", null}
+ });
+ }
+
+ public static final String NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:test";
+ private static Date revision;
+ static {
+ try {
+ revision = new SimpleDateFormat("yyyy-MM-dd").parse("2014-03-13");
+ } catch (ParseException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static ContainerNode augmentChoiceHell() {
+
+ DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> b = Builders.containerBuilder();
+ b.withNodeIdentifier(getNodeIdentifier("container"));
+
+ b.withChild(
+ Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("ch2"))
+ .withChild(Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c2Leaf")).withValue("2").build())
+ .withChild(
+ Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("c2DeepChoice"))
+ .withChild(Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c2DeepChoiceCase1Leaf2")).withValue("2").build())
+ .build()
+ )
+ .build()
+ );
+
+ b.withChild(
+ Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("ch3")).withChild(
+ Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c3Leaf")).withValue("3").build())
+ .build());
+
+ b.withChild(
+ Builders.augmentationBuilder().withNodeIdentifier(getAugmentIdentifier("augLeaf")).withChild(
+ Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("augLeaf")).withValue("augment").build())
+ .build());
+
+ b.withChild(
+ Builders.augmentationBuilder().withNodeIdentifier(getAugmentIdentifier("ch")).withChild(
+ Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("ch"))
+ .withChild(
+ Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c1Leaf")).withValue("1").build())
+ .withChild(
+ Builders.augmentationBuilder().withNodeIdentifier(getAugmentIdentifier("c1Leaf_AnotherAugment", "deepChoice"))
+ .withChild(
+ Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c1Leaf_AnotherAugment")).withValue("1").build())
+ .withChild(
+ Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("deepChoice"))
+ .withChild(
+ Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("deepLeafc1")).withValue("1").build()
+ ).build()
+ ).build()
+ ).build()
+ ).build());
+
+ return b.build();
+ }
+
+ private static InstanceIdentifier.NodeIdentifier getNodeIdentifier(String localName) {
+ return new InstanceIdentifier.NodeIdentifier(new QName(URI.create(NAMESPACE), revision, localName));
+ }
+
+ public static InstanceIdentifier.AugmentationIdentifier getAugmentIdentifier(String... childNames) {
+ Set<QName> qn = Sets.newHashSet();
+
+ for (String childName : childNames) {
+ qn.add(getNodeIdentifier(childName).getNodeType());
+ }
+
+ return new InstanceIdentifier.AugmentationIdentifier(null, qn);
+ }
+
+ public NormalizedNodeXmlTranslationTest(String yangPath, String xmlPath, ContainerNode expectedNode) {
+ this.schema = parseTestSchema(yangPath);
+ this.xmlPath = xmlPath;
+ this.containerNode = (ContainerSchemaNode) NormalizedDataBuilderTest.getSchemaNode(schema, "test", "container");
+ this.expectedNode = expectedNode;
+ }
+
+ private final ContainerNode expectedNode;
+ private final ContainerSchemaNode containerNode;
+ private final SchemaContext schema;
+ private final String xmlPath;
+
+
+ SchemaContext parseTestSchema(String... yangPath) {
+ YangParserImpl yangParserImpl = new YangParserImpl();
+ Set<Module> modules = yangParserImpl.parseYangModelsFromStreams(getTestYangs(yangPath));
+ return yangParserImpl.resolveSchemaContext(modules);
+ }
+
+ List<InputStream> getTestYangs(String... yangPaths) {
+
+ return Lists.newArrayList(Collections2.transform(Lists.newArrayList(yangPaths),
+ new Function<String, InputStream>() {
+ @Override
+ public InputStream apply(String input) {
+ InputStream resourceAsStream = NormalizedDataBuilderTest.class.getResourceAsStream(input);
+ Preconditions.checkNotNull(resourceAsStream, "File %s was null", resourceAsStream);
+ return resourceAsStream;
+ }
+ }));
+ }
+
+ @Test
+ public void testTranslation() throws Exception {
+ Document doc = loadDocument(xmlPath);
+
+ ContainerNode built = new ContainerNodeDomParser(DomUtils.defaultValueCodecProvider()).parse(
+ Collections.singletonList(doc.getDocumentElement()), containerNode);
+
+ if (expectedNode != null)
+ junit.framework.Assert.assertEquals(expectedNode, built);
+
+ logger.info("{}", built);
+
+ final Document newDoc = XmlDocumentUtils.getDocument();
+ final NodeSerializerDispatcher<Element> dispatcher = new DomNodeSerializerDispatcher(newDoc, DomUtils.defaultValueCodecProvider());
+
+ Iterable<Element> els = new ContainerNodeDomSerializer(newDoc,
+ dispatcher).serialize(containerNode, built);
+
+ Element el = els.iterator().next();
+
+ Assert.assertEquals(toString(doc.getDocumentElement()).replaceAll("\\s*", ""),
+ toString(el).replaceAll("\\s*", ""));
+ }
+
+
+ private Document loadDocument(String xmlPath) throws Exception {
+ InputStream resourceAsStream = NormalizedDataBuilderTest.class.getResourceAsStream(xmlPath);
+
+ Document currentConfigElement = readXmlToDocument(resourceAsStream);
+ Preconditions.checkNotNull(currentConfigElement);
+ return currentConfigElement;
+ }
+
+ private static final DocumentBuilderFactory BUILDERFACTORY;
+
+ static {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ factory.setCoalescing(true);
+ factory.setIgnoringElementContentWhitespace(true);
+ factory.setIgnoringComments(true);
+ BUILDERFACTORY = factory;
+ }
+
+ private Document readXmlToDocument(InputStream xmlContent) throws IOException, SAXException {
+ DocumentBuilder dBuilder;
+ try {
+ dBuilder = BUILDERFACTORY.newDocumentBuilder();
+ } catch (ParserConfigurationException e) {
+ throw new RuntimeException("Failed to parse XML document", e);
+ }
+ Document doc = dBuilder.parse(xmlContent);
+
+ doc.getDocumentElement().normalize();
+ return doc;
+ }
+
+ public static String toString(Element xml) {
+ try {
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+
+ StreamResult result = new StreamResult(new StringWriter());
+ DOMSource source = new DOMSource(xml);
+ transformer.transform(source, result);
+
+ return result.getWriter().toString();
+ } catch (IllegalArgumentException | TransformerFactoryConfigurationError | TransformerException e) {
+ throw new RuntimeException("Unable to serialize xml element " + xml, e);
+ }
+ }
+}
--- /dev/null
+// vi: set smarttab et sw=4 tabstop=4:
+module test {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:test";
+ prefix "test";
+
+ organization "Cisco Systems, Inc.";
+
+ revision "2014-3-13" {
+ description
+ "Initial revision";
+ }
+
+
+ container container {
+ choice ch2{}
+ choice ch3{
+ case c3 {
+ leaf c3Leaf {
+ type string;
+ }
+ }
+ }
+ }
+
+ augment "/container/" {
+ leaf augLeaf {
+ type string;
+ }
+ }
+
+ augment "/container/" {
+ choice ch{}
+ }
+
+ augment "/container/ch/" {
+ case c1 {
+ leaf c1Leaf {
+ type string;
+ }
+ }
+
+ leaf c12 {
+ type string;
+ }
+ }
+ augment "/container/ch/c1/" {
+ leaf c1Leaf_AnotherAugment {
+ type string;
+ }
+
+ choice deepChoice{}
+ }
+
+ augment "/container/ch3/" {
+ case c32 {
+ leaf c32Leaf {
+ type string;
+ }
+ }
+
+ leaf c34LeafS {
+ type string;
+ }
+ }
+
+
+ augment "/container/ch/c1/deepChoice/" {
+ case deepCase1 {
+ leaf deepLeafc1 {
+ type string;
+ }
+ }
+ case deepCase2 {
+ leaf deepLeafc2 {
+ type string;
+ }
+ }
+ }
+
+ augment "/container/ch2/" {
+ case c2 {
+ leaf c2Leaf {
+ type string;
+ }
+
+ choice c2DeepChoice {
+ case c2DeepChoiceCase1 {
+ leaf c2DeepChoiceCase1Leaf1 {
+ type string;
+ }
+ }
+ case c2DeepChoiceCase2 {
+ leaf c2DeepChoiceCase1Leaf2 {
+ type string;
+ }
+ }
+ }
+ }
+ }
+
+ augment "/container/ch2/" {
+ leaf c22Leaf {
+ type string;
+ }
+ }
+
+
+}
\ No newline at end of file
--- /dev/null
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+
+ <c2Leaf>2</c2Leaf>
+ <c2DeepChoiceCase1Leaf2>2</c2DeepChoiceCase1Leaf2>
+ <!--<c2DeepChoiceCase1Leaf1>2</c2DeepChoiceCase1Leaf1>-->
+
+ <c3Leaf>3</c3Leaf>
+
+ <augLeaf>augment</augLeaf>
+
+ <c1Leaf>1</c1Leaf>
+ <c1Leaf_AnotherAugment>1</c1Leaf_AnotherAugment>
+ <deepLeafc1>1</deepLeafc1>
+ <!--<deepLeafc2>1</deepLeafc2>-->
+</container>
\ No newline at end of file
--- /dev/null
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+
+ <c22Leaf>2</c22Leaf>
+
+ <c34LeafS>3</c34LeafS>
+
+ <augLeaf>augment</augLeaf>
+
+ <c1Leaf>1</c1Leaf>
+ <c1Leaf_AnotherAugment>1</c1Leaf_AnotherAugment>
+ <deepLeafc2>1</deepLeafc2>
+</container>
\ No newline at end of file
<uint32>32</uint32>
<uint16>16</uint16>
</containerInList>
+ <stringAugmentedToList>augmentInList</stringAugmentedToList>
+ <stringAugmentedToListInCase1>augmentInListCase1</stringAugmentedToListInCase1>
</list>
<list>
<uint32InList>2</uint32InList>
<uint32>32</uint32>
<uint16>16</uint16>
</containerInList>
+ <!--<stringAugmentedToListInCase1>augmentInListCase1</stringAugmentedToListInCase1>-->
+ <stringAugmentedToListInCase2>augmentInListCase2</stringAugmentedToListInCase2>
</list>
<list>
<uint32InList>3</uint32InList>
</list>
- <augmentUint32>999</augmentUint32>
-
<augmentString1>choice1Case1</augmentString1>
+ <!--<augmentString2>choice1Case1</augmentString2>-->
<augmentInt1>41</augmentInt1>
+ <!--<stringInAugmentedCaseInAugmentedChoice>deep</stringInAugmentedCaseInAugmentedChoice>-->
+ <stringInAugmentedCaseInAugmentedChoiceFromAugment>deep</stringInAugmentedCaseInAugmentedChoiceFromAugment>
<augmentContainer>
<augmentStringInaugmentContainer>choice2Case1</augmentStringInaugmentContainer>
</augmentContainer>
+ <augmentUint32>999</augmentUint32>
+
+
</container>
\ No newline at end of file
--- /dev/null
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+ <augmentString1>choice1Case1</augmentString1>
+ <!--<augmentString2>choice1Case1</augmentString2>-->
+ <augmentInt1>41</augmentInt1>
+ <!--<stringInAugmentedCaseInAugmentedChoice>deep</stringInAugmentedCaseInAugmentedChoice>-->
+ <stringInAugmentedCaseInAugmentedChoice2>deep</stringInAugmentedCaseInAugmentedChoice2>
+
+ <augmentedList>
+ <augmentStringInaugmentList>aug1</augmentStringInaugmentList>
+ </augmentedList>
+
+ <augmentedList>
+ <augmentStringInaugmentList>aug2</augmentStringInaugmentList>
+ <augmentedContainerInAugmentedListInAugmentedCase>
+ <leafInAugmentedContainerInAugmentedListInAugmentedCase>
+ 66
+ </leafInAugmentedContainerInAugmentedListInAugmentedCase>
+ </augmentedContainerInAugmentedListInAugmentedCase>
+
+ <augmentedListInAugmentedListInAugmentedCase>
+ <leafInAugmentedListInAugmentedListInAugmentedCase>
+ 661
+ </leafInAugmentedListInAugmentedListInAugmentedCase>
+ <leafInAugmentedListInAugmentedListInAugmentedCase>
+ 662
+ </leafInAugmentedListInAugmentedListInAugmentedCase>
+ </augmentedListInAugmentedListInAugmentedCase>
+
+ <augmentedListInAugmentedListInAugmentedCase>
+ <leafInAugmentedListInAugmentedListInAugmentedCase>
+ 6621
+ </leafInAugmentedListInAugmentedListInAugmentedCase>
+ </augmentedListInAugmentedListInAugmentedCase>
+ </augmentedList>
+
+ <augmentedList>
+ <augmentStringInaugmentList>aug3</augmentStringInaugmentList>
+ <augmentedContainerInAugmentedListInAugmentedCase/>
+
+ <augmentedListInAugmentedListInAugmentedCase/>
+ </augmentedList>
+
+</container>
\ No newline at end of file
type string;
}
- uses listGroup;
+ uses listGroup {
+ augment "list/" {
+ leaf stringAugmentedToList{
+ type string;
+ }
+
+ choice choiceInList {
+ case caseInList1 {
+ leaf stringAugmentedToListInCase1 {
+ type string;
+ }
+ }
+ case caseInList2 {
+ leaf stringAugmentedToListInCase2 {
+ type string;
+ }
+ }
+ }
+ }
+ }
+
+ list directList {
+ leaf stringInDirectList {
+ type string;
+ }
+ }
+
uses innerContainerGrouping;
choice choice{}
}
}
+ augment "/container/directList/" {
+ leaf augmentedString {
+ type uint32;
+ }
+ }
+
augment "/container/choice/" {
case test-identity-augment {
when "/container/identityRef = 'test-identity'";
}
}
+ augment "/container/choice/test-identity-augment/" {
+
+ choice augmentedChoiceInCase {
+
+ case augmentedCaseInAugmentedChoice {
+ leaf stringInAugmentedCaseInAugmentedChoice {
+ type string;
+ }
+ }
+
+ case augmentedCaseInAugmentedChoice2 {
+ leaf stringInAugmentedCaseInAugmentedChoice2 {
+ type string;
+ }
+ }
+ }
+ }
+
+ augment "/container/choice/test-identity-augment/augmentedChoiceInCase/" {
+ case augmentedCaseInAugmentedChoiceFromAugment {
+ leaf stringInAugmentedCaseInAugmentedChoiceFromAugment {
+ type string;
+ }
+ }
+ }
+
augment "/container/choice2/" {
case test-identity-augment {
when "/container/identityRef = 'test-identity'";
}
+ augment "/container/choice2/test-identity-augment2/augmentedList/" {
+
+ container augmentedContainerInAugmentedListInAugmentedCase {
+ leaf-list leafInAugmentedContainerInAugmentedListInAugmentedCase {
+ type uint32;
+ }
+ }
+
+ list augmentedListInAugmentedListInAugmentedCase {
+ leaf-list leafInAugmentedListInAugmentedListInAugmentedCase {
+ type uint32;
+ }
+ }
+ }
+
identity test-identity {}
identity test-identity2 {
base test-identity;