1 package org.opendaylight.controller.sal.rest.impl;
3 import static com.google.common.base.Preconditions.checkNotNull;
5 import java.io.IOException;
9 import javax.activation.UnsupportedDataTypeException;
11 import org.opendaylight.controller.sal.restconf.impl.*;
12 import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO.IdentityValue;
13 import org.opendaylight.yangtools.yang.common.QName;
14 import org.opendaylight.yangtools.yang.data.api.*;
15 import org.opendaylight.yangtools.yang.model.api.*;
16 import org.opendaylight.yangtools.yang.model.api.type.*;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
20 import com.google.common.base.Preconditions;
21 import com.google.gson.stream.JsonWriter;
25 private final Set<LeafListSchemaNode> foundLeafLists = new HashSet<>();
26 private final Set<ListSchemaNode> foundLists = new HashSet<>();
27 private final Logger logger = LoggerFactory.getLogger(JsonMapper.class);
29 public void write(JsonWriter writer, CompositeNode data, DataNodeContainer schema) throws IOException {
30 Preconditions.checkNotNull(writer);
31 Preconditions.checkNotNull(data);
32 Preconditions.checkNotNull(schema);
36 if (schema instanceof ContainerSchemaNode) {
37 writeContainer(writer, data, (ContainerSchemaNode) schema);
38 } else if (schema instanceof ListSchemaNode) {
39 writeList(writer, null, data, (ListSchemaNode) schema);
41 throw new UnsupportedDataTypeException(
42 "Schema can be ContainerSchemaNode or ListSchemaNode. Other types are not supported yet.");
47 foundLeafLists.clear();
51 private void writeChildrenOfParent(JsonWriter writer, CompositeNode parent, DataNodeContainer parentSchema)
54 checkNotNull(parentSchema);
56 for (Node<?> child : parent.getChildren()) {
57 DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchema.getChildNodes());
59 if (childSchema == null) {
60 throw new UnsupportedDataTypeException("Probably the data node \"" + child.getNodeType().getLocalName()
61 + "\" is not conform to schema");
64 if (childSchema instanceof ContainerSchemaNode) {
65 Preconditions.checkState(child instanceof CompositeNode,
66 "Data representation of Container should be CompositeNode - " + child.getNodeType());
67 writeContainer(writer, (CompositeNode) child, (ContainerSchemaNode) childSchema);
68 } else if (childSchema instanceof ListSchemaNode) {
69 if (!foundLists.contains(childSchema)) {
70 Preconditions.checkState(child instanceof CompositeNode,
71 "Data representation of List should be CompositeNode - " + child.getNodeType());
72 foundLists.add((ListSchemaNode) childSchema);
73 writeList(writer, parent, (CompositeNode) child, (ListSchemaNode) childSchema);
75 } else if (childSchema instanceof LeafListSchemaNode) {
76 if (!foundLeafLists.contains(childSchema)) {
77 Preconditions.checkState(child instanceof SimpleNode<?>,
78 "Data representation of LeafList should be SimpleNode - " + child.getNodeType());
79 foundLeafLists.add((LeafListSchemaNode) childSchema);
80 writeLeafList(writer, parent, (SimpleNode<?>) child, (LeafListSchemaNode) childSchema);
82 } else if (childSchema instanceof LeafSchemaNode) {
83 Preconditions.checkState(child instanceof SimpleNode<?>,
84 "Data representation of LeafList should be SimpleNode - " + child.getNodeType());
85 writeLeaf(writer, (SimpleNode<?>) child, (LeafSchemaNode) childSchema);
87 throw new UnsupportedDataTypeException("Schema can be ContainerSchemaNode, ListSchemaNode, "
88 + "LeafListSchemaNode, or LeafSchemaNode. Other types are not supported yet.");
92 for (Node<?> child : parent.getChildren()) {
93 DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchema.getChildNodes());
94 if (childSchema instanceof LeafListSchemaNode) {
95 foundLeafLists.remove((LeafListSchemaNode) childSchema);
96 } else if (childSchema instanceof ListSchemaNode) {
97 foundLists.remove((ListSchemaNode) childSchema);
102 private DataSchemaNode findFirstSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
103 for (DataSchemaNode dsn : dataSchemaNode) {
104 if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
106 } else if (dsn instanceof ChoiceNode) {
107 for (ChoiceCaseNode choiceCase : ((ChoiceNode) dsn).getCases()) {
108 DataSchemaNode foundDsn = findFirstSchemaForNode(node, choiceCase.getChildNodes());
109 if (foundDsn != null) {
118 private void writeContainer(JsonWriter writer, CompositeNode node, ContainerSchemaNode schema) throws IOException {
119 writeName(node, schema, writer);
120 writer.beginObject();
121 writeChildrenOfParent(writer, node, schema);
125 private void writeList(JsonWriter writer, CompositeNode nodeParent, CompositeNode node, ListSchemaNode schema)
127 writeName(node, schema, writer);
130 if (nodeParent != null) {
131 List<CompositeNode> nodeLists = nodeParent.getCompositesByName(node.getNodeType());
132 for (CompositeNode nodeList : nodeLists) {
133 writer.beginObject();
134 writeChildrenOfParent(writer, nodeList, schema);
138 writer.beginObject();
139 writeChildrenOfParent(writer, node, schema);
146 private void writeLeafList(JsonWriter writer, CompositeNode nodeParent, SimpleNode<?> node,
147 LeafListSchemaNode schema) throws IOException {
148 writeName(node, schema, writer);
151 List<SimpleNode<?>> nodeLeafLists = nodeParent.getSimpleNodesByName(node.getNodeType());
152 for (SimpleNode<?> nodeLeafList : nodeLeafLists) {
153 writeValueOfNodeByType(writer, nodeLeafList, schema.getType(), schema);
158 private void writeLeaf(JsonWriter writer, SimpleNode<?> node, LeafSchemaNode schema) throws IOException {
159 writeName(node, schema, writer);
160 writeValueOfNodeByType(writer, node, schema.getType(), schema);
163 private void writeValueOfNodeByType(JsonWriter writer, SimpleNode<?> node, TypeDefinition<?> type,
164 DataSchemaNode schema) throws IOException {
166 TypeDefinition<?> baseType = RestUtil.resolveBaseTypeFrom(type);
168 // TODO check InstanceIdentifierTypeDefinition
169 if (baseType instanceof IdentityrefTypeDefinition) {
170 if (node.getValue() instanceof QName) {
171 IdentityValuesDTO valueDTO = (IdentityValuesDTO) RestCodec.from(baseType).serialize(node.getValue());
172 IdentityValue valueFromDTO = valueDTO.getValuesWithNamespaces().get(0);
173 String moduleName = ControllerContext.getInstance().findModuleByNamespace(
174 URI.create(valueFromDTO.getNamespace()));
175 writer.value(moduleName + ":" + valueFromDTO.getValue());
177 logger.debug("Value of " + baseType.getQName().getNamespace() + ":"
178 + baseType.getQName().getLocalName() + " is not instance of " + QName.class + " but is "
179 + node.getValue().getClass());
180 writer.value(String.valueOf(node.getValue()));
182 } else if (baseType instanceof DecimalTypeDefinition || baseType instanceof IntegerTypeDefinition
183 || baseType instanceof UnsignedIntegerTypeDefinition) {
184 writer.value(new NumberForJsonWriter((String) RestCodec.from(baseType).serialize(node.getValue())));
185 } else if (baseType instanceof BooleanTypeDefinition) {
186 writer.value(Boolean.parseBoolean((String) RestCodec.from(baseType).serialize(node.getValue())));
187 } else if (baseType instanceof EmptyTypeDefinition) {
188 writeEmptyDataTypeToJson(writer);
190 String value = String.valueOf(RestCodec.from(baseType).serialize(node.getValue()));
192 value = String.valueOf(node.getValue());
194 writer.value(value.equals("null") ? "" : value);
198 private void writeEmptyDataTypeToJson(JsonWriter writer) throws IOException {
204 private void writeName(Node<?> node, DataSchemaNode schema, JsonWriter writer) throws IOException {
205 String nameForOutput = node.getNodeType().getLocalName();
206 if (schema.isAugmenting()) {
207 ControllerContext contContext = ControllerContext.getInstance();
208 CharSequence moduleName;
209 moduleName = contContext.toRestconfIdentifier(schema.getQName());
210 if (moduleName != null) {
211 nameForOutput = moduleName.toString();
214 writer.name(nameForOutput);
217 private static final class NumberForJsonWriter extends Number {
219 private static final long serialVersionUID = -3147729419814417666L;
220 private final String value;
222 public NumberForJsonWriter(String value) {
227 public int intValue() {
228 throw new IllegalStateException("Should not be invoked");
232 public long longValue() {
233 throw new IllegalStateException("Should not be invoked");
237 public float floatValue() {
238 throw new IllegalStateException("Should not be invoked");
242 public double doubleValue() {
243 throw new IllegalStateException("Should not be invoked");
247 public String toString() {