1 package org.opendaylight.controller.sal.restconf.impl
5 import javax.ws.rs.core.Response
6 import org.opendaylight.controller.md.sal.common.api.TransactionStatus
7 import org.opendaylight.controller.sal.rest.api.RestconfService
8 import org.opendaylight.yangtools.yang.data.api.CompositeNode
9 import org.opendaylight.yangtools.yang.model.api.ChoiceNode
10 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
11 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
13 class RestconfImpl implements RestconfService {
15 val static RestconfImpl INSTANCE = new RestconfImpl
21 extension ControllerContext controllerContext
24 if (INSTANCE !== null) {
25 throw new IllegalStateException("Already instantiated");
29 static def getInstance() {
33 override readAllData() {
34 // return broker.readOperationalData("".toInstanceIdentifier.getInstanceIdentifier);
35 throw new UnsupportedOperationException("Reading all data is currently not supported.")
38 override getModules() {
39 throw new UnsupportedOperationException("TODO: auto-generated method stub")
46 override readData(String identifier) {
47 val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
48 val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
49 return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
52 override createConfigurationData(String identifier, CompositeNode payload) {
53 val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
54 val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
55 val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
56 switch status.result {
57 case TransactionStatus.COMMITED: Response.status(Response.Status.OK).build
58 default: Response.status(Response.Status.INTERNAL_SERVER_ERROR).build
62 override updateConfigurationData(String identifier, CompositeNode payload) {
63 val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
64 val value = resolveNodeNamespaceBySchema(payload, identifierWithSchemaNode.schemaNode)
65 val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,value).get();
66 switch status.result {
67 case TransactionStatus.COMMITED: Response.status(Response.Status.NO_CONTENT).build
68 default: Response.status(Response.Status.INTERNAL_SERVER_ERROR).build
72 override invokeRpc(String identifier, CompositeNode payload) {
73 val rpc = identifier.toQName;
74 val value = resolveNodeNamespaceBySchema(payload, controllerContext.getRpcInputSchema(rpc))
75 val rpcResult = broker.invokeRpc(rpc, value);
76 val schema = controllerContext.getRpcOutputSchema(rpc);
77 return new StructuredData(rpcResult.result, schema);
80 override readConfigurationData(String identifier) {
81 val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
82 val data = broker.readConfigurationData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
83 return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
86 override readOperationalData(String identifier) {
87 val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
88 val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
89 return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
92 override updateConfigurationDataLegacy(String identifier, CompositeNode payload) {
93 updateConfigurationData(identifier,payload);
96 override createConfigurationDataLegacy(String identifier, CompositeNode payload) {
97 createConfigurationData(identifier,payload);
100 private def InstanceIdWithSchemaNode resolveInstanceIdentifier(String identifier) {
101 val identifierWithSchemaNode = identifier.toInstanceIdentifier
102 if (identifierWithSchemaNode === null) {
103 throw new ResponseException(Response.Status.BAD_REQUEST, "URI has bad format");
105 return identifierWithSchemaNode
108 private def CompositeNode resolveNodeNamespaceBySchema(CompositeNode node, DataSchemaNode schema) {
109 if (node instanceof CompositeNodeWrapper) {
110 addNamespaceToNodeFromSchemaRecursively(node as CompositeNodeWrapper, schema)
111 return (node as CompositeNodeWrapper).unwrap(null)
116 private def void addNamespaceToNodeFromSchemaRecursively(NodeWrapper<?> nodeBuilder, DataSchemaNode schema) {
117 if (schema === null) {
118 throw new ResponseException(Response.Status.BAD_REQUEST,
119 "Data has bad format\n" + nodeBuilder.localName + " does not exist in yang schema.");
121 val moduleName = controllerContext.findModuleByNamespace(schema.QName.namespace);
122 if (nodeBuilder.namespace === null || nodeBuilder.namespace == schema.QName.namespace ||
123 nodeBuilder.namespace.path == moduleName) {
124 nodeBuilder.qname = schema.QName
126 throw new ResponseException(Response.Status.BAD_REQUEST,
127 "Data has bad format\nIf data is in XML format then namespace for " + nodeBuilder.localName +
128 " should be " + schema.QName.namespace + ".\n If data is in Json format then module name for " +
129 nodeBuilder.localName + " should be " + moduleName + ".");
131 if (nodeBuilder instanceof CompositeNodeWrapper) {
132 val List<NodeWrapper<?>> children = (nodeBuilder as CompositeNodeWrapper).getValues
133 for (child : children) {
134 addNamespaceToNodeFromSchemaRecursively(child,
135 findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes))
140 private def DataSchemaNode findFirstSchemaByLocalName(String localName, Set<DataSchemaNode> schemas) {
141 for (schema : schemas) {
142 if (schema instanceof ChoiceNode) {
143 for (caze : (schema as ChoiceNode).cases) {
144 val result = findFirstSchemaByLocalName(localName, caze.childNodes)
145 if (result !== null) {
150 return schemas.findFirst[n|n.QName.localName.equals(localName)]