* 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.controller.cluster.datastore.node.utils.transformer;
+import static com.google.common.base.Preconditions.checkState;
+
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import java.io.IOException;
+import com.google.common.base.Optional;
import java.net.URI;
-import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
-import java.util.Set;
import javax.xml.transform.dom.DOMSource;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
+import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
+import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* The NormalizedNodePruner removes all nodes from the input NormalizedNode that do not have a corresponding
- * schema element in the passed in SchemaContext
- *
+ * schema element in the passed in SchemaContext.
*/
public class NormalizedNodePruner implements NormalizedNodeStreamWriter {
+ private static final Logger LOG = LoggerFactory.getLogger(NormalizedNodePruner.class);
+
+ public static final URI BASE_NAMESPACE = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0");
private final SimpleStack<NormalizedNodeBuilderWrapper> stack = new SimpleStack<>();
- private NormalizedNode<?,?> normalizedNode;
- private final Set<URI> validNamespaces;
+ private final DataSchemaContextNode<?> nodePathSchemaNode;
+
+ private NormalizedNode<?, ?> normalizedNode;
private boolean sealed = false;
- public NormalizedNodePruner(SchemaContext schemaContext) {
- validNamespaces = new HashSet<>(schemaContext.getModules().size());
- for(org.opendaylight.yangtools.yang.model.api.Module module : schemaContext.getModules()){
- validNamespaces.add(module.getNamespace());
- }
+ public NormalizedNodePruner(final YangInstanceIdentifier nodePath, final SchemaContext schemaContext) {
+ nodePathSchemaNode = findSchemaNodeForNodePath(nodePath, schemaContext);
}
- @Override
- public void leafNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, Object o) throws IOException, IllegalArgumentException {
+ @SuppressWarnings("unchecked")
+ @Override
+ public void leafNode(final NodeIdentifier nodeIdentifier, final Object value) {
checkNotSealed();
- if(!isValidNamespace(nodeIdentifier)){
- return;
- }
NormalizedNodeBuilderWrapper parent = stack.peek();
- Preconditions.checkState(parent != null, "leafNode has no parent");
- parent.builder()
- .addChild(Builders.leafBuilder()
- .withNodeIdentifier(nodeIdentifier)
- .withValue(o)
- .build());
+ LeafNode<Object> leafNode = Builders.leafBuilder().withNodeIdentifier(nodeIdentifier).withValue(value).build();
+ if (parent != null) {
+ if (hasValidSchema(nodeIdentifier.getNodeType(), parent)) {
+ parent.builder().addChild(leafNode);
+ }
+ } else {
+ // If there's no parent node then this is a stand alone LeafNode.
+ if (nodePathSchemaNode != null) {
+ this.normalizedNode = leafNode;
+ }
+
+ sealed = true;
+ }
}
@Override
- public void startLeafSet(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
-
+ public void startLeafSet(final NodeIdentifier nodeIdentifier, final int count) {
checkNotSealed();
-
addBuilder(Builders.leafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
}
@Override
- public void leafSetEntryNode(Object o) throws IOException, IllegalArgumentException {
+ public void startOrderedLeafSet(final NodeIdentifier nodeIdentifier, final int str) {
+ checkNotSealed();
+ addBuilder(Builders.orderedLeafSetBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
+ }
+ @SuppressWarnings("unchecked")
+ @Override
+ public void leafSetEntryNode(final QName name, final Object value) {
checkNotSealed();
NormalizedNodeBuilderWrapper parent = stack.peek();
- Preconditions.checkState(parent != null, "leafSetEntryNode has no parent");
- if(!isValidNamespace(parent.identifier())){
- return;
- }
-
- parent.builder()
- .addChild(Builders.leafSetEntryBuilder()
- .withValue(o)
- .withNodeIdentifier(new YangInstanceIdentifier.NodeWithValue(parent.nodeType(), o))
+ if (parent != null) {
+ if (hasValidSchema(name, parent)) {
+ parent.builder().addChild(Builders.leafSetEntryBuilder().withValue(value)
+ .withNodeIdentifier(new NodeWithValue<>(parent.nodeType(), value))
.build());
+ }
+ } else {
+ // If there's no parent LeafSetNode then this is a stand alone
+ // LeafSetEntryNode.
+ if (nodePathSchemaNode != null) {
+ this.normalizedNode = Builders.leafSetEntryBuilder().withValue(value).withNodeIdentifier(
+ new NodeWithValue<>(name, value)).build();
+ }
+
+ sealed = true;
+ }
}
@Override
- public void startContainerNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
-
+ public void startContainerNode(final NodeIdentifier nodeIdentifier, final int count) {
checkNotSealed();
-
addBuilder(Builders.containerBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
}
@Override
- public void startUnkeyedList(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
+ public void startYangModeledAnyXmlNode(final NodeIdentifier nodeIdentifier, final int count) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+ @Override
+ public void startUnkeyedList(final NodeIdentifier nodeIdentifier, final int count) {
checkNotSealed();
-
addBuilder(Builders.unkeyedListBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
}
@Override
- public void startUnkeyedListItem(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalStateException {
-
+ public void startUnkeyedListItem(final NodeIdentifier nodeIdentifier, final int count) {
checkNotSealed();
-
addBuilder(Builders.unkeyedListEntryBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
}
@Override
- public void startMapNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
-
+ public void startMapNode(final NodeIdentifier nodeIdentifier, final int count) {
checkNotSealed();
-
addBuilder(Builders.mapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
}
@Override
- public void startMapEntryNode(YangInstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifierWithPredicates, int i) throws IOException, IllegalArgumentException {
-
+ public void startMapEntryNode(final NodeIdentifierWithPredicates nodeIdentifierWithPredicates, final int count) {
checkNotSealed();
-
- addBuilder(Builders.mapEntryBuilder().withNodeIdentifier(nodeIdentifierWithPredicates), nodeIdentifierWithPredicates);
+ addBuilder(Builders.mapEntryBuilder().withNodeIdentifier(nodeIdentifierWithPredicates),
+ nodeIdentifierWithPredicates);
}
@Override
- public void startOrderedMapNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
-
+ public void startOrderedMapNode(final NodeIdentifier nodeIdentifier, final int count) {
checkNotSealed();
-
addBuilder(Builders.orderedMapBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
}
@Override
- public void startChoiceNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, int i) throws IOException, IllegalArgumentException {
-
+ public void startChoiceNode(final NodeIdentifier nodeIdentifier, final int count) {
checkNotSealed();
-
addBuilder(Builders.choiceBuilder().withNodeIdentifier(nodeIdentifier), nodeIdentifier);
}
@Override
- public void startAugmentationNode(YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifier) throws IOException, IllegalArgumentException {
-
+ public void startAugmentationNode(final AugmentationIdentifier augmentationIdentifier) {
checkNotSealed();
-
addBuilder(Builders.augmentationBuilder().withNodeIdentifier(augmentationIdentifier), augmentationIdentifier);
}
+ @SuppressWarnings("unchecked")
@Override
- public void anyxmlNode(YangInstanceIdentifier.NodeIdentifier nodeIdentifier, Object o) throws IOException, IllegalArgumentException {
-
+ public void anyxmlNode(final NodeIdentifier nodeIdentifier, final Object value) {
checkNotSealed();
- if(!isValidNamespace(nodeIdentifier)){
- return;
- }
NormalizedNodeBuilderWrapper parent = stack.peek();
- Preconditions.checkState(parent != null, "anyxmlNode has no parent");
- parent.builder().addChild(Builders.anyXmlBuilder().withNodeIdentifier(nodeIdentifier).withValue((DOMSource) o).build());
+ AnyXmlNode anyXmlNode = Builders.anyXmlBuilder().withNodeIdentifier(nodeIdentifier).withValue((DOMSource) value)
+ .build();
+ if (parent != null) {
+ if (hasValidSchema(nodeIdentifier.getNodeType(), parent)) {
+ parent.builder().addChild(anyXmlNode);
+ }
+ } else {
+ // If there's no parent node then this is a stand alone AnyXmlNode.
+ if (nodePathSchemaNode != null) {
+ this.normalizedNode = anyXmlNode;
+ }
+
+ sealed = true;
+ }
}
+ @SuppressWarnings("unchecked")
@Override
- public void endNode() throws IOException, IllegalStateException {
-
+ public void endNode() {
checkNotSealed();
NormalizedNodeBuilderWrapper child = stack.pop();
- Preconditions.checkState(child != null, "endNode called on an empty stack");
+ checkState(child != null, "endNode called on an empty stack");
- if(!isValidNamespace(child.identifier())){
+ if (!child.getSchema().isPresent()) {
+ LOG.debug("Schema not found for {}", child.identifier());
return;
}
- NormalizedNode<?,?> normalizedNode = child.builder().build();
- if(stack.size() > 0){
+ NormalizedNode<?, ?> newNode = child.builder().build();
+ if (stack.size() > 0) {
NormalizedNodeBuilderWrapper parent = stack.peek();
- parent.builder().addChild(normalizedNode);
+ parent.builder().addChild(newNode);
} else {
- this.normalizedNode = normalizedNode;
+ this.normalizedNode = newNode;
sealed = true;
}
}
@Override
- public void close() throws IOException {
+ public void close() {
sealed = true;
}
@Override
- public void flush() throws IOException {
-
+ public void flush() {
+ // No-op
}
- public NormalizedNode<?,?> normalizedNode(){
+ public NormalizedNode<?, ?> normalizedNode() {
return normalizedNode;
}
- private void checkNotSealed(){
- Preconditions.checkState(!sealed, "Pruner can be used only once");
- }
-
- private boolean isValidNamespace(QName qName){
- return validNamespaces.contains(qName.getNamespace());
+ private void checkNotSealed() {
+ checkState(!sealed, "Pruner can be used only once");
}
- private boolean isValidNamespace(YangInstanceIdentifier.AugmentationIdentifier augmentationIdentifier){
- Set<QName> possibleChildNames = augmentationIdentifier.getPossibleChildNames();
-
- for(QName qName : possibleChildNames){
- if(isValidNamespace(qName)){
- return true;
- }
+ private static boolean hasValidSchema(final QName name, final NormalizedNodeBuilderWrapper parent) {
+ boolean valid = parent.getSchema().isPresent() && parent.getSchema().get().getChild(name) != null;
+ if (!valid) {
+ LOG.debug("Schema not found for {}", name);
}
- return false;
+ return valid;
}
- private boolean isValidNamespace(YangInstanceIdentifier.PathArgument identifier){
- if(identifier instanceof YangInstanceIdentifier.AugmentationIdentifier){
- return isValidNamespace((YangInstanceIdentifier.AugmentationIdentifier) identifier);
+ private NormalizedNodeBuilderWrapper addBuilder(final NormalizedNodeContainerBuilder<?, ?, ?, ?> builder,
+ final PathArgument identifier) {
+ final Optional<DataSchemaContextNode<?>> schemaNode;
+ NormalizedNodeBuilderWrapper parent = stack.peek();
+ if (parent == null) {
+ schemaNode = Optional.fromNullable(nodePathSchemaNode);
+ } else if (parent.getSchema().isPresent()) {
+ schemaNode = Optional.fromNullable(parent.getSchema().get().getChild(identifier));
+ } else {
+ schemaNode = Optional.absent();
}
- return isValidNamespace(identifier.getNodeType());
- }
-
- private NormalizedNodeBuilderWrapper addBuilder(NormalizedNodeContainerBuilder<?,?,?,?> builder, YangInstanceIdentifier.PathArgument identifier){
- NormalizedNodeBuilderWrapper wrapper = new NormalizedNodeBuilderWrapper(builder, identifier);
+ NormalizedNodeBuilderWrapper wrapper = new NormalizedNodeBuilderWrapper(builder, identifier, schemaNode);
stack.push(wrapper);
return wrapper;
}
+ private static DataSchemaContextNode<?> findSchemaNodeForNodePath(final YangInstanceIdentifier nodePath,
+ final SchemaContext schemaContext) {
+ DataSchemaContextNode<?> schemaNode = DataSchemaContextTree.from(schemaContext).getRoot();
+ for (PathArgument arg : nodePath.getPathArguments()) {
+ schemaNode = schemaNode.getChild(arg);
+ if (schemaNode == null) {
+ break;
+ }
+ }
+
+ return schemaNode;
+ }
+
@VisibleForTesting
static class SimpleStack<E> {
List<E> stack = new LinkedList<>();
- void push(E element){
+ void push(final E element) {
stack.add(element);
}
- E pop(){
- if(size() == 0){
+ E pop() {
+ if (size() == 0) {
return null;
}
return stack.remove(stack.size() - 1);
}
- E peek(){
- if(size() == 0){
+ E peek() {
+ if (size() == 0) {
return null;
}
return stack.get(stack.size() - 1);
}
- int size(){
+ int size() {
return stack.size();
}
}
-
- @VisibleForTesting
- SimpleStack<NormalizedNodeBuilderWrapper> stack(){
- return stack;
- }
-
-
}