* 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 static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
+
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.ImmutableMap;
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.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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.net.URI;
-import java.text.ParseException;
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.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+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;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
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.eclipse.jdt.annotation.NonNull;
+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.api.DOMSchemaService;
+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.rest.impl.NormalizedNodeContext;
import org.opendaylight.netconf.sal.streams.listeners.ListenerAdapter;
import org.opendaylight.netconf.sal.streams.listeners.NotificationListenerAdapter;
import org.opendaylight.netconf.sal.streams.listeners.Notificator;
import org.opendaylight.netconf.sal.streams.websockets.WebSocketServer;
+import org.opendaylight.restconf.common.OperationsContent;
import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
-import org.opendaylight.restconf.common.context.NormalizedNodeContext;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
-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.validation.RestconfValidationUtils;
+import org.opendaylight.restconf.common.util.OperationsResourceUtils;
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.CreateDataChangeEventSubscriptionInput1.Scope;
import org.opendaylight.yang.gen.v1.urn.sal.restconf.event.subscription.rev140708.NotificationOutputTypeGrouping.NotificationOutputType;
+import org.opendaylight.yangtools.yang.common.Empty;
+import org.opendaylight.yangtools.yang.common.ErrorTag;
+import org.opendaylight.yangtools.yang.common.ErrorType;
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.common.Revision;
+import org.opendaylight.yangtools.yang.common.XMLNamespace;
+import org.opendaylight.yangtools.yang.common.YangConstants;
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.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.SystemLeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.SystemMapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.builder.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.api.schema.builder.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.api.schema.builder.ListNodeBuilder;
+import org.opendaylight.yangtools.yang.data.api.schema.builder.NormalizedNodeBuilder;
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;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.SchemaAwareBuilders;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
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.model.util.SimpleSchemaContext;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class RestconfImpl implements RestconfService {
-
- private static final RestconfImpl INSTANCE = new RestconfImpl();
-
+@Singleton
+public final class RestconfImpl implements RestconfService {
/**
* Notifications are served on port 8181.
*/
private static final Logger LOG = LoggerFactory.getLogger(RestconfImpl.class);
- private static final DataChangeScope DEFAULT_SCOPE = DataChangeScope.BASE;
-
private static final LogicalDatastoreType DEFAULT_DATASTORE = LogicalDatastoreType.CONFIGURATION;
- private static final URI NAMESPACE_EVENT_SUBSCRIPTION_AUGMENT = URI.create("urn:sal:restconf:event:subscription");
+ private static final XMLNamespace NAMESPACE_EVENT_SUBSCRIPTION_AUGMENT =
+ XMLNamespace.of("urn:sal:restconf:event:subscription");
private static final String DATASTORE_PARAM_NAME = "datastore";
private static final String NETCONF_BASE_PAYLOAD_NAME = "data";
- private static final QName NETCONF_BASE_QNAME = QName.create(QNameModule.create(URI.create(NETCONF_BASE), null),
+ private static final QName NETCONF_BASE_QNAME = QName.create(QNameModule.create(XMLNamespace.of(NETCONF_BASE)),
NETCONF_BASE_PAYLOAD_NAME).intern();
- private static final QNameModule SAL_REMOTE_AUGMENT;
-
- 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 QNameModule SAL_REMOTE_AUGMENT = QNameModule.create(NAMESPACE_EVENT_SUBSCRIPTION_AUGMENT,
+ Revision.of("2014-07-08"));
private static final AugmentationIdentifier SAL_REMOTE_AUG_IDENTIFIER =
new AugmentationIdentifier(ImmutableSet.of(
.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) {
+ @Inject
+ public 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;
+ /**
+ * Factory method.
+ *
+ * @deprecated Just use {@link #RestconfImpl(BrokerFacade, ControllerContext)} constructor instead.
+ */
+ @Deprecated
+ public static RestconfImpl newInstance(final BrokerFacade broker, final ControllerContext controllerContext) {
+ return new RestconfImpl(broker, controllerContext);
}
@Override
+ @Deprecated
public NormalizedNodeContext getModules(final UriInfo uriInfo) {
- final Set<Module> allModules = this.controllerContext.getAllModules();
- final MapNode allModuleMap = makeModuleMapNode(allModules);
+ final MapNode allModuleMap = makeModuleMapNode(controllerContext.getAllModules());
- final SchemaContext schemaContext = this.controllerContext.getGlobalSchema();
+ final EffectiveModelContext schemaContext = controllerContext.getGlobalSchema();
final Module restconfModule = getRestconfModule();
- final DataSchemaNode modulesSchemaNode = this.controllerContext.getRestconfModuleRestConfSchemaNode(
+ final DataSchemaNode modulesSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
restconfModule, Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
- Preconditions.checkState(modulesSchemaNode instanceof ContainerSchemaNode);
+ checkState(modulesSchemaNode instanceof ContainerSchemaNode);
- final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> moduleContainerBuilder =
- Builders.containerBuilder((ContainerSchemaNode) modulesSchemaNode);
+ final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> moduleContainerBuilder =
+ SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) modulesSchemaNode);
moduleContainerBuilder.withChild(allModuleMap);
- return new NormalizedNodeContext(new InstanceIdentifierContext<>(null, modulesSchemaNode, null, schemaContext),
+ return new NormalizedNodeContext(new InstanceIdentifierContext(null, modulesSchemaNode, null, schemaContext),
moduleContainerBuilder.build(), QueryParametersParser.parseWriterParameters(uriInfo));
}
* Valid only for mount point.
*/
@Override
+ @Deprecated
public NormalizedNodeContext getModules(final String identifier, final UriInfo uriInfo) {
- Preconditions.checkNotNull(identifier);
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);
}
- final InstanceIdentifierContext<?> mountPointIdentifier =
- this.controllerContext.toMountPointIdentifier(identifier);
+ final InstanceIdentifierContext mountPointIdentifier =
+ controllerContext.toMountPointIdentifier(identifier);
final DOMMountPoint mountPoint = mountPointIdentifier.getMountPoint();
- final Set<Module> modules = this.controllerContext.getAllModules(mountPoint);
- final MapNode mountPointModulesMap = makeModuleMapNode(modules);
+ final MapNode mountPointModulesMap = makeModuleMapNode(controllerContext.getAllModules(mountPoint));
final Module restconfModule = getRestconfModule();
- final DataSchemaNode modulesSchemaNode = this.controllerContext.getRestconfModuleRestConfSchemaNode(
+ final DataSchemaNode modulesSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
restconfModule, Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
- Preconditions.checkState(modulesSchemaNode instanceof ContainerSchemaNode);
+ checkState(modulesSchemaNode instanceof ContainerSchemaNode);
- final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> moduleContainerBuilder =
- Builders.containerBuilder((ContainerSchemaNode) modulesSchemaNode);
+ final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> moduleContainerBuilder =
+ SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) modulesSchemaNode);
moduleContainerBuilder.withChild(mountPointModulesMap);
return new NormalizedNodeContext(
- new InstanceIdentifierContext<>(null, modulesSchemaNode, mountPoint,
- this.controllerContext.getGlobalSchema()),
+ new InstanceIdentifierContext(null, modulesSchemaNode, mountPoint,
+ controllerContext.getGlobalSchema()),
moduleContainerBuilder.build(), QueryParametersParser.parseWriterParameters(uriInfo));
}
@Override
+ @Deprecated
public NormalizedNodeContext getModule(final String identifier, final UriInfo uriInfo) {
- Preconditions.checkNotNull(identifier);
- final QName moduleNameAndRevision = getModuleNameAndRevision(identifier);
+ final Entry<String, Revision> nameRev = getModuleNameAndRevision(requireNonNull(identifier));
Module module = null;
DOMMountPoint mountPoint = null;
- final SchemaContext schemaContext;
+ final EffectiveModelContext schemaContext;
if (identifier.contains(ControllerContext.MOUNT)) {
- final InstanceIdentifierContext<?> mountPointIdentifier =
- this.controllerContext.toMountPointIdentifier(identifier);
+ final InstanceIdentifierContext mountPointIdentifier =
+ controllerContext.toMountPointIdentifier(identifier);
mountPoint = mountPointIdentifier.getMountPoint();
- module = this.controllerContext.findModuleByNameAndRevision(mountPoint, moduleNameAndRevision);
- schemaContext = mountPoint.getSchemaContext();
+ module = controllerContext.findModuleByNameAndRevision(mountPoint, nameRev.getKey(),
+ nameRev.getValue());
+ schemaContext = modelContext(mountPoint);
} else {
- module = this.controllerContext.findModuleByNameAndRevision(moduleNameAndRevision);
- schemaContext = this.controllerContext.getGlobalSchema();
+ module = controllerContext.findModuleByNameAndRevision(nameRev.getKey(), nameRev.getValue());
+ schemaContext = controllerContext.getGlobalSchema();
}
if (module == null) {
- final String errMsg = "Module with name '" + moduleNameAndRevision.getLocalName() + "' and revision '"
- + moduleNameAndRevision.getRevision() + "' 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();
final Set<Module> modules = Collections.singleton(module);
final MapNode moduleMap = makeModuleMapNode(modules);
- final DataSchemaNode moduleSchemaNode = this.controllerContext
+ final DataSchemaNode moduleSchemaNode = controllerContext
.getRestconfModuleRestConfSchemaNode(restconfModule, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
- Preconditions.checkState(moduleSchemaNode instanceof ListSchemaNode);
+ checkState(moduleSchemaNode instanceof ListSchemaNode);
return new NormalizedNodeContext(
- new InstanceIdentifierContext<>(null, moduleSchemaNode, mountPoint, schemaContext), moduleMap,
+ new InstanceIdentifierContext(null, moduleSchemaNode, mountPoint, schemaContext), moduleMap,
QueryParametersParser.parseWriterParameters(uriInfo));
}
@Override
+ @Deprecated
public NormalizedNodeContext getAvailableStreams(final UriInfo uriInfo) {
- final SchemaContext schemaContext = this.controllerContext.getGlobalSchema();
+ final EffectiveModelContext schemaContext = controllerContext.getGlobalSchema();
final Set<String> availableStreams = Notificator.getStreamNames();
final Module restconfModule = getRestconfModule();
- final DataSchemaNode streamSchemaNode = this.controllerContext
+ final DataSchemaNode streamSchemaNode = controllerContext
.getRestconfModuleRestConfSchemaNode(restconfModule, Draft02.RestConfModule.STREAM_LIST_SCHEMA_NODE);
- Preconditions.checkState(streamSchemaNode instanceof ListSchemaNode);
+ checkState(streamSchemaNode instanceof ListSchemaNode);
- final CollectionNodeBuilder<MapEntryNode, MapNode> listStreamsBuilder =
- Builders.mapBuilder((ListSchemaNode) streamSchemaNode);
+ final CollectionNodeBuilder<MapEntryNode, SystemMapNode> listStreamsBuilder =
+ SchemaAwareBuilders.mapBuilder((ListSchemaNode) streamSchemaNode);
for (final String streamName : availableStreams) {
listStreamsBuilder.withChild(toStreamEntryNode(streamName, streamSchemaNode));
}
- final DataSchemaNode streamsContainerSchemaNode = this.controllerContext.getRestconfModuleRestConfSchemaNode(
+ final DataSchemaNode streamsContainerSchemaNode = controllerContext.getRestconfModuleRestConfSchemaNode(
restconfModule, Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
- Preconditions.checkState(streamsContainerSchemaNode instanceof ContainerSchemaNode);
+ checkState(streamsContainerSchemaNode instanceof ContainerSchemaNode);
- final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> streamsContainerBuilder =
- Builders.containerBuilder((ContainerSchemaNode) streamsContainerSchemaNode);
+ final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> streamsContainerBuilder =
+ SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) streamsContainerSchemaNode);
streamsContainerBuilder.withChild(listStreamsBuilder.build());
return new NormalizedNodeContext(
- new InstanceIdentifierContext<>(null, streamsContainerSchemaNode, null, schemaContext),
+ new InstanceIdentifierContext(null, streamsContainerSchemaNode, null, schemaContext),
streamsContainerBuilder.build(), QueryParametersParser.parseWriterParameters(uriInfo));
}
@Override
- public NormalizedNodeContext getOperations(final UriInfo uriInfo) {
- final Set<Module> allModules = this.controllerContext.getAllModules();
- return operationsFromModulesToNormalizedContext(allModules, null);
+ @Deprecated
+ public String getOperationsJSON() {
+ return OperationsContent.JSON.bodyFor(controllerContext.getGlobalSchema());
}
@Override
- public NormalizedNodeContext getOperations(final String identifier, final UriInfo uriInfo) {
- Set<Module> modules = null;
- DOMMountPoint mountPoint = null;
- if (identifier.contains(ControllerContext.MOUNT)) {
- final InstanceIdentifierContext<?> mountPointIdentifier =
- this.controllerContext.toMountPointIdentifier(identifier);
- mountPoint = mountPointIdentifier.getMountPoint();
- 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);
- }
-
- return operationsFromModulesToNormalizedContext(modules, mountPoint);
+ @Deprecated
+ public String getOperationsXML() {
+ return OperationsContent.XML.bodyFor(controllerContext.getGlobalSchema());
}
- /**
- * Special case only for GET restconf/operations use (since moment of
- * pre-Beryllium Yang parser and Yang model API removal). The method is
- * creating fake schema context with fake module and fake data by use own
- * implementations of schema nodes and module.
- *
- * @param modules
- * set of modules for get RPCs from every module
- * @param mountPoint
- * mount point, if in use otherwise null
- * @return {@link NormalizedNodeContext}
- */
- private static NormalizedNodeContext operationsFromModulesToNormalizedContext(final Set<Module> modules,
- final DOMMountPoint mountPoint) {
-
- final Collection<Module> neededModules = new ArrayList<>(modules.size());
- final ArrayList<LeafSchemaNode> fakeRpcSchema = new ArrayList<>();
-
- for (final Module m : modules) {
- final Set<RpcDefinition> rpcs = m.getRpcs();
- if (!rpcs.isEmpty()) {
- neededModules.add(m);
-
- fakeRpcSchema.ensureCapacity(fakeRpcSchema.size() + rpcs.size());
- rpcs.forEach(rpc -> fakeRpcSchema.add(new FakeLeafSchemaNode(rpc.getQName())));
- }
- }
-
- final ContainerSchemaNode fakeCont = new FakeContainerSchemaNode(fakeRpcSchema);
- final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> containerBuilder =
- Builders.containerBuilder(fakeCont);
-
- for (final LeafSchemaNode leaf : fakeRpcSchema) {
- containerBuilder.withChild(Builders.leafBuilder(leaf).build());
+ @Override
+ @Deprecated
+ public NormalizedNodeContext getOperations(final String identifier, final UriInfo uriInfo) {
+ if (!identifier.contains(ControllerContext.MOUNT)) {
+ 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);
}
- final Collection<Module> fakeModules = new ArrayList<>(neededModules.size() + 1);
- neededModules.forEach(imp -> fakeModules.add(new FakeImportedModule(imp)));
- fakeModules.add(new FakeRestconfModule(neededModules, fakeCont));
-
- final SchemaContext fakeSchemaCtx = SimpleSchemaContext.forModules(ImmutableSet.copyOf(fakeModules));
- final InstanceIdentifierContext<ContainerSchemaNode> instanceIdentifierContext =
- new InstanceIdentifierContext<>(null, fakeCont, mountPoint, fakeSchemaCtx);
- return new NormalizedNodeContext(instanceIdentifierContext, containerBuilder.build());
+ final InstanceIdentifierContext mountPointIdentifier = controllerContext.toMountPointIdentifier(identifier);
+ final DOMMountPoint mountPoint = mountPointIdentifier.getMountPoint();
+ final var entry = OperationsResourceUtils.contextForModelContext(modelContext(mountPoint), mountPoint);
+ return new NormalizedNodeContext(entry.getKey(), entry.getValue());
}
private Module getRestconfModule() {
- final Module restconfModule = this.controllerContext.getRestconfModule();
+ final Module restconfModule = controllerContext.getRestconfModule();
if (restconfModule == null) {
LOG.debug("ietf-restconf module was not found.");
throw new RestconfDocumentedException("ietf-restconf module was not found.", ErrorType.APPLICATION,
return restconfModule;
}
- private static QName getModuleNameAndRevision(final String identifier) {
+ private static Entry<String, Revision> getModuleNameAndRevision(final String identifier) {
final int mountIndex = identifier.indexOf(ControllerContext.MOUNT);
String moduleNameAndRevision = "";
if (mountIndex >= 0) {
moduleNameAndRevision = identifier;
}
- final Splitter splitter = Splitter.on("/").omitEmptyStrings();
- final Iterable<String> split = splitter.split(moduleNameAndRevision);
- final List<String> pathArgs = Lists.<String>newArrayList(split);
+ final Splitter splitter = Splitter.on('/').omitEmptyStrings();
+ final List<String> 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);
}
try {
- final String moduleName = pathArgs.get(0);
- final String revision = pathArgs.get(1);
- 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);
+ 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);
throw new RestconfDocumentedException("URI has bad format. It should be \'moduleName/yyyy-MM-dd\'",
- ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
+ ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE, e);
}
}
@Override
public NormalizedNodeContext invokeRpc(final String identifier, final NormalizedNodeContext payload,
final UriInfo uriInfo) {
- final SchemaPath type = payload.getInstanceIdentifierContext().getSchemaNode().getPath();
- final URI namespace = payload.getInstanceIdentifierContext().getSchemaNode().getQName().getNamespace();
- final CheckedFuture<DOMRpcResult, DOMRpcException> response;
+ if (payload == null) {
+ // no payload specified, reroute this to no payload invokeRpc implementation
+ return invokeRpc(identifier, uriInfo);
+ }
+
+ final SchemaNode schema = payload.getInstanceIdentifierContext().getSchemaNode();
+ final ListenableFuture<? extends DOMRpcResult> response;
final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint();
- final SchemaContext schemaContext;
+ final NormalizedNode input = nonnullInput(schema, payload.getData());
+ final EffectiveModelContext schemaContext;
if (mountPoint != null) {
final Optional<DOMRpcService> mountRpcServices = mountPoint.getService(DOMRpcService.class);
- if (!mountRpcServices.isPresent()) {
+ if (mountRpcServices.isEmpty()) {
LOG.debug("Error: Rpc service is missing.");
throw new RestconfDocumentedException("Rpc service is missing.");
}
- schemaContext = mountPoint.getSchemaContext();
- response = mountRpcServices.get().invokeRpc(type, payload.getData());
+ schemaContext = modelContext(mountPoint);
+ response = mountRpcServices.get().invokeRpc(schema.getQName(), input);
} else {
+ final XMLNamespace namespace = schema.getQName().getNamespace();
if (namespace.toString().equals(SAL_REMOTE_NAMESPACE)) {
if (identifier.contains(CREATE_DATA_SUBSCR)) {
response = invokeSalRemoteRpcSubscribeRPC(payload);
throw new RestconfDocumentedException(msg, ErrorType.RPC, ErrorTag.OPERATION_NOT_SUPPORTED);
}
} else {
- response = this.broker.invokeRpc(type, payload.getData());
+ response = broker.invokeRpc(schema.getQName(), input);
}
- schemaContext = this.controllerContext.getGlobalSchema();
+ schemaContext = controllerContext.getGlobalSchema();
}
final DOMRpcResult result = checkRpcResponse(response);
RpcDefinition resultNodeSchema = null;
- final NormalizedNode<?, ?> resultData = result.getResult();
+ final NormalizedNode resultData;
if (result != null && result.getResult() != null) {
+ resultData = result.getResult();
resultNodeSchema = (RpcDefinition) payload.getInstanceIdentifierContext().getSchemaNode();
+ } else {
+ resultData = null;
}
- return new NormalizedNodeContext(
- 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);
+ if (resultData != null && ((ContainerNode) resultData).isEmpty()) {
+ throw new WebApplicationException(Response.Status.NO_CONTENT);
+ } else {
+ return new NormalizedNodeContext(
+ new InstanceIdentifierContext(null, resultNodeSchema, mountPoint, schemaContext),
+ resultData, QueryParametersParser.parseWriterParameters(uriInfo));
}
+ }
- String identifierEncoded = null;
- DOMMountPoint mountPoint = null;
- final SchemaContext schemaContext;
+ @SuppressFBWarnings(value = "NP_LOAD_OF_KNOWN_NULL_VALUE",
+ justification = "Looks like a false positive, see below FIXME")
+ private NormalizedNodeContext invokeRpc(final String identifier, final UriInfo uriInfo) {
+ final DOMMountPoint mountPoint;
+ final String identifierEncoded;
+ final EffectiveModelContext schemaContext;
if (identifier.contains(ControllerContext.MOUNT)) {
// mounted RPC call - look up mount instance.
- final InstanceIdentifierContext<?> mountPointId = this.controllerContext.toMountPointIdentifier(identifier);
+ final InstanceIdentifierContext mountPointId = controllerContext.toMountPointIdentifier(identifier);
mountPoint = mountPointId.getMountPoint();
- schemaContext = mountPoint.getSchemaContext();
+ schemaContext = modelContext(mountPoint);
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 {
+ } else if (identifier.indexOf('/') == CHAR_NOT_FOUND) {
identifierEncoded = identifier;
- schemaContext = this.controllerContext.getGlobalSchema();
+ mountPoint = null;
+ schemaContext = controllerContext.getGlobalSchema();
+ } else {
+ 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);
}
- final String identifierDecoded = this.controllerContext.urlPathArgDecode(identifierEncoded);
-
- RpcDefinition rpc = null;
+ final String identifierDecoded = ControllerContext.urlPathArgDecode(identifierEncoded);
+ final RpcDefinition rpc;
if (mountPoint == null) {
- rpc = this.controllerContext.getRpcDefinition(identifierDecoded, null);
+ rpc = controllerContext.getRpcDefinition(identifierDecoded);
} else {
- rpc = findRpc(mountPoint.getSchemaContext(), identifierDecoded);
+ rpc = findRpc(modelContext(mountPoint), identifierDecoded);
}
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.");
- // FIXME : find a correct Error from specification
- throw new IllegalStateException("RPC " + rpc + " does'n need input value!");
+ LOG.debug("No input specified for RPC {} with an input section", rpc);
+ throw new RestconfDocumentedException("No input specified for RPC " + rpc
+ + " with an input section defined", ErrorType.RPC, ErrorTag.MISSING_ELEMENT);
}
- final CheckedFuture<DOMRpcResult, DOMRpcException> response;
+ final ContainerNode input = defaultInput(rpc.getQName());
+ final ListenableFuture<? extends DOMRpcResult> response;
if (mountPoint != null) {
final Optional<DOMRpcService> mountRpcServices = mountPoint.getService(DOMRpcService.class);
- if (!mountRpcServices.isPresent()) {
+ if (mountRpcServices.isEmpty()) {
throw new RestconfDocumentedException("Rpc service is missing.");
}
- response = mountRpcServices.get().invokeRpc(rpc.getPath(), null);
+ response = mountRpcServices.get().invokeRpc(rpc.getQName(), input);
} else {
- response = this.broker.invokeRpc(rpc.getPath(), null);
+ response = broker.invokeRpc(rpc.getQName(), input);
}
- final DOMRpcResult result = checkRpcResponse(response);
+ final NormalizedNode result = checkRpcResponse(response).getResult();
+ if (result != null && ((ContainerNode) result).isEmpty()) {
+ throw new WebApplicationException(Response.Status.NO_CONTENT);
+ }
+
+ // FIXME: in reference to the above @SupressFBWarnings: "mountPoint" reference here trips up SpotBugs, as it
+ // thinks it can only ever be null. Except it can very much be non-null. The core problem is the horrible
+ // structure of this code where we have a sh*tload of checks for mountpoint above and all over the
+ // codebase where all that difference should have been properly encapsulated.
+ //
+ // This is legacy code, so if anybody cares to do that refactor, feel free to contribute, but I am not
+ // doing that work.
+ return new NormalizedNodeContext(new InstanceIdentifierContext(null, rpc, mountPoint, schemaContext), result,
+ QueryParametersParser.parseWriterParameters(uriInfo));
+ }
- return new NormalizedNodeContext(new InstanceIdentifierContext<>(null, rpc, mountPoint, schemaContext),
- result.getResult(), QueryParametersParser.parseWriterParameters(uriInfo));
+ private static @NonNull NormalizedNode nonnullInput(final SchemaNode rpc, final NormalizedNode input) {
+ return input != null ? input : defaultInput(rpc.getQName());
}
- private static DOMRpcResult checkRpcResponse(final CheckedFuture<DOMRpcResult, DOMRpcException> response) {
+ private static @NonNull ContainerNode defaultInput(final QName rpcName) {
+ return ImmutableNodes.containerNode(YangConstants.operationInputQName(rpcName.getModule()));
+ }
+
+ @SuppressWarnings("checkstyle:avoidHidingCauseException")
+ private static DOMRpcResult checkRpcResponse(final ListenableFuture<? extends DOMRpcResult> response) {
if (response == null) {
return null;
}
try {
final DOMRpcResult retValue = response.get();
- if (retValue.getErrors() == null || retValue.getErrors().isEmpty()) {
+ 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);
- throw new RestconfDocumentedException(errMsg, ErrorType.RPC, ErrorTag.PARTIAL_OPERATION);
+ 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);
Throwable cause = e.getCause();
- if (cause != null) {
- while (cause.getCause() != null) {
- cause = cause.getCause();
- }
-
- if (cause instanceof IllegalArgumentException) {
- throw new RestconfDocumentedException(cause.getMessage(), ErrorType.PROTOCOL,
- ErrorTag.INVALID_VALUE);
- } else if (cause instanceof DOMRpcImplementationNotAvailableException) {
- throw new RestconfDocumentedException(cause.getMessage(), ErrorType.APPLICATION,
- ErrorTag.OPERATION_NOT_SUPPORTED);
- }
- throw new RestconfDocumentedException("The operation encountered an unexpected error while executing.",
- cause);
- } else {
+ if (cause == null) {
throw new RestconfDocumentedException("The operation encountered an unexpected error while executing.",
- e);
+ e);
+ }
+ while (cause.getCause() != null) {
+ cause = cause.getCause();
+ }
+
+ if (cause instanceof IllegalArgumentException) {
+ throw new RestconfDocumentedException(cause.getMessage(), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
+ } else if (cause instanceof DOMRpcImplementationNotAvailableException) {
+ throw new RestconfDocumentedException(cause.getMessage(), ErrorType.APPLICATION,
+ ErrorTag.OPERATION_NOT_SUPPORTED);
}
+ throw new RestconfDocumentedException("The operation encountered an unexpected error while executing.",
+ cause);
} 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);
}
}
}
}
- private CheckedFuture<DOMRpcResult, DOMRpcException>
- invokeSalRemoteRpcSubscribeRPC(final NormalizedNodeContext payload) {
+ private ListenableFuture<DOMRpcResult> invokeSalRemoteRpcSubscribeRPC(final NormalizedNodeContext payload) {
final ContainerNode value = (ContainerNode) payload.getData();
final QName rpcQName = payload.getInstanceIdentifierContext().getSchemaNode().getQName();
- final Optional<DataContainerChild<? extends PathArgument, ?>> path = value.getChild(new NodeIdentifier(
- QName.create(payload.getInstanceIdentifierContext().getSchemaNode().getQName(), "path")));
- final Object pathValue = path.isPresent() ? path.get().getValue() : null;
+ final Optional<DataContainerChild> path =
+ value.findChildByArg(new NodeIdentifier(QName.create(rpcQName, "path")));
+ final Object pathValue = path.isPresent() ? path.get().body() : 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;
NotificationOutputType outputType = null;
if (!pathIdentifier.isEmpty()) {
final String fullRestconfIdentifier =
- DATA_SUBSCR + this.controllerContext.toFullRestconfIdentifier(pathIdentifier, null);
+ DATA_SUBSCR + controllerContext.toFullRestconfIdentifier(pathIdentifier, null);
LogicalDatastoreType datastore =
parseEnumTypeParameter(value, LogicalDatastoreType.class, DATASTORE_PARAM_NAME);
datastore = datastore == null ? DEFAULT_DATASTORE : datastore;
- DataChangeScope scope = parseEnumTypeParameter(value, DataChangeScope.class, SCOPE_PARAM_NAME);
- scope = scope == null ? DEFAULT_SCOPE : scope;
+ Scope scope = parseEnumTypeParameter(value, Scope.class, SCOPE_PARAM_NAME);
+ scope = scope == null ? Scope.BASE : scope;
outputType = parseEnumTypeParameter(value, NotificationOutputType.class, OUTPUT_TYPE_PARAM_NAME);
outputType = outputType == null ? NotificationOutputType.XML : outputType;
}
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");
.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])) {
break;
}
}
+
+ // TODO: this flag is always ignored
boolean tagged = false;
if (withDefaUsed) {
- if (withDefa.equals("report-all-tagged")) {
+ if ("report-all-tagged".equals(withDefa)) {
tagged = true;
withDefa = null;
}
- if (withDefa.equals("report-all")) {
+ if ("report-all".equals(withDefa)) {
withDefa = null;
}
}
- final InstanceIdentifierContext<?> iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
+ final InstanceIdentifierContext iiWithData = controllerContext.toInstanceIdentifier(identifier);
final DOMMountPoint mountPoint = iiWithData.getMountPoint();
- NormalizedNode<?, ?> data = null;
+ NormalizedNode data = null;
final YangInstanceIdentifier normalizedII = iiWithData.getInstanceIdentifier();
if (mountPoint != null) {
- data = this.broker.readConfigurationData(mountPoint, normalizedII, withDefa);
+ data = broker.readConfigurationData(mountPoint, normalizedII, withDefa);
} else {
- data = this.broker.readConfigurationData(normalizedII, withDefa);
+ data = 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));
+ return new NormalizedNodeContext(iiWithData, data, QueryParametersParser.parseWriterParameters(uriInfo));
}
@Override
public NormalizedNodeContext readOperationalData(final String identifier, final UriInfo uriInfo) {
- final InstanceIdentifierContext<?> iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
+ final InstanceIdentifierContext iiWithData = controllerContext.toInstanceIdentifier(identifier);
final DOMMountPoint mountPoint = iiWithData.getMountPoint();
- NormalizedNode<?, ?> data = null;
+ NormalizedNode data = null;
final YangInstanceIdentifier normalizedII = iiWithData.getInstanceIdentifier();
if (mountPoint != null) {
- data = this.broker.readOperationalData(mountPoint, normalizedII);
+ data = broker.readOperationalData(mountPoint, normalizedII);
} else {
- data = this.broker.readOperationalData(normalizedII);
+ data = 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) {
"Point parameter can be used only with 'after' or 'before' values of Insert parameter.");
}
- Preconditions.checkNotNull(identifier);
+ requireNonNull(identifier);
- final InstanceIdentifierContext<?> iiWithData = payload.getInstanceIdentifierContext();
+ final InstanceIdentifierContext iiWithData = payload.getInstanceIdentifierContext();
validateInput(iiWithData.getSchemaNode(), payload);
validateTopLevelNodeName(payload, iiWithData.getInstanceIdentifier());
while (true) {
if (mountPoint != null) {
- result = this.broker.commitMountPointDataPut(mountPoint, normalizedII, payload.getData(), insert,
+ result = broker.commitMountPointDataPut(mountPoint, normalizedII, payload.getData(), insert,
point);
} else {
- result = this.broker.commitConfigurationDataPut(this.controllerContext.getGlobalSchema(), normalizedII,
+ result = broker.commitConfigurationDataPut(controllerContext.getGlobalSchema(), normalizedII,
payload.getData(), insert, point);
}
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();
}
}
private static void validateTopLevelNodeName(final NormalizedNodeContext node,
final YangInstanceIdentifier identifier) {
- final String payloadName = node.getData().getNodeType().getLocalName();
+ final String payloadName = node.getData().getIdentifier().getNodeType().getLocalName();
// no arguments
if (identifier.isEmpty()) {
// no "data" payload
- if (!node.getData().getNodeType().equals(NETCONF_BASE_QNAME)) {
+ if (!node.getData().getIdentifier().getNodeType().equals(NETCONF_BASE_QNAME)) {
throw new RestconfDocumentedException("Instance identifier has to contain at least one path argument",
ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
}
*
*/
private static void validateListKeysEqualityInPayloadAndUri(final NormalizedNodeContext payload) {
- Preconditions.checkArgument(payload != null);
- final InstanceIdentifierContext<?> iiWithData = payload.getInstanceIdentifierContext();
+ checkArgument(payload != null);
+ final InstanceIdentifierContext iiWithData = payload.getInstanceIdentifierContext();
final PathArgument lastPathArgument = iiWithData.getInstanceIdentifier().getLastPathArgument();
final SchemaNode schemaNode = iiWithData.getSchemaNode();
- final NormalizedNode<?, ?> data = payload.getData();
+ final NormalizedNode data = payload.getData();
if (schemaNode instanceof ListSchemaNode) {
final List<QName> keyDefinitions = ((ListSchemaNode) schemaNode).getKeyDefinition();
if (lastPathArgument instanceof NodeIdentifierWithPredicates && data instanceof MapEntryNode) {
- final Map<QName, Object> uriKeyValues =
- ((NodeIdentifierWithPredicates) lastPathArgument).getKeyValues();
+ final Map<QName, Object> uriKeyValues = ((NodeIdentifierWithPredicates) lastPathArgument).asMap();
isEqualUriAndPayloadKeyValues(uriKeyValues, (MapEntryNode) data, keyDefinitions);
}
}
public static void isEqualUriAndPayloadKeyValues(final Map<QName, Object> uriKeyValues, final MapEntryNode payload,
final List<QName> keyDefinitions) {
- final Map<QName, Object> mutableCopyUriKeyValues = Maps.newHashMap(uriKeyValues);
+ final Map<QName, Object> mutableCopyUriKeyValues = new HashMap<>(uriKeyValues);
for (final QName keyDefinition : keyDefinitions) {
- final Object uriKeyValue = mutableCopyUriKeyValues.remove(keyDefinition);
- // should be caught during parsing URI to InstanceIdentifier
- RestconfValidationUtils.checkDocumentedError(uriKeyValue != null, ErrorType.PROTOCOL, ErrorTag.DATA_MISSING,
- "Missing key " + keyDefinition + " in URI.");
+ final Object uriKeyValue = RestconfDocumentedException.throwIfNull(
+ // should be caught during parsing URI to InstanceIdentifier
+ mutableCopyUriKeyValues.remove(keyDefinition), ErrorType.PROTOCOL, ErrorTag.DATA_MISSING,
+ "Missing key %s in URI.", keyDefinition);
- final Object dataKeyValue = payload.getIdentifier().getKeyValues().get(keyDefinition);
+ final Object dataKeyValue = payload.getIdentifier().getValue(keyDefinition);
if (!Objects.deepEquals(uriKeyValue, dataKeyValue)) {
final String errMsg = "The value '" + uriKeyValue + "' for key '" + keyDefinition.getLocalName()
throw new RestconfDocumentedException("Input is required.", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
}
final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint();
- final InstanceIdentifierContext<?> iiWithData = payload.getInstanceIdentifierContext();
+ final InstanceIdentifierContext iiWithData = payload.getInstanceIdentifierContext();
final YangInstanceIdentifier normalizedII = iiWithData.getInstanceIdentifier();
boolean insertUsed = false;
String insert = null;
String point = null;
- for (final Entry<String, List<String>> entry : uriInfo.getQueryParameters().entrySet()) {
- switch (entry.getKey()) {
- case "insert":
- if (!insertUsed) {
- insertUsed = true;
- insert = entry.getValue().iterator().next();
- } else {
- throw new RestconfDocumentedException("Insert parameter can be used only once.");
- }
- break;
- case "point":
- if (!pointUsed) {
- pointUsed = true;
- point = entry.getValue().iterator().next();
- } else {
- throw new RestconfDocumentedException("Point parameter can be used only once.");
- }
- break;
- default:
- throw new RestconfDocumentedException("Bad parameter for post: " + entry.getKey());
+ if (uriInfo != null) {
+ for (final Entry<String, List<String>> entry : uriInfo.getQueryParameters().entrySet()) {
+ switch (entry.getKey()) {
+ case "insert":
+ if (!insertUsed) {
+ insertUsed = true;
+ insert = entry.getValue().iterator().next();
+ } else {
+ throw new RestconfDocumentedException("Insert parameter can be used only once.");
+ }
+ break;
+ case "point":
+ if (!pointUsed) {
+ pointUsed = true;
+ point = entry.getValue().iterator().next();
+ } else {
+ throw new RestconfDocumentedException("Point parameter can be used only once.");
+ }
+ break;
+ default:
+ throw new RestconfDocumentedException("Bad parameter for post: " + entry.getKey());
+ }
}
}
"Point parameter can be used only with 'after' or 'before' values of Insert parameter.");
}
- CheckedFuture<Void, TransactionCommitFailedException> future;
+ FluentFuture<? extends CommitInfo> future;
if (mountPoint != null) {
- future = this.broker.commitConfigurationDataPost(mountPoint, normalizedII, payload.getData(), insert,
+ future = broker.commitConfigurationDataPost(mountPoint, normalizedII, payload.getData(), insert,
point);
} else {
- future = this.broker.commitConfigurationDataPost(this.controllerContext.getGlobalSchema(), normalizedII,
+ future = broker.commitConfigurationDataPost(controllerContext.getGlobalSchema(), normalizedII,
payload.getData(), insert, point);
}
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.");
return responseBuilder.build();
}
- // 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) {
final UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
uriBuilder.path("config");
try {
- uriBuilder.path(this.controllerContext.toFullRestconfIdentifier(normalizedII, mountPoint));
+ uriBuilder.path(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();
@Override
public Response deleteConfigurationData(final String identifier) {
- final InstanceIdentifierContext<?> iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
+ final InstanceIdentifierContext iiWithData = controllerContext.toInstanceIdentifier(identifier);
final DOMMountPoint mountPoint = iiWithData.getMountPoint();
final YangInstanceIdentifier normalizedII = iiWithData.getInstanceIdentifier();
- final CheckedFuture<Void, TransactionCommitFailedException> future;
+ final FluentFuture<? extends CommitInfo> future;
if (mountPoint != null) {
- future = this.broker.commitConfigurationDataDelete(mountPoint, normalizedII);
+ future = broker.commitConfigurationDataDelete(mountPoint, normalizedII);
} else {
- future = this.broker.commitConfigurationDataDelete(normalizedII);
+ future = broker.commitConfigurationDataDelete(normalizedII);
}
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<Throwable> 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);
+ 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();
* <ul>
* <li>datastore - default CONFIGURATION (other values of
* {@link LogicalDatastoreType} enum type)</li>
- * <li>scope - default BASE (other values of {@link DataChangeScope})</li>
+ * <li>scope - default BASE (other values of {@link Scope})</li>
* </ul>
*/
@Override
String filter = null;
boolean leafNodesOnlyUsed = false;
boolean leafNodesOnly = false;
+ boolean skipNotificationDataUsed = false;
+ boolean skipNotificationData = false;
for (final Entry<String, List<String>> entry : uriInfo.getQueryParameters().entrySet()) {
switch (entry.getKey()) {
throw new RestconfDocumentedException("Odl-leaf-nodes-only parameter can be used only once.");
}
break;
+ case "odl-skip-notification-data":
+ if (!skipNotificationDataUsed) {
+ skipNotificationDataUsed = true;
+ skipNotificationData = Boolean.parseBoolean(entry.getValue().iterator().next());
+ } else {
+ throw new RestconfDocumentedException(
+ "Odl-skip-notification-data parameter can be used only once.");
+ }
+ break;
default:
throw new RestconfDocumentedException("Bad parameter used with notifications: " + entry.getKey());
}
}
URI response = null;
if (identifier.contains(DATA_SUBSCR)) {
- response = dataSubs(identifier, uriInfo, start, stop, filter, leafNodesOnly);
+ response = dataSubs(identifier, uriInfo, start, stop, filter, leafNodesOnly, skipNotificationData);
} else if (identifier.contains(NOTIFICATION_STREAM)) {
response = notifStream(identifier, uriInfo, start, stop, filter);
}
if (response != null) {
// prepare node with value of location
- final InstanceIdentifierContext<?> iid = prepareIIDSubsStreamOutput();
- final NormalizedNodeAttrBuilder<NodeIdentifier, Object, LeafNode<Object>> builder =
+ final InstanceIdentifierContext iid = prepareIIDSubsStreamOutput();
+ final NormalizedNodeBuilder<NodeIdentifier, Object, LeafNode<Object>> builder =
ImmutableLeafNodeBuilder.create().withValue(response.toString());
builder.withNodeIdentifier(
NodeIdentifier.create(QName.create("subscribe:to:notification", "2016-10-28", "location")));
// prepare new header with location
- final Map<String, Object> headers = new HashMap<>();
- headers.put("Location", response);
-
- return new NormalizedNodeContext(iid, builder.build(), headers);
+ return new NormalizedNodeContext(iid, builder.build(), ImmutableMap.of("Location", response));
}
final String msg = "Bad type of notification of sal-remote";
* @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 EffectiveModelContext schemaCtx = controllerContext.getGlobalSchema();
final DataSchemaNode location = ((ContainerSchemaNode) schemaCtx
- .findModuleByNamespaceAndRevision(qnameBase.getNamespace(), qnameBase.getRevision())
+ .findModule(qnameBase.getModule()).orElse(null)
.getDataChildByName(qnameBase)).getDataChildByName(QName.create(qnameBase, "location"));
final List<PathArgument> path = new ArrayList<>();
path.add(NodeIdentifier.create(qnameBase));
path.add(NodeIdentifier.create(QName.create(qnameBase, "location")));
- return new InstanceIdentifierContext<SchemaNode>(YangInstanceIdentifier.create(path), location, null,
- schemaCtx);
+ return new InstanceIdentifierContext(YangInstanceIdentifier.create(path), location, null, schemaCtx);
}
/**
}
for (final NotificationListenerAdapter listener : listeners) {
- this.broker.registerToListenNotification(listener);
- listener.setQueryParams(start,
- java.util.Optional.ofNullable(stop), java.util.Optional.ofNullable(filter), false);
+ broker.registerToListenNotification(listener);
+ listener.setQueryParams(start, Optional.ofNullable(stop), Optional.ofNullable(filter), false, false);
}
final UriBuilder uriBuilder = uriInfo.getAbsolutePathBuilder();
final WebSocketServer webSocketServerInstance = WebSocketServer.getInstance(NOTIFICATION_PORT);
final int notificationPort = webSocketServerInstance.getPort();
- final UriBuilder uriToWebsocketServerBuilder = uriBuilder.port(notificationPort).scheme("ws");
+
+ final UriBuilder uriToWebsocketServerBuilder = uriBuilder.port(notificationPort).scheme(getWsScheme(uriInfo));
return uriToWebsocketServerBuilder.replacePath(streamName).build();
}
+ private static String getWsScheme(final UriInfo uriInfo) {
+ URI uri = uriInfo.getAbsolutePath();
+ if (uri == null) {
+ return "ws";
+ }
+ String subscriptionScheme = uri.getScheme().toLowerCase(Locale.ROOT);
+ return subscriptionScheme.equals("https") ? "wss" : "ws";
+ }
+
/**
* Register data change listener by stream name.
*
* @return {@link URI} of location
*/
private URI dataSubs(final String identifier, final UriInfo uriInfo, final Instant start, final Instant stop,
- final String filter, final boolean leafNodesOnly) {
+ final String filter, final boolean leafNodesOnly, final boolean skipNotificationData) {
final String streamName = Notificator.createStreamNameFromUri(identifier);
if (Strings.isNullOrEmpty(streamName)) {
throw new RestconfDocumentedException("Stream name is empty.", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
throw new RestconfDocumentedException("Stream was not found.", ErrorType.PROTOCOL,
ErrorTag.UNKNOWN_ELEMENT);
}
- listener.setQueryParams(start, java.util.Optional.ofNullable(stop),
- java.util.Optional.ofNullable(filter), leafNodesOnly);
+ listener.setQueryParams(start, Optional.ofNullable(stop), Optional.ofNullable(filter), leafNodesOnly,
+ skipNotificationData);
final Map<String, String> paramToValues = resolveValuesFromUri(identifier);
final LogicalDatastoreType datastore =
throw new RestconfDocumentedException("Stream name doesn't contains datastore value (pattern /datastore=)",
ErrorType.APPLICATION, ErrorTag.MISSING_ATTRIBUTE);
}
- final DataChangeScope scope =
- parserURIEnumParameter(DataChangeScope.class, paramToValues.get(SCOPE_PARAM_NAME));
+ final Scope scope = parserURIEnumParameter(Scope.class, paramToValues.get(SCOPE_PARAM_NAME));
if (scope == null) {
throw new RestconfDocumentedException("Stream name doesn't contains datastore value (pattern /scope=)",
ErrorType.APPLICATION, ErrorTag.MISSING_ATTRIBUTE);
}
- this.broker.registerToListenDataChanges(datastore, scope, listener);
+ broker.registerToListenDataChanges(datastore, scope, listener);
final UriBuilder uriBuilder = uriInfo.getAbsolutePathBuilder();
final WebSocketServer webSocketServerInstance = WebSocketServer.getInstance(NOTIFICATION_PORT);
final int notificationPort = webSocketServerInstance.getPort();
- final UriBuilder uriToWebsocketServerBuilder = uriBuilder.port(notificationPort).scheme("ws");
+ final UriBuilder uriToWebsocketServerBuilder = uriBuilder.port(notificationPort).scheme(getWsScheme(uriInfo));
return uriToWebsocketServerBuilder.replacePath(streamName).build();
}
}
try {
- return this.broker.patchConfigurationDataWithinTransaction(context);
+ return broker.patchConfigurationDataWithinTransaction(context);
} catch (final Exception e) {
LOG.debug("Patch transaction failed", e);
- throw new RestconfDocumentedException(e.getMessage());
+ throw new RestconfDocumentedException(e.getMessage(), e);
}
}
}
try {
- return this.broker.patchConfigurationDataWithinTransaction(context);
+ return broker.patchConfigurationDataWithinTransaction(context);
} catch (final Exception e) {
LOG.debug("Patch transaction failed", e);
- throw new RestconfDocumentedException(e.getMessage());
+ throw new RestconfDocumentedException(e.getMessage(), e);
}
}
*/
private static <T> T parseEnumTypeParameter(final ContainerNode value, final Class<T> classDescriptor,
final String paramName) {
- final Optional<DataContainerChild<? extends PathArgument, ?>> optAugNode = value.getChild(
- SAL_REMOTE_AUG_IDENTIFIER);
- if (!optAugNode.isPresent()) {
+ final Optional<DataContainerChild> optAugNode = value.findChildByArg(SAL_REMOTE_AUG_IDENTIFIER);
+ if (optAugNode.isEmpty()) {
return null;
}
- final DataContainerChild<? extends PathArgument, ?> augNode = optAugNode.get();
+ final DataContainerChild augNode = optAugNode.get();
if (!(augNode instanceof AugmentationNode)) {
return null;
}
- final Optional<DataContainerChild<? extends PathArgument, ?>> enumNode = ((AugmentationNode) augNode).getChild(
- new NodeIdentifier(QName.create(SAL_REMOTE_AUGMENT, paramName)));
- if (!enumNode.isPresent()) {
+ final Optional<DataContainerChild> enumNode = ((AugmentationNode) augNode).findChildByArg(
+ new NodeIdentifier(QName.create(SAL_REMOTE_AUGMENT, paramName)));
+ if (enumNode.isEmpty()) {
return null;
}
- final Object rawValue = enumNode.get().getValue();
+ final Object rawValue = enumNode.get().body();
if (!(rawValue instanceof String)) {
return null;
}
return result;
}
- private MapNode makeModuleMapNode(final Set<Module> modules) {
- Preconditions.checkNotNull(modules);
+ private MapNode makeModuleMapNode(final Collection<? extends Module> modules) {
+ requireNonNull(modules);
final Module restconfModule = getRestconfModule();
- final DataSchemaNode moduleSchemaNode = this.controllerContext
+ final DataSchemaNode moduleSchemaNode = controllerContext
.getRestconfModuleRestConfSchemaNode(restconfModule, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
- Preconditions.checkState(moduleSchemaNode instanceof ListSchemaNode);
+ checkState(moduleSchemaNode instanceof ListSchemaNode);
- final CollectionNodeBuilder<MapEntryNode, MapNode> listModuleBuilder =
- Builders.mapBuilder((ListSchemaNode) moduleSchemaNode);
+ final CollectionNodeBuilder<MapEntryNode, SystemMapNode> listModuleBuilder =
+ SchemaAwareBuilders.mapBuilder((ListSchemaNode) moduleSchemaNode);
for (final Module module : modules) {
listModuleBuilder.withChild(toModuleEntryNode(module, moduleSchemaNode));
return listModuleBuilder.build();
}
- protected MapEntryNode toModuleEntryNode(final Module module, final DataSchemaNode moduleSchemaNode) {
- Preconditions.checkArgument(moduleSchemaNode instanceof ListSchemaNode,
+ private static MapEntryNode toModuleEntryNode(final Module module, final DataSchemaNode moduleSchemaNode) {
+ checkArgument(moduleSchemaNode instanceof ListSchemaNode,
"moduleSchemaNode has to be of type ListSchemaNode");
final ListSchemaNode listModuleSchemaNode = (ListSchemaNode) moduleSchemaNode;
- final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> moduleNodeValues =
- Builders.mapEntryBuilder(listModuleSchemaNode);
+ final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> moduleNodeValues =
+ SchemaAwareBuilders.mapEntryBuilder(listModuleSchemaNode);
List<DataSchemaNode> instanceDataChildrenByName =
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());
+ checkState(nameSchemaNode instanceof LeafSchemaNode);
+ moduleNodeValues.withChild(
+ SchemaAwareBuilders.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 String revision = module.getQNameModule().getFormattedRevision();
- moduleNodeValues
- .withChild(Builders.leafBuilder((LeafSchemaNode) revisionSchemaNode).withValue(revision).build());
+ checkState(revisionSchemaNode instanceof LeafSchemaNode);
+ final Optional<Revision> revision = qNameModule.getRevision();
+ moduleNodeValues.withChild(SchemaAwareBuilders.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());
+ checkState(namespaceSchemaNode instanceof LeafSchemaNode);
+ moduleNodeValues.withChild(SchemaAwareBuilders.leafBuilder((LeafSchemaNode) namespaceSchemaNode)
+ .withValue(qNameModule.getNamespace().toString()).build());
instanceDataChildrenByName =
ControllerContext.findInstanceDataChildrenByName(listModuleSchemaNode, "feature");
final DataSchemaNode featureSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
- Preconditions.checkState(featureSchemaNode instanceof LeafListSchemaNode);
- final ListNodeBuilder<Object, LeafSetEntryNode<Object>> featuresBuilder =
- Builders.leafSetBuilder((LeafListSchemaNode) featureSchemaNode);
+ checkState(featureSchemaNode instanceof LeafListSchemaNode);
+ final ListNodeBuilder<Object, SystemLeafSetNode<Object>> featuresBuilder =
+ SchemaAwareBuilders.leafSetBuilder((LeafListSchemaNode) featureSchemaNode);
for (final FeatureDefinition feature : module.getFeatures()) {
- featuresBuilder.withChild(Builders.leafSetEntryBuilder((LeafListSchemaNode) featureSchemaNode)
+ featuresBuilder.withChild(SchemaAwareBuilders.leafSetEntryBuilder((LeafListSchemaNode) featureSchemaNode)
.withValue(feature.getQName().getLocalName()).build());
}
moduleNodeValues.withChild(featuresBuilder.build());
}
protected MapEntryNode toStreamEntryNode(final String streamName, final DataSchemaNode streamSchemaNode) {
- Preconditions.checkArgument(streamSchemaNode instanceof ListSchemaNode,
+ checkArgument(streamSchemaNode instanceof ListSchemaNode,
"streamSchemaNode has to be of type ListSchemaNode");
final ListSchemaNode listStreamSchemaNode = (ListSchemaNode) streamSchemaNode;
- final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> streamNodeValues =
- Builders.mapEntryBuilder(listStreamSchemaNode);
+ final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> streamNodeValues =
+ SchemaAwareBuilders.mapEntryBuilder(listStreamSchemaNode);
List<DataSchemaNode> instanceDataChildrenByName =
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());
+ checkState(nameSchemaNode instanceof LeafSchemaNode);
+ streamNodeValues.withChild(
+ SchemaAwareBuilders.leafBuilder((LeafSchemaNode) nameSchemaNode).withValue(streamName).build());
instanceDataChildrenByName =
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());
+ checkState(descriptionSchemaNode instanceof LeafSchemaNode);
+ streamNodeValues.withChild(SchemaAwareBuilders.leafBuilder((LeafSchemaNode) nameSchemaNode)
+ .withValue("DESCRIPTION_PLACEHOLDER")
+ .build());
instanceDataChildrenByName =
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());
+ checkState(replaySupportSchemaNode instanceof LeafSchemaNode);
+ streamNodeValues.withChild(SchemaAwareBuilders.leafBuilder((LeafSchemaNode) replaySupportSchemaNode)
+ .withValue(Boolean.TRUE).build());
instanceDataChildrenByName =
ControllerContext.findInstanceDataChildrenByName(listStreamSchemaNode, "replay-log-creation-time");
final DataSchemaNode replayLogCreationTimeSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
- Preconditions.checkState(replayLogCreationTimeSchemaNode instanceof LeafSchemaNode);
+ checkState(replayLogCreationTimeSchemaNode instanceof LeafSchemaNode);
streamNodeValues.withChild(
- Builders.leafBuilder((LeafSchemaNode) replayLogCreationTimeSchemaNode).withValue("").build());
+ SchemaAwareBuilders.leafBuilder((LeafSchemaNode) replayLogCreationTimeSchemaNode).withValue("").build());
instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(listStreamSchemaNode, "events");
final DataSchemaNode eventsSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
- Preconditions.checkState(eventsSchemaNode instanceof LeafSchemaNode);
- streamNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) eventsSchemaNode).build());
+ checkState(eventsSchemaNode instanceof LeafSchemaNode);
+ streamNodeValues.withChild(
+ SchemaAwareBuilders.leafBuilder((LeafSchemaNode) eventsSchemaNode).withValue(Empty.value()).build());
return streamNodeValues.build();
}
* contains list of qnames of notifications
* @return - checked future object
*/
- private static CheckedFuture<DOMRpcResult, DOMRpcException> invokeSalRemoteRpcNotifiStrRPC(
- final NormalizedNodeContext payload) {
+ private ListenableFuture<DOMRpcResult> invokeSalRemoteRpcNotifiStrRPC(final NormalizedNodeContext payload) {
final ContainerNode data = (ContainerNode) payload.getData();
LeafSetNode leafSet = null;
String outputType = "XML";
- for (final DataContainerChild<? extends PathArgument, ?> dataChild : data.getValue()) {
+ for (final DataContainerChild dataChild : data.body()) {
if (dataChild instanceof LeafSetNode) {
leafSet = (LeafSetNode) dataChild;
} else if (dataChild instanceof AugmentationNode) {
- outputType = (String) ((AugmentationNode) dataChild).getValue().iterator().next().getValue();
+ outputType = (String) ((AugmentationNode) dataChild).body().iterator().next().body();
}
}
- final Collection<LeafSetEntryNode> entryNodes = leafSet.getValue();
+ final Collection<LeafSetEntryNode<?>> entryNodes = leafSet.body();
final List<SchemaPath> paths = new ArrayList<>();
String streamName = CREATE_NOTIFICATION_STREAM + "/";
- final Iterator<LeafSetEntryNode> iterator = entryNodes.iterator();
+ StringBuilder streamNameBuilder = new StringBuilder(streamName);
+ final Iterator<LeafSetEntryNode<?>> iterator = entryNodes.iterator();
while (iterator.hasNext()) {
- final QName valueQName = QName.create((String) iterator.next().getValue());
- final Module module =
- ControllerContext.getInstance().findModuleByNamespace(valueQName.getModule().getNamespace());
- Preconditions.checkNotNull(module,
- "Module for namespace " + valueQName.getModule().getNamespace() + " does not exist");
+ final QName valueQName = QName.create((String) iterator.next().body());
+ final XMLNamespace namespace = valueQName.getModule().getNamespace();
+ final Module module = controllerContext.findModuleByNamespace(namespace);
+ checkNotNull(module, "Module for namespace %s does not exist", namespace);
NotificationDefinition notifiDef = null;
for (final NotificationDefinition notification : module.getNotifications()) {
if (notification.getQName().equals(valueQName)) {
}
}
final String moduleName = module.getName();
- Preconditions.checkNotNull(notifiDef,
- "Notification " + valueQName + "doesn't exist in module " + moduleName);
- paths.add(notifiDef.getPath());
- streamName = streamName + moduleName + ":" + valueQName.getLocalName();
+ checkNotNull(notifiDef, "Notification %s does not exist in module %s", valueQName, moduleName);
+ paths.add(SchemaPath.of(Absolute.of(notifiDef.getQName())));
+ streamNameBuilder.append(moduleName).append(':').append(valueQName.getLocalName());
if (iterator.hasNext()) {
- streamName = streamName + ",";
+ streamNameBuilder.append(',');
}
}
+ streamName = streamNameBuilder.toString();
+
final QName rpcQName = payload.getInstanceIdentifierContext().getSchemaNode().getQName();
final QName outputQname = QName.create(rpcQName, "output");
final QName streamNameQname = QName.create(rpcQName, "notification-stream-identifier");
.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.immediateFuture(new DefaultDOMRpcResult(output));
+ }
- return Futures.immediateCheckedFuture(defaultDOMRpcResult);
+ private static EffectiveModelContext modelContext(final DOMMountPoint mountPoint) {
+ return mountPoint.getService(DOMSchemaService.class)
+ .flatMap(svc -> Optional.ofNullable(svc.getGlobalContext()))
+ .orElse(null);
}
}