Merge changes I442a0ee9,I11825b90
[controller.git] / opendaylight / md-sal / sal-protocolbuffer-encoding / src / main / java / org / opendaylight / controller / cluster / datastore / node / NormalizedNodeToProtocolBufferNode.java
1 package org.opendaylight.controller.cluster.datastore.node;
2
3 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
4 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.Node;
5 import org.opendaylight.yangtools.yang.common.QName;
6 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
7 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
8 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
9 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
10 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
11 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
12 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
13 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
14 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
15 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
16 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
17 import org.opendaylight.yangtools.yang.data.api.schema.MixinNode;
18 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
19 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
20 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
21
22 import java.util.Map;
23
24 /**
25  * NormalizedNodeToProtocolBufferNode walks the NormalizedNode tree converting it to the
26  * NormalizedMessage.Node
27  *
28  * {@link org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode } is a tree like structure that provides a generic structure for a yang data
29  * model
30  *
31  *
32  */
33 public class NormalizedNodeToProtocolBufferNode {
34
35
36   private final Node.Builder builderRoot;
37   private NormalizedNodeMessages.Container container;
38
39   public NormalizedNodeToProtocolBufferNode() {
40
41     builderRoot = Node.newBuilder();
42   }
43
44   public void encode(String parentPath, NormalizedNode<?, ?> normalizedNode) {
45     if (parentPath == null) {
46       parentPath = "";
47     }
48
49     NormalizedNodeMessages.Container.Builder containerBuilder =
50         NormalizedNodeMessages.Container.newBuilder();
51
52     if(normalizedNode != null) {
53
54       navigateNormalizedNode(0, parentPath, normalizedNode, builderRoot);
55       // here we need to put back the Node Tree in Container
56
57       container= containerBuilder.setParentPath(parentPath).setNormalizedNode(
58           builderRoot.build()).build();
59     }else {
60       //this can happen when an attempt was made to read from datastore and normalized node was null.
61       container = containerBuilder.setParentPath(parentPath).build();
62
63     }
64
65   }
66
67
68   private void navigateDataContainerNode(int level,final String parentPath,
69       final DataContainerNode<?> dataContainerNode, Node.Builder builderParent) {
70
71     String newParentPath = parentPath + "/" + dataContainerNode.getIdentifier().toString();
72     String type = getDataContainerType(dataContainerNode).getSimpleName();
73     builderParent.setPath(dataContainerNode.getIdentifier().toString())
74         .setType(type);
75
76     final Iterable<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> value =
77         dataContainerNode.getValue();
78     for (NormalizedNode<?, ?> node : value) {
79       Node.Builder builderChild = Node.newBuilder();
80       if (node instanceof MixinNode && node instanceof NormalizedNodeContainer) {
81
82         navigateNormalizedNodeContainerMixin(level, newParentPath,
83             (NormalizedNodeContainer<?, ?, ?>) node, builderChild);
84       } else {
85         navigateNormalizedNode(level, newParentPath,node, builderChild);
86       }
87       builderParent.addChild(builderChild);
88     }
89
90   }
91
92   private Class getDataContainerType(
93       NormalizedNodeContainer<?, ?, ?> dataContainerNode) {
94     if (dataContainerNode instanceof ChoiceNode) {
95       return ChoiceNode.class;
96     } else if (dataContainerNode instanceof AugmentationNode) {
97       return AugmentationNode.class;
98     } else if (dataContainerNode instanceof ContainerNode) {
99       return ContainerNode.class;
100     } else if (dataContainerNode instanceof MapEntryNode) {
101       return MapEntryNode.class;
102     } else if (dataContainerNode instanceof UnkeyedListEntryNode) {
103       return UnkeyedListEntryNode.class;
104     } else if (dataContainerNode instanceof MapNode) {
105       return MapNode.class;
106     } else if (dataContainerNode instanceof LeafSetNode){
107       return LeafSetNode.class;
108     }
109     throw new IllegalArgumentException(
110         "could not find the data container node type "
111             + dataContainerNode.toString());
112   }
113
114   private void navigateNormalizedNodeContainerMixin(int level, final String parentPath,
115       NormalizedNodeContainer<?, ?, ?> node, Node.Builder builderParent) {
116     String newParentPath = parentPath + "/" + node.getIdentifier().toString();
117
118     builderParent.setPath(node.getIdentifier().toString()).setType(
119         this.getDataContainerType(node).getSimpleName());
120     final Iterable<? extends NormalizedNode<?, ?>> value = node.getValue();
121     for (NormalizedNode normalizedNode : value) {
122       // child node builder
123       Node.Builder builderChild = Node.newBuilder();
124       if (normalizedNode instanceof MixinNode
125           && normalizedNode instanceof NormalizedNodeContainer) {
126         navigateNormalizedNodeContainerMixin(level + 1,newParentPath,
127             (NormalizedNodeContainer) normalizedNode, builderChild);
128       } else {
129         navigateNormalizedNode(level,newParentPath, normalizedNode, builderChild);
130       }
131       builderParent.addChild(builderChild);
132
133     }
134
135
136
137   }
138
139
140   private void navigateNormalizedNode(int level,
141       String parentPath,NormalizedNode<?, ?> normalizedNode, Node.Builder builderParent) {
142
143     if (normalizedNode instanceof DataContainerNode) {
144
145       final DataContainerNode<?> dataContainerNode =
146           (DataContainerNode) normalizedNode;
147
148       navigateDataContainerNode(level + 1, parentPath,dataContainerNode, builderParent);
149     } else {
150
151       if (normalizedNode instanceof LeafNode) {
152         buildLeafNode(parentPath,normalizedNode, builderParent);
153       } else if (normalizedNode instanceof LeafSetEntryNode) {
154         buildLeafSetEntryNode(parentPath,normalizedNode,builderParent);
155       }
156
157     }
158
159   }
160
161   private void buildLeafSetEntryNode(String parentPath,NormalizedNode<?, ?> normalizedNode,
162       Node.Builder builderParent) {
163     String path = parentPath + "/" + normalizedNode.getIdentifier().toString();
164     LeafSetEntryNode leafSetEntryNode = (LeafSetEntryNode) normalizedNode;
165     Map<QName, String> attributes = leafSetEntryNode.getAttributes();
166     if (!attributes.isEmpty()) {
167       NormalizedNodeMessages.Attribute.Builder builder = null;
168       for (Map.Entry<QName, String> attribute : attributes.entrySet()) {
169         builder = NormalizedNodeMessages.Attribute.newBuilder();
170         builder.setName(attribute.getKey().toString()).setValue(
171             normalizedNode.getValue().toString());
172         builderParent.addAttributes(builder.build());
173       }
174     }
175     builderParent.setPath(normalizedNode.getIdentifier().toString()).setType(
176         LeafSetEntryNode.class.getSimpleName()).setValue(normalizedNode.getValue().toString());
177   }
178
179   private void buildLeafNode(String parentPath,NormalizedNode<?, ?> normalizedNode,
180       Node.Builder builderParent) {
181     String path = parentPath + "/" + normalizedNode.getIdentifier().toString();
182     LeafNode leafNode = (LeafNode) normalizedNode;
183     Map<QName, String> attributes = leafNode.getAttributes();
184     if (!attributes.isEmpty()) {
185       NormalizedNodeMessages.Attribute.Builder builder = null;
186       for (Map.Entry<QName, String> attribute : attributes.entrySet()) {
187         builder = NormalizedNodeMessages.Attribute.newBuilder();
188         builder.setName(attribute.getKey().toString()).setValue(
189             normalizedNode.getValue().toString());
190         builderParent.addAttributes(builder.build());
191       }
192     }
193     builderParent.setPath(normalizedNode.getIdentifier().toString()).setType(
194         LeafNode.class.getSimpleName()).setValue(normalizedNode.getValue().toString());
195   }
196
197   public NormalizedNodeMessages.Container getContainer() {
198     return container;
199   }
200 }