X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=restconf%2Frestconf-nb-bierman02%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetconf%2Fsal%2Frestconf%2Fimpl%2FRestconfImpl.java;h=b2d9f541a6969c53b8f19091a675c067ddd414a3;hb=16c314d9c3b27f5b96b619e0a9e3a722ca5dc4ca;hp=95d5995e2124db5e945c419501ffaea1e026ad62;hpb=885d26cbe6ab845352c8d853190dcec0310d0ded;p=netconf.git diff --git a/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java b/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java index 95d5995e21..b2d9f541a6 100644 --- a/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java +++ b/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java @@ -5,12 +5,10 @@ * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ - package org.opendaylight.netconf.sal.restconf.impl; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.CharMatcher; -import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Predicates; import com.google.common.base.Splitter; @@ -19,8 +17,9 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; -import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FluentFuture; import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; import java.net.URI; import java.time.Instant; import java.time.format.DateTimeFormatter; @@ -39,6 +38,7 @@ import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; @@ -48,16 +48,15 @@ import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; -import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; -import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException; -import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; -import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcException; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationNotAvailableException; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcService; -import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult; +import org.opendaylight.mdsal.common.api.CommitInfo; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.common.api.OptimisticLockFailedException; +import org.opendaylight.mdsal.common.api.TransactionCommitFailedException; +import org.opendaylight.mdsal.dom.api.DOMMountPoint; +import org.opendaylight.mdsal.dom.api.DOMRpcImplementationNotAvailableException; +import org.opendaylight.mdsal.dom.api.DOMRpcResult; +import org.opendaylight.mdsal.dom.api.DOMRpcService; +import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult; import org.opendaylight.netconf.sal.rest.api.Draft02; import org.opendaylight.netconf.sal.rest.api.RestconfService; import org.opendaylight.netconf.sal.streams.listeners.ListenerAdapter; @@ -71,6 +70,7 @@ import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag; import org.opendaylight.restconf.common.errors.RestconfError.ErrorType; import org.opendaylight.restconf.common.patch.PatchContext; import org.opendaylight.restconf.common.patch.PatchStatusContext; +import org.opendaylight.restconf.common.util.DataChangeScope; import org.opendaylight.restconf.common.validation.RestconfValidationUtils; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime; import org.opendaylight.yang.gen.v1.urn.sal.restconf.event.subscription.rev140708.NotificationOutputTypeGrouping.NotificationOutputType; @@ -117,9 +117,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public final class RestconfImpl implements RestconfService { - - private static final RestconfImpl INSTANCE = new RestconfImpl(); - /** * Notifications are served on port 8181. */ @@ -174,23 +171,17 @@ public final class RestconfImpl implements RestconfService { .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true) .appendOffset("+HH:MM", "Z").toFormatter(); - private BrokerFacade broker; + private final BrokerFacade broker; - private ControllerContext controllerContext; + private final ControllerContext controllerContext; - public void setBroker(final BrokerFacade broker) { + private RestconfImpl(final BrokerFacade broker, final ControllerContext controllerContext) { this.broker = broker; - } - - public void setControllerContext(final ControllerContext controllerContext) { this.controllerContext = controllerContext; } - private RestconfImpl() { - } - - public static RestconfImpl getInstance() { - return INSTANCE; + public static RestconfImpl newInstance(final BrokerFacade broker, final ControllerContext controllerContext) { + return new RestconfImpl(broker, controllerContext); } @Override @@ -222,7 +213,7 @@ public final class RestconfImpl implements RestconfService { if (!identifier.contains(ControllerContext.MOUNT)) { final String errMsg = "URI has bad format. If modules behind mount point should be showed," + " URI has to end with " + ControllerContext.MOUNT; - LOG.debug(errMsg + " for " + identifier); + LOG.debug("{} for {}", errMsg, identifier); throw new RestconfDocumentedException(errMsg, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE); } @@ -267,10 +258,9 @@ public final class RestconfImpl implements RestconfService { } if (module == null) { - final String errMsg = "Module with name '" + nameRev.getKey() + "' and revision '" - + nameRev.getValue() + "' was not found."; - LOG.debug(errMsg); - throw new RestconfDocumentedException(errMsg, ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT); + LOG.debug("Module with name '{}' and revision '{}' was not found.", nameRev.getKey(), nameRev.getValue()); + throw new RestconfDocumentedException("Module with name '" + nameRev.getKey() + "' and revision '" + + nameRev.getValue() + "' was not found.", ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT); } final Module restconfModule = getRestconfModule(); @@ -332,11 +322,10 @@ public final class RestconfImpl implements RestconfService { modules = this.controllerContext.getAllModules(mountPoint); } else { - final String errMsg = - "URI has bad format. If operations behind mount point should be showed, URI has to " + "end with "; - LOG.debug(errMsg + ControllerContext.MOUNT + " for " + identifier); - throw new RestconfDocumentedException(errMsg + ControllerContext.MOUNT, ErrorType.PROTOCOL, - ErrorTag.INVALID_VALUE); + final String errMsg = "URI has bad format. If operations behind mount point should be showed, URI has to " + + " end with " + ControllerContext.MOUNT; + LOG.debug("{} for {}", errMsg, identifier); + throw new RestconfDocumentedException(errMsg, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE); } return operationsFromModulesToNormalizedContext(modules, mountPoint); @@ -411,7 +400,7 @@ public final class RestconfImpl implements RestconfService { final Splitter splitter = Splitter.on('/').omitEmptyStrings(); final List pathArgs = splitter.splitToList(moduleNameAndRevision); if (pathArgs.size() < 2) { - LOG.debug("URI has bad format. It should be \'moduleName/yyyy-MM-dd\' " + identifier); + LOG.debug("URI has bad format. It should be \'moduleName/yyyy-MM-dd\' {}", identifier); throw new RestconfDocumentedException( "URI has bad format. End of URI should be in format \'moduleName/yyyy-MM-dd\'", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE); @@ -420,7 +409,7 @@ public final class RestconfImpl implements RestconfService { try { return new SimpleImmutableEntry<>(pathArgs.get(0), Revision.of(pathArgs.get(1))); } catch (final DateTimeParseException e) { - LOG.debug("URI has bad format. It should be \'moduleName/yyyy-MM-dd\' " + identifier); + LOG.debug("URI has bad format. It should be \'moduleName/yyyy-MM-dd\' {}", identifier); throw new RestconfDocumentedException("URI has bad format. It should be \'moduleName/yyyy-MM-dd\'", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE, e); } @@ -434,9 +423,14 @@ public final class RestconfImpl implements RestconfService { @Override public NormalizedNodeContext invokeRpc(final String identifier, final NormalizedNodeContext payload, final UriInfo uriInfo) { + if (payload == null) { + // no payload specified, reroute this to no payload invokeRpc implementation + return invokeRpc(identifier, "", uriInfo); + } + final SchemaPath type = payload.getInstanceIdentifierContext().getSchemaNode().getPath(); final URI namespace = payload.getInstanceIdentifierContext().getSchemaNode().getQName().getNamespace(); - final CheckedFuture response; + final ListenableFuture response; final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint(); final SchemaContext schemaContext; @@ -483,7 +477,7 @@ public final class RestconfImpl implements RestconfService { @Override public NormalizedNodeContext invokeRpc(final String identifier, final String noPayload, final UriInfo uriInfo) { - if (noPayload != null && !CharMatcher.WHITESPACE.matchesAllOf(noPayload)) { + if (noPayload != null && !CharMatcher.whitespace().matchesAllOf(noPayload)) { throw new RestconfDocumentedException("Content must be empty.", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE); } @@ -500,13 +494,11 @@ public final class RestconfImpl implements RestconfService { final String remoteRpcName = identifier.substring(startOfRemoteRpcName); identifierEncoded = remoteRpcName; - } else if (identifier.indexOf("/") != CHAR_NOT_FOUND) { - final String slashErrorMsg = String.format( - "Identifier %n%s%ncan\'t contain slash " - + "character (/).%nIf slash is part of identifier name then use %%2F placeholder.", - identifier); - LOG.debug(slashErrorMsg); - throw new RestconfDocumentedException(slashErrorMsg, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE); + } else if (identifier.indexOf('/') != CHAR_NOT_FOUND) { + LOG.debug("Identifier {} cannot contain slash character (/).", identifier); + throw new RestconfDocumentedException(String.format("Identifier %n%s%ncan\'t contain slash character (/).%n" + + "If slash is part of identifier name then use %%2F placeholder.", identifier), ErrorType.PROTOCOL, + ErrorTag.INVALID_VALUE); } else { identifierEncoded = identifier; schemaContext = this.controllerContext.getGlobalSchema(); @@ -522,17 +514,17 @@ public final class RestconfImpl implements RestconfService { } if (rpc == null) { - LOG.debug("RPC " + identifierDecoded + " does not exist."); + LOG.debug("RPC {} does not exist.", identifierDecoded); throw new RestconfDocumentedException("RPC does not exist.", ErrorType.RPC, ErrorTag.UNKNOWN_ELEMENT); } if (!rpc.getInput().getChildNodes().isEmpty()) { - LOG.debug("RPC " + rpc + " does not need input value."); + LOG.debug("RPC {} does not need input value.", rpc); throw new RestconfDocumentedException("RPC " + rpc + " does not take any input value.", ErrorType.RPC, ErrorTag.INVALID_VALUE); } - final CheckedFuture response; + final ListenableFuture response; if (mountPoint != null) { final Optional mountRpcServices = mountPoint.getService(DOMRpcService.class); if (!mountRpcServices.isPresent()) { @@ -550,7 +542,7 @@ public final class RestconfImpl implements RestconfService { } @SuppressWarnings("checkstyle:avoidHidingCauseException") - private static DOMRpcResult checkRpcResponse(final CheckedFuture response) { + private static DOMRpcResult checkRpcResponse(final ListenableFuture response) { if (response == null) { return null; } @@ -559,11 +551,11 @@ public final class RestconfImpl implements RestconfService { if (retValue.getErrors().isEmpty()) { return retValue; } - LOG.debug("RpcError message", retValue.getErrors()); + LOG.debug("RpcError message {}", retValue.getErrors()); throw new RestconfDocumentedException("RpcError message", null, retValue.getErrors()); } catch (final InterruptedException e) { final String errMsg = "The operation was interrupted while executing and did not complete."; - LOG.debug("Rpc Interrupt - " + errMsg, e); + LOG.debug("Rpc Interrupt - {}", errMsg, e); throw new RestconfDocumentedException(errMsg, ErrorType.RPC, ErrorTag.PARTIAL_OPERATION, e); } catch (final ExecutionException e) { LOG.debug("Execution RpcError: ", e); @@ -588,7 +580,7 @@ public final class RestconfImpl implements RestconfService { } } catch (final CancellationException e) { final String errMsg = "The operation was cancelled while executing."; - LOG.debug("Cancel RpcExecution: " + errMsg, e); + LOG.debug("Cancel RpcExecution: {}", errMsg, e); throw new RestconfDocumentedException(errMsg, ErrorType.RPC, ErrorTag.PARTIAL_OPERATION); } } @@ -603,8 +595,7 @@ public final class RestconfImpl implements RestconfService { } } - private CheckedFuture - invokeSalRemoteRpcSubscribeRPC(final NormalizedNodeContext payload) { + private ListenableFuture invokeSalRemoteRpcSubscribeRPC(final NormalizedNodeContext payload) { final ContainerNode value = (ContainerNode) payload.getData(); final QName rpcQName = payload.getInstanceIdentifierContext().getSchemaNode().getQName(); final java.util.Optional> path = value.getChild( @@ -613,9 +604,9 @@ public final class RestconfImpl implements RestconfService { final Object pathValue = path.isPresent() ? path.get().getValue() : null; if (!(pathValue instanceof YangInstanceIdentifier)) { - final String errMsg = "Instance identifier was not normalized correctly "; - LOG.debug(errMsg + rpcQName); - throw new RestconfDocumentedException(errMsg, ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED); + LOG.debug("Instance identifier {} was not normalized correctly", rpcQName); + throw new RestconfDocumentedException("Instance identifier was not normalized correctly", + ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED); } final YangInstanceIdentifier pathIdentifier = (YangInstanceIdentifier) pathValue; @@ -640,9 +631,10 @@ public final class RestconfImpl implements RestconfService { } if (Strings.isNullOrEmpty(streamName)) { - final String errMsg = "Path is empty or contains value node which is not Container or List build-in type."; - LOG.debug(errMsg + pathIdentifier); - throw new RestconfDocumentedException(errMsg, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE); + LOG.debug("Path is empty or contains value node which is not Container or List built-in type at {}", + pathIdentifier); + throw new RestconfDocumentedException("Path is empty or contains value node which is not Container or List " + + "built-in type.", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE); } final QName outputQname = QName.create(rpcQName, "output"); @@ -653,20 +645,18 @@ public final class RestconfImpl implements RestconfService { .withChild(ImmutableNodes.leafNode(streamNameQname, streamName)).build(); if (!Notificator.existListenerFor(streamName)) { - Notificator.createListener(pathIdentifier, streamName, outputType); + Notificator.createListener(pathIdentifier, streamName, outputType, controllerContext); } - final DOMRpcResult defaultDOMRpcResult = new DefaultDOMRpcResult(output); - - return Futures.immediateCheckedFuture(defaultDOMRpcResult); + return Futures.immediateFuture(new DefaultDOMRpcResult(output)); } private static RpcDefinition findRpc(final SchemaContext schemaContext, final String identifierDecoded) { final String[] splittedIdentifier = identifierDecoded.split(":"); if (splittedIdentifier.length != 2) { - final String errMsg = identifierDecoded + " couldn't be splitted to 2 parts (module:rpc name)"; - LOG.debug(errMsg); - throw new RestconfDocumentedException(errMsg, ErrorType.APPLICATION, ErrorTag.INVALID_VALUE); + LOG.debug("{} could not be split to 2 parts (module:rpc name)", identifierDecoded); + throw new RestconfDocumentedException(identifierDecoded + " could not be split to 2 parts " + + "(module:rpc name)", ErrorType.APPLICATION, ErrorTag.INVALID_VALUE); } for (final Module module : schemaContext.getModules()) { if (module.getName().equals(splittedIdentifier[0])) { @@ -721,10 +711,7 @@ public final class RestconfImpl implements RestconfService { data = this.broker.readConfigurationData(normalizedII, withDefa); } if (data == null) { - final String errMsg = - "Request could not be completed because the relevant data model content does not exist "; - LOG.debug(errMsg + identifier); - throw new RestconfDocumentedException(errMsg, ErrorType.APPLICATION, ErrorTag.DATA_MISSING); + throw dataMissing(identifier); } return new NormalizedNodeContext(iiWithData, data, QueryParametersParser.parseWriterParameters(uriInfo, tagged)); @@ -742,14 +729,18 @@ public final class RestconfImpl implements RestconfService { data = this.broker.readOperationalData(normalizedII); } if (data == null) { - final String errMsg = - "Request could not be completed because the relevant data model content does not exist "; - LOG.debug(errMsg + identifier); - throw new RestconfDocumentedException(errMsg, ErrorType.APPLICATION, ErrorTag.DATA_MISSING); + throw dataMissing(identifier); } return new NormalizedNodeContext(iiWithData, data, QueryParametersParser.parseWriterParameters(uriInfo)); } + private static RestconfDocumentedException dataMissing(final String identifier) { + LOG.debug("Request could not be completed because the relevant data model content does not exist {}", + identifier); + return new RestconfDocumentedException("Request could not be completed because the relevant data model content " + + "does not exist", ErrorType.APPLICATION, ErrorTag.DATA_MISSING); + } + @Override public Response updateConfigurationData(final String identifier, final NormalizedNodeContext payload, final UriInfo uriInfo) { @@ -829,21 +820,28 @@ public final class RestconfImpl implements RestconfService { } try { - result.getFutureOfPutData().checkedGet(); - return Response.status(result.getStatus()).build(); - } catch (final TransactionCommitFailedException e) { - if (e instanceof OptimisticLockFailedException) { + result.getFutureOfPutData().get(); + } catch (final InterruptedException e) { + LOG.debug("Update failed for {}", identifier, e); + throw new RestconfDocumentedException(e.getMessage(), e); + } catch (final ExecutionException e) { + final TransactionCommitFailedException failure = Throwables.getCauseAs(e, + TransactionCommitFailedException.class); + if (failure instanceof OptimisticLockFailedException) { if (--tries <= 0) { - LOG.debug("Got OptimisticLockFailedException on last try - failing " + identifier); - throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList()); + LOG.debug("Got OptimisticLockFailedException on last try - failing {}", identifier); + throw new RestconfDocumentedException(e.getMessage(), e, failure.getErrorList()); } - LOG.debug("Got OptimisticLockFailedException - trying again " + identifier); - } else { - LOG.debug("Update failed for " + identifier, e); - throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList()); + LOG.debug("Got OptimisticLockFailedException - trying again {}", identifier); + continue; } + + LOG.debug("Update failed for {}", identifier, e); + throw RestconfDocumentedException.decodeAndThrow(e.getMessage(), failure); } + + return Response.status(result.getStatus()).build(); } } @@ -969,7 +967,7 @@ public final class RestconfImpl implements RestconfService { "Point parameter can be used only with 'after' or 'before' values of Insert parameter."); } - CheckedFuture future; + FluentFuture future; if (mountPoint != null) { future = this.broker.commitConfigurationDataPost(mountPoint, normalizedII, payload.getData(), insert, point); @@ -979,12 +977,14 @@ public final class RestconfImpl implements RestconfService { } try { - future.checkedGet(); - } catch (final RestconfDocumentedException e) { - throw e; - } catch (final TransactionCommitFailedException e) { - LOG.info("Error creating data " + (uriInfo != null ? uriInfo.getPath() : ""), e); - throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList()); + future.get(); + } catch (final InterruptedException e) { + LOG.info("Error creating data {}", uriInfo != null ? uriInfo.getPath() : "", e); + throw new RestconfDocumentedException(e.getMessage(), e); + } catch (final ExecutionException e) { + LOG.info("Error creating data {}", uriInfo != null ? uriInfo.getPath() : "", e); + throw RestconfDocumentedException.decodeAndThrow(e.getMessage(), Throwables.getCauseAs(e, + TransactionCommitFailedException.class)); } LOG.trace("Successfuly created data."); @@ -1011,7 +1011,7 @@ public final class RestconfImpl implements RestconfService { try { uriBuilder.path(this.controllerContext.toFullRestconfIdentifier(normalizedII, mountPoint)); } catch (final Exception e) { - LOG.info("Location for instance identifier" + normalizedII + "wasn't created", e); + LOG.info("Location for instance identifier {} was not created", normalizedII, e); return null; } return uriBuilder.build(); @@ -1023,7 +1023,7 @@ public final class RestconfImpl implements RestconfService { final DOMMountPoint mountPoint = iiWithData.getMountPoint(); final YangInstanceIdentifier normalizedII = iiWithData.getInstanceIdentifier(); - final CheckedFuture future; + final FluentFuture future; if (mountPoint != null) { future = this.broker.commitConfigurationDataDelete(mountPoint, normalizedII); } else { @@ -1031,18 +1031,19 @@ public final class RestconfImpl implements RestconfService { } try { - future.checkedGet(); - } catch (final TransactionCommitFailedException e) { + future.get(); + } catch (final InterruptedException e) { + throw new RestconfDocumentedException(e.getMessage(), e); + } catch (final ExecutionException e) { final Optional searchedException = Iterables.tryFind(Throwables.getCausalChain(e), - Predicates.instanceOf(ModifiedNodeDoesNotExistException.class)); + Predicates.instanceOf(ModifiedNodeDoesNotExistException.class)).toJavaUtil(); if (searchedException.isPresent()) { - throw new RestconfDocumentedException("Data specified for delete doesn't exist.", - ErrorType.APPLICATION, ErrorTag.DATA_MISSING, e); + throw new RestconfDocumentedException("Data specified for delete doesn't exist.", ErrorType.APPLICATION, + ErrorTag.DATA_MISSING, e); } - final String errMsg = "Error while deleting data"; - LOG.info(errMsg, e); - throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList()); + throw RestconfDocumentedException.decodeAndThrow(e.getMessage(), Throwables.getCauseAs(e, + TransactionCommitFailedException.class)); } return Response.status(Status.OK).build(); @@ -1158,9 +1159,9 @@ public final class RestconfImpl implements RestconfService { * @return {@link InstanceIdentifierContext} of location leaf for * notification */ - private static InstanceIdentifierContext prepareIIDSubsStreamOutput() { + private InstanceIdentifierContext prepareIIDSubsStreamOutput() { final QName qnameBase = QName.create("subscribe:to:notification", "2016-10-28", "notifi"); - final SchemaContext schemaCtx = ControllerContext.getInstance().getGlobalSchema(); + final SchemaContext schemaCtx = controllerContext.getGlobalSchema(); final DataSchemaNode location = ((ContainerSchemaNode) schemaCtx .findModule(qnameBase.getModule()).orElse(null) .getDataChildByName(qnameBase)).getDataChildByName(QName.create(qnameBase, "location")); @@ -1216,7 +1217,7 @@ public final class RestconfImpl implements RestconfService { return uriToWebsocketServerBuilder.replacePath(streamName).build(); } - private String getWsScheme(UriInfo uriInfo) { + private static String getWsScheme(final UriInfo uriInfo) { URI uri = uriInfo.getAbsolutePath(); if (uri == null) { return "ws"; @@ -1398,7 +1399,7 @@ public final class RestconfImpl implements RestconfService { return listModuleBuilder.build(); } - protected MapEntryNode toModuleEntryNode(final Module module, final DataSchemaNode moduleSchemaNode) { + private MapEntryNode toModuleEntryNode(final Module module, final DataSchemaNode moduleSchemaNode) { Preconditions.checkArgument(moduleSchemaNode instanceof ListSchemaNode, "moduleSchemaNode has to be of type ListSchemaNode"); final ListSchemaNode listModuleSchemaNode = (ListSchemaNode) moduleSchemaNode; @@ -1412,22 +1413,22 @@ public final class RestconfImpl implements RestconfService { moduleNodeValues .withChild(Builders.leafBuilder((LeafSchemaNode) nameSchemaNode).withValue(module.getName()).build()); + final QNameModule qNameModule = module.getQNameModule(); + instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(listModuleSchemaNode, "revision"); final DataSchemaNode revisionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null); Preconditions.checkState(revisionSchemaNode instanceof LeafSchemaNode); - final java.util.Optional revision = module.getQNameModule().getRevision(); - if (revision.isPresent()) { - moduleNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) revisionSchemaNode) - .withValue(revision.get().toString()).build()); - } + final java.util.Optional revision = qNameModule.getRevision(); + moduleNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) revisionSchemaNode) + .withValue(revision.map(Revision::toString).orElse("")).build()); instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(listModuleSchemaNode, "namespace"); final DataSchemaNode namespaceSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null); Preconditions.checkState(namespaceSchemaNode instanceof LeafSchemaNode); moduleNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) namespaceSchemaNode) - .withValue(module.getNamespace().toString()).build()); + .withValue(qNameModule.getNamespace().toString()).build()); instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(listModuleSchemaNode, "feature"); @@ -1469,7 +1470,7 @@ public final class RestconfImpl implements RestconfService { final DataSchemaNode replaySupportSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null); Preconditions.checkState(replaySupportSchemaNode instanceof LeafSchemaNode); streamNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) replaySupportSchemaNode) - .withValue(Boolean.valueOf(true)).build()); + .withValue(Boolean.TRUE).build()); instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(listStreamSchemaNode, "replay-log-creation-time"); @@ -1493,8 +1494,7 @@ public final class RestconfImpl implements RestconfService { * contains list of qnames of notifications * @return - checked future object */ - private static CheckedFuture invokeSalRemoteRpcNotifiStrRPC( - final NormalizedNodeContext payload) { + private ListenableFuture invokeSalRemoteRpcNotifiStrRPC(final NormalizedNodeContext payload) { final ContainerNode data = (ContainerNode) payload.getData(); LeafSetNode leafSet = null; String outputType = "XML"; @@ -1514,8 +1514,7 @@ public final class RestconfImpl implements RestconfService { final Iterator iterator = entryNodes.iterator(); while (iterator.hasNext()) { final QName valueQName = QName.create((String) iterator.next().getValue()); - final Module module = - ControllerContext.getInstance().findModuleByNamespace(valueQName.getModule().getNamespace()); + final Module module = controllerContext.findModuleByNamespace(valueQName.getModule().getNamespace()); Preconditions.checkNotNull(module, "Module for namespace " + valueQName.getModule().getNamespace() + " does not exist"); NotificationDefinition notifiDef = null; @@ -1546,11 +1545,9 @@ public final class RestconfImpl implements RestconfService { .withChild(ImmutableNodes.leafNode(streamNameQname, streamName)).build(); if (!Notificator.existNotificationListenerFor(streamName)) { - Notificator.createNotificationListener(paths, streamName, outputType); + Notificator.createNotificationListener(paths, streamName, outputType, controllerContext); } - final DOMRpcResult defaultDOMRpcResult = new DefaultDOMRpcResult(output); - - return Futures.immediateCheckedFuture(defaultDOMRpcResult); + return Futures.immediateFuture(new DefaultDOMRpcResult(output)); } }