ArpHandler to ignore ip packet sent to default GW
[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.ArrayList
4 import java.util.List
5 import java.util.Set
6 import javax.ws.rs.core.Response
7 import org.opendaylight.controller.md.sal.common.api.TransactionStatus
8 import org.opendaylight.controller.sal.rest.api.RestconfService
9 import org.opendaylight.yangtools.yang.common.QName
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.impl.NodeFactory
13 import org.opendaylight.yangtools.yang.model.api.ChoiceNode
14 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
15 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
16 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
17 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
18 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
19 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
20 import org.opendaylight.yangtools.yang.model.api.TypeDefinition
21 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition
22
23 import static javax.ws.rs.core.Response.Status.*
24
25 class RestconfImpl implements RestconfService {
26
27     val static RestconfImpl INSTANCE = new RestconfImpl
28
29     @Property
30     BrokerFacade broker
31
32     @Property
33     extension ControllerContext controllerContext
34
35     private new() {
36         if (INSTANCE !== null) {
37             throw new IllegalStateException("Already instantiated");
38         }
39     }
40
41     static def getInstance() {
42         return INSTANCE
43     }
44
45     override readAllData() {
46 //        return broker.readOperationalData("".toInstanceIdentifier.getInstanceIdentifier);
47         throw new UnsupportedOperationException("Reading all data is currently not supported.")
48     }
49
50     override getModules() {
51         throw new UnsupportedOperationException("TODO: auto-generated method stub")
52     }
53
54     override getRoot() {
55         return null;
56     }
57
58     override readData(String identifier) {
59         val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
60         val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
61         return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
62     }
63
64     override createConfigurationData(String identifier, CompositeNode payload) {
65         val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
66         val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode)
67         val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier, value).get();
68         switch status.result {
69             case TransactionStatus.COMMITED: Response.status(NO_CONTENT).build
70             default: Response.status(INTERNAL_SERVER_ERROR).build
71         }
72     }
73
74     override updateConfigurationData(String identifier, CompositeNode payload) {
75         val identifierWithSchemaNode = identifier.resolveInstanceIdentifier
76         val value = normalizeNode(payload, identifierWithSchemaNode.schemaNode)
77         val status = broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier, value).get();
78         switch status.result {
79             case TransactionStatus.COMMITED: Response.status(OK).build
80             default: Response.status(INTERNAL_SERVER_ERROR).build
81         }
82     }
83
84     override invokeRpc(String identifier, CompositeNode payload) {
85         val rpc = identifier.rpcDefinition
86         if (rpc === null) {
87             throw new ResponseException(NOT_FOUND, "RPC does not exist.");
88         }
89         val value = normalizeNode(payload, rpc.input)
90         val List<Node<?>> input = new ArrayList
91         input.add(value)
92         val rpcRequest = NodeFactory.createMutableCompositeNode(rpc.QName, null, input, null, null)
93         val rpcResult = broker.invokeRpc(rpc.QName, rpcRequest);
94         if (!rpcResult.successful) {
95             throw new ResponseException(INTERNAL_SERVER_ERROR, "Operation failed")
96         }
97         if (rpcResult.result === null) {
98             return null
99         }
100         return new StructuredData(rpcResult.result, rpc.output)
101     }
102
103     override readConfigurationData(String identifier) {
104         val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
105         val data = broker.readConfigurationData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
106         return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
107     }
108
109     override readOperationalData(String identifier) {
110         val instanceIdentifierWithSchemaNode = identifier.resolveInstanceIdentifier
111         val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
112         return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
113     }
114
115     override updateConfigurationDataLegacy(String identifier, CompositeNode payload) {
116         updateConfigurationData(identifier, payload);
117     }
118
119     override createConfigurationDataLegacy(String identifier, CompositeNode payload) {
120         createConfigurationData(identifier, payload);
121     }
122
123     private def InstanceIdWithSchemaNode resolveInstanceIdentifier(String identifier) {
124         val identifierWithSchemaNode = identifier.toInstanceIdentifier
125         if (identifierWithSchemaNode === null) {
126             throw new ResponseException(BAD_REQUEST, "URI has bad format");
127         }
128         return identifierWithSchemaNode
129     }
130
131     private def CompositeNode normalizeNode(CompositeNode node, DataSchemaNode schema) {
132         if (node instanceof CompositeNodeWrapper) {
133             normalizeNode(node as CompositeNodeWrapper, schema, null)
134             return (node as CompositeNodeWrapper).unwrap()
135         }
136         return node
137     }
138
139     private def void normalizeNode(NodeWrapper<?> nodeBuilder, DataSchemaNode schema, QName previousAugment) {
140         if (schema === null) {
141             throw new ResponseException(BAD_REQUEST,
142                 "Data has bad format\n" + nodeBuilder.localName + " does not exist in yang schema.");
143         }
144         var validQName = schema.QName
145         var currentAugment = previousAugment;
146         if (schema.augmenting) {
147             currentAugment = schema.QName
148         } else if (previousAugment !== null && schema.QName.namespace !== previousAugment.namespace) {
149             validQName = QName.create(currentAugment, schema.QName.localName);
150         }
151         val moduleName = controllerContext.findModuleByNamespace(validQName.namespace);
152         if (nodeBuilder.namespace === null || nodeBuilder.namespace == validQName.namespace ||
153             nodeBuilder.namespace.toString == moduleName) {
154             nodeBuilder.qname = validQName
155         } else {
156             throw new ResponseException(BAD_REQUEST,
157                 "Data has bad format\nIf data is in XML format then namespace for " + nodeBuilder.localName +
158                     " should be " + schema.QName.namespace + ".\n If data is in Json format then module name for " +
159                     nodeBuilder.localName + " should be " + moduleName + ".");
160         }
161
162         if (nodeBuilder instanceof CompositeNodeWrapper) {
163             val List<NodeWrapper<?>> children = (nodeBuilder as CompositeNodeWrapper).getValues
164             for (child : children) {
165                 normalizeNode(child,
166                     findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes),
167                     currentAugment)
168             }
169             if(schema instanceof ListSchemaNode) {
170                 val listKeys = (schema as ListSchemaNode).keyDefinition
171                 for (listKey : listKeys) {
172                     var foundKey = false
173                     for (child : children) {
174                         if (child.unwrap.nodeType.localName == listKey.localName) {
175                             foundKey = true;
176                         }
177                     }
178                     if (!foundKey) {
179                         throw new ResponseException(BAD_REQUEST,
180                             "Missing key \"" + listKey.localName + "\" of list \"" + schema.QName.localName + "\"")
181                     }
182                 }
183             }
184         } else if (nodeBuilder instanceof SimpleNodeWrapper) {
185             val simpleNode = (nodeBuilder as SimpleNodeWrapper)
186             val value = simpleNode.value
187             var inputValue = value;
188             
189             if (schema.typeDefinition instanceof IdentityrefTypeDefinition) {
190                 if (value instanceof String) {
191                     inputValue = new IdentityValuesDTO(validQName.namespace.toString, value as String, null)
192                 } // else value is instance of ValuesDTO
193             }
194             
195             val outputValue = RestCodec.from(schema.typeDefinition)?.deserialize(inputValue);
196             simpleNode.setValue(outputValue)
197         } else if (nodeBuilder instanceof EmptyNodeWrapper) {
198             val emptyNodeBuilder = nodeBuilder as EmptyNodeWrapper
199             if (schema instanceof LeafSchemaNode) {
200                 emptyNodeBuilder.setComposite(false);
201             } else if (schema instanceof ContainerSchemaNode) {
202
203                 // FIXME: Add presence check
204                 emptyNodeBuilder.setComposite(true);
205             }
206         }
207     }
208
209     private def dispatch TypeDefinition<?> typeDefinition(LeafSchemaNode node) {
210         var baseType = node.type
211         while (baseType.baseType !== null) {
212             baseType = baseType.baseType;
213         }
214         baseType
215     }
216
217     private def dispatch TypeDefinition<?> typeDefinition(LeafListSchemaNode node) {
218         var TypeDefinition<?> baseType = node.type
219         while (baseType.baseType !== null) {
220             baseType = baseType.baseType;
221         }
222         baseType
223     }
224
225     private def DataSchemaNode findFirstSchemaByLocalName(String localName, Set<DataSchemaNode> schemas) {
226         for (schema : schemas) {
227             if (schema instanceof ChoiceNode) {
228                 for (caze : (schema as ChoiceNode).cases) {
229                     val result = findFirstSchemaByLocalName(localName, caze.childNodes)
230                     if (result !== null) {
231                         return result
232                     }
233                 }
234             } else {
235                 val result = schemas.findFirst[n|n.QName.localName.equals(localName)]
236                 if (result !== null) {
237                     return result;
238
239                 }
240             }
241         }
242         return null
243     }
244
245 }