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;
11 import java.text.ParseException;
12 import java.text.SimpleDateFormat;
13 import java.util.ArrayList;
14 import java.util.Arrays;
15 import java.util.Date;
16 import java.util.HashMap;
17 import java.util.List;
19 import java.util.concurrent.Future;
21 import javax.ws.rs.core.Response;
22 import javax.ws.rs.core.Response.Status;
23 import javax.ws.rs.core.UriBuilder;
24 import javax.ws.rs.core.UriInfo;
26 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
27 import org.opendaylight.controller.sal.core.api.mount.MountInstance;
28 import org.opendaylight.controller.sal.rest.api.RestconfService;
29 import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
30 import org.opendaylight.controller.sal.streams.listeners.Notificator;
31 import org.opendaylight.controller.sal.streams.websockets.WebSocketServer;
32 import org.opendaylight.yangtools.concepts.Codec;
33 import org.opendaylight.yangtools.yang.common.QName;
34 import org.opendaylight.yangtools.yang.common.RpcResult;
35 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
36 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
37 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder;
38 import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
39 import org.opendaylight.yangtools.yang.data.api.Node;
40 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
41 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
42 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
43 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
44 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
45 import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
46 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
47 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
48 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
49 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
50 import org.opendaylight.yangtools.yang.model.api.Module;
51 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
52 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
53 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
54 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
55 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
56 import org.opendaylight.yangtools.yang.model.util.EmptyType;
57 import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
58 import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
60 import com.google.common.base.Objects;
61 import com.google.common.base.Preconditions;
62 import com.google.common.base.Predicate;
63 import com.google.common.base.Splitter;
64 import com.google.common.base.Strings;
65 import com.google.common.collect.Iterables;
66 import com.google.common.collect.Lists;
68 @SuppressWarnings("all")
69 public class RestconfImpl implements RestconfService {
70 private final static RestconfImpl INSTANCE = new RestconfImpl();
72 private final static String MOUNT_POINT_MODULE_NAME = "ietf-netconf";
74 private final static SimpleDateFormat REVISION_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
76 private final static String RESTCONF_MODULE_DRAFT02_REVISION = "2013-10-19";
78 private final static String RESTCONF_MODULE_DRAFT02_NAME = "ietf-restconf";
80 private final static String RESTCONF_MODULE_DRAFT02_NAMESPACE = "urn:ietf:params:xml:ns:yang:ietf-restconf";
82 private final static String RESTCONF_MODULE_DRAFT02_RESTCONF_GROUPING_SCHEMA_NODE = "restconf";
84 private final static String RESTCONF_MODULE_DRAFT02_RESTCONF_CONTAINER_SCHEMA_NODE = "restconf";
86 private final static String RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE = "modules";
88 private final static String RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE = "module";
90 private final static String RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE = "streams";
92 private final static String RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE = "stream";
94 private final static String RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE = "operations";
96 private final static String SAL_REMOTE_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote";
98 private final static String SAL_REMOTE_RPC_SUBSRCIBE = "create-data-change-event-subscription";
100 private BrokerFacade broker;
102 private ControllerContext controllerContext;
104 public void setBroker(final BrokerFacade broker) {
105 this.broker = broker;
108 public void setControllerContext(final ControllerContext controllerContext) {
109 this.controllerContext = controllerContext;
112 private RestconfImpl() {
115 public static RestconfImpl getInstance() {
120 public StructuredData getModules() {
121 final Module restconfModule = this.getRestconfModule();
123 final List<Node<?>> modulesAsData = new ArrayList<Node<?>>();
124 final DataSchemaNode moduleSchemaNode =
125 this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
127 Set<Module> allModules = this.controllerContext.getAllModules();
128 for (final Module module : allModules) {
129 CompositeNode moduleCompositeNode = this.toModuleCompositeNode(module, moduleSchemaNode);
130 modulesAsData.add(moduleCompositeNode);
133 final DataSchemaNode modulesSchemaNode =
134 this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
135 QName qName = modulesSchemaNode.getQName();
136 final CompositeNode modulesNode = NodeFactory.createImmutableCompositeNode(qName, null, modulesAsData);
137 return new StructuredData(modulesNode, modulesSchemaNode, null);
141 public StructuredData getAvailableStreams() {
142 Set<String> availableStreams = Notificator.getStreamNames();
144 final List<Node<?>> streamsAsData = new ArrayList<Node<?>>();
145 Module restconfModule = this.getRestconfModule();
146 final DataSchemaNode streamSchemaNode =
147 this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE);
148 for (final String streamName : availableStreams) {
149 streamsAsData.add(this.toStreamCompositeNode(streamName, streamSchemaNode));
152 final DataSchemaNode streamsSchemaNode =
153 this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE);
154 QName qName = streamsSchemaNode.getQName();
155 final CompositeNode streamsNode = NodeFactory.createImmutableCompositeNode(qName, null, streamsAsData);
156 return new StructuredData(streamsNode, streamsSchemaNode, null);
160 public StructuredData getModules(final String identifier) {
161 Set<Module> modules = null;
162 MountInstance mountPoint = null;
163 if (identifier.contains(ControllerContext.MOUNT)) {
164 InstanceIdWithSchemaNode mountPointIdentifier =
165 this.controllerContext.toMountPointIdentifier(identifier);
166 mountPoint = mountPointIdentifier.getMountPoint();
167 modules = this.controllerContext.getAllModules(mountPoint);
170 throw new ResponseException(Status.BAD_REQUEST,
171 "URI has bad format. If modules behind mount point should be showed, URI has to end with " +
172 ControllerContext.MOUNT);
175 final List<Node<?>> modulesAsData = new ArrayList<Node<?>>();
176 Module restconfModule = this.getRestconfModule();
177 final DataSchemaNode moduleSchemaNode =
178 this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
180 for (final Module module : modules) {
181 modulesAsData.add(this.toModuleCompositeNode(module, moduleSchemaNode));
184 final DataSchemaNode modulesSchemaNode =
185 this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
186 QName qName = modulesSchemaNode.getQName();
187 final CompositeNode modulesNode = NodeFactory.createImmutableCompositeNode(qName, null, modulesAsData);
188 return new StructuredData(modulesNode, modulesSchemaNode, mountPoint);
192 public StructuredData getModule(final String identifier) {
193 final QName moduleNameAndRevision = this.getModuleNameAndRevision(identifier);
194 Module module = null;
195 MountInstance mountPoint = null;
196 if (identifier.contains(ControllerContext.MOUNT)) {
197 InstanceIdWithSchemaNode mountPointIdentifier =
198 this.controllerContext.toMountPointIdentifier(identifier);
199 mountPoint = mountPointIdentifier.getMountPoint();
200 module = this.controllerContext.findModuleByNameAndRevision(mountPoint, moduleNameAndRevision);
203 module = this.controllerContext.findModuleByNameAndRevision(moduleNameAndRevision);
206 if (module == null) {
207 throw new ResponseException(Status.BAD_REQUEST,
208 "Module with name '" + moduleNameAndRevision.getLocalName() + "' and revision '" +
209 moduleNameAndRevision.getRevision() + "' was not found.");
212 Module restconfModule = this.getRestconfModule();
213 final DataSchemaNode moduleSchemaNode =
214 this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
215 final CompositeNode moduleNode = this.toModuleCompositeNode(module, moduleSchemaNode);
216 return new StructuredData(moduleNode, moduleSchemaNode, mountPoint);
220 public StructuredData getOperations() {
221 Set<Module> allModules = this.controllerContext.getAllModules();
222 return this.operationsFromModulesToStructuredData(allModules, null);
226 public StructuredData getOperations(final String identifier) {
227 Set<Module> modules = null;
228 MountInstance mountPoint = null;
229 if (identifier.contains(ControllerContext.MOUNT)) {
230 InstanceIdWithSchemaNode mountPointIdentifier =
231 this.controllerContext.toMountPointIdentifier(identifier);
232 mountPoint = mountPointIdentifier.getMountPoint();
233 modules = this.controllerContext.getAllModules(mountPoint);
236 throw new ResponseException(Status.BAD_REQUEST,
237 "URI has bad format. If operations behind mount point should be showed, URI has to end with " +
238 ControllerContext.MOUNT);
241 return this.operationsFromModulesToStructuredData(modules, mountPoint);
244 private StructuredData operationsFromModulesToStructuredData(final Set<Module> modules,
245 final MountInstance mountPoint) {
246 final List<Node<?>> operationsAsData = new ArrayList<Node<?>>();
247 Module restconfModule = this.getRestconfModule();
248 final DataSchemaNode operationsSchemaNode =
249 this.getSchemaNode(restconfModule, RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE);
250 QName qName = operationsSchemaNode.getQName();
251 SchemaPath path = operationsSchemaNode.getPath();
252 ContainerSchemaNodeBuilder containerSchemaNodeBuilder =
253 new ContainerSchemaNodeBuilder(RESTCONF_MODULE_DRAFT02_NAME, 0, qName, path);
254 final ContainerSchemaNodeBuilder fakeOperationsSchemaNode = containerSchemaNodeBuilder;
255 for (final Module module : modules) {
256 Set<RpcDefinition> rpcs = module.getRpcs();
257 for (final RpcDefinition rpc : rpcs) {
258 QName rpcQName = rpc.getQName();
259 SimpleNode<Object> immutableSimpleNode =
260 NodeFactory.<Object>createImmutableSimpleNode(rpcQName, null, null);
261 operationsAsData.add(immutableSimpleNode);
263 String name = module.getName();
264 LeafSchemaNodeBuilder leafSchemaNodeBuilder = new LeafSchemaNodeBuilder(name, 0, rpcQName, null);
265 final LeafSchemaNodeBuilder fakeRpcSchemaNode = leafSchemaNodeBuilder;
266 fakeRpcSchemaNode.setAugmenting(true);
268 EmptyType instance = EmptyType.getInstance();
269 fakeRpcSchemaNode.setType(instance);
270 fakeOperationsSchemaNode.addChildNode(fakeRpcSchemaNode.build());
274 final CompositeNode operationsNode =
275 NodeFactory.createImmutableCompositeNode(qName, null, operationsAsData);
276 ContainerSchemaNode schemaNode = fakeOperationsSchemaNode.build();
277 return new StructuredData(operationsNode, schemaNode, mountPoint);
280 private Module getRestconfModule() {
281 QName qName = QName.create(RESTCONF_MODULE_DRAFT02_NAMESPACE, RESTCONF_MODULE_DRAFT02_REVISION,
282 RESTCONF_MODULE_DRAFT02_NAME);
283 final Module restconfModule = this.controllerContext.findModuleByNameAndRevision(qName);
284 if (restconfModule == null) {
285 throw new ResponseException(Status.INTERNAL_SERVER_ERROR, "Restconf module was not found.");
288 return restconfModule;
291 private QName getModuleNameAndRevision(final String identifier) {
292 final int mountIndex = identifier.indexOf(ControllerContext.MOUNT);
293 String moduleNameAndRevision = "";
294 if (mountIndex >= 0) {
295 moduleNameAndRevision = identifier.substring(mountIndex + ControllerContext.MOUNT.length());
298 moduleNameAndRevision = identifier;
301 Splitter splitter = Splitter.on("/").omitEmptyStrings();
302 Iterable<String> split = splitter.split(moduleNameAndRevision);
303 final List<String> pathArgs = Lists.<String>newArrayList(split);
304 if (pathArgs.size() < 2) {
305 throw new ResponseException(Status.BAD_REQUEST,
306 "URI has bad format. End of URI should be in format \'moduleName/yyyy-MM-dd\'");
310 final String moduleName = pathArgs.get( 0 );
311 String revision = pathArgs.get(1);
312 final Date moduleRevision = REVISION_FORMAT.parse(revision);
313 return QName.create(null, moduleRevision, moduleName);
315 catch (ParseException e) {
316 throw new ResponseException(Status.BAD_REQUEST, "URI has bad format. It should be \'moduleName/yyyy-MM-dd\'");
320 private CompositeNode toStreamCompositeNode(final String streamName, final DataSchemaNode streamSchemaNode) {
321 final List<Node<?>> streamNodeValues = new ArrayList<Node<?>>();
322 List<DataSchemaNode> instanceDataChildrenByName =
323 this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) streamSchemaNode),
325 final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
326 streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(nameSchemaNode.getQName(), null,
329 instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
330 ((DataNodeContainer) streamSchemaNode), "description");
331 final DataSchemaNode descriptionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
332 streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(descriptionSchemaNode.getQName(), null,
333 "DESCRIPTION_PLACEHOLDER"));
335 instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
336 ((DataNodeContainer) streamSchemaNode), "replay-support");
337 final DataSchemaNode replaySupportSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
338 streamNodeValues.add(NodeFactory.<Boolean>createImmutableSimpleNode(replaySupportSchemaNode.getQName(), null,
339 Boolean.valueOf(true)));
341 instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
342 ((DataNodeContainer) streamSchemaNode), "replay-log-creation-time");
343 final DataSchemaNode replayLogCreationTimeSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
344 streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(replayLogCreationTimeSchemaNode.getQName(),
347 instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
348 ((DataNodeContainer) streamSchemaNode), "events");
349 final DataSchemaNode eventsSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
350 streamNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(eventsSchemaNode.getQName(),
353 return NodeFactory.createImmutableCompositeNode(streamSchemaNode.getQName(), null, streamNodeValues);
356 private CompositeNode toModuleCompositeNode(final Module module, final DataSchemaNode moduleSchemaNode) {
357 final List<Node<?>> moduleNodeValues = new ArrayList<Node<?>>();
358 List<DataSchemaNode> instanceDataChildrenByName =
359 this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) moduleSchemaNode), "name");
360 final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
361 moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(nameSchemaNode.getQName(),
362 null, module.getName()));
364 instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
365 ((DataNodeContainer) moduleSchemaNode), "revision");
366 final DataSchemaNode revisionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
367 Date _revision = module.getRevision();
368 moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(revisionSchemaNode.getQName(), null,
369 REVISION_FORMAT.format(_revision)));
371 instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
372 ((DataNodeContainer) moduleSchemaNode), "namespace");
373 final DataSchemaNode namespaceSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
374 moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(namespaceSchemaNode.getQName(), null,
375 module.getNamespace().toString()));
377 instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
378 ((DataNodeContainer) moduleSchemaNode), "feature");
379 final DataSchemaNode featureSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
380 for (final FeatureDefinition feature : module.getFeatures()) {
381 moduleNodeValues.add(NodeFactory.<String>createImmutableSimpleNode(featureSchemaNode.getQName(), null,
382 feature.getQName().getLocalName()));
385 return NodeFactory.createImmutableCompositeNode(moduleSchemaNode.getQName(), null, moduleNodeValues);
388 private DataSchemaNode getSchemaNode(final Module restconfModule, final String schemaNodeName) {
389 Set<GroupingDefinition> groupings = restconfModule.getGroupings();
391 final Predicate<GroupingDefinition> filter = new Predicate<GroupingDefinition>() {
393 public boolean apply(final GroupingDefinition g) {
394 return Objects.equal(g.getQName().getLocalName(),
395 RESTCONF_MODULE_DRAFT02_RESTCONF_GROUPING_SCHEMA_NODE);
399 Iterable<GroupingDefinition> filteredGroups = Iterables.filter(groupings, filter);
401 final GroupingDefinition restconfGrouping = Iterables.getFirst(filteredGroups, null);
403 List<DataSchemaNode> instanceDataChildrenByName =
404 this.controllerContext.findInstanceDataChildrenByName(restconfGrouping,
405 RESTCONF_MODULE_DRAFT02_RESTCONF_CONTAINER_SCHEMA_NODE);
406 final DataSchemaNode restconfContainer = Iterables.getFirst(instanceDataChildrenByName, null);
408 if (Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE)) {
409 List<DataSchemaNode> instances =
410 this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
411 RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE);
412 return Iterables.getFirst(instances, null);
414 else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE)) {
415 List<DataSchemaNode> instances =
416 this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
417 RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE);
418 return Iterables.getFirst(instances, null);
420 else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE)) {
421 List<DataSchemaNode> instances =
422 this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
423 RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE);
424 final DataSchemaNode modules = Iterables.getFirst(instances, null);
425 instances = this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) modules),
426 RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE);
427 return Iterables.getFirst(instances, null);
429 else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE)) {
430 List<DataSchemaNode> instances =
431 this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
432 RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
433 return Iterables.getFirst(instances, null);
435 else if(Objects.equal(schemaNodeName, RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE)) {
436 List<DataSchemaNode> instances =
437 this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) restconfContainer),
438 RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE);
439 final DataSchemaNode modules = Iterables.getFirst(instances, null);
440 instances = this.controllerContext.findInstanceDataChildrenByName(((DataNodeContainer) modules),
441 RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE);
442 return Iterables.getFirst(instances, null);
449 public Object getRoot() {
454 public StructuredData invokeRpc(final String identifier, final CompositeNode payload) {
455 final RpcDefinition rpc = this.resolveIdentifierInInvokeRpc(identifier);
456 if (Objects.equal(rpc.getQName().getNamespace().toString(), SAL_REMOTE_NAMESPACE) &&
457 Objects.equal(rpc.getQName().getLocalName(), SAL_REMOTE_RPC_SUBSRCIBE)) {
459 final CompositeNode value = this.normalizeNode(payload, rpc.getInput(), null);
460 final SimpleNode<? extends Object> pathNode = value == null ? null :
461 value.getFirstSimpleByName( QName.create(rpc.getQName(), "path") );
462 final Object pathValue = pathNode == null ? null : pathNode.getValue();
464 if (!(pathValue instanceof InstanceIdentifier)) {
465 throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
466 "Instance identifier was not normalized correctly.");
469 final InstanceIdentifier pathIdentifier = ((InstanceIdentifier) pathValue);
470 String streamName = null;
471 if (!Iterables.isEmpty(pathIdentifier.getPath())) {
472 String fullRestconfIdentifier = this.controllerContext.toFullRestconfIdentifier(pathIdentifier);
473 streamName = Notificator.createStreamNameFromUri(fullRestconfIdentifier);
476 if (Strings.isNullOrEmpty(streamName)) {
477 throw new ResponseException(Status.BAD_REQUEST,
478 "Path is empty or contains data node which is not Container or List build-in type.");
481 final SimpleNode<String> streamNameNode = NodeFactory.<String>createImmutableSimpleNode(
482 QName.create(rpc.getOutput().getQName(), "stream-name"), null, streamName);
483 final List<Node<?>> output = new ArrayList<Node<?>>();
484 output.add(streamNameNode);
486 final MutableCompositeNode responseData = NodeFactory.createMutableCompositeNode(
487 rpc.getOutput().getQName(), null, output, null, null);
489 if (!Notificator.existListenerFor(pathIdentifier)) {
490 Notificator.createListener(pathIdentifier, streamName);
493 return new StructuredData(responseData, rpc.getOutput(), null);
496 RpcDefinition rpcDefinition = this.controllerContext.getRpcDefinition(identifier);
497 return this.callRpc(rpcDefinition, payload);
501 public StructuredData invokeRpc(final String identifier, final String noPayload) {
502 if (!Strings.isNullOrEmpty(noPayload)) {
503 throw new ResponseException(Status.UNSUPPORTED_MEDIA_TYPE,
504 "Content-Type contains unsupported Media Type.");
507 final RpcDefinition rpc = this.resolveIdentifierInInvokeRpc(identifier);
508 return this.callRpc(rpc, null);
511 private RpcDefinition resolveIdentifierInInvokeRpc(final String identifier) {
512 if (identifier.indexOf("/") < 0) {
513 final String identifierDecoded = this.controllerContext.urlPathArgDecode(identifier);
514 final RpcDefinition rpc = this.controllerContext.getRpcDefinition(identifierDecoded);
519 throw new ResponseException(Status.NOT_FOUND, "RPC does not exist.");
522 final String slashErrorMsg = String.format(
523 "Identifier %n%s%ncan\'t contain slash character (/).%nIf slash is part of identifier name then use %%2F placeholder.",
526 throw new ResponseException(Status.NOT_FOUND, slashErrorMsg);
529 private StructuredData callRpc(final RpcDefinition rpc, final CompositeNode payload) {
531 throw new ResponseException(Status.NOT_FOUND, "RPC does not exist.");
534 CompositeNode rpcRequest = null;
535 if (payload == null) {
536 rpcRequest = NodeFactory.createMutableCompositeNode(rpc.getQName(), null, null, null, null);
539 final CompositeNode value = this.normalizeNode(payload, rpc.getInput(), null);
540 final List<Node<?>> input = new ArrayList<Node<?>>();
543 rpcRequest = NodeFactory.createMutableCompositeNode(rpc.getQName(), null, input, null, null);
546 final RpcResult<CompositeNode> rpcResult = broker.invokeRpc(rpc.getQName(), rpcRequest);
548 if (!rpcResult.isSuccessful()) {
549 throw new ResponseException(Status.INTERNAL_SERVER_ERROR, "Operation failed");
552 CompositeNode result = rpcResult.getResult();
553 if (result == null) {
557 return new StructuredData(result, rpc.getOutput(), null);
561 public StructuredData readConfigurationData(final String identifier) {
562 final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
563 CompositeNode data = null;
564 MountInstance mountPoint = iiWithData.getMountPoint();
565 if (mountPoint != null) {
566 data = broker.readConfigurationDataBehindMountPoint(mountPoint, iiWithData.getInstanceIdentifier());
569 data = broker.readConfigurationData(iiWithData.getInstanceIdentifier());
572 return new StructuredData(data, iiWithData.getSchemaNode(), iiWithData.getMountPoint());
576 public StructuredData readOperationalData(final String identifier) {
577 final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
578 CompositeNode data = null;
579 MountInstance mountPoint = iiWithData.getMountPoint();
580 if (mountPoint != null) {
581 data = broker.readOperationalDataBehindMountPoint(mountPoint, iiWithData.getInstanceIdentifier());
584 data = broker.readOperationalData(iiWithData.getInstanceIdentifier());
587 return new StructuredData(data, iiWithData.getSchemaNode(), mountPoint);
591 public Response updateConfigurationData(final String identifier, final CompositeNode payload) {
592 final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
593 MountInstance mountPoint = iiWithData.getMountPoint();
594 final CompositeNode value = this.normalizeNode(payload, iiWithData.getSchemaNode(), mountPoint);
595 RpcResult<TransactionStatus> status = null;
598 if (mountPoint != null) {
599 status = broker.commitConfigurationDataPutBehindMountPoint(
600 mountPoint, iiWithData.getInstanceIdentifier(), value).get();
602 status = broker.commitConfigurationDataPut(iiWithData.getInstanceIdentifier(), value).get();
605 catch( Exception e ) {
606 throw new ResponseException( e, "Error updating data" );
609 if( status.getResult() == TransactionStatus.COMMITED )
610 return Response.status(Status.OK).build();
612 return Response.status(Status.INTERNAL_SERVER_ERROR).build();
616 public Response createConfigurationData(final String identifier, final CompositeNode payload) {
617 URI payloadNS = this.namespace(payload);
618 if (payloadNS == null) {
619 throw new ResponseException(Status.BAD_REQUEST,
620 "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)");
623 InstanceIdWithSchemaNode iiWithData = null;
624 CompositeNode value = null;
625 if (this.representsMountPointRootData(payload)) {
626 // payload represents mount point data and URI represents path to the mount point
628 if (this.endsWithMountPoint(identifier)) {
629 throw new ResponseException(Status.BAD_REQUEST,
630 "URI has bad format. URI should be without \"" + ControllerContext.MOUNT +
631 "\" for POST operation.");
634 final String completeIdentifier = this.addMountPointIdentifier(identifier);
635 iiWithData = this.controllerContext.toInstanceIdentifier(completeIdentifier);
637 value = this.normalizeNode(payload, iiWithData.getSchemaNode(), iiWithData.getMountPoint());
640 final InstanceIdWithSchemaNode incompleteInstIdWithData =
641 this.controllerContext.toInstanceIdentifier(identifier);
642 final DataNodeContainer parentSchema = (DataNodeContainer) incompleteInstIdWithData.getSchemaNode();
643 MountInstance mountPoint = incompleteInstIdWithData.getMountPoint();
644 final Module module = this.findModule(mountPoint, payload);
645 if (module == null) {
646 throw new ResponseException(Status.BAD_REQUEST,
647 "Module was not found for \"" + payloadNS + "\"");
650 String payloadName = this.getName(payload);
651 final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(
652 parentSchema, payloadName, module.getNamespace());
653 value = this.normalizeNode(payload, schemaNode, mountPoint);
655 iiWithData = this.addLastIdentifierFromData(incompleteInstIdWithData, value, schemaNode);
658 RpcResult<TransactionStatus> status = null;
659 MountInstance mountPoint = iiWithData.getMountPoint();
661 if (mountPoint != null) {
662 Future<RpcResult<TransactionStatus>> future =
663 broker.commitConfigurationDataPostBehindMountPoint(
664 mountPoint, iiWithData.getInstanceIdentifier(), value);
665 status = future == null ? null : future.get();
668 Future<RpcResult<TransactionStatus>> future =
669 broker.commitConfigurationDataPost(iiWithData.getInstanceIdentifier(), value);
670 status = future == null ? null : future.get();
673 catch( ResponseException e) { throw e; }
674 catch( Exception e ) {
675 throw new ResponseException( e, "Error creating data" );
678 if (status == null) {
679 return Response.status(Status.ACCEPTED).build();
682 if( status.getResult() == TransactionStatus.COMMITED )
683 return Response.status(Status.NO_CONTENT).build();
685 return Response.status(Status.INTERNAL_SERVER_ERROR).build();
689 public Response createConfigurationData(final CompositeNode payload) {
690 URI payloadNS = this.namespace(payload);
691 if (payloadNS == null) {
692 throw new ResponseException(Status.BAD_REQUEST,
693 "Data has bad format. Root element node must have namespace (XML format) or module name(JSON format)");
696 final Module module = this.findModule(null, payload);
697 if (module == null) {
698 throw new ResponseException(Status.BAD_REQUEST,
699 "Data has bad format. Root element node has incorrect namespace (XML format) or module name(JSON format)");
702 String payloadName = this.getName(payload);
703 final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(
704 module, payloadName, module.getNamespace());
705 final CompositeNode value = this.normalizeNode(payload, schemaNode, null);
706 final InstanceIdWithSchemaNode iiWithData = this.addLastIdentifierFromData(null, value, schemaNode);
707 RpcResult<TransactionStatus> status = null;
708 MountInstance mountPoint = iiWithData.getMountPoint();
711 if (mountPoint != null) {
712 Future<RpcResult<TransactionStatus>> future =
713 broker.commitConfigurationDataPostBehindMountPoint(
714 mountPoint, iiWithData.getInstanceIdentifier(), value);
715 status = future == null ? null : future.get();
718 Future<RpcResult<TransactionStatus>> future =
719 broker.commitConfigurationDataPost(iiWithData.getInstanceIdentifier(), value);
720 status = future == null ? null : future.get();
723 catch( ResponseException e) { throw e; }
724 catch( Exception e ) {
725 throw new ResponseException( e, "Error creating data" );
728 if (status == null) {
729 return Response.status(Status.ACCEPTED).build();
732 if( status.getResult() == TransactionStatus.COMMITED )
733 return Response.status(Status.NO_CONTENT).build();
735 return Response.status(Status.INTERNAL_SERVER_ERROR).build();
739 public Response deleteConfigurationData(final String identifier) {
740 final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
741 RpcResult<TransactionStatus> status = null;
742 MountInstance mountPoint = iiWithData.getMountPoint();
745 if (mountPoint != null) {
746 status = broker.commitConfigurationDataDeleteBehindMountPoint(
747 mountPoint, iiWithData.getInstanceIdentifier()).get();
750 status = broker.commitConfigurationDataDelete(iiWithData.getInstanceIdentifier()).get();
753 catch( Exception e ) {
754 throw new ResponseException( e, "Error creating data" );
757 if( status.getResult() == TransactionStatus.COMMITED )
758 return Response.status(Status.OK).build();
760 return Response.status(Status.INTERNAL_SERVER_ERROR).build();
764 public Response subscribeToStream(final String identifier, final UriInfo uriInfo) {
765 final String streamName = Notificator.createStreamNameFromUri(identifier);
766 if (Strings.isNullOrEmpty(streamName)) {
767 throw new ResponseException(Status.BAD_REQUEST, "Stream name is empty.");
770 final ListenerAdapter listener = Notificator.getListenerFor(streamName);
771 if (listener == null) {
772 throw new ResponseException(Status.BAD_REQUEST, "Stream was not found.");
775 broker.registerToListenDataChanges(listener);
777 final UriBuilder uriBuilder = uriInfo.getAbsolutePathBuilder();
778 UriBuilder port = uriBuilder.port(WebSocketServer.PORT);
779 final URI uriToWebsocketServer = port.replacePath(streamName).build();
781 return Response.status(Status.OK).location(uriToWebsocketServer).build();
784 private Module findModule(final MountInstance mountPoint, final CompositeNode data) {
785 if (data instanceof CompositeNodeWrapper) {
786 return findModule(mountPoint, (CompositeNodeWrapper)data);
788 else if (data != null) {
789 URI namespace = data.getNodeType().getNamespace();
790 if (mountPoint != null) {
791 return this.controllerContext.findModuleByNamespace(mountPoint, namespace);
794 return this.controllerContext.findModuleByNamespace(namespace);
798 throw new IllegalArgumentException("Unhandled parameter types: " +
799 Arrays.<Object>asList(mountPoint, data).toString());
803 private Module findModule(final MountInstance mountPoint, final CompositeNodeWrapper data) {
804 URI namespace = data.getNamespace();
805 Preconditions.<URI>checkNotNull(namespace);
807 Module module = null;
808 if (mountPoint != null) {
809 module = this.controllerContext.findModuleByNamespace(mountPoint, namespace);
810 if (module == null) {
811 module = this.controllerContext.findModuleByName(mountPoint, namespace.toString());
815 module = this.controllerContext.findModuleByNamespace(namespace);
816 if (module == null) {
817 module = this.controllerContext.findModuleByName(namespace.toString());
824 private InstanceIdWithSchemaNode addLastIdentifierFromData(
825 final InstanceIdWithSchemaNode identifierWithSchemaNode,
826 final CompositeNode data, final DataSchemaNode schemaOfData) {
827 InstanceIdentifier instanceIdentifier = null;
828 if (identifierWithSchemaNode != null) {
829 instanceIdentifier = identifierWithSchemaNode.getInstanceIdentifier();
832 final InstanceIdentifier iiOriginal = instanceIdentifier;
833 InstanceIdentifierBuilder iiBuilder = null;
834 if (iiOriginal == null) {
835 iiBuilder = InstanceIdentifier.builder();
838 iiBuilder = InstanceIdentifier.builder(iiOriginal);
841 if ((schemaOfData instanceof ListSchemaNode)) {
842 HashMap<QName,Object> keys = this.resolveKeysFromData(((ListSchemaNode) schemaOfData), data);
843 iiBuilder.nodeWithKey(schemaOfData.getQName(), keys);
846 iiBuilder.node(schemaOfData.getQName());
849 InstanceIdentifier instance = iiBuilder.toInstance();
850 MountInstance mountPoint = null;
851 if (identifierWithSchemaNode != null) {
852 mountPoint=identifierWithSchemaNode.getMountPoint();
855 return new InstanceIdWithSchemaNode(instance, schemaOfData, mountPoint);
858 private HashMap<QName,Object> resolveKeysFromData(final ListSchemaNode listNode,
859 final CompositeNode dataNode) {
860 final HashMap<QName,Object> keyValues = new HashMap<QName, Object>();
861 List<QName> _keyDefinition = listNode.getKeyDefinition();
862 for (final QName key : _keyDefinition) {
863 SimpleNode<? extends Object> head = null;
864 String localName = key.getLocalName();
865 List<SimpleNode<? extends Object>> simpleNodesByName = dataNode.getSimpleNodesByName(localName);
866 if (simpleNodesByName != null) {
867 head = Iterables.getFirst(simpleNodesByName, null);
870 Object dataNodeKeyValueObject = null;
872 dataNodeKeyValueObject = head.getValue();
875 if (dataNodeKeyValueObject == null) {
876 throw new ResponseException(Status.BAD_REQUEST,
877 "Data contains list \"" + dataNode.getNodeType().getLocalName() +
878 "\" which does not contain key: \"" + key.getLocalName() + "\"");
881 keyValues.put(key, dataNodeKeyValueObject);
887 private boolean endsWithMountPoint(final String identifier) {
888 return identifier.endsWith(ControllerContext.MOUNT) ||
889 identifier.endsWith(ControllerContext.MOUNT + "/");
892 private boolean representsMountPointRootData(final CompositeNode data) {
893 URI namespace = this.namespace(data);
894 return (SchemaContext.NAME.getNamespace().equals( namespace ) /* ||
895 MOUNT_POINT_MODULE_NAME.equals( namespace.toString() )*/ ) &&
896 SchemaContext.NAME.getLocalName().equals( this.localName(data) );
899 private String addMountPointIdentifier(final String identifier) {
900 boolean endsWith = identifier.endsWith("/");
902 return (identifier + ControllerContext.MOUNT);
905 return identifier + "/" + ControllerContext.MOUNT;
908 private CompositeNode normalizeNode(final CompositeNode node, final DataSchemaNode schema,
909 final MountInstance mountPoint) {
910 if (schema == null) {
911 QName nodeType = node == null ? null : node.getNodeType();
912 String localName = nodeType == null ? null : nodeType.getLocalName();
913 String _plus = ("Data schema node was not found for " + localName);
914 throw new ResponseException(Status.INTERNAL_SERVER_ERROR,
915 "Data schema node was not found for " + localName );
918 if (!(schema instanceof DataNodeContainer)) {
919 throw new ResponseException(Status.BAD_REQUEST,
920 "Root element has to be container or list yang datatype.");
923 if ((node instanceof CompositeNodeWrapper)) {
924 boolean isChangeAllowed = ((CompositeNodeWrapper) node).isChangeAllowed();
925 if (isChangeAllowed) {
927 this.normalizeNode(((CompositeNodeWrapper) node), schema, null, mountPoint);
929 catch (NumberFormatException e) {
930 throw new ResponseException(Status.BAD_REQUEST, e.getMessage());
934 return ((CompositeNodeWrapper) node).unwrap();
940 private void normalizeNode(final NodeWrapper<? extends Object> nodeBuilder,
941 final DataSchemaNode schema, final QName previousAugment,
942 final MountInstance mountPoint) {
943 if (schema == null) {
944 throw new ResponseException(Status.BAD_REQUEST,
945 "Data has bad format.\n\"" + nodeBuilder.getLocalName() +
946 "\" does not exist in yang schema.");
949 QName currentAugment = null;
950 if (nodeBuilder.getQname() != null) {
951 currentAugment = previousAugment;
954 currentAugment = this.normalizeNodeName(nodeBuilder, schema, previousAugment, mountPoint);
955 if (nodeBuilder.getQname() == null) {
956 throw new ResponseException(Status.BAD_REQUEST,
957 "Data has bad format.\nIf data is in XML format then namespace for \"" +
958 nodeBuilder.getLocalName() +
959 "\" should be \"" + schema.getQName().getNamespace() + "\".\n" +
960 "If data is in JSON format then module name for \"" + nodeBuilder.getLocalName() +
961 "\" should be corresponding to namespace \"" +
962 schema.getQName().getNamespace() + "\".");
966 if ((nodeBuilder instanceof CompositeNodeWrapper)) {
967 final List<NodeWrapper<?>> children = ((CompositeNodeWrapper) nodeBuilder).getValues();
968 for (final NodeWrapper<? extends Object> child : children) {
969 final List<DataSchemaNode> potentialSchemaNodes =
970 this.controllerContext.findInstanceDataChildrenByName(
971 ((DataNodeContainer) schema), child.getLocalName());
973 if (potentialSchemaNodes.size() > 1 && child.getNamespace() == null) {
974 StringBuilder builder = new StringBuilder();
975 for (final DataSchemaNode potentialSchemaNode : potentialSchemaNodes) {
976 builder.append(" ").append(potentialSchemaNode.getQName().getNamespace().toString())
980 throw new ResponseException(Status.BAD_REQUEST,
981 "Node \"" + child.getLocalName() +
982 "\" is added as augment from more than one module. " +
983 "Therefore node must have namespace (XML format) or module name (JSON format)." +
984 "\nThe node is added as augment from modules with namespaces:\n" + builder);
987 boolean rightNodeSchemaFound = false;
988 for (final DataSchemaNode potentialSchemaNode : potentialSchemaNodes) {
989 if (!rightNodeSchemaFound) {
990 final QName potentialCurrentAugment =
991 this.normalizeNodeName(child, potentialSchemaNode, currentAugment, mountPoint);
992 if (child.getQname() != null ) {
993 this.normalizeNode(child, potentialSchemaNode, potentialCurrentAugment, mountPoint);
994 rightNodeSchemaFound = true;
999 if (!rightNodeSchemaFound) {
1000 throw new ResponseException(Status.BAD_REQUEST,
1001 "Schema node \"" + child.getLocalName() + "\" was not found in module.");
1005 if ((schema instanceof ListSchemaNode)) {
1006 final List<QName> listKeys = ((ListSchemaNode) schema).getKeyDefinition();
1007 for (final QName listKey : listKeys) {
1008 boolean foundKey = false;
1009 for (final NodeWrapper<? extends Object> child : children) {
1010 if (Objects.equal(child.unwrap().getNodeType().getLocalName(), listKey.getLocalName())) {
1016 throw new ResponseException(Status.BAD_REQUEST,
1017 "Missing key in URI \"" + listKey.getLocalName() +
1018 "\" of list \"" + schema.getQName().getLocalName() + "\"");
1024 if ((nodeBuilder instanceof SimpleNodeWrapper)) {
1025 final SimpleNodeWrapper simpleNode = ((SimpleNodeWrapper) nodeBuilder);
1026 final Object value = simpleNode.getValue();
1027 Object inputValue = value;
1028 TypeDefinition<? extends Object> typeDefinition = this.typeDefinition(schema);
1029 if ((typeDefinition instanceof IdentityrefTypeDefinition)) {
1030 if ((value instanceof String)) {
1031 inputValue = new IdentityValuesDTO( nodeBuilder.getNamespace().toString(),
1032 (String) value, null, (String) value );
1033 } // else value is already instance of IdentityValuesDTO
1036 Codec<Object,Object> codec = RestCodec.from(typeDefinition, mountPoint);
1037 Object outputValue = codec == null ? null : codec.deserialize(inputValue);
1039 simpleNode.setValue(outputValue);
1042 if ((nodeBuilder instanceof EmptyNodeWrapper)) {
1043 final EmptyNodeWrapper emptyNodeBuilder = ((EmptyNodeWrapper) nodeBuilder);
1044 if ((schema instanceof LeafSchemaNode)) {
1045 emptyNodeBuilder.setComposite(false);
1048 if ((schema instanceof ContainerSchemaNode)) {
1049 // FIXME: Add presence check
1050 emptyNodeBuilder.setComposite(true);
1058 private QName normalizeNodeName(final NodeWrapper<? extends Object> nodeBuilder,
1059 final DataSchemaNode schema, final QName previousAugment,
1060 final MountInstance mountPoint) {
1061 QName validQName = schema.getQName();
1062 QName currentAugment = previousAugment;
1063 if (schema.isAugmenting()) {
1064 currentAugment = schema.getQName();
1066 else if (previousAugment != null &&
1067 !Objects.equal( schema.getQName().getNamespace(), previousAugment.getNamespace())) {
1068 validQName = QName.create(currentAugment, schema.getQName().getLocalName());
1071 String moduleName = null;
1072 if (mountPoint == null) {
1073 moduleName = controllerContext.findModuleNameByNamespace(validQName.getNamespace());
1076 moduleName = controllerContext.findModuleNameByNamespace(mountPoint, validQName.getNamespace());
1079 if (nodeBuilder.getNamespace() == null ||
1080 Objects.equal(nodeBuilder.getNamespace(), validQName.getNamespace()) ||
1081 Objects.equal(nodeBuilder.getNamespace().toString(), moduleName) /*||
1082 Note: this check is wrong - can never be true as it compares a URI with a String
1083 not sure what the intention is so commented out...
1084 Objects.equal(nodeBuilder.getNamespace(), MOUNT_POINT_MODULE_NAME)*/ ) {
1086 nodeBuilder.setQname(validQName);
1089 return currentAugment;
1092 private URI namespace(final CompositeNode data) {
1093 if (data instanceof CompositeNodeWrapper) {
1094 return ((CompositeNodeWrapper)data).getNamespace();
1096 else if (data != null) {
1097 return data.getNodeType().getNamespace();
1100 throw new IllegalArgumentException("Unhandled parameter types: " +
1101 Arrays.<Object>asList(data).toString());
1105 private String localName(final CompositeNode data) {
1106 if (data instanceof CompositeNodeWrapper) {
1107 return ((CompositeNodeWrapper)data).getLocalName();
1109 else if (data != null) {
1110 return data.getNodeType().getLocalName();
1113 throw new IllegalArgumentException("Unhandled parameter types: " +
1114 Arrays.<Object>asList(data).toString());
1118 private String getName(final CompositeNode data) {
1119 if (data instanceof CompositeNodeWrapper) {
1120 return ((CompositeNodeWrapper)data).getLocalName();
1122 else if (data != null) {
1123 return data.getNodeType().getLocalName();
1126 throw new IllegalArgumentException("Unhandled parameter types: " +
1127 Arrays.<Object>asList(data).toString());
1131 private TypeDefinition<? extends Object> _typeDefinition(final LeafSchemaNode node) {
1132 TypeDefinition<?> baseType = node.getType();
1133 while (baseType.getBaseType() != null) {
1134 baseType = baseType.getBaseType();
1140 private TypeDefinition<? extends Object> typeDefinition(final LeafListSchemaNode node) {
1141 TypeDefinition<?> baseType = node.getType();
1142 while (baseType.getBaseType() != null) {
1143 baseType = baseType.getBaseType();
1149 private TypeDefinition<? extends Object> typeDefinition(final DataSchemaNode node) {
1150 if (node instanceof LeafListSchemaNode) {
1151 return typeDefinition((LeafListSchemaNode)node);
1153 else if (node instanceof LeafSchemaNode) {
1154 return _typeDefinition((LeafSchemaNode)node);
1157 throw new IllegalArgumentException("Unhandled parameter types: " +
1158 Arrays.<Object>asList(node).toString());