Instance identifier support
[controller.git] / opendaylight / md-sal / sal-rest-connector / src / main / java / org / opendaylight / controller / sal / rest / impl / JsonReader.java
1 package org.opendaylight.controller.sal.rest.impl;
2
3 import java.io.InputStream;
4 import java.io.InputStreamReader;
5 import java.net.URI;
6 import java.util.Map.Entry;
7 import java.util.Set;
8
9 import org.opendaylight.controller.sal.rest.impl.RestUtil.PrefixMapingFromJson;
10 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
11 import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
12 import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
13 import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
14
15 import com.google.common.collect.Lists;
16 import com.google.gson.JsonElement;
17 import com.google.gson.JsonObject;
18 import com.google.gson.JsonParser;
19 import com.google.gson.JsonPrimitive;
20
21 class JsonReader {
22
23     public CompositeNodeWrapper read(InputStream entityStream) throws UnsupportedFormatException {
24         JsonParser parser = new JsonParser();
25
26         JsonElement rootElement = parser.parse(new InputStreamReader(entityStream));
27         if (!rootElement.isJsonObject()) {
28             throw new UnsupportedFormatException("Root element of Json has to be Object");
29         }
30
31         Set<Entry<String, JsonElement>> entrySetsOfRootJsonObject = rootElement.getAsJsonObject().entrySet();
32         if (entrySetsOfRootJsonObject.size() != 1) {
33             throw new UnsupportedFormatException("Json Object should contain one element");
34         } else {
35             Entry<String, JsonElement> childEntry = Lists.newArrayList(entrySetsOfRootJsonObject).get(0);
36             String firstElementName = childEntry.getKey();
37             JsonElement firstElementType = childEntry.getValue();
38             if (firstElementType.isJsonObject()) { // container in yang
39                 return createStructureWithRoot(firstElementName, firstElementType.getAsJsonObject());
40             }
41             if (firstElementType.isJsonArray()) { // list in yang
42                 if (firstElementType.getAsJsonArray().size() == 1) {
43                     JsonElement firstElementInArray = firstElementType.getAsJsonArray().get(0);
44                     if (firstElementInArray.isJsonObject()) {
45                         return createStructureWithRoot(firstElementName, firstElementInArray.getAsJsonObject());
46                     }
47                     throw new UnsupportedFormatException(
48                             "Array as the first element in Json Object can have only Object element");
49                 }
50             }
51             throw new UnsupportedFormatException(
52                     "First element in Json Object has to be \"Object\" or \"Array with one Object element\". Other scenarios are not supported yet.");
53         }
54     }
55
56     private CompositeNodeWrapper createStructureWithRoot(String rootObjectName, JsonObject rootObject) {
57         CompositeNodeWrapper firstNode = new CompositeNodeWrapper(getNamespaceFor(rootObjectName),
58                 getLocalNameFor(rootObjectName));
59         for (Entry<String, JsonElement> childOfFirstNode : rootObject.entrySet()) {
60             addChildToParent(childOfFirstNode.getKey(), childOfFirstNode.getValue(), firstNode);
61         }
62         return firstNode;
63     }
64
65     private void addChildToParent(String childName, JsonElement childType, CompositeNodeWrapper parent) {
66         if (childType.isJsonObject()) {
67             CompositeNodeWrapper child = new CompositeNodeWrapper(getNamespaceFor(childName), getLocalNameFor(childName));
68             parent.addValue(child);
69             for (Entry<String, JsonElement> childOfChild : childType.getAsJsonObject().entrySet()) {
70                 addChildToParent(childOfChild.getKey(), childOfChild.getValue(), child);
71             }
72         } else if (childType.isJsonArray()) {
73             if (childType.getAsJsonArray().size() == 1 && childType.getAsJsonArray().get(0).isJsonNull()) {
74                 parent.addValue(new EmptyNodeWrapper(getNamespaceFor(childName), getLocalNameFor(childName)));
75
76             } else {
77                 for (JsonElement childOfChildType : childType.getAsJsonArray()) {
78                     addChildToParent(childName, childOfChildType, parent);
79                 }
80             }
81         } else if (childType.isJsonPrimitive()) {
82             JsonPrimitive childPrimitive = childType.getAsJsonPrimitive();
83             String value = childPrimitive.getAsString();
84             parent.addValue(new SimpleNodeWrapper(getNamespaceFor(childName), getLocalNameFor(childName),
85                     resolveValueOfElement(value)));
86         }
87     }
88
89     private URI getNamespaceFor(String jsonElementName) {
90         String[] moduleNameAndLocalName = jsonElementName.split(":");
91         // it is not "moduleName:localName"
92         if (moduleNameAndLocalName.length != 2) {
93             return null;
94         }
95         return URI.create(moduleNameAndLocalName[0]);
96     }
97
98     private String getLocalNameFor(String jsonElementName) {
99         String[] moduleNameAndLocalName = jsonElementName.split(":");
100         // it is not "moduleName:localName"
101         if (moduleNameAndLocalName.length != 2) {
102             return jsonElementName;
103         }
104         return moduleNameAndLocalName[1];
105     }
106
107     private Object resolveValueOfElement(String value) {
108         // it could be instance-identifier Built-In Type
109         if (value.startsWith("/")) {
110             IdentityValuesDTO resolvedValue = RestUtil.asInstanceIdentifier(value, new PrefixMapingFromJson());
111             if (resolvedValue != null) {
112                 return resolvedValue;
113             }
114         }
115         // it could be identityref Built-In Type
116         URI namespace = getNamespaceFor(value);
117         if (namespace != null) {
118             return new IdentityValuesDTO(namespace.toString(), getLocalNameFor(value), null);
119         }
120         // it is not "prefix:value" but just "value"
121         return value;
122     }
123
124 }