X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=restconf%2Fsal-rest-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetconf%2Fsal%2Frestconf%2Fimpl%2FRestconfImpl.java;h=19a130fafe6f921aecda5c6f30ea8e7480dd00aa;hb=4281bb297a90bc3c71a50d610147727ff67ea9ea;hp=928abe0eaf61c13431975d96de2a9bbea6d68073;hpb=8f8b49c1f6a113e88672f935c9cb497944af39f8;p=netconf.git diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java index 928abe0eaf..19a130fafe 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/restconf/impl/RestconfImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015 Brocade Communication Systems, Inc., Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2014 - 2016 Brocade Communication Systems, Inc., Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, @@ -8,36 +8,39 @@ 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; import com.google.common.base.Strings; +import com.google.common.base.Throwables; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import com.google.common.collect.Sets; import com.google.common.util.concurrent.CheckedFuture; -import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import java.net.URI; -import java.net.URISyntaxException; -import java.text.DateFormat; import java.text.ParseException; -import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoField; +import java.time.temporal.TemporalAccessor; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.Set; import java.util.concurrent.CancellationException; -import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; @@ -68,7 +71,9 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types. import org.opendaylight.yang.gen.v1.urn.sal.restconf.event.subscription.rev140708.NotificationOutputTypeGrouping.NotificationOutputType; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; @@ -81,6 +86,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode; import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.MapNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.tree.ModifiedNodeDoesNotExistException; import org.opendaylight.yangtools.yang.data.impl.schema.Builders; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder; @@ -102,7 +108,7 @@ import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaPath; -import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.EffectiveSchemaContext; +import org.opendaylight.yangtools.yang.model.util.SimpleSchemaContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -117,14 +123,8 @@ public class RestconfImpl implements RestconfService { private static final int CHAR_NOT_FOUND = -1; - private static final SimpleDateFormat REVISION_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); - private static final String SAL_REMOTE_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote"; - private BrokerFacade broker; - - private ControllerContext controllerContext; - private static final Logger LOG = LoggerFactory.getLogger(RestconfImpl.class); private static final DataChangeScope DEFAULT_SCOPE = DataChangeScope.BASE; @@ -143,11 +143,24 @@ public class RestconfImpl implements RestconfService { private static final String NETCONF_BASE_PAYLOAD_NAME = "data"; - private static final QName NETCONF_BASE_QNAME; + private static final QName NETCONF_BASE_QNAME = QName.create(QNameModule.create(URI.create(NETCONF_BASE), null), + NETCONF_BASE_PAYLOAD_NAME).intern(); private static final QNameModule SAL_REMOTE_AUGMENT; - private static final YangInstanceIdentifier.AugmentationIdentifier SAL_REMOTE_AUG_IDENTIFIER; + static { + try { + SAL_REMOTE_AUGMENT = QNameModule.create(NAMESPACE_EVENT_SUBSCRIPTION_AUGMENT, + SimpleDateFormatUtil.getRevisionFormat().parse("2014-07-08")); + } catch (final ParseException e) { + throw new ExceptionInInitializerError(e); + } + } + + private static final AugmentationIdentifier SAL_REMOTE_AUG_IDENTIFIER = + new AugmentationIdentifier(ImmutableSet.of( + QName.create(SAL_REMOTE_AUGMENT, "scope"), QName.create(SAL_REMOTE_AUGMENT, "datastore"), + QName.create(SAL_REMOTE_AUGMENT, "notification-output-type"))); public static final CharSequence DATA_SUBSCR = "data-change-event-subscription"; private static final CharSequence CREATE_DATA_SUBSCR = "create-" + DATA_SUBSCR; @@ -155,24 +168,19 @@ public class RestconfImpl implements RestconfService { public static final CharSequence NOTIFICATION_STREAM = "notification-stream"; private static final CharSequence CREATE_NOTIFICATION_STREAM = "create-" + NOTIFICATION_STREAM; - static { - try { - final Date eventSubscriptionAugRevision = new SimpleDateFormat("yyyy-MM-dd").parse("2014-07-08"); - NETCONF_BASE_QNAME = - QName.create(QNameModule.create(new URI(NETCONF_BASE), null), NETCONF_BASE_PAYLOAD_NAME); - SAL_REMOTE_AUGMENT = QNameModule.create(NAMESPACE_EVENT_SUBSCRIPTION_AUGMENT, eventSubscriptionAugRevision); - SAL_REMOTE_AUG_IDENTIFIER = new YangInstanceIdentifier.AugmentationIdentifier(Sets.newHashSet( - QName.create(SAL_REMOTE_AUGMENT, "scope"), QName.create(SAL_REMOTE_AUGMENT, "datastore"), - QName.create(SAL_REMOTE_AUGMENT, "notification-output-type"))); - } catch (final ParseException e) { - final String errMsg = "It wasn't possible to convert revision date of sal-remote-augment to date"; - LOG.debug(errMsg); - throw new RestconfDocumentedException(errMsg, ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED); - } catch (final URISyntaxException e) { - final String errMsg = "It wasn't possible to create instance of URI class with " + NETCONF_BASE + " URI"; - throw new RestconfDocumentedException(errMsg, ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED); - } - } + private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder() + .appendValue(ChronoField.YEAR, 4).appendLiteral('-') + .appendValue(ChronoField.MONTH_OF_YEAR, 2).appendLiteral('-') + .appendValue(ChronoField.DAY_OF_MONTH, 2).appendLiteral('T') + .appendValue(ChronoField.HOUR_OF_DAY, 2).appendLiteral(':') + .appendValue(ChronoField.MINUTE_OF_HOUR, 2).appendLiteral(':') + .appendValue(ChronoField.SECOND_OF_MINUTE, 2) + .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true) + .appendOffset("+HH:MM", "Z").toFormatter(); + + private BrokerFacade broker; + + private ControllerContext controllerContext; public void setBroker(final BrokerFacade broker) { this.broker = broker; @@ -210,7 +218,7 @@ public class RestconfImpl implements RestconfService { } /** - * Valid only for mount point + * Valid only for mount point. */ @Override public NormalizedNodeContext getModules(final String identifier, final UriInfo uriInfo) { @@ -344,12 +352,12 @@ public class RestconfImpl implements RestconfService { * implementations of schema nodes and module. * * @param modules - * - set of modules for get RPCs from every module + * set of modules for get RPCs from every module * @param mountPoint - * - mount point, if in use otherwise null + * mount point, if in use otherwise null * @return {@link NormalizedNodeContext} */ - private NormalizedNodeContext operationsFromModulesToNormalizedContext(final Set modules, + private static NormalizedNodeContext operationsFromModulesToNormalizedContext(final Set modules, final DOMMountPoint mountPoint) { final Collection neededModules = new ArrayList<>(modules.size()); @@ -377,8 +385,7 @@ public class RestconfImpl implements RestconfService { neededModules.forEach(imp -> fakeModules.add(new FakeImportedModule(imp))); fakeModules.add(new FakeRestconfModule(neededModules, fakeCont)); - final SchemaContext fakeSchemaCtx = - EffectiveSchemaContext.resolveSchemaContext(ImmutableSet.copyOf(fakeModules)); + final SchemaContext fakeSchemaCtx = SimpleSchemaContext.forModules(ImmutableSet.copyOf(fakeModules)); final InstanceIdentifierContext instanceIdentifierContext = new InstanceIdentifierContext<>(null, fakeCont, mountPoint, fakeSchemaCtx); return new NormalizedNodeContext(instanceIdentifierContext, containerBuilder.build()); @@ -406,7 +413,7 @@ public class RestconfImpl implements RestconfService { final Splitter splitter = Splitter.on("/").omitEmptyStrings(); final Iterable split = splitter.split(moduleNameAndRevision); - final List pathArgs = Lists. newArrayList(split); + final List pathArgs = Lists.newArrayList(split); if (pathArgs.size() < 2) { LOG.debug("URI has bad format. It should be \'moduleName/yyyy-MM-dd\' " + identifier); throw new RestconfDocumentedException( @@ -417,8 +424,7 @@ public class RestconfImpl implements RestconfService { try { final String moduleName = pathArgs.get(0); final String revision = pathArgs.get(1); - final Date moduleRevision = REVISION_FORMAT.parse(revision); - return QName.create(null, moduleRevision, moduleName); + return QName.create(null, SimpleDateFormatUtil.getRevisionFormat().parse(revision), moduleName); } catch (final ParseException e) { 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\'", @@ -469,22 +475,90 @@ public class RestconfImpl implements RestconfService { RpcDefinition resultNodeSchema = null; final NormalizedNode resultData = result.getResult(); - if ((result != null) && (result.getResult() != null)) { + if (result != null && result.getResult() != null) { resultNodeSchema = (RpcDefinition) payload.getInstanceIdentifierContext().getSchemaNode(); } return new NormalizedNodeContext( - new InstanceIdentifierContext(null, resultNodeSchema, mountPoint, schemaContext), + new InstanceIdentifierContext<>(null, resultNodeSchema, mountPoint, schemaContext), resultData, QueryParametersParser.parseWriterParameters(uriInfo)); } + @Override + public NormalizedNodeContext invokeRpc(final String identifier, final String noPayload, final UriInfo uriInfo) { + if (noPayload != null && !CharMatcher.WHITESPACE.matchesAllOf(noPayload)) { + throw new RestconfDocumentedException("Content must be empty.", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE); + } + + String identifierEncoded = null; + DOMMountPoint mountPoint = null; + final SchemaContext schemaContext; + if (identifier.contains(ControllerContext.MOUNT)) { + // mounted RPC call - look up mount instance. + final InstanceIdentifierContext mountPointId = this.controllerContext.toMountPointIdentifier(identifier); + mountPoint = mountPointId.getMountPoint(); + schemaContext = mountPoint.getSchemaContext(); + final int startOfRemoteRpcName = + identifier.lastIndexOf(ControllerContext.MOUNT) + ControllerContext.MOUNT.length() + 1; + 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 { + identifierEncoded = identifier; + schemaContext = this.controllerContext.getGlobalSchema(); + } + + final String identifierDecoded = this.controllerContext.urlPathArgDecode(identifierEncoded); + + RpcDefinition rpc = null; + if (mountPoint == null) { + rpc = this.controllerContext.getRpcDefinition(identifierDecoded, null); + } else { + rpc = findRpc(mountPoint.getSchemaContext(), identifierDecoded); + } + + if (rpc == null) { + LOG.debug("RPC " + identifierDecoded + " does not exist."); + 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."); + // FIXME : find a correct Error from specification + throw new IllegalStateException("RPC " + rpc + " does'n need input value!"); + } + + final CheckedFuture response; + if (mountPoint != null) { + final Optional mountRpcServices = mountPoint.getService(DOMRpcService.class); + if (!mountRpcServices.isPresent()) { + throw new RestconfDocumentedException("Rpc service is missing."); + } + response = mountRpcServices.get().invokeRpc(rpc.getPath(), null); + } else { + response = this.broker.invokeRpc(rpc.getPath(), null); + } + + final DOMRpcResult result = checkRpcResponse(response); + + return new NormalizedNodeContext(new InstanceIdentifierContext<>(null, rpc, mountPoint, schemaContext), + result.getResult(), QueryParametersParser.parseWriterParameters(uriInfo)); + } + private static DOMRpcResult checkRpcResponse(final CheckedFuture response) { if (response == null) { return null; } try { final DOMRpcResult retValue = response.get(); - if ((retValue.getErrors() == null) || retValue.getErrors().isEmpty()) { + if (retValue.getErrors() == null || retValue.getErrors().isEmpty()) { return retValue; } LOG.debug("RpcError message", retValue.getErrors()); @@ -522,10 +596,10 @@ public class RestconfImpl implements RestconfService { } private static void validateInput(final SchemaNode inputSchema, final NormalizedNodeContext payload) { - if ((inputSchema != null) && (payload.getData() == null)) { + if (inputSchema != null && payload.getData() == null) { // expected a non null payload throw new RestconfDocumentedException("Input is required.", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE); - } else if ((inputSchema == null) && (payload.getData() != null)) { + } else if (inputSchema == null && payload.getData() != null) { // did not expect any input throw new RestconfDocumentedException("No input expected.", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE); } @@ -545,7 +619,7 @@ public class RestconfImpl implements RestconfService { throw new RestconfDocumentedException(errMsg, ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED); } - final YangInstanceIdentifier pathIdentifier = ((YangInstanceIdentifier) pathValue); + final YangInstanceIdentifier pathIdentifier = (YangInstanceIdentifier) pathValue; String streamName = (String) CREATE_DATA_SUBSCR; NotificationOutputType outputType = null; if (!pathIdentifier.isEmpty()) { @@ -588,74 +662,6 @@ public class RestconfImpl implements RestconfService { return Futures.immediateCheckedFuture(defaultDOMRpcResult); } - @Override - public NormalizedNodeContext invokeRpc(final String identifier, final String noPayload, final UriInfo uriInfo) { - if ((noPayload != null) && !CharMatcher.WHITESPACE.matchesAllOf(noPayload)) { - throw new RestconfDocumentedException("Content must be empty.", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE); - } - - String identifierEncoded = null; - DOMMountPoint mountPoint = null; - final SchemaContext schemaContext; - if (identifier.contains(ControllerContext.MOUNT)) { - // mounted RPC call - look up mount instance. - final InstanceIdentifierContext mountPointId = this.controllerContext.toMountPointIdentifier(identifier); - mountPoint = mountPointId.getMountPoint(); - schemaContext = mountPoint.getSchemaContext(); - final int startOfRemoteRpcName = - identifier.lastIndexOf(ControllerContext.MOUNT) + ControllerContext.MOUNT.length() + 1; - 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 { - identifierEncoded = identifier; - schemaContext = this.controllerContext.getGlobalSchema(); - } - - final String identifierDecoded = this.controllerContext.urlPathArgDecode(identifierEncoded); - - RpcDefinition rpc = null; - if (mountPoint == null) { - rpc = this.controllerContext.getRpcDefinition(identifierDecoded, null); - } else { - rpc = findRpc(mountPoint.getSchemaContext(), identifierDecoded); - } - - if (rpc == null) { - LOG.debug("RPC " + identifierDecoded + " does not exist."); - throw new RestconfDocumentedException("RPC does not exist.", ErrorType.RPC, ErrorTag.UNKNOWN_ELEMENT); - } - - if (rpc.getInput() != null) { - LOG.debug("RPC " + rpc + " does not need input value."); - // FIXME : find a correct Error from specification - throw new IllegalStateException("RPC " + rpc + " does'n need input value!"); - } - - final CheckedFuture response; - if (mountPoint != null) { - final Optional mountRpcServices = mountPoint.getService(DOMRpcService.class); - if (!mountRpcServices.isPresent()) { - throw new RestconfDocumentedException("Rpc service is missing."); - } - response = mountRpcServices.get().invokeRpc(rpc.getPath(), null); - } else { - response = this.broker.invokeRpc(rpc.getPath(), null); - } - - final DOMRpcResult result = checkRpcResponse(response); - - return new NormalizedNodeContext(new InstanceIdentifierContext<>(null, rpc, mountPoint, schemaContext), - result.getResult(), QueryParametersParser.parseWriterParameters(uriInfo)); - } - private static RpcDefinition findRpc(final SchemaContext schemaContext, final String identifierDecoded) { final String[] splittedIdentifier = identifierDecoded.split(":"); if (splittedIdentifier.length != 2) { @@ -677,23 +683,26 @@ public class RestconfImpl implements RestconfService { @Override public NormalizedNodeContext readConfigurationData(final String identifier, final UriInfo uriInfo) { - boolean withDefa_used = false; + boolean withDefaUsed = false; String withDefa = null; for (final Entry> entry : uriInfo.getQueryParameters().entrySet()) { switch (entry.getKey()) { case "with-defaults": - if (!withDefa_used) { - withDefa_used = true; + if (!withDefaUsed) { + withDefaUsed = true; withDefa = entry.getValue().iterator().next(); } else { throw new RestconfDocumentedException("With-defaults parameter can be used only once."); } break; + default: + LOG.info("Unknown key : {}.", entry.getKey()); + break; } } boolean tagged = false; - if (withDefa_used) { + if (withDefaUsed) { if (withDefa.equals("report-all-tagged")) { tagged = true; withDefa = null; @@ -745,24 +754,24 @@ public class RestconfImpl implements RestconfService { @Override public Response updateConfigurationData(final String identifier, final NormalizedNodeContext payload, final UriInfo uriInfo) { - boolean insert_used = false; - boolean point_used = false; + boolean insertUsed = false; + boolean pointUsed = false; String insert = null; String point = null; for (final Entry> entry : uriInfo.getQueryParameters().entrySet()) { switch (entry.getKey()) { case "insert": - if (!insert_used) { - insert_used = true; + if (!insertUsed) { + insertUsed = true; insert = entry.getValue().iterator().next(); } else { throw new RestconfDocumentedException("Insert parameter can be used only once."); } break; case "point": - if (!point_used) { - point_used = true; + if (!pointUsed) { + pointUsed = true; point = entry.getValue().iterator().next(); } else { throw new RestconfDocumentedException("Point parameter can be used only once."); @@ -773,10 +782,10 @@ public class RestconfImpl implements RestconfService { } } - if (point_used && !insert_used) { + if (pointUsed && !insertUsed) { throw new RestconfDocumentedException("Point parameter can't be used without Insert parameter."); } - if (point_used && (insert.equals("first") || insert.equals("last"))) { + if (pointUsed && (insert.equals("first") || insert.equals("last"))) { throw new RestconfDocumentedException( "Point parameter can be used only with 'after' or 'before' values of Insert parameter."); } @@ -809,7 +818,7 @@ public class RestconfImpl implements RestconfService { * (and having to document the behavior). */ PutResult result = null; - final TryOfPutData tryPutData = new TryOfPutData(); + int tries = 2; while (true) { if (mountPoint != null) { @@ -819,56 +828,23 @@ public class RestconfImpl implements RestconfService { result = this.broker.commitConfigurationDataPut(this.controllerContext.getGlobalSchema(), normalizedII, payload.getData(), insert, point); } - final CountDownLatch waiter = new CountDownLatch(1); - Futures.addCallback(result.getFutureOfPutData(), new FutureCallback() { - - @Override - public void onSuccess(final Void result) { - handlingLoggerPut(null, tryPutData, identifier); - waiter.countDown(); - } - - @Override - public void onFailure(final Throwable t) { - waiter.countDown(); - handlingLoggerPut(t, tryPutData, identifier); - } - }); try { - waiter.await(); - } catch (final Exception e) { - final String msg = "Problem while waiting for response"; - LOG.warn(msg); - throw new RestconfDocumentedException(msg, e); - } - - if (tryPutData.isDone()) { - break; - } else { - throw new RestconfDocumentedException("Problem while PUT operations"); - } - } - - return Response.status(result.getStatus()).build(); - } + result.getFutureOfPutData().checkedGet(); + return Response.status(result.getStatus()).build(); + } catch (final TransactionCommitFailedException e) { + if (e instanceof OptimisticLockFailedException) { + if (--tries <= 0) { + LOG.debug("Got OptimisticLockFailedException on last try - failing " + identifier); + throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList()); + } - protected void handlingLoggerPut(final Throwable t, final TryOfPutData tryPutData, final String identifier) { - if (t != null) { - if (t instanceof OptimisticLockFailedException) { - if (tryPutData.countGet() <= 0) { - LOG.debug("Got OptimisticLockFailedException on last try - failing " + identifier); - throw new RestconfDocumentedException(t.getMessage(), t); + 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); - tryPutData.countDown(); - } else { - LOG.debug("Update ConfigDataStore fail " + identifier, t); - throw new RestconfDocumentedException(t.getMessage(), t); } - } else { - LOG.trace("PUT Successful " + identifier); - tryPutData.done(); } } @@ -897,7 +873,7 @@ public class RestconfImpl implements RestconfService { /** * Validates whether keys in {@code payload} are equal to values of keys in - * {@code iiWithData} for list schema node + * {@code iiWithData} for list schema node. * * @throws RestconfDocumentedException * if key values or key count in payload and URI isn't equal @@ -911,7 +887,7 @@ public class RestconfImpl implements RestconfService { final NormalizedNode data = payload.getData(); if (schemaNode instanceof ListSchemaNode) { final List keyDefinitions = ((ListSchemaNode) schemaNode).getKeyDefinition(); - if ((lastPathArgument instanceof NodeIdentifierWithPredicates) && (data instanceof MapEntryNode)) { + if (lastPathArgument instanceof NodeIdentifierWithPredicates && data instanceof MapEntryNode) { final Map uriKeyValues = ((NodeIdentifierWithPredicates) lastPathArgument).getKeyValues(); isEqualUriAndPayloadKeyValues(uriKeyValues, (MapEntryNode) data, keyDefinitions); @@ -919,7 +895,8 @@ public class RestconfImpl implements RestconfService { } } - private static void isEqualUriAndPayloadKeyValues(final Map uriKeyValues, final MapEntryNode payload, + @VisibleForTesting + public static void isEqualUriAndPayloadKeyValues(final Map uriKeyValues, final MapEntryNode payload, final List keyDefinitions) { final Map mutableCopyUriKeyValues = Maps.newHashMap(uriKeyValues); @@ -931,7 +908,7 @@ public class RestconfImpl implements RestconfService { final Object dataKeyValue = payload.getIdentifier().getKeyValues().get(keyDefinition); - if (!uriKeyValue.equals(dataKeyValue)) { + if (!Objects.deepEquals(uriKeyValue, dataKeyValue)) { final String errMsg = "The value '" + uriKeyValue + "' for key '" + keyDefinition.getLocalName() + "' specified in the URI doesn't match the value '" + dataKeyValue + "' specified in the message body. "; @@ -946,37 +923,6 @@ public class RestconfImpl implements RestconfService { return createConfigurationData(payload, uriInfo); } - // FIXME create RestconfIdetifierHelper and move this method there - private static YangInstanceIdentifier checkConsistencyOfNormalizedNodeContext(final NormalizedNodeContext payload) { - Preconditions.checkArgument(payload != null); - Preconditions.checkArgument(payload.getData() != null); - Preconditions.checkArgument(payload.getData().getNodeType() != null); - Preconditions.checkArgument(payload.getInstanceIdentifierContext() != null); - Preconditions.checkArgument(payload.getInstanceIdentifierContext().getInstanceIdentifier() != null); - - final QName payloadNodeQname = payload.getData().getNodeType(); - final YangInstanceIdentifier yangIdent = payload.getInstanceIdentifierContext().getInstanceIdentifier(); - if (payloadNodeQname.compareTo(yangIdent.getLastPathArgument().getNodeType()) > 0) { - return yangIdent; - } - final InstanceIdentifierContext parentContext = payload.getInstanceIdentifierContext(); - final SchemaNode parentSchemaNode = parentContext.getSchemaNode(); - if (parentSchemaNode instanceof DataNodeContainer) { - final DataNodeContainer cast = (DataNodeContainer) parentSchemaNode; - for (final DataSchemaNode child : cast.getChildNodes()) { - if (payloadNodeQname.compareTo(child.getQName()) == 0) { - return YangInstanceIdentifier.builder(yangIdent).node(child.getQName()).build(); - } - } - } - if (parentSchemaNode instanceof RpcDefinition) { - return yangIdent; - } - final String errMsg = "Error parsing input: DataSchemaNode has not children "; - LOG.info(errMsg + yangIdent); - throw new RestconfDocumentedException(errMsg, ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE); - } - @Override public Response createConfigurationData(final NormalizedNodeContext payload, final UriInfo uriInfo) { if (payload == null) { @@ -986,24 +932,24 @@ public class RestconfImpl implements RestconfService { final InstanceIdentifierContext iiWithData = payload.getInstanceIdentifierContext(); final YangInstanceIdentifier normalizedII = iiWithData.getInstanceIdentifier(); - boolean insert_used = false; - boolean point_used = false; + boolean insertUsed = false; + boolean pointUsed = false; String insert = null; String point = null; for (final Entry> entry : uriInfo.getQueryParameters().entrySet()) { switch (entry.getKey()) { case "insert": - if (!insert_used) { - insert_used = true; + if (!insertUsed) { + insertUsed = true; insert = entry.getValue().iterator().next(); } else { throw new RestconfDocumentedException("Insert parameter can be used only once."); } break; case "point": - if (!point_used) { - point_used = true; + if (!pointUsed) { + pointUsed = true; point = entry.getValue().iterator().next(); } else { throw new RestconfDocumentedException("Point parameter can be used only once."); @@ -1014,10 +960,10 @@ public class RestconfImpl implements RestconfService { } } - if (point_used && !insert_used) { + if (pointUsed && !insertUsed) { throw new RestconfDocumentedException("Point parameter can't be used without Insert parameter."); } - if (point_used && (insert.equals("first") || insert.equals("last"))) { + if (pointUsed && (insert.equals("first") || insert.equals("last"))) { throw new RestconfDocumentedException( "Point parameter can be used only with 'after' or 'before' values of Insert parameter."); } @@ -1031,30 +977,17 @@ public class RestconfImpl implements RestconfService { payload.getData(), insert, point); } - final CountDownLatch waiter = new CountDownLatch(1); - Futures.addCallback(future, new FutureCallback() { - - @Override - public void onSuccess(final Void result) { - handlerLoggerPost(null, uriInfo); - waiter.countDown(); - } - - @Override - public void onFailure(final Throwable t) { - waiter.countDown(); - handlerLoggerPost(t, uriInfo); - } - }); - try { - waiter.await(); - } catch (final Exception e) { - final String msg = "Problem while waiting for response"; - LOG.warn(msg); - throw new RestconfDocumentedException(msg, e); + 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()); } + LOG.trace("Successfuly created data."); + final ResponseBuilder responseBuilder = Response.status(Status.NO_CONTENT); // FIXME: Provide path to result. final URI location = resolveLocation(uriInfo, "", mountPoint, normalizedII); @@ -1064,16 +997,38 @@ public class RestconfImpl implements RestconfService { return responseBuilder.build(); } - protected void handlerLoggerPost(final Throwable t, final UriInfo uriInfo) { - if (t != null) { - final String errMsg = "Error creating data "; - LOG.warn(errMsg + (uriInfo != null ? uriInfo.getPath() : ""), t); - throw new RestconfDocumentedException(errMsg, t); - } else { - LOG.trace("Successfuly create data."); + // FIXME create RestconfIdetifierHelper and move this method there + private static YangInstanceIdentifier checkConsistencyOfNormalizedNodeContext(final NormalizedNodeContext payload) { + Preconditions.checkArgument(payload != null); + Preconditions.checkArgument(payload.getData() != null); + Preconditions.checkArgument(payload.getData().getNodeType() != null); + Preconditions.checkArgument(payload.getInstanceIdentifierContext() != null); + Preconditions.checkArgument(payload.getInstanceIdentifierContext().getInstanceIdentifier() != null); + + final QName payloadNodeQname = payload.getData().getNodeType(); + final YangInstanceIdentifier yangIdent = payload.getInstanceIdentifierContext().getInstanceIdentifier(); + if (payloadNodeQname.compareTo(yangIdent.getLastPathArgument().getNodeType()) > 0) { + return yangIdent; } + final InstanceIdentifierContext parentContext = payload.getInstanceIdentifierContext(); + final SchemaNode parentSchemaNode = parentContext.getSchemaNode(); + if (parentSchemaNode instanceof DataNodeContainer) { + final DataNodeContainer cast = (DataNodeContainer) parentSchemaNode; + for (final DataSchemaNode child : cast.getChildNodes()) { + if (payloadNodeQname.compareTo(child.getQName()) == 0) { + return YangInstanceIdentifier.builder(yangIdent).node(child.getQName()).build(); + } + } + } + if (parentSchemaNode instanceof RpcDefinition) { + return yangIdent; + } + final String errMsg = "Error parsing input: DataSchemaNode has not children "; + LOG.info(errMsg + yangIdent); + throw new RestconfDocumentedException(errMsg, ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE); } + @SuppressWarnings("checkstyle:IllegalCatch") private URI resolveLocation(final UriInfo uriInfo, final String uriBehindBase, final DOMMountPoint mountPoint, final YangInstanceIdentifier normalizedII) { if (uriInfo == null) { @@ -1105,57 +1060,29 @@ public class RestconfImpl implements RestconfService { future = this.broker.commitConfigurationDataDelete(normalizedII); } - final CountDownLatch waiter = new CountDownLatch(1); - final ResultOperation result = new ResultOperation(); - Futures.addCallback(future, new FutureCallback() { - - @Override - public void onSuccess(final Void result) { - LOG.trace("Successfuly delete data."); - waiter.countDown(); - } - - @Override - public void onFailure(final Throwable t) { - waiter.countDown(); - result.setFailed(t); + try { + future.checkedGet(); + } catch (final TransactionCommitFailedException e) { + final Optional searchedException = Iterables.tryFind(Throwables.getCausalChain(e), + Predicates.instanceOf(ModifiedNodeDoesNotExistException.class)); + if (searchedException.isPresent()) { + throw new RestconfDocumentedException("Data specified for delete doesn't exist.", ErrorType.APPLICATION, + ErrorTag.DATA_MISSING); } - }); - - try { - waiter.await(); - } catch (final Exception e) { - final String msg = "Problem while waiting for response"; - LOG.warn(msg); - throw new RestconfDocumentedException(msg, e); - } - if (result.failed() != null) { - final Throwable t = result.failed(); final String errMsg = "Error while deleting data"; - LOG.info(errMsg, t); - throw new RestconfDocumentedException(errMsg, RestconfError.ErrorType.APPLICATION, - RestconfError.ErrorTag.OPERATION_FAILED, t); + LOG.info(errMsg, e); + throw new RestconfDocumentedException(e.getMessage(), e, e.getErrorList()); } - return Response.status(Status.OK).build(); - } - private class ResultOperation { - private Throwable t = null; - - public void setFailed(final Throwable t) { - this.t = t; - } - - public Throwable failed() { - return this.t; - } + return Response.status(Status.OK).build(); } /** * Subscribes to some path in schema context (stream) to listen on changes * on this stream. * + *

