2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.sal.restconf.impl;
10 import com.google.common.base.Objects;
11 import com.google.common.base.Preconditions;
12 import com.google.common.base.Predicate;
13 import com.google.common.base.Splitter;
14 import com.google.common.base.Strings;
15 import com.google.common.collect.Iterables;
16 import com.google.common.collect.Lists;
19 import java.text.ParseException;
20 import java.text.SimpleDateFormat;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Date;
24 import java.util.HashMap;
25 import java.util.List;
27 import java.util.concurrent.Future;
29 import javax.ws.rs.core.Response;
30 import javax.ws.rs.core.Response.Status;
31 import javax.ws.rs.core.UriBuilder;
32 import javax.ws.rs.core.UriInfo;
34 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
35 import org.opendaylight.controller.sal.core.api.mount.MountInstance;
36 import org.opendaylight.controller.sal.rest.api.RestconfService;
37 import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
38 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
39 import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
40 import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
41 import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
42 import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
43 import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
44 import org.opendaylight.controller.sal.restconf.impl.ResponseException;
45 import org.opendaylight.controller.sal.restconf.impl.RestCodec;
46 import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
47 import org.opendaylight.controller.sal.restconf.impl.StructuredData;
48 import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
49 import org.opendaylight.controller.sal.streams.listeners.Notificator;
50 import org.opendaylight.controller.sal.streams.websockets.WebSocketServer;
51 import org.opendaylight.yangtools.concepts.Codec;
52 import org.opendaylight.yangtools.yang.common.QName;
53 import org.opendaylight.yangtools.yang.common.RpcResult;
54 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
55 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
56 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder;
57 import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
58 import org.opendaylight.yangtools.yang.data.api.Node;
59 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
60 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
61 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
62 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
63 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
64 import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
65 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
66 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
67 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
68 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
69 import org.opendaylight.yangtools.yang.model.api.Module;
70 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
71 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
72 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
73 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
74 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
75 import org.opendaylight.yangtools.yang.model.util.EmptyType;
76 import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
77 import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
79 @SuppressWarnings("all")
80 public class RestconfImpl implements RestconfService {
81 private final static RestconfImpl INSTANCE = new RestconfImpl();
83 private final static String MOUNT_POINT_MODULE_NAME = "ietf-netconf";
85 private final static SimpleDateFormat REVISION_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
87 private final static String RESTCONF_MODULE_DRAFT02_REVISION = "2013-10-19";
89 private final static String RESTCONF_MODULE_DRAFT02_NAME = "ietf-restconf";
91 private final static String RESTCONF_MODULE_DRAFT02_NAMESPACE = "urn:ietf:params:xml:ns:yang:ietf-restconf";
93 private final static String RESTCONF_MODULE_DRAFT02_RESTCONF_GROUPING_SCHEMA_NODE = "restconf";
95 private final static String RESTCONF_MODULE_DRAFT02_RESTCONF_CONTAINER_SCHEMA_NODE = "restconf";
97 private final static String RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE = "modules";
99 private final static String RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE = "module";
101 private final static String RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE = "streams";
103 private final static String RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE = "stream";
105 private final static String RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE = "operations";
107 private final static String SAL_REMOTE_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote";
109 private final static String SAL_REMOTE_RPC_SUBSRCIBE = "create-data-change-event-subscription";
111 private BrokerFacade broker;
113 private ControllerContext controllerContext;
115 public void setBroker(final BrokerFacade broker) {
116 this.broker = broker;
119 public void setControllerContext(final ControllerContext controllerContext) {
120 this.controllerContext = controllerContext;
123 private RestconfImpl() {
126 public static RestconfImpl getInstance() {
131 public StructuredData getModules() {
132 final Module restconfModule = this.getRestconfModule();
134 final List<Node<?>> modulesAsData = new ArrayList<Node<?>>();
135 final DataSchemaNode moduleSchemaNode =
136 this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
138 Set<Module> allModules = this.controllerContext.getAllModules();
139 for (final Module module : allModules) {
140 CompositeNode moduleCompositeNode = this.toModuleCompositeNode(module, moduleSchemaNode);
141 modulesAsData.add(moduleCompositeNode);
144 final DataSchemaNode modulesSchemaNode =
145 this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
146 QName qName = modulesSchemaNode.getQName();
147 final CompositeNode modulesNode = NodeFactory.createImmutableCompositeNode(qName, null, modulesAsData);
148 return new StructuredData(modulesNode, modulesSchemaNode, null);
152 public StructuredData getAvailableStreams() {
153 Set<String> availableStreams = Notificator.getStreamNames();
155 final List<Node<?>> streamsAsData = new ArrayList<Node<?>>();
156 Module restconfModule = this.getRestconfModule();
157 final DataSchemaNode streamSchemaNode =
158 this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE);
159 for (final String streamName : availableStreams) {
160 streamsAsData.add(this.toStreamCompositeNode(streamName, streamSchemaNode));
163 final DataSchemaNode streamsSchemaNode =
164 this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE);
165 QName qName = streamsSchemaNode.getQName();
166 final CompositeNode streamsNode = NodeFactory.createImmutableCompositeNode(qName, null, streamsAsData);
167 return new StructuredData(streamsNode, streamsSchemaNode, null);
171 public StructuredData getModules(final String identifier) {
172 Set<Module> modules = null;
173 MountInstance mountPoint = null;
174 if (identifier.contains(ControllerContext.MOUNT)) {
175 InstanceIdWithSchemaNode mountPointIdentifier =
176 this.controllerContext.toMountPointIdentifier(identifier);
177 mountPoint = mountPointIdentifier.getMountPoint();
178 modules = this.controllerContext.getAllModules(mountPoint);
181 throw new ResponseException(Status.BAD_REQUEST,
182 "URI has bad format. If modules behind mount point should be showed, URI has to end with " +
183 ControllerContext.MOUNT);
186 final List<Node<?>> modulesAsData = new ArrayList<Node<?>>();
187 Module restconfModule = this.getRestconfModule();
188 final DataSchemaNode moduleSchemaNode =
189 this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
191 for (final Module module : modules) {
192 modulesAsData.add(this.toModuleCompositeNode(module, moduleSchemaNode));
195 final DataSchemaNode modulesSchemaNode =
196 this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
197 QName qName = modulesSchemaNode.getQName();
198 final CompositeNode modulesNode = NodeFactory.createImmutableCompositeNode(qName, null, modulesAsData);
199 return new StructuredData(modulesNode, modulesSchemaNode, mountPoint);
203 public StructuredData getModule(final String identifier) {
204 final QName moduleNameAndRevision = this.getModuleNameAndRevision(identifier);
205 Module module = null;
206 MountInstance mountPoint = null;
207 if (identifier.contains(ControllerContext.MOUNT)) {
208 InstanceIdWithSchemaNode mountPointIdentifier =
209 this.controllerContext.toMountPointIdentifier(identifier);
210 mountPoint = mountPointIdentifier.getMountPoint();
211 module = this.controllerContext.findModuleByNameAndRevision(mountPoint, moduleNameAndRevision);
214 module = this.controllerContext.findModuleByNameAndRevision(moduleNameAndRevision);
217 if (module == null) {
218 throw new ResponseException(Status.BAD_REQUEST,
219 "Module with name '" + moduleNameAndRevision.getLocalName() + "' and revision '" +
220 moduleNameAndRevision.getRevision() + "' was not found.");
223 Module restconfModule = this.getRestconfModule();
224 final DataSchemaNode moduleSchemaNode =
225 this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
226 final CompositeNode moduleNode = this.toModuleCompositeNode(module, moduleSchemaNode);
227 return new StructuredData(moduleNode, moduleSchemaNode, mountPoint);
231 public StructuredData getOperations() {
232 Set<Module> allModules = this.controllerContext.getAllModules();
233 return this.operationsFromModulesToStructuredData(allModules, null);
237 public StructuredData getOperations(final String identifier) {
238 Set<Module> modules = null;
239 MountInstance mountPoint = null;
240 if (identifier.contains(ControllerContext.MOUNT)) {
241 InstanceIdWithSchemaNode mountPointIdentifier =
242 this.controllerContext.toMountPointIdentifier(identifier);
243 mountPoint = mountPointIdentifier.getMountPoint();
244 modules = this.controllerContext.getAllModules(mountPoint);
247 throw new ResponseException(Status.BAD_REQUEST,
248 "URI has bad format. If operations behind mount point should be showed, URI has to end with " +
249 ControllerContext.MOUNT);
252 return this.operationsFromModulesToStructuredData(modules, mountPoint);
255 private StructuredData operationsFromModulesToStructuredData(final Set<Module> modules,
256 final MountInstance mountPoint) {
257 final List<Node<?>> operationsAsData = new ArrayList<Node<?>>();
258 Module restconfModule = this.getRestconfModule();
259 final DataSchemaNode operationsSchemaNode =
260 this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE);
261 QName qName = operationsSchemaNode.getQName();
262 SchemaPath path = operationsSchemaNode.getPath();
263 ContainerSchemaNodeBuilder containerSchemaNodeBuilder =
264 new ContainerSchemaNodeBuilder(RESTCONF_MODULE_DRAFT02_NAME, 0, qName, path);
265 final ContainerSchemaNodeBuilder fakeOperationsSchemaNode = containerSchemaNodeBuilder;
266 for (final Module module : modules) {
267 Set<RpcDefinition> rpcs = module.getRpcs();
268 for (final RpcDefinition rpc : rpcs) {
269 QName rpcQName = rpc.getQName();
270 SimpleNode<Object> immutableSimpleNode =
271 NodeFactory.<Object>createImmutableSimpleNode(rpcQName, null, null);
272 operationsAsData.add(immutableSimpleNode);
274 String name = module.getName();
275 LeafSchemaNodeBuilder leafSchemaNodeBuilder = new LeafSchemaNodeBuilder(name, 0, rpcQName, null);
276 final LeafSchemaNodeBuilder fakeRpcSchemaNode = leafSchemaNodeBuilder;
277 fakeRpcSchemaNode.setAugmenting(true);
279 EmptyType instance = EmptyType.getInstance();
280 fakeRpcSchemaNode.setType(instance);
281 fakeOperationsSchemaNode.addChildNode(fakeRpcSchemaNode.build());
285 final CompositeNode operationsNode =
286 NodeFactory.createImmutableCompositeNode(qName, null, operationsAsData);
287 ContainerSchemaNode schemaNode = fakeOperationsSchemaNode.build();
288 return new StructuredData(operationsNode, schemaNode, mountPoint);
291 private Module getRestconfModule() {
292 QName qName = QName.create(RESTCONF_MODULE_DRAFT02_NAMESPACE, RESTCONF_MODULE_DRAFT02_REVISION,
293 RESTCONF_MODULE_DRAFT02_NAME);
294 final Module restconfModule = this.controllerContext.findModuleByNameAndRevision(qName);
295 if (restconfModule == null) {
296 throw new ResponseException(Status.INTERNAL_SERVER_ERROR, "Restconf module was not found.");
299 return restconfModule;
302 private QName getModuleNameAndRevision(final String identifier) {
303 final int mountIndex = identifier.indexOf(ControllerContext.MOUNT);
304 String moduleNameAndRevision = "";
305 if (mountIndex >= 0) {
306 moduleNameAndRevision = identifier.substring(mountIndex + ControllerContext.MOUNT.length());
309 moduleNameAndRevision = identifier;
312 Splitter splitter = Splitter.on("/").omitEmptyStrings();
313 Iterable<String> split = splitter.split(moduleNameAndRevision);
314 final List<String> pathArgs = Lists.<String>newArrayList(split);
315 if (pathArgs.size() < 2) {
316 throw new ResponseException(Status.BAD_REQUEST,
317 "URI has bad format. End of URI should be in format \'moduleName/yyyy-MM-dd\'");
321 final String moduleName = pathArgs.get( 0 );
322 String revision = pathArgs.get(1);
323 final Date moduleRevision = REVISION_FORMAT.parse(revision);
324 return QName.create(null, moduleRevision, moduleName);
326 catch (ParseException e) {
327 throw new ResponseException(Status.BAD_REQUEST, "URI has bad format. It should be \'moduleName/yyyy-MM-dd\'");
331 private CompositeNode toStreamCompositeNode(final String streamName, final DataSchemaNode streamSchemaNode) {
332 final List<Node<?>> streamNodeValues = new ArrayList<Node<?>>();
333 List<DataSchemaNode> instanceDataChildrenByName =
334 this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) streamSchemaNode),
336 final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
337 streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(nameSchemaNode.getQName(), null,
340 instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
341 ((DataNodeContainer) streamSchemaNode), "description");
342 final DataSchemaNode descriptionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
343 streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(descriptionSchemaNode.getQName(), null,
344 "DESCRIPTION_PLACEHOLDER"));
346 instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
347 ((DataNodeContainer) streamSchemaNode), "replay-support");
348 final DataSchemaNode replaySupportSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
349 streamNodeValues.add(NodeFactory.<Boolean>createImmutableSimpleNode(replaySupportSchemaNode.getQName(), null,
350 Boolean.valueOf(true)));
352 instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
353 ((DataNodeContainer) streamSchemaNode), "replay-log-creation-time");
354 final DataSchemaNode replayLogCreationTimeSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
355 streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(replayLogCreationTimeSchemaNode.getQName(),
358 instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
359 ((DataNodeContainer) streamSchemaNode), "events");
360 final DataSchemaNode eventsSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
361 streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(eventsSchemaNode.getQName(),
364 return NodeFactory.createImmutableCompositeNode(streamSchemaNode.getQName(), null, streamNodeValues);
367 private CompositeNode toModuleCompositeNode(final Module module, final DataSchemaNode moduleSchemaNode) {
368 final List<Node<?>> moduleNodeValues = new ArrayList<Node<?>>();
369 List<DataSchemaNode> instanceDataChildrenByName =
370 this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) moduleSchemaNode), "name");
371 final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
372 moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(nameSchemaNode.getQName(),
373 null, module.getName()));
375 instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
376 ((DataNodeContainer) moduleSchemaNode), "revision");
377 final DataSchemaNode revisionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
378 Date _revision = module.getRevision();
379 moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(revisionSchemaNode.getQName(), null,
380 REVISION_FORMAT.format(_revision)));
382 instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
383 ((DataNodeContainer) moduleSchemaNode), "namespace");
384 final DataSchemaNode namespaceSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
385 moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(namespaceSchemaNode.getQName(), null,
386 module.getNamespace().toString()));
388 instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
389 ((DataNodeContainer) moduleSchemaNode), "feature");
390 final DataSchemaNode featureSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
391 for (final FeatureDefinition feature : module.getFeatures()) {
392 moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(featureSchemaNode.getQName(), null,
393 feature.getQName().getLocalName()));
396 return NodeFactory.createImmutableCompositeNode(moduleSchemaNode.getQName(), null, moduleNodeValues);
399 private DataSchemaNode getSchemaNode(final Module restconfModule, final String schemaNodeName) {
400 Set<GroupingDefinition> groupings = restconfModule.getGroupings();
402 final Predicate<GroupingDefinition> filter = new Predicate<GroupingDefinition>() {
404 public boolean apply(final GroupingDefinition g) {
405 return Objects.equal(g.getQName().getLocalName(),
406 RESTCONF_MODULE_DRAFT02_RESTCONF_GROUPING_SCHEMA_NODE);
410 Iterable<GroupingDefinition> filteredGroups = Iterables.filter(groupings, filter);
412 final GroupingDefinition restconfGrouping = Iterables.getFirst(filteredGroups, null);
414 List<DataSchemaNode> instanceDataChildrenByName =
415 this.controllerContext.findInstanceDataChildrenByName(restconfGrouping,
416 RESTCONF_MODULE_DRAFT02_RESTCONF_CONTAINER_SCHEMA_NODE);
417 final DataSchemaNode restconfContainer = Iterables.getFirst(instanceDataChildrenByName, null);
419 if (Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE)) {
420 List<DataSchemaNode> instances =
421 this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
422 RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE);
423 return Iterables.getFirst(instances, null);
425 else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE)) {
426 List<DataSchemaNode> instances =
427 this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
428 RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE);
429 return Iterables.getFirst(instances, null);
431 else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE)) {
432 List<DataSchemaNode> instances =
433 this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
434 RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE);
435 final DataSchemaNode modules = Iterables.getFirst(instances, null);
436 instances = this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) modules),
437 RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE);
438 return Iterables.getFirst(instances, null);
440 else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE)) {
441 List<DataSchemaNode> instances =
442 this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
443 RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
444 return Iterables.getFirst(instances, null);
446 else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE)) {
447 List<DataSchemaNode> instances =
448 this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
449 RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
450 final DataSchemaNode modules = Iterables.getFirst(instances, null);
451 instances = this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) modules),
452 RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
453 return Iterables.getFirst(instances, null);
460 public Object getRoot() {
465 public StructuredData invokeRpc(final String identifier, final CompositeNode payload) {
466 final RpcDefinition rpc = this.resolveIdentifierInInvokeRpc(identifier);
467 if (Objects.equal(rpc.getQName().getNamespace().toString(), SAL_REMOTE_NAMESPACE) &&
468 Objects.equal(rpc.getQName().getLocalName(), SAL_REMOTE_RPC_SUBSRCIBE)) {
470 final CompositeNode value = this.normalizeNode(payload, rpc.getInput(), null);
471 final SimpleNode<? extends Object> pathNode = value == null ? null :
472 value.getFirstSimpleByName( QName.create(rpc.getQName(), "path") );
473 final Object pathValue = pathNode == null ? null : pathNode.getValue();
475 if (!(pathValue instanceof InstanceIdentifier)) {
476 throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
477 "Instance identifier was not normalized correctly.");
480 final InstanceIdentifier pathIdentifier = ((InstanceIdentifier) pathValue);
481 String streamName = null;
482 if (!Iterables.isEmpty(pathIdentifier.getPath())) {
483 String fullRestconfIdentifier = this.controllerContext.toFullRestconfIdentifier(pathIdentifier);
484 streamName = Notificator.createStreamNameFromUri(fullRestconfIdentifier);
487 if (Strings.isNullOrEmpty(streamName)) {
488 throw new ResponseException(Status.BAD_REQUEST,
489 "Path is empty or contains data node which is not Container or List build-in type.");
492 final SimpleNode<String> streamNameNode = NodeFactory.<String>createImmutableSimpleNode(
493 QName.create(rpc.getOutput().getQName(), "stream-name"), null, streamName);
494 final List<Node<?>> output = new ArrayList<Node<?>>();
495 output.add(streamNameNode);
497 final MutableCompositeNode responseData = NodeFactory.createMutableCompositeNode(
498 rpc.getOutput().getQName(), null, output, null, null);
500 if (!Notificator.existListenerFor(pathIdentifier)) {
501 Notificator.createListener(pathIdentifier, streamName);
504 return new StructuredData(responseData, rpc.getOutput(), null);
507 RpcDefinition rpcDefinition = this.controllerContext.getRpcDefinition(identifier);
508 return this.callRpc(rpcDefinition, payload);
512 public StructuredData invokeRpc(final String identifier, final String noPayload) {
513 if (!Strings.isNullOrEmpty(noPayload)) {
514 throw new ResponseException(Status.UNSUPPORTED_MEDIA_TYPE,
515 "Content-Type contains unsupported Media Type.");
518 final RpcDefinition rpc = this.resolveIdentifierInInvokeRpc(identifier);
519 return this.callRpc(rpc, null);
522 private RpcDefinition resolveIdentifierInInvokeRpc(final String identifier) {
523 if (identifier.indexOf("/") < 0) {
524 final String identifierDecoded = this.controllerContext.urlPathArgDecode(identifier);
525 final RpcDefinition rpc = this.controllerContext.getRpcDefinition(identifierDecoded);
530 throw new ResponseException(Status.NOT_FOUND, "RPC does not exist.");
533 final String slashErrorMsg = String.format(
534 "Identifier %n%s%ncan\'t contain slash character (/).%nIf slash is part of identifier name then use %%2F placeholder.",
537 throw new ResponseException(Status.NOT_FOUND, slashErrorMsg);
540 private StructuredData callRpc(final RpcDefinition rpc, final CompositeNode payload) {
542 throw new ResponseException(Status.NOT_FOUND, "RPC does not exist.");
545 CompositeNode rpcRequest = null;
546 if (payload == null) {
547 rpcRequest = NodeFactory.createMutableCompositeNode(rpc.getQName(), null, null, null, null);
550 final CompositeNode value = this.normalizeNode(payload, rpc.getInput(), null);
551 final List<Node<?>> input = new ArrayList<Node<?>>();
554 rpcRequest = NodeFactory.createMutableCompositeNode(rpc.getQName(), null, input, null, null);
557 final RpcResult<CompositeNode> rpcResult = broker.invokeRpc(rpc.getQName(), rpcRequest);
559 if (!rpcResult.isSuccessful()) {
560 throw new ResponseException(Status.INTERNAL_SERVER_ERROR, "Operation failed");
563 CompositeNode result = rpcResult.getResult();
564 if (result == null) {
568 return new StructuredData(result, rpc.getOutput(), null);
572 public StructuredData readConfigurationData(final String identifier) {
573 final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
574 CompositeNode data = null;
575 MountInstance mountPoint = iiWithData.getMountPoint();
576 if (mountPoint != null) {
577 data = broker.readConfigurationDataBehindMountPoint(mountPoint, iiWithData.getInstanceIdentifier());
580 data = broker.readConfigurationData(iiWithData.getInstanceIdentifier());
583 return new StructuredData(data, iiWithData.getSchemaNode(), iiWithData.getMountPoint());
587 public StructuredData readOperationalData(final String identifier) {
588 final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
589 CompositeNode data = null;
590 MountInstance mountPoint = iiWithData.getMountPoint();
591 if (mountPoint != null) {
592 data = broker.readOperationalDataBehindMountPoint(mountPoint, iiWithData.getInstanceIdentifier());
595 data = broker.readOperationalData(iiWithData.getInstanceIdentifier());
598 return new StructuredData(data, iiWithData.getSchemaNode(), mountPoint);
602 public Response updateConfigurationData(final String identifier, final CompositeNode payload) {
603 final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
604 MountInstance mountPoint = iiWithData.getMountPoint();
605 final CompositeNode value = this.normalizeNode(payload, iiWithData.getSchemaNode(), mountPoint);
606 RpcResult<TransactionStatus> status = null;
609 if (mountPoint != null) {
610 status = broker.commitConfigurationDataPutBehindMountPoint(
611 mountPoint, iiWithData.getInstanceIdentifier(), value).get();
613 status = broker.commitConfigurationDataPut(iiWithData.getInstanceIdentifier(), value).get();
616 catch( Exception e ) {
617 throw new ResponseException( e, "Error updating data" );
620 if( status.getResult() == TransactionStatus.COMMITED )
621 return Response.status(Status.OK).build();
623 return Response.status(Status.INTERNAL_SERVER_ERROR).build();
627 public Response createConfigurationData(final String identifier, final CompositeNode payload) {
628 URI payloadNS = this.namespace(payload);
629 if (payloadNS == null) {
630 throw new ResponseException(Status.BAD_REQUEST,
631 "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)");
634 InstanceIdWithSchemaNode iiWithData = null;
635 CompositeNode value = null;
636 if (this.representsMountPointRootData(payload)) {
637 // payload represents mount point data and URI represents path to the mount point
639 if (this.endsWithMountPoint(identifier)) {
640 throw new ResponseException(Status.BAD_REQUEST,
641 "URI has bad format. URI should be without \"" + ControllerContext.MOUNT +
642 "\" for POST operation.");
645 final String completeIdentifier = this.addMountPointIdentifier(identifier);
646 iiWithData = this.controllerContext.toInstanceIdentifier(completeIdentifier);
648 value = this.normalizeNode(payload, iiWithData.getSchemaNode(), iiWithData.getMountPoint());
651 final InstanceIdWithSchemaNode incompleteInstIdWithData =
652 this.controllerContext.toInstanceIdentifier(identifier);
653 final DataNodeContainer parentSchema = (DataNodeContainer) incompleteInstIdWithData.getSchemaNode();
654 MountInstance mountPoint = incompleteInstIdWithData.getMountPoint();
655 final Module module = this.findModule(mountPoint, payload);
656 if (module == null) {
657 throw new ResponseException(Status.BAD_REQUEST,
658 "Module was not found for \"" + payloadNS + "\"");
661 String payloadName = this.getName(payload);
662 final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(
663 parentSchema, payloadName, module.getNamespace());
664 value = this.normalizeNode(payload, schemaNode, mountPoint);
666 iiWithData = this.addLastIdentifierFromData(incompleteInstIdWithData, value, schemaNode);
669 RpcResult<TransactionStatus> status = null;
670 MountInstance mountPoint = iiWithData.getMountPoint();
672 if (mountPoint != null) {
673 Future<RpcResult<TransactionStatus>> future =
674 broker.commitConfigurationDataPostBehindMountPoint(
675 mountPoint, iiWithData.getInstanceIdentifier(), value);
676 status = future == null ? null : future.get();
679 Future<RpcResult<TransactionStatus>> future =
680 broker.commitConfigurationDataPost(iiWithData.getInstanceIdentifier(), value);
681 status = future == null ? null : future.get();
684 catch( Exception e ) {
685 throw new ResponseException( e, "Error creating data" );
688 if (status == null) {
689 return Response.status(Status.ACCEPTED).build();
692 if( status.getResult() == TransactionStatus.COMMITED )
693 return Response.status(Status.NO_CONTENT).build();
695 return Response.status(Status.INTERNAL_SERVER_ERROR).build();
699 public Response createConfigurationData(final CompositeNode payload) {
700 URI payloadNS = this.namespace(payload);
701 if (payloadNS == null) {
702 throw new ResponseException(Status.BAD_REQUEST,
703 "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)");
706 final Module module = this.findModule(null, payload);
707 if (module == null) {
708 throw new ResponseException(Status.BAD_REQUEST,
709 "Data has bad format. Root element node has incorrect namespace (XML format) or module name(JSON format)");
712 String payloadName = this.getName(payload);
713 final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(
714 module, payloadName, module.getNamespace());
715 final CompositeNode value = this.normalizeNode(payload, schemaNode, null);
716 final InstanceIdWithSchemaNode iiWithData = this.addLastIdentifierFromData(null, value, schemaNode);
717 RpcResult<TransactionStatus> status = null;
718 MountInstance mountPoint = iiWithData.getMountPoint();
721 if (mountPoint != null) {
722 Future<RpcResult<TransactionStatus>> future =
723 broker.commitConfigurationDataPostBehindMountPoint(
724 mountPoint, iiWithData.getInstanceIdentifier(), value);
725 status = future == null ? null : future.get();
728 Future<RpcResult<TransactionStatus>> future =
729 broker.commitConfigurationDataPost(iiWithData.getInstanceIdentifier(), value);
730 status = future == null ? null : future.get();
733 catch( Exception e ) {
734 throw new ResponseException( e, "Error creating data" );
737 if (status == null) {
738 return Response.status(Status.ACCEPTED).build();
741 if( status.getResult() == TransactionStatus.COMMITED )
742 return Response.status(Status.NO_CONTENT).build();
744 return Response.status(Status.INTERNAL_SERVER_ERROR).build();
748 public Response deleteConfigurationData(final String identifier) {
749 final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
750 RpcResult<TransactionStatus> status = null;
751 MountInstance mountPoint = iiWithData.getMountPoint();
754 if (mountPoint != null) {
755 status = broker.commitConfigurationDataDeleteBehindMountPoint(
756 mountPoint, iiWithData.getInstanceIdentifier()).get();
759 status = broker.commitConfigurationDataDelete(iiWithData.getInstanceIdentifier()).get();
762 catch( Exception e ) {
763 throw new ResponseException( e, "Error creating data" );
766 if( status.getResult() == TransactionStatus.COMMITED )
767 return Response.status(Status.OK).build();
769 return Response.status(Status.INTERNAL_SERVER_ERROR).build();
773 public Response subscribeToStream(final String identifier, final UriInfo uriInfo) {
774 final String streamName = Notificator.createStreamNameFromUri(identifier);
775 if (Strings.isNullOrEmpty(streamName)) {
776 throw new ResponseException(Status.BAD_REQUEST, "Stream name is empty.");
779 final ListenerAdapter listener = Notificator.getListenerFor(streamName);
780 if (listener == null) {
781 throw new ResponseException(Status.BAD_REQUEST, "Stream was not found.");
784 broker.registerToListenDataChanges(listener);
786 final UriBuilder uriBuilder = uriInfo.getAbsolutePathBuilder();
787 UriBuilder port = uriBuilder.port(WebSocketServer.PORT);
788 final URI uriToWebsocketServer = port.replacePath(streamName).build();
790 return Response.status(Status.OK).location(uriToWebsocketServer).build();
793 private Module findModule(final MountInstance mountPoint, final CompositeNode data) {
794 if (data instanceof CompositeNodeWrapper) {
795 return findModule(mountPoint, (CompositeNodeWrapper)data);
797 else if (data != null) {
798 URI namespace = data.getNodeType().getNamespace();
799 if (mountPoint != null) {
800 return this.controllerContext.findModuleByNamespace(mountPoint, namespace);
803 return this.controllerContext.findModuleByNamespace(namespace);
807 throw new IllegalArgumentException("Unhandled parameter types: " +
808 Arrays.<Object>asList(mountPoint, data).toString());
812 private Module findModule(final MountInstance mountPoint, final CompositeNodeWrapper data) {
813 URI namespace = data.getNamespace();
814 Preconditions.<URI>checkNotNull(namespace);
816 Module module = null;
817 if (mountPoint != null) {
818 module = this.controllerContext.findModuleByNamespace(mountPoint, namespace);
819 if (module == null) {
820 module = this.controllerContext.findModuleByName(mountPoint, namespace.toString());
824 module = this.controllerContext.findModuleByNamespace(namespace);
825 if (module == null) {
826 module = this.controllerContext.findModuleByName(namespace.toString());
833 private InstanceIdWithSchemaNode addLastIdentifierFromData(
834 final InstanceIdWithSchemaNode identifierWithSchemaNode,
835 final CompositeNode data, final DataSchemaNode schemaOfData) {
836 InstanceIdentifier instanceIdentifier = null;
837 if (identifierWithSchemaNode != null) {
838 instanceIdentifier = identifierWithSchemaNode.getInstanceIdentifier();
841 final InstanceIdentifier iiOriginal = instanceIdentifier;
842 InstanceIdentifierBuilder iiBuilder = null;
843 if (iiOriginal == null) {
844 iiBuilder = InstanceIdentifier.builder();
847 iiBuilder = InstanceIdentifier.builder(iiOriginal);
850 if ((schemaOfData instanceof ListSchemaNode)) {
851 HashMap<QName,Object> keys = this.resolveKeysFromData(((ListSchemaNode) schemaOfData), data);
852 iiBuilder.nodeWithKey(schemaOfData.getQName(), keys);
855 iiBuilder.node(schemaOfData.getQName());
858 InstanceIdentifier instance = iiBuilder.toInstance();
859 MountInstance mountPoint = null;
860 if (identifierWithSchemaNode != null) {
861 mountPoint=identifierWithSchemaNode.getMountPoint();
864 return new InstanceIdWithSchemaNode(instance, schemaOfData, mountPoint);
867 private HashMap<QName,Object> resolveKeysFromData(final ListSchemaNode listNode,
868 final CompositeNode dataNode) {
869 final HashMap<QName,Object> keyValues = new HashMap<QName, Object>();
870 List<QName> _keyDefinition = listNode.getKeyDefinition();
871 for (final QName key : _keyDefinition) {
872 SimpleNode<? extends Object> head = null;
873 String localName = key.getLocalName();
874 List<SimpleNode<? extends Object>> simpleNodesByName = dataNode.getSimpleNodesByName(localName);
875 if (simpleNodesByName != null) {
876 head = Iterables.getFirst(simpleNodesByName, null);
879 Object dataNodeKeyValueObject = null;
881 dataNodeKeyValueObject = head.getValue();
884 if (dataNodeKeyValueObject == null) {
885 throw new ResponseException(Status.BAD_REQUEST,
886 "Data contains list \"" + dataNode.getNodeType().getLocalName() +
887 "\" which does not contain key: \"" + key.getLocalName() + "\"");
890 keyValues.put(key, dataNodeKeyValueObject);
896 private boolean endsWithMountPoint(final String identifier) {
897 return identifier.endsWith(ControllerContext.MOUNT) ||
898 identifier.endsWith(ControllerContext.MOUNT + "/");
901 private boolean representsMountPointRootData(final CompositeNode data) {
902 URI namespace = this.namespace(data);
903 return (SchemaContext.NAME.getNamespace().equals( namespace ) /* ||
904 MOUNT_POINT_MODULE_NAME.equals( namespace.toString() )*/ ) &&
905 SchemaContext.NAME.getLocalName().equals( this.localName(data) );
908 private String addMountPointIdentifier(final String identifier) {
909 boolean endsWith = identifier.endsWith("/");
911 return (identifier + ControllerContext.MOUNT);
914 return identifier + "/" + ControllerContext.MOUNT;
917 private CompositeNode normalizeNode(final CompositeNode node, final DataSchemaNode schema,
918 final MountInstance mountPoint) {
919 if (schema == null) {
920 QName nodeType = node == null ? null : node.getNodeType();
921 String localName = nodeType == null ? null : nodeType.getLocalName();
922 String _plus = ("Data schema node was not found for " + localName);
923 throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
924 "Data schema node was not found for " + localName );
927 if (!(schema instanceof DataNodeContainer)) {
928 throw new ResponseException(Status.BAD_REQUEST,
929 "Root element has to be container or list yang datatype.");
932 if ((node instanceof CompositeNodeWrapper)) {
933 boolean isChangeAllowed = ((CompositeNodeWrapper) node).isChangeAllowed();
934 if (isChangeAllowed) {
936 this.normalizeNode(((CompositeNodeWrapper) node), schema, null, mountPoint);
938 catch (NumberFormatException e) {
939 throw new ResponseException(Status.BAD_REQUEST, e.getMessage());
943 return ((CompositeNodeWrapper) node).unwrap();
949 private void normalizeNode(final NodeWrapper<? extends Object> nodeBuilder,
950 final DataSchemaNode schema, final QName previousAugment,
951 final MountInstance mountPoint) {
952 if (schema == null) {
953 throw new ResponseException(Status.BAD_REQUEST,
954 "Data has bad format.\n\"" + nodeBuilder.getLocalName() +
955 "\" does not exist in yang schema.");
958 QName currentAugment = null;
959 if (nodeBuilder.getQname() != null) {
960 currentAugment = previousAugment;
963 currentAugment = this.normalizeNodeName(nodeBuilder, schema, previousAugment, mountPoint);
964 if (nodeBuilder.getQname() == null) {
965 throw new ResponseException(Status.BAD_REQUEST,
966 "Data has bad format.\nIf data is in XML format then namespace for \"" +
967 nodeBuilder.getLocalName() +
968 "\" should be \"" + schema.getQName().getNamespace() + "\".\n" +
969 "If data is in JSON format then module name for \"" + nodeBuilder.getLocalName() +
970 "\" should be corresponding to namespace \"" +
971 schema.getQName().getNamespace() + "\".");
975 if ((nodeBuilder instanceof CompositeNodeWrapper)) {
976 final List<NodeWrapper<?>> children = ((CompositeNodeWrapper) nodeBuilder).getValues();
977 for (final NodeWrapper<? extends Object> child : children) {
978 final List<DataSchemaNode> potentialSchemaNodes =
979 this.controllerContext.findInstanceDataChildrenByName(
980 ((DataNodeContainer) schema), child.getLocalName());
982 if (potentialSchemaNodes.size() > 1 && child.getNamespace() == null) {
983 StringBuilder builder = new StringBuilder();
984 for (final DataSchemaNode potentialSchemaNode : potentialSchemaNodes) {
985 builder.append(" ").append(potentialSchemaNode.getQName().getNamespace().toString())
989 throw new ResponseException(Status.BAD_REQUEST,
990 "Node \"" + child.getLocalName() +
991 "\" is added as augment from more than one module. " +
992 "Therefore node must have namespace (XML format) or module name (JSON format)." +
993 "\nThe node is added as augment from modules with namespaces:\n" + builder);
996 boolean rightNodeSchemaFound = false;
997 for (final DataSchemaNode potentialSchemaNode : potentialSchemaNodes) {
998 if (!rightNodeSchemaFound) {
999 final QName potentialCurrentAugment =
1000 this.normalizeNodeName(child, potentialSchemaNode, currentAugment, mountPoint);
1001 if (child.getQname() != null ) {
1002 this.normalizeNode(child, potentialSchemaNode, potentialCurrentAugment, mountPoint);
1003 rightNodeSchemaFound = true;
1008 if (!rightNodeSchemaFound) {
1009 throw new ResponseException(Status.BAD_REQUEST,
1010 "Schema node \"" + child.getLocalName() + "\" was not found in module.");
1014 if ((schema instanceof ListSchemaNode)) {
1015 final List<QName> listKeys = ((ListSchemaNode) schema).getKeyDefinition();
1016 for (final QName listKey : listKeys) {
1017 boolean foundKey = false;
1018 for (final NodeWrapper<? extends Object> child : children) {
1019 if (Objects.equal(child.unwrap().getNodeType().getLocalName(), listKey.getLocalName())) {
1025 throw new ResponseException(Status.BAD_REQUEST,
1026 "Missing key in URI \"" + listKey.getLocalName() +
1027 "\" of list \"" + schema.getQName().getLocalName() + "\"");
1033 if ((nodeBuilder instanceof SimpleNodeWrapper)) {
1034 final SimpleNodeWrapper simpleNode = ((SimpleNodeWrapper) nodeBuilder);
1035 final Object value = simpleNode.getValue();
1036 Object inputValue = value;
1037 TypeDefinition<? extends Object> typeDefinition = this.typeDefinition(schema);
1038 if ((typeDefinition instanceof IdentityrefTypeDefinition)) {
1039 if ((value instanceof String)) {
1040 inputValue = new IdentityValuesDTO( nodeBuilder.getNamespace().toString(),
1041 (String) value, null, (String) value );
1042 } // else value is already instance of IdentityValuesDTO
1045 Codec<Object,Object> codec = RestCodec.from(typeDefinition, mountPoint);
1046 Object outputValue = codec == null ? null : codec.deserialize(inputValue);
1048 simpleNode.setValue(outputValue);
1051 if ((nodeBuilder instanceof EmptyNodeWrapper)) {
1052 final EmptyNodeWrapper emptyNodeBuilder = ((EmptyNodeWrapper) nodeBuilder);
1053 if ((schema instanceof LeafSchemaNode)) {
1054 emptyNodeBuilder.setComposite(false);
1057 if ((schema instanceof ContainerSchemaNode)) {
1058 // FIXME: Add presence check
1059 emptyNodeBuilder.setComposite(true);
1067 private QName normalizeNodeName(final NodeWrapper<? extends Object> nodeBuilder,
1068 final DataSchemaNode schema, final QName previousAugment,
1069 final MountInstance mountPoint) {
1070 QName validQName = schema.getQName();
1071 QName currentAugment = previousAugment;
1072 if (schema.isAugmenting()) {
1073 currentAugment = schema.getQName();
1075 else if (previousAugment != null &&
1076 !Objects.equal( schema.getQName().getNamespace(), previousAugment.getNamespace())) {
1077 validQName = QName.create(currentAugment, schema.getQName().getLocalName());
1080 String moduleName = null;
1081 if (mountPoint == null) {
1082 moduleName = controllerContext.findModuleNameByNamespace(validQName.getNamespace());
1085 moduleName = controllerContext.findModuleNameByNamespace(mountPoint, validQName.getNamespace());
1088 if (nodeBuilder.getNamespace() == null ||
1089 Objects.equal(nodeBuilder.getNamespace(), validQName.getNamespace()) ||
1090 Objects.equal(nodeBuilder.getNamespace().toString(), moduleName) /*||
1091 Note: this check is wrong - can never be true as it compares a URI with a String
1092 not sure what the intention is so commented out...
1093 Objects.equal(nodeBuilder.getNamespace(), MOUNT_POINT_MODULE_NAME)*/ ) {
1095 nodeBuilder.setQname(validQName);
1098 return currentAugment;
1101 private URI namespace(final CompositeNode data) {
1102 if (data instanceof CompositeNodeWrapper) {
1103 return ((CompositeNodeWrapper)data).getNamespace();
1105 else if (data != null) {
1106 return data.getNodeType().getNamespace();
1109 throw new IllegalArgumentException("Unhandled parameter types: " +
1110 Arrays.<Object>asList(data).toString());
1114 private String localName(final CompositeNode data) {
1115 if (data instanceof CompositeNodeWrapper) {
1116 return ((CompositeNodeWrapper)data).getLocalName();
1118 else if (data != null) {
1119 return data.getNodeType().getLocalName();
1122 throw new IllegalArgumentException("Unhandled parameter types: " +
1123 Arrays.<Object>asList(data).toString());
1127 private String getName(final CompositeNode data) {
1128 if (data instanceof CompositeNodeWrapper) {
1129 return ((CompositeNodeWrapper)data).getLocalName();
1131 else if (data != null) {
1132 return data.getNodeType().getLocalName();
1135 throw new IllegalArgumentException("Unhandled parameter types: " +
1136 Arrays.<Object>asList(data).toString());
1140 private TypeDefinition<? extends Object> _typeDefinition(final LeafSchemaNode node) {
1141 TypeDefinition<?> baseType = node.getType();
1142 while (baseType.getBaseType() != null) {
1143 baseType = baseType.getBaseType();
1149 private TypeDefinition<? extends Object> typeDefinition(final LeafListSchemaNode node) {
1150 TypeDefinition<?> baseType = node.getType();
1151 while (baseType.getBaseType() != null) {
1152 baseType = baseType.getBaseType();
1158 private TypeDefinition<? extends Object> typeDefinition(final DataSchemaNode node) {
1159 if (node instanceof LeafListSchemaNode) {
1160 return typeDefinition((LeafListSchemaNode)node);
1162 else if (node instanceof LeafSchemaNode) {
1163 return _typeDefinition((LeafSchemaNode)node);
1166 throw new IllegalArgumentException("Unhandled parameter types: " +
1167 Arrays.<Object>asList(node).toString());