Merge "creating a default subnet"
[controller.git] / opendaylight / md-sal / sal-rest-connector / src / main / java / org / opendaylight / controller / sal / rest / impl / JsonMapper.java
1 package org.opendaylight.controller.sal.rest.impl;
2
3 import static com.google.common.base.Preconditions.checkNotNull;
4
5 import java.io.IOException;
6 import java.util.HashSet;
7 import java.util.List;
8 import java.util.Set;
9
10 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
11 import org.opendaylight.yangtools.yang.data.api.Node;
12 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
13 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
14 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
15 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
16 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
17 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
18 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
19 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
20 import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
21 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
22 import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
23 import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
24 import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
25 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
26
27 import com.google.gson.stream.JsonWriter;
28
29 class JsonMapper {
30     
31     private final Set<LeafListSchemaNode> foundLeafLists = new HashSet<>();
32     private final Set<ListSchemaNode> foundLists = new HashSet<>();
33     
34     public void write(JsonWriter writer, CompositeNode data, DataNodeContainer schema) throws IOException {
35         writer.beginObject();
36         writeChildrenOfParent(writer, data, schema);
37         writer.endObject();
38         foundLeafLists.clear();
39         foundLists.clear();
40     }
41
42     private void writeChildrenOfParent(JsonWriter writer, CompositeNode parent, DataNodeContainer parentSchema) throws IOException {
43         checkNotNull(parent);
44         checkNotNull(parentSchema);
45         
46         for (Node<?> child : parent.getChildren()) {
47             DataSchemaNode childSchema = findSchemaForNode(child, parentSchema.getChildNodes());
48             if (childSchema instanceof ContainerSchemaNode) {
49                 writeContainer(writer, (CompositeNode) child, (ContainerSchemaNode) childSchema);
50             } else if (childSchema instanceof ListSchemaNode) {
51                 if (!foundLists.contains(childSchema)) {
52                     foundLists.add((ListSchemaNode) childSchema);
53                     writeList(writer, (CompositeNode) child, (ListSchemaNode) childSchema);
54                 }
55             } else if (childSchema instanceof LeafListSchemaNode) {
56                 if (!foundLeafLists.contains(childSchema)) {
57                     foundLeafLists.add((LeafListSchemaNode) childSchema);
58                     writeLeafList(writer, (SimpleNode<?>) child, (LeafListSchemaNode) childSchema);
59                 }
60             } else if (childSchema instanceof LeafSchemaNode) {
61                 writeLeaf(writer, (SimpleNode<?>) child, (LeafSchemaNode) childSchema);
62             }
63         }
64         
65         for (Node<?> child : parent.getChildren()) {
66             DataSchemaNode childSchema = findSchemaForNode(child, parentSchema.getChildNodes());
67             if (childSchema instanceof LeafListSchemaNode) {
68                 foundLeafLists.remove((LeafListSchemaNode) childSchema);
69             } else if (childSchema instanceof ListSchemaNode) {
70                 foundLists.remove((ListSchemaNode) childSchema);
71             }
72         }
73     }
74     
75     private DataSchemaNode findSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
76         for (DataSchemaNode dsn : dataSchemaNode) {
77             if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
78                 return dsn;
79             }
80         }
81         return null;
82     }
83     
84     private void writeContainer(JsonWriter writer, CompositeNode node, ContainerSchemaNode schema) throws IOException {
85         writer.name(node.getNodeType().getLocalName());
86         writer.beginObject();
87         writeChildrenOfParent(writer, node, schema);
88         writer.endObject();
89     }
90     
91     private void writeList(JsonWriter writer, CompositeNode node, ListSchemaNode schema) throws IOException {
92             writer.name(node.getNodeType().getLocalName());
93             writer.beginArray();
94             
95             if (node.getParent() != null) {
96                 CompositeNode parent = node.getParent();
97                 List<CompositeNode> nodeLists = parent.getCompositesByName(node.getNodeType());
98                 for (CompositeNode nodeList : nodeLists) {
99                     writer.beginObject();
100                     writeChildrenOfParent(writer, nodeList, schema);
101                     writer.endObject();
102                 }
103             } else {
104                 writer.beginObject();
105                 writeChildrenOfParent(writer, node, schema);
106                 writer.endObject();
107             }
108             
109             writer.endArray();
110     }
111     
112     private void writeLeafList(JsonWriter writer, SimpleNode<?> node, LeafListSchemaNode schema) throws IOException {
113             writer.name(node.getNodeType().getLocalName());
114             writer.beginArray();
115             
116             CompositeNode parent = node.getParent();
117             List<SimpleNode<?>> nodeLeafLists = parent.getSimpleNodesByName(node.getNodeType());
118             for (SimpleNode<?> nodeLeafList : nodeLeafLists) {
119                 writeValueOfNodeByType(writer, nodeLeafList, schema.getType());
120             }
121             
122             writer.endArray();
123     }
124     
125     private void writeLeaf(JsonWriter writer, SimpleNode<?> node, LeafSchemaNode schema) throws IOException {
126         writer.name(node.getNodeType().getLocalName());
127         writeValueOfNodeByType(writer, node, schema.getType());
128     }
129     
130     private void writeValueOfNodeByType(JsonWriter writer, SimpleNode<?> node, TypeDefinition<?> type) throws IOException {
131         if (!(node.getValue() instanceof String)) {
132             throw new IllegalStateException("Value in SimpleNode should be type String");
133         }
134         
135         String value = (String) node.getValue();
136         // TODO check Leafref, InstanceIdentifierTypeDefinition, IdentityrefTypeDefinition, UnionTypeDefinition
137         if (type.getBaseType() != null) {
138             writeValueOfNodeByType(writer, node, type.getBaseType());
139         } else if (type instanceof InstanceIdentifierTypeDefinition) {
140             writer.value(((InstanceIdentifierTypeDefinition) type).getPathStatement().toString());
141         } else if (type instanceof DecimalTypeDefinition 
142                 || type instanceof IntegerTypeDefinition
143                 || type instanceof UnsignedIntegerTypeDefinition) {
144             writer.value(new NumberForJsonWriter(value));
145         } else if (type instanceof BooleanTypeDefinition) {
146             writer.value(Boolean.parseBoolean(value));
147         } else if (type instanceof EmptyTypeDefinition) {
148             writer.value("[null]");
149         } else {
150             writer.value(value);
151         }
152     }
153     
154     private static final class NumberForJsonWriter extends Number {
155         
156         private static final long serialVersionUID = -3147729419814417666L;
157         private final String value;
158         
159         public NumberForJsonWriter(String value) {
160             this.value = value;
161         }
162
163         @Override
164         public int intValue() {
165             throw new IllegalStateException("Should not be invoked");
166         }
167
168         @Override
169         public long longValue() {
170             throw new IllegalStateException("Should not be invoked");
171         }
172
173         @Override
174         public float floatValue() {
175             throw new IllegalStateException("Should not be invoked");
176         }
177
178         @Override
179         public double doubleValue() {
180             throw new IllegalStateException("Should not be invoked");
181         }
182
183         @Override
184         public String toString() {
185             return value;
186         }
187         
188     }
189
190 }