* Additional parameters for subscribing to stream are loaded via rpc input * parameters: *

    @@ -1166,49 +1093,59 @@ public class RestconfImpl implements RestconfService { */ @Override public NormalizedNodeContext subscribeToStream(final String identifier, final UriInfo uriInfo) { - boolean startTime_used = false; - boolean stopTime_used = false; - boolean filter_used = false; - Date start = null; - Date stop = null; + boolean startTimeUsed = false; + boolean stopTimeUsed = false; + Instant start = Instant.now(); + Instant stop = null; + boolean filterUsed = false; String filter = null; + boolean leafNodesOnlyUsed = false; + boolean leafNodesOnly = false; for (final Entry> entry : uriInfo.getQueryParameters().entrySet()) { switch (entry.getKey()) { case "start-time": - if (!startTime_used) { - startTime_used = true; + if (!startTimeUsed) { + startTimeUsed = true; start = parseDateFromQueryParam(entry); } else { throw new RestconfDocumentedException("Start-time parameter can be used only once."); } break; case "stop-time": - if (!stopTime_used) { - stopTime_used = true; + if (!stopTimeUsed) { + stopTimeUsed = true; stop = parseDateFromQueryParam(entry); } else { throw new RestconfDocumentedException("Stop-time parameter can be used only once."); } break; case "filter": - if (!filter_used) { - filter_used = true; + if (!filterUsed) { + filterUsed = true; filter = entry.getValue().iterator().next(); } else { throw new RestconfDocumentedException("Filter parameter can be used only once."); } break; + case "odl-leaf-nodes-only": + if (!leafNodesOnlyUsed) { + leafNodesOnlyUsed = true; + leafNodesOnly = Boolean.parseBoolean(entry.getValue().iterator().next()); + } else { + throw new RestconfDocumentedException("Odl-leaf-nodes-only parameter can be used only once."); + } + break; default: throw new RestconfDocumentedException("Bad parameter used with notifications: " + entry.getKey()); } } - if (!startTime_used && stopTime_used) { + if (!startTimeUsed && stopTimeUsed) { throw new RestconfDocumentedException("Stop-time parameter has to be used with start-time parameter."); } URI response = null; if (identifier.contains(DATA_SUBSCR)) { - response = dataSubs(identifier, uriInfo, start, stop, filter); + response = dataSubs(identifier, uriInfo, start, stop, filter, leafNodesOnly); } else if (identifier.contains(NOTIFICATION_STREAM)) { response = notifStream(identifier, uriInfo, start, stop, filter); } @@ -1233,37 +1170,25 @@ public class RestconfImpl implements RestconfService { throw new RestconfDocumentedException(msg); } - private Date parseDateFromQueryParam(final Entry> entry) { + private static Instant parseDateFromQueryParam(final Entry> entry) { final DateAndTime event = new DateAndTime(entry.getValue().iterator().next()); - String numOf_ms = ""; final String value = event.getValue(); - if (value.contains(".")) { - numOf_ms = numOf_ms + "."; - final int lastChar = value.contains("Z") ? value.indexOf("Z") : (value.contains("+") ? value.indexOf("+") - : (value.contains("-") ? value.indexOf("-") : value.length())); - for (int i = 0; i < (lastChar - value.indexOf(".") - 1); i++) { - numOf_ms = numOf_ms + "S"; - } - } - String zone = ""; - if (!value.contains("Z")) { - zone = zone + "XXX"; - } - final DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss" + numOf_ms + zone); - + final TemporalAccessor p; try { - return dateFormatter.parse(value.contains("Z") ? value.replace('T', ' ').substring(0, value.indexOf("Z")) - : value.replace('T', ' ')); - } catch (final ParseException e) { - throw new RestconfDocumentedException("Cannot parse of value in date: " + value + e); + p = FORMATTER.parse(value); + } catch (final DateTimeParseException e) { + throw new RestconfDocumentedException("Cannot parse of value in date: " + value, e); } + return Instant.from(p); } /** + * Prepare instance identifier. + * * @return {@link InstanceIdentifierContext} of location leaf for * notification */ - private InstanceIdentifierContext prepareIIDSubsStreamOutput() { + private static InstanceIdentifierContext prepareIIDSubsStreamOutput() { final QName qnameBase = QName.create("subscribe:to:notification", "2016-10-28", "notifi"); final SchemaContext schemaCtx = ControllerContext.getInstance().getGlobalSchema(); final DataSchemaNode location = ((ContainerSchemaNode) schemaCtx @@ -1278,35 +1203,36 @@ public class RestconfImpl implements RestconfService { } /** - * Register notification listener by stream name + * Register notification listener by stream name. * * @param identifier - * - stream name + * stream name * @param uriInfo - * - uriInfo + * uriInfo * @param stop - * - stop-time of getting notification + * stop-time of getting notification * @param start - * - start-time of getting notification + * start-time of getting notification * @param filter - * - indicate wh ich subset of allpossible events are of interest + * indicate which subset of all possible events are of interest * @return {@link URI} of location */ - private URI notifStream(final String identifier, final UriInfo uriInfo, final Date start, final Date stop, - final String filter) { + private URI notifStream(final String identifier, final UriInfo uriInfo, final Instant start, + final Instant stop, final String filter) { final String streamName = Notificator.createStreamNameFromUri(identifier); if (Strings.isNullOrEmpty(streamName)) { throw new RestconfDocumentedException("Stream name is empty.", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE); } final List listeners = Notificator.getNotificationListenerFor(streamName); - if ((listeners == null) || listeners.isEmpty()) { + if (listeners == null || listeners.isEmpty()) { throw new RestconfDocumentedException("Stream was not found.", ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT); } for (final NotificationListenerAdapter listener : listeners) { this.broker.registerToListenNotification(listener); - listener.setQueryParams(start, stop, filter); + listener.setQueryParams(start, + java.util.Optional.ofNullable(stop), java.util.Optional.ofNullable(filter), false); } final UriBuilder uriBuilder = uriInfo.getAbsolutePathBuilder(); @@ -1324,22 +1250,22 @@ public class RestconfImpl implements RestconfService { } /** - * Register data change listener by stream name + * Register data change listener by stream name. * * @param identifier - * - stream name + * stream name * @param uriInfo - * - uri info + * uri info * @param stop - * - start-time of getting notification + * start-time of getting notification * @param start - * - stop-time of getting notification + * stop-time of getting notification * @param filter - * - indicate which subset of all possible events are of interest + * indicate which subset of all possible events are of interest * @return {@link URI} of location */ - private URI dataSubs(final String identifier, final UriInfo uriInfo, final Date start, final Date stop, - final String filter) { + private URI dataSubs(final String identifier, final UriInfo uriInfo, final Instant start, final Instant stop, + final String filter, final boolean leafNodesOnly) { final String streamName = Notificator.createStreamNameFromUri(identifier); if (Strings.isNullOrEmpty(streamName)) { throw new RestconfDocumentedException("Stream name is empty.", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE); @@ -1350,7 +1276,8 @@ public class RestconfImpl implements RestconfService { throw new RestconfDocumentedException("Stream was not found.", ErrorType.PROTOCOL, ErrorTag.UNKNOWN_ELEMENT); } - listener.setQueryParams(start, stop, filter); + listener.setQueryParams(start, java.util.Optional.ofNullable(stop), + java.util.Optional.ofNullable(filter), leafNodesOnly); final Map paramToValues = resolveValuesFromUri(identifier); final LogicalDatastoreType datastore = @@ -1382,9 +1309,10 @@ public class RestconfImpl implements RestconfService { return uriToWebsocketServer; } + @SuppressWarnings("checkstyle:IllegalCatch") @Override - public PATCHStatusContext patchConfigurationData(final String identifier, final PATCHContext context, - final UriInfo uriInfo) { + public PatchStatusContext patchConfigurationData(final String identifier, final PatchContext context, + final UriInfo uriInfo) { if (context == null) { throw new RestconfDocumentedException("Input is required.", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE); } @@ -1397,8 +1325,9 @@ public class RestconfImpl implements RestconfService { } } + @SuppressWarnings("checkstyle:IllegalCatch") @Override - public PATCHStatusContext patchConfigurationData(final PATCHContext context, @Context final UriInfo uriInfo) { + public PatchStatusContext patchConfigurationData(final PatchContext context, @Context final UriInfo uriInfo) { if (context == null) { throw new RestconfDocumentedException("Input is required.", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE); } @@ -1412,7 +1341,7 @@ public class RestconfImpl implements RestconfService { } /** - * Load parameter for subscribing to stream from input composite node + * Load parameter for subscribing to stream from input composite node. * * @param value * contains value @@ -1441,7 +1370,7 @@ public class RestconfImpl implements RestconfService { /** * Checks whether {@code value} is one of the string representation of - * enumeration {@code classDescriptor} + * enumeration {@code classDescriptor}. * * @return enum object if string value of {@code classDescriptor} * enumeration is equal to {@code value}. Other cases null. @@ -1501,35 +1430,35 @@ public class RestconfImpl implements RestconfService { Builders.mapEntryBuilder(listModuleSchemaNode); List instanceDataChildrenByName = - ControllerContext.findInstanceDataChildrenByName((listModuleSchemaNode), "name"); + ControllerContext.findInstanceDataChildrenByName(listModuleSchemaNode, "name"); final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null); Preconditions.checkState(nameSchemaNode instanceof LeafSchemaNode); moduleNodeValues .withChild(Builders.leafBuilder((LeafSchemaNode) nameSchemaNode).withValue(module.getName()).build()); instanceDataChildrenByName = - ControllerContext.findInstanceDataChildrenByName((listModuleSchemaNode), "revision"); + ControllerContext.findInstanceDataChildrenByName(listModuleSchemaNode, "revision"); final DataSchemaNode revisionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null); Preconditions.checkState(revisionSchemaNode instanceof LeafSchemaNode); - final String revision = REVISION_FORMAT.format(module.getRevision()); + final String revision = module.getQNameModule().getFormattedRevision(); moduleNodeValues .withChild(Builders.leafBuilder((LeafSchemaNode) revisionSchemaNode).withValue(revision).build()); instanceDataChildrenByName = - ControllerContext.findInstanceDataChildrenByName((listModuleSchemaNode), "namespace"); + 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()); instanceDataChildrenByName = - ControllerContext.findInstanceDataChildrenByName((listModuleSchemaNode), "feature"); + ControllerContext.findInstanceDataChildrenByName(listModuleSchemaNode, "feature"); final DataSchemaNode featureSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null); Preconditions.checkState(featureSchemaNode instanceof LeafListSchemaNode); final ListNodeBuilder> featuresBuilder = Builders.leafSetBuilder((LeafListSchemaNode) featureSchemaNode); for (final FeatureDefinition feature : module.getFeatures()) { - featuresBuilder.withChild(Builders.leafSetEntryBuilder(((LeafListSchemaNode) featureSchemaNode)) + featuresBuilder.withChild(Builders.leafSetEntryBuilder((LeafListSchemaNode) featureSchemaNode) .withValue(feature.getQName().getLocalName()).build()); } moduleNodeValues.withChild(featuresBuilder.build()); @@ -1545,33 +1474,33 @@ public class RestconfImpl implements RestconfService { Builders.mapEntryBuilder(listStreamSchemaNode); List instanceDataChildrenByName = - ControllerContext.findInstanceDataChildrenByName((listStreamSchemaNode), "name"); + ControllerContext.findInstanceDataChildrenByName(listStreamSchemaNode, "name"); final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null); Preconditions.checkState(nameSchemaNode instanceof LeafSchemaNode); streamNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) nameSchemaNode).withValue(streamName).build()); instanceDataChildrenByName = - ControllerContext.findInstanceDataChildrenByName((listStreamSchemaNode), "description"); + ControllerContext.findInstanceDataChildrenByName(listStreamSchemaNode, "description"); final DataSchemaNode descriptionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null); Preconditions.checkState(descriptionSchemaNode instanceof LeafSchemaNode); streamNodeValues.withChild( Builders.leafBuilder((LeafSchemaNode) nameSchemaNode).withValue("DESCRIPTION_PLACEHOLDER").build()); instanceDataChildrenByName = - ControllerContext.findInstanceDataChildrenByName((listStreamSchemaNode), "replay-support"); + ControllerContext.findInstanceDataChildrenByName(listStreamSchemaNode, "replay-support"); final DataSchemaNode replaySupportSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null); Preconditions.checkState(replaySupportSchemaNode instanceof LeafSchemaNode); streamNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) replaySupportSchemaNode) .withValue(Boolean.valueOf(true)).build()); instanceDataChildrenByName = - ControllerContext.findInstanceDataChildrenByName((listStreamSchemaNode), "replay-log-creation-time"); + ControllerContext.findInstanceDataChildrenByName(listStreamSchemaNode, "replay-log-creation-time"); final DataSchemaNode replayLogCreationTimeSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null); Preconditions.checkState(replayLogCreationTimeSchemaNode instanceof LeafSchemaNode); streamNodeValues.withChild( Builders.leafBuilder((LeafSchemaNode) replayLogCreationTimeSchemaNode).withValue("").build()); - instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName((listStreamSchemaNode), "events"); + instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(listStreamSchemaNode, "events"); final DataSchemaNode eventsSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null); Preconditions.checkState(eventsSchemaNode instanceof LeafSchemaNode); streamNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) eventsSchemaNode).withValue("").build()); @@ -1580,14 +1509,14 @@ public class RestconfImpl implements RestconfService { } /** - * Prepare stream for notification + * Prepare stream for notification. * * @param payload - * - contains list of qnames of notifications + * contains list of qnames of notifications * @return - checked future object */ - private CheckedFuture - invokeSalRemoteRpcNotifiStrRPC(final NormalizedNodeContext payload) { + private static CheckedFuture invokeSalRemoteRpcNotifiStrRPC( + final NormalizedNodeContext payload) { final ContainerNode data = (ContainerNode) payload.getData(); LeafSetNode leafSet = null; String outputType = "XML"; @@ -1595,7 +1524,7 @@ public class RestconfImpl implements RestconfService { if (dataChild instanceof LeafSetNode) { leafSet = (LeafSetNode) dataChild; } else if (dataChild instanceof AugmentationNode) { - outputType = (String) (((AugmentationNode) dataChild).getValue()).iterator().next().getValue(); + outputType = (String) ((AugmentationNode) dataChild).getValue().iterator().next().getValue(); } } @@ -1643,25 +1572,4 @@ public class RestconfImpl implements RestconfService { return Futures.immediateCheckedFuture(defaultDOMRpcResult); } - - private class TryOfPutData { - int tries = 2; - boolean done = false; - - void countDown() { - this.tries--; - } - - void done() { - this.done = true; - } - - boolean isDone() { - return this.done; - } - - int countGet() { - return this.tries; - } - } }