Merge "Bug 164"
[controller.git] / opendaylight / md-sal / sal-rest-connector / src / main / java / org / opendaylight / controller / sal / restconf / impl / RestconfImpl.xtend
1 package org.opendaylight.controller.sal.restconf.impl
2
3 import java.util.List
4 import javax.ws.rs.core.Response
5 import org.opendaylight.controller.sal.rest.api.RestconfService
6 import org.opendaylight.yangtools.yang.data.api.CompositeNode
7 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
8 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
9 import org.opendaylight.controller.md.sal.common.api.TransactionStatus
10 import javax.ws.rs.WebApplicationException
11
12 class RestconfImpl implements RestconfService {
13     
14     val static RestconfImpl INSTANCE = new RestconfImpl
15
16     @Property
17     BrokerFacade broker
18
19     @Property
20     extension ControllerContext controllerContext
21     
22     private new() {
23         if (INSTANCE !== null) {
24             throw new IllegalStateException("Already instantiated");
25         }
26     }
27     
28     static def getInstance() {
29         return INSTANCE
30     }
31
32     override readAllData() {
33 //        return broker.readOperationalData("".toInstanceIdentifier.getInstanceIdentifier);
34         throw new UnsupportedOperationException("Reading all data is currently not supported.")
35     }
36
37     override getModules() {
38         throw new UnsupportedOperationException("TODO: auto-generated method stub")
39     }
40
41     override getRoot() {
42         return null;
43     }
44
45     override readData(String identifier) {
46         val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
47         val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
48         return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
49     }
50
51     override createConfigurationData(String identifier, CompositeNode payload) {
52         val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
53         val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
54         val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
55         switch status.result {
56             case TransactionStatus.COMMITED: Response.status(Response.Status.OK).build
57             default: Response.status(Response.Status.INTERNAL_SERVER_ERROR).build
58         }
59     }
60
61     override updateConfigurationData(String identifier, CompositeNode payload) {
62         val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
63         val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
64         val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
65         switch status.result {
66             case TransactionStatus.COMMITED: Response.status(Response.Status.NO_CONTENT).build
67             default: Response.status(Response.Status.INTERNAL_SERVER_ERROR).build
68         }
69     }
70
71     override invokeRpc(String identifier, CompositeNode payload) {
72         val rpc = identifier.toQName;
73         val value = resolveNodeNamespaceBySchema(payload, controllerContext.getRpcInputSchema(rpc))
74         val rpcResult = broker.invokeRpc(rpc, value);
75         val schema = controllerContext.getRpcOutputSchema(rpc);
76         return new StructuredData(rpcResult.result, schema);
77     }
78     
79     override readConfigurationData(String identifier) {
80         val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
81         val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
82         return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
83     }
84     
85     override readOperationalData(String identifier) {
86         val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
87         val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
88         return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
89     }
90     
91     override updateConfigurationDataLegacy(String identifier, CompositeNode payload) {
92         updateConfigurationData(identifier,payload);
93     }
94     
95     override createConfigurationDataLegacy(String identifier, CompositeNode payload) {
96         createConfigurationData(identifier,payload);
97     }
98     
99     override createOperationalData(String identifier, CompositeNode payload) {
100         val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
101         val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
102         val status = broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
103         switch status.result {
104             case TransactionStatus.COMMITED: Response.status(Response.Status.OK).build
105             default: Response.status(Response.Status.INTERNAL_SERVER_ERROR).build
106         }
107     }
108     
109     override updateOperationalData(String identifier, CompositeNode payload) {
110         val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
111         val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
112         val status = broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
113         switch status.result {
114             case TransactionStatus.COMMITED: Response.status(Response.Status.NO_CONTENT).build
115             default: Response.status(Response.Status.INTERNAL_SERVER_ERROR).build
116         }
117     }
118     
119     private def InstanceIdWithSchemaNode resolveInstanceIdentifier(String identifier) {
120         val identifierWithSchemaNode = identifier.toInstanceIdentifier
121         if (identifierWithSchemaNode === null) {
122             throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST).entity("URI has bad format")
123                     .build());
124         }
125         return identifierWithSchemaNode
126     }
127     
128     private def CompositeNode resolveNodeNamespaceBySchema(CompositeNode node, DataSchemaNode schema) {
129         if (node instanceof CompositeNodeWrapper) {
130             addNamespaceToNodeFromSchemaRecursively(node as CompositeNodeWrapper, schema)
131             return (node as CompositeNodeWrapper).unwrap(null)
132         }
133         return node
134     }
135
136     private def void addNamespaceToNodeFromSchemaRecursively(NodeWrapper<?> nodeBuilder, DataSchemaNode schema) {
137         if (nodeBuilder.namespace === null) {
138             nodeBuilder.namespace = schema.QName.namespace
139         }
140         if (nodeBuilder instanceof CompositeNodeWrapper) {
141             val List<NodeWrapper<?>> children = (nodeBuilder as CompositeNodeWrapper).getValues
142             for (child : children) {
143                 addNamespaceToNodeFromSchemaRecursively(child,
144                     (schema as DataNodeContainer).childNodes.findFirst[n|n.QName.localName.equals(child.localName)])
145             }
146         }
147     }
148
149 }