--- /dev/null
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.nb.rfc8040;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import java.net.URI;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
+import org.opendaylight.yangtools.concepts.Immutable;
+
+/**
+ * Abstract base class for StartTimeParameter and StopTimeParameter.
+ */
+@Beta
+@NonNullByDefault
+public abstract class AbstractReplayParameter implements Immutable {
+ private static final URI CAPABILITY = URI.create("urn:ietf:params:restconf:capability:replay:1.0");
+
+ private final DateAndTime value;
+
+ AbstractReplayParameter(final DateAndTime value) {
+ this.value = requireNonNull(value);
+ }
+
+ public final DateAndTime value() {
+ return value;
+ }
+
+ public final String uriValue() {
+ return value.getValue();
+ }
+
+ public static final URI capabilityUri() {
+ return CAPABILITY;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.nb.rfc8040;
+
+import static java.util.Objects.requireNonNull;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * Enumeration of possible {@code content} values as defined by
+ * <a href="https://datatracker.ietf.org/doc/html/rfc8040#section-4.8.1">RFC8040, section 4.8.1</a>.
+ */
+public enum ContentParameter {
+ /**
+ * Return all descendant data nodes.
+ */
+ ALL("all"),
+ /**
+ * Return only configuration descendant data nodes.
+ */
+ CONFIG("config"),
+ /**
+ * Return only non-configuration descendant data nodes.
+ */
+ NONCONFIG("nonconfig");
+
+ private final @NonNull String uriValue;
+
+ ContentParameter(final String uriValue) {
+ this.uriValue = requireNonNull(uriValue);
+ }
+
+ public @NonNull String uriValue() {
+ return uriValue;
+ }
+
+ public static @NonNull String uriName() {
+ return "content";
+ }
+
+ // Note: returns null of unknowns
+ public static @Nullable ContentParameter forUriValue(final String uriValue) {
+ switch (uriValue) {
+ case "all":
+ return ALL;
+ case "config":
+ return CONFIG;
+ case "nonconfig":
+ return NONCONFIG;
+ default:
+ return null;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.nb.rfc8040;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.net.URI;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.concepts.Immutable;
+
+/**
+ * This class represents a {@code depth} parameter as defined in
+ * <a href="https://datatracker.ietf.org/doc/html/rfc8040#section-4.8.3">RFC8040 section 4.8.2</a>.
+ */
+public final class DepthParameter implements Immutable {
+ private static final @NonNull URI CAPABILITY = URI.create("urn:ietf:params:restconf:capability:depth:1.0");
+
+ private final int value;
+
+ private DepthParameter(final int value) {
+ this.value = value;
+ checkArgument(value >= 1 && value <= 65535);
+ }
+
+ public static DepthParameter of(final int value) {
+ return new DepthParameter(value);
+ }
+
+ public static @Nullable DepthParameter forUriValue(final String uriValue) {
+ return uriValue.equals("unbounded") ? null : of(Integer.parseUnsignedInt(uriValue, 10));
+ }
+
+ public int value() {
+ return value;
+ }
+
+ public static @NonNull String uriName() {
+ return "depth";
+ }
+
+ public @NonNull String uriValue() {
+ return String.valueOf(value);
+ }
+
+ public static @NonNull URI capabilityUri() {
+ return CAPABILITY;
+ }
+}
import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
+import java.net.URI;
import java.text.ParseException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.opendaylight.restconf.nb.rfc8040.ApiPath.ApiIdentifier;
import org.opendaylight.yangtools.concepts.Immutable;
/**
- * This class represents a "fields" parameter as defined in
+ * This class represents a {@code fields} parameter as defined in
* <a href="https://datatracker.ietf.org/doc/html/rfc8040#section-4.8.3">RFC8040 section 4.8.3</a>.
*/
@Beta
}
}
+ private static final URI CAPABILITY = URI.create("urn:ietf:params:restconf:capability:fields:1.0");
+
private final ImmutableList<NodeSelector> nodeSelectors;
FieldsParameter(final ImmutableList<NodeSelector> nodeSelectors) {
return new FieldsParameterParser().parse(str);
}
+ public static String uriName() {
+ return "fields";
+ }
+
+ public static URI capabilityUri() {
+ return CAPABILITY;
+ }
+
/**
* Selectors for nodes which should be reported. Guaranteed to have at least one element.
*
--- /dev/null
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.nb.rfc8040;
+
+import static java.util.Objects.requireNonNull;
+
+import java.net.URI;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yangtools.concepts.Immutable;
+
+/**
+ * This class represents a {@code filter} parameter as defined in
+ * <a href="https://datatracker.ietf.org/doc/html/rfc8040#section-4.8.4">RFC8040 section 4.8.4</a>.
+ */
+@NonNullByDefault
+public final class FilterParameter implements Immutable {
+ private static final URI CAPABILITY = URI.create("urn:ietf:params:restconf:capability:filter:1.0");
+
+ // FIXME: can we have a parsed, but not bound version of an XPath, please?
+ private final String value;
+
+ private FilterParameter(final String value) {
+ this.value = requireNonNull(value);
+ }
+
+ public static FilterParameter forUriValue(final String uriValue) {
+ return new FilterParameter(uriValue);
+ }
+
+ public static String uriName() {
+ return "filter";
+ }
+
+ public String uriValue() {
+ return value;
+ }
+
+ public static URI capabilityUri() {
+ return CAPABILITY;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.nb.rfc8040;
+
+import static java.util.Objects.requireNonNull;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * Enumeration of possible {@code insert} values as defined by
+ * <a href="https://datatracker.ietf.org/doc/html/rfc8040#section-4.8.1">RFC8040, section 4.8.1</a>.
+ */
+public enum InsertParameter {
+ /**
+ * Insert the new data after the insertion point, as specified by the value of the "point" parameter.
+ */
+ AFTER("after"),
+ /**
+ * Insert the new data before the insertion point, as specified by the value of the "point" parameter.
+ */
+ BEFORE("before"),
+ /**
+ * Insert the new data as the new first entry.
+ */
+ FIRST("first"),
+ /**
+ * Insert the new data as the new last entry.
+ */
+ LAST("last");
+
+ private @NonNull String uriValue;
+
+ InsertParameter(final String uriValue) {
+ this.uriValue = requireNonNull(uriValue);
+ }
+
+ public @NonNull String uriValue() {
+ return uriValue;
+ }
+
+ public static @NonNull String uriName() {
+ return "insert";
+ }
+
+ // Note: returns null of unknowns
+ public static @Nullable InsertParameter forUriValue(final String uriValue) {
+ switch (uriValue) {
+ case "after":
+ return AFTER;
+ case "before":
+ return BEFORE;
+ case "first":
+ return FIRST;
+ case "last":
+ return LAST;
+ default:
+ return null;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.nb.rfc8040;
+
+import static java.util.Objects.requireNonNull;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yangtools.concepts.Immutable;
+
+/**
+ * This class represents a {@code point} parameter as defined in
+ * <a href="https://datatracker.ietf.org/doc/html/rfc8040#section-4.8.4">RFC8040 section 4.8.4</a>.
+ */
+@NonNullByDefault
+public final class PointParameter implements Immutable {
+ // FIXME: This should be ApiPath
+ private final String value;
+
+ private PointParameter(final String value) {
+ this.value = requireNonNull(value);
+ }
+
+ public static PointParameter forUriValue(final String uriValue) {
+ return new PointParameter(uriValue);
+ }
+
+ public static String uriName() {
+ return "point";
+ }
+
+ public String value() {
+ return value;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.nb.rfc8040;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
+
+/**
+ * This class represents a {@code start-time} parameter as defined in
+ * <a href="https://datatracker.ietf.org/doc/html/rfc8040#section-4.8.7">RFC8040 section 4.8.7</a>.
+ */
+@NonNullByDefault
+public final class StartTimeParameter extends AbstractReplayParameter {
+ private StartTimeParameter(final DateAndTime value) {
+ super(value);
+ }
+
+ public static StartTimeParameter of(final DateAndTime value) {
+ return new StartTimeParameter(value);
+ }
+
+ public static String uriName() {
+ return "start-time";
+ }
+
+ public static StartTimeParameter forUriValue(final String uriValue) {
+ return of(new DateAndTime(uriValue));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.nb.rfc8040;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
+
+/**
+ * This class represents a {@code stop-time} parameter as defined in
+ * <a href="https://datatracker.ietf.org/doc/html/rfc8040#section-4.8.8">RFC8040 section 4.8.8</a>.
+ */
+@NonNullByDefault
+public final class StopTimeParameter extends AbstractReplayParameter {
+ private StopTimeParameter(final DateAndTime value) {
+ super(value);
+ }
+
+ public static StopTimeParameter of(final DateAndTime value) {
+ return new StopTimeParameter(value);
+ }
+
+ public static String uriName() {
+ return "stop-time";
+ }
+
+ public static StopTimeParameter forUriValue(final String uriValue) {
+ return of(new DateAndTime(uriValue));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.nb.rfc8040;
+
+import static java.util.Objects.requireNonNull;
+
+import java.net.URI;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * Enumeration of possible {@code with-defaults} parameter values as defined by
+ * <a href="https://datatracker.ietf.org/doc/html/rfc8040#section-4.8.9">RFC8040, section 4.8.9</a>.
+ */
+public enum WithDefaultsParameter {
+ /**
+ * Data nodes set to the YANG default by the client are reported.
+ */
+ EXPLICIT("explicit"),
+ /**
+ * All data nodes are reported.
+ */
+ REPORT_ALL("report-all"),
+ /**
+ * All data nodes are reported, and defaults are tagged.
+ */
+ REPORT_ALL_TAGGED("report-all-tagged"),
+ /**
+ * Data nodes set to the YANG default are not reported.
+ */
+ TRIM("trim");
+
+ private static final @NonNull URI CAPABILITY = URI.create("urn:ietf:params:restconf:capability:with-defaults:1.0");
+
+ private final @NonNull String uriValue;
+
+ WithDefaultsParameter(final String uriValue) {
+ this.uriValue = requireNonNull(uriValue);
+ }
+
+ public static @NonNull String uriName() {
+ return "with-defaults";
+ }
+
+ public @NonNull String uriValue() {
+ return uriValue;
+ }
+
+ public static @Nullable WithDefaultsParameter forUriValue(final String uriValue) {
+ switch (uriValue) {
+ case "explicit":
+ return EXPLICIT;
+ case "report-all":
+ return REPORT_ALL;
+ case "report-all-tagged":
+ return REPORT_ALL_TAGGED;
+ case "trim":
+ return TRIM;
+ default:
+ return null;
+ }
+ }
+
+ public static @NonNull URI capabilityUri() {
+ return CAPABILITY;
+ }
+}
import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.restconf.common.context.WriterParameters;
+import org.opendaylight.restconf.nb.rfc8040.ContentParameter;
+import org.opendaylight.restconf.nb.rfc8040.WithDefaultsParameter;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
public static final class Builder extends WriterParametersBuilder {
private List<YangInstanceIdentifier> fieldPaths;
private List<Set<QName>> fields;
- private String withDefault;
+ private WithDefaultsParameter withDefault;
private boolean tagged;
- private String content;
+ private ContentParameter content;
Builder() {
// Hidden on purpose
}
- public Builder setContent(final String content) {
+ public Builder setContent(final ContentParameter content) {
this.content = content;
return this;
}
return this;
}
- public Builder setWithDefault(final String withDefault) {
+ public Builder setWithDefault(final WithDefaultsParameter withDefault) {
this.withDefault = withDefault;
return this;
}
private final List<YangInstanceIdentifier> fieldPaths;
private final List<Set<QName>> fields;
- private final String withDefault;
+ private final WithDefaultsParameter withDefault;
+ private final ContentParameter content;
private final boolean tagged;
- private final String content;
private QueryParameters(final Builder builder) {
super(builder);
return new Builder();
}
- public String getContent() {
+ public ContentParameter getContent() {
return content;
}
return fieldPaths;
}
- public String getWithDefault() {
+ public WithDefaultsParameter getWithDefault() {
return withDefault;
}
package org.opendaylight.restconf.nb.rfc8040.rests.services.impl;
import static java.util.Objects.requireNonNull;
-import static org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfDataServiceConstant.PostPutQueryParameters.INSERT;
-import static org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfDataServiceConstant.PostPutQueryParameters.POINT;
import static org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfStreamsConstants.NOTIFICATION_STREAM;
import static org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfStreamsConstants.STREAMS_PATH;
import static org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfStreamsConstants.STREAM_ACCESS_PATH_PART;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
import org.opendaylight.restconf.common.patch.PatchContext;
import org.opendaylight.restconf.common.patch.PatchStatusContext;
+import org.opendaylight.restconf.nb.rfc8040.InsertParameter;
+import org.opendaylight.restconf.nb.rfc8040.PointParameter;
import org.opendaylight.restconf.nb.rfc8040.Rfc8040;
import org.opendaylight.restconf.nb.rfc8040.handlers.SchemaContextHandler;
import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
import org.opendaylight.restconf.nb.rfc8040.rests.utils.PostDataTransactionUtil;
import org.opendaylight.restconf.nb.rfc8040.rests.utils.PutDataTransactionUtil;
import org.opendaylight.restconf.nb.rfc8040.rests.utils.ReadDataTransactionUtil;
-import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfDataServiceConstant;
-import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfDataServiceConstant.PostPutQueryParameters.Insert;
import org.opendaylight.restconf.nb.rfc8040.streams.Configuration;
import org.opendaylight.restconf.nb.rfc8040.streams.listeners.NotificationListenerAdapter;
import org.opendaylight.restconf.nb.rfc8040.utils.mapping.RestconfMappingNodeUtil;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
import org.slf4j.Logger;
public class RestconfDataServiceImpl implements RestconfDataService {
// FIXME: we should be able to interpret 'point' and refactor this class into a behavior
private static final class QueryParams implements Immutable {
- final @Nullable String point;
- final @Nullable Insert insert;
+ final @Nullable PointParameter point;
+ final @Nullable InsertParameter insert;
- QueryParams(final @Nullable Insert insert, final @Nullable String point) {
+ QueryParams(final @Nullable InsertParameter insert, final @Nullable PointParameter point) {
this.insert = insert;
this.point = point;
}
private static final Logger LOG = LoggerFactory.getLogger(RestconfDataServiceImpl.class);
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MMM-dd HH:mm:ss");
+ private static final QName NETCONF_BASE_QNAME = SchemaContext.NAME;
private final RestconfStreamsSubscriptionService delegRestconfSubscrService;
private final SchemaContextHandler schemaContextHandler;
ErrorType.PROTOCOL, ErrorTag.DATA_MISSING);
}
- if (parameters.getContent().equals(RestconfDataServiceConstant.ReadData.ALL)
- || parameters.getContent().equals(RestconfDataServiceConstant.ReadData.CONFIG)) {
- final QName type = node.getIdentifier().getNodeType();
- return Response.status(Status.OK)
+ switch (parameters.getContent()) {
+ case ALL:
+ case CONFIG:
+ final QName type = node.getIdentifier().getNodeType();
+ return Response.status(Status.OK)
.entity(new NormalizedNodeContext(instanceIdentifier, node, parameters))
.header("ETag", '"' + type.getModule().getRevision().map(Revision::toString).orElse(null)
+ "-" + type.getLocalName() + '"')
.header("Last-Modified", FORMATTER.format(LocalDateTime.now(Clock.systemUTC())))
.build();
+ default:
+ return Response.status(Status.OK)
+ .entity(new NormalizedNodeContext(instanceIdentifier, node, parameters))
+ .build();
}
-
- return Response.status(Status.OK)
- .entity(new NormalizedNodeContext(instanceIdentifier, node, parameters))
- .build();
}
private void createAllYangNotificationStreams(final EffectiveModelContext schemaContext, final UriInfo uriInfo) {
private static QueryParams checkQueryParameters(final UriInfo uriInfo) {
boolean insertUsed = false;
boolean pointUsed = false;
- Insert insert = null;
- String point = null;
+ InsertParameter insert = null;
+ PointParameter point = null;
for (final Entry<String, List<String>> entry : uriInfo.getQueryParameters().entrySet()) {
- switch (entry.getKey()) {
- case INSERT:
- if (insertUsed) {
- throw new RestconfDocumentedException("Insert parameter can be used only once.",
- ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT);
- }
-
- insertUsed = true;
- final String str = entry.getValue().get(0);
- insert = Insert.forValue(str);
- if (insert == null) {
- throw new RestconfDocumentedException("Unrecognized insert parameter value '" + str + "'",
- ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT);
- }
- break;
- case POINT:
- if (pointUsed) {
- throw new RestconfDocumentedException("Point parameter can be used only once.",
- ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT);
- }
-
- pointUsed = true;
- point = entry.getValue().get(0);
- break;
- default:
- throw new RestconfDocumentedException("Bad parameter for post: " + entry.getKey(),
- ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT);
+ final String uriName = entry.getKey();
+ if (InsertParameter.uriName().equals(uriName)) {
+ if (insertUsed) {
+ throw new RestconfDocumentedException("Insert parameter can be used only once.",
+ ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT);
+ }
+
+ insertUsed = true;
+ final String str = entry.getValue().get(0);
+ insert = InsertParameter.forUriValue(str);
+ if (insert == null) {
+ throw new RestconfDocumentedException("Unrecognized insert parameter value '" + str + "'",
+ ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT);
+ }
+ } else if (PointParameter.uriName().equals(uriName)) {
+ if (pointUsed) {
+ throw new RestconfDocumentedException("Point parameter can be used only once.",
+ ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT);
+ }
+
+ pointUsed = true;
+ point = PointParameter.forUriValue(entry.getValue().get(0));
+ } else {
+ throw new RestconfDocumentedException("Bad parameter for post: " + uriName,
+ ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT);
}
}
return new QueryParams(insert, point);
}
- private static void checkQueryParams(final boolean insertUsed, final boolean pointUsed, final Insert insert) {
+ private static void checkQueryParams(final boolean insertUsed, final boolean pointUsed,
+ final InsertParameter insert) {
if (pointUsed) {
if (!insertUsed) {
throw new RestconfDocumentedException("Point parameter can't be used without Insert parameter.",
ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT);
}
-
- if (insert != Insert.BEFORE && insert != Insert.AFTER) {
+ if (insert != InsertParameter.BEFORE && insert != InsertParameter.AFTER) {
throw new RestconfDocumentedException(
"Point parameter can be used only with 'after' or 'before' values of Insert parameter.",
ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT);
final YangInstanceIdentifier yangIIdContext = context.getInstanceIdentifier();
final NormalizedNode data = payload.getData();
- if (yangIIdContext.isEmpty()
- && !RestconfDataServiceConstant.NETCONF_BASE_QNAME.equals(data.getIdentifier().getNodeType())) {
+ if (yangIIdContext.isEmpty() && !NETCONF_BASE_QNAME.equals(data.getIdentifier().getNodeType())) {
throw new RestconfDocumentedException("Instance identifier need to contain at least one path argument",
ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
}
*/
@VisibleForTesting
public static void validTopLevelNodeName(final YangInstanceIdentifier path, final NormalizedNodeContext payload) {
- final String payloadName = payload.getData().getIdentifier().getNodeType().getLocalName();
-
+ final QName dataNodeType = payload.getData().getIdentifier().getNodeType();
if (path.isEmpty()) {
- if (!payload.getData().getIdentifier().getNodeType().equals(
- RestconfDataServiceConstant.NETCONF_BASE_QNAME)) {
+ if (!NETCONF_BASE_QNAME.equals(dataNodeType)) {
throw new RestconfDocumentedException("Instance identifier has to contain at least one path argument",
ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
}
} else {
final String identifierName = path.getLastPathArgument().getNodeType().getLocalName();
+ final String payloadName = dataNodeType.getLocalName();
if (!payloadName.equals(identifierName)) {
throw new RestconfDocumentedException(
"Payload name (" + payloadName + ") is different from identifier name (" + identifierName + ")",
import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
+import org.opendaylight.restconf.nb.rfc8040.InsertParameter;
+import org.opendaylight.restconf.nb.rfc8040.PointParameter;
import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfTransaction;
-import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfDataServiceConstant.PostPutQueryParameters.Insert;
import org.opendaylight.restconf.nb.rfc8040.utils.parser.IdentifierCodec;
import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
import org.opendaylight.yangtools.yang.common.ErrorTag;
*/
public static Response postData(final UriInfo uriInfo, final NormalizedNodePayload payload,
final RestconfStrategy strategy,
- final EffectiveModelContext schemaContext, final Insert insert,
- final String point) {
+ final EffectiveModelContext schemaContext, final InsertParameter insert,
+ final PointParameter point) {
final YangInstanceIdentifier path = payload.getInstanceIdentifierContext().getInstanceIdentifier();
final FluentFuture<? extends CommitInfo> future = submitData(path, payload.getData(),
strategy, schemaContext, insert, point);
final NormalizedNode data,
final RestconfStrategy strategy,
final EffectiveModelContext schemaContext,
- final Insert insert, final String point) {
+ final InsertParameter insert,
+ final PointParameter point) {
final RestconfTransaction transaction = strategy.prepareWriteExecution();
if (insert == null) {
makePost(path, data, schemaContext, transaction);
}
private static void insertWithPointPost(final YangInstanceIdentifier path, final NormalizedNode data,
- final EffectiveModelContext schemaContext, final String point,
+ final EffectiveModelContext schemaContext, final PointParameter point,
final NormalizedNodeContainer<?> readList, final boolean before,
final RestconfTransaction transaction) {
final YangInstanceIdentifier parent = path.getParent().getParent();
transaction.remove(parent);
final InstanceIdentifierContext<?> instanceIdentifier =
- ParserIdentifier.toInstanceIdentifier(point, schemaContext, Optional.empty());
+ // FIXME: Point should be able to give us this method
+ ParserIdentifier.toInstanceIdentifier(point.value(), schemaContext, Optional.empty());
int lastItemPosition = 0;
for (final NormalizedNode nodeChild : readList.body()) {
if (nodeChild.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) {
import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
+import org.opendaylight.restconf.nb.rfc8040.InsertParameter;
+import org.opendaylight.restconf.nb.rfc8040.PointParameter;
import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfTransaction;
-import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfDataServiceConstant.PostPutQueryParameters.Insert;
import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
import org.opendaylight.yangtools.yang.common.ErrorTag;
import org.opendaylight.yangtools.yang.common.ErrorType;
* @return {@link Response}
*/
public static Response putData(final NormalizedNodePayload payload, final EffectiveModelContext schemaContext,
- final RestconfStrategy strategy, final Insert insert, final String point) {
+ final RestconfStrategy strategy, final InsertParameter insert,
+ final PointParameter point) {
final YangInstanceIdentifier path = payload.getInstanceIdentifierContext().getInstanceIdentifier();
final FluentFuture<Boolean> existsFuture = strategy.exists(LogicalDatastoreType.CONFIGURATION, path);
final EffectiveModelContext schemaContext,
final RestconfStrategy strategy,
final NormalizedNode data,
- final Insert insert, final String point) {
+ final InsertParameter insert,
+ final PointParameter point) {
final RestconfTransaction transaction = strategy.prepareWriteExecution();
if (insert == null) {
return makePut(path, schemaContext, transaction, data);
private static void insertWithPointPut(final RestconfTransaction transaction,
final YangInstanceIdentifier path,
final NormalizedNode data,
- final EffectiveModelContext schemaContext, final String point,
+ final EffectiveModelContext schemaContext, final PointParameter point,
final NormalizedNodeContainer<?> readList, final boolean before) {
transaction.remove(path.getParent());
final InstanceIdentifierContext<?> instanceIdentifier =
- ParserIdentifier.toInstanceIdentifier(point, schemaContext, Optional.empty());
+ // FIXME: Point should be able to give us this method
+ ParserIdentifier.toInstanceIdentifier(point.value(), schemaContext, Optional.empty());
int lastItemPosition = 0;
for (final NormalizedNode nodeChild : readList.body()) {
if (nodeChild.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) {
import com.google.common.annotations.VisibleForTesting;
import com.google.common.primitives.Ints;
import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
import org.opendaylight.restconf.common.errors.RestconfError;
+import org.opendaylight.restconf.nb.rfc8040.ContentParameter;
+import org.opendaylight.restconf.nb.rfc8040.DepthParameter;
+import org.opendaylight.restconf.nb.rfc8040.FieldsParameter;
+import org.opendaylight.restconf.nb.rfc8040.WithDefaultsParameter;
import org.opendaylight.restconf.nb.rfc8040.legacy.QueryParameters;
import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
-import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfDataServiceConstant.ReadData.WithDefaults;
import org.opendaylight.yangtools.yang.common.ErrorTag;
import org.opendaylight.yangtools.yang.common.ErrorType;
import org.opendaylight.yangtools.yang.common.QName;
* </ul>
*/
public final class ReadDataTransactionUtil {
+ // depth values
+ // FIXME: these are known to DepthParameter
+ private static final String UNBOUNDED = "unbounded";
+ private static final int MIN_DEPTH = 1;
+ private static final int MAX_DEPTH = 65535;
+
private static final Set<String> ALLOWED_PARAMETERS = Set.of(
- RestconfDataServiceConstant.ReadData.CONTENT,
- RestconfDataServiceConstant.ReadData.DEPTH,
- RestconfDataServiceConstant.ReadData.FIELDS,
- RestconfDataServiceConstant.ReadData.WITH_DEFAULTS);
- private static final List<String> DEFAULT_CONTENT = List.of(RestconfDataServiceConstant.ReadData.ALL);
- private static final List<String> DEFAULT_DEPTH = List.of(RestconfDataServiceConstant.ReadData.UNBOUNDED);
+ ContentParameter.uriName(),
+ DepthParameter.uriName(),
+ FieldsParameter.uriName(),
+ WithDefaultsParameter.uriName());
+ private static final List<String> DEFAULT_CONTENT = List.of(ContentParameter.ALL.uriValue());
+ private static final List<String> DEFAULT_DEPTH = List.of(UNBOUNDED);
+ private static final List<String> POSSIBLE_CONTENT = Arrays.stream(ContentParameter.values())
+ .map(ContentParameter::uriValue)
+ .collect(Collectors.toUnmodifiableList());
+ private static final List<String> POSSIBLE_WITH_DEFAULTS = Arrays.stream(WithDefaultsParameter.values())
+ .map(WithDefaultsParameter::uriValue)
+ .collect(Collectors.toUnmodifiableList());
+
private static final String READ_TYPE_TX = "READ";
private ReadDataTransactionUtil() {
checkParametersTypes(queryParams.keySet(), ALLOWED_PARAMETERS);
// read parameters from URI or set default values
- final List<String> content = queryParams.getOrDefault(
- RestconfDataServiceConstant.ReadData.CONTENT, DEFAULT_CONTENT);
- final List<String> depth = queryParams.getOrDefault(
- RestconfDataServiceConstant.ReadData.DEPTH, DEFAULT_DEPTH);
- final List<String> withDefaults = queryParams.getOrDefault(
- RestconfDataServiceConstant.ReadData.WITH_DEFAULTS, List.of());
+ final List<String> content = queryParams.getOrDefault(ContentParameter.uriName(), DEFAULT_CONTENT);
+ final List<String> depth = queryParams.getOrDefault(DepthParameter.uriName(), DEFAULT_DEPTH);
+ final List<String> withDefaults = queryParams.getOrDefault(WithDefaultsParameter.uriName(), List.of());
// fields
- final List<String> fields = queryParams.getOrDefault(RestconfDataServiceConstant.ReadData.FIELDS, List.of());
+ final List<String> fields = queryParams.getOrDefault(FieldsParameter.uriName(), List.of());
// parameter can be in URI at most once
- checkParameterCount(content, RestconfDataServiceConstant.ReadData.CONTENT);
- checkParameterCount(depth, RestconfDataServiceConstant.ReadData.DEPTH);
- checkParameterCount(fields, RestconfDataServiceConstant.ReadData.FIELDS);
- checkParameterCount(withDefaults, RestconfDataServiceConstant.ReadData.WITH_DEFAULTS);
+ checkParameterCount(content, ContentParameter.uriName());
+ checkParameterCount(depth, DepthParameter.uriName());
+ checkParameterCount(fields, FieldsParameter.uriName());
+ checkParameterCount(withDefaults, WithDefaultsParameter.uriName());
// check and set content
- final String contentValue = content.get(0);
- switch (contentValue) {
- case RestconfDataServiceConstant.ReadData.ALL:
- case RestconfDataServiceConstant.ReadData.CONFIG:
- case RestconfDataServiceConstant.ReadData.NONCONFIG:
- // FIXME: we really want to have a proper enumeration for this field
- builder.setContent(contentValue);
- break;
- default:
- throw new RestconfDocumentedException(
- new RestconfError(ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
- "Invalid content parameter: " + contentValue, null,
- "The content parameter value must be either config, nonconfig or all (default)"));
- }
+ final String contentValueStr = content.get(0);
+ builder.setContent(RestconfDocumentedException.throwIfNull(
+ ContentParameter.forUriValue(contentValueStr), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
+ "Invalid content parameter: %s, allowed values are %s", contentValueStr, POSSIBLE_CONTENT));
// check and set depth
- if (!depth.get(0).equals(RestconfDataServiceConstant.ReadData.UNBOUNDED)) {
+ if (!depth.get(0).equals(UNBOUNDED)) {
final Integer value = Ints.tryParse(depth.get(0));
- if (value == null || value < RestconfDataServiceConstant.ReadData.MIN_DEPTH
- || value > RestconfDataServiceConstant.ReadData.MAX_DEPTH) {
+ if (value == null || value < MIN_DEPTH || value > MAX_DEPTH) {
throw new RestconfDocumentedException(
new RestconfError(ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
"Invalid depth parameter: " + depth, null,
// check and set withDefaults parameter
if (!withDefaults.isEmpty()) {
final String str = withDefaults.get(0);
- final WithDefaults val = WithDefaults.forValue(str);
+ final WithDefaultsParameter val = WithDefaultsParameter.forUriValue(str);
if (val == null) {
throw new RestconfDocumentedException(new RestconfError(ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
"Invalid with-defaults parameter: " + str, null,
- "The with-defaults parameter must be a string in " + WithDefaults.possibleValues()));
+ "The with-defaults parameter must be a string in " + POSSIBLE_WITH_DEFAULTS));
}
switch (val) {
builder.setTagged(true);
break;
default:
- builder.setWithDefault(val.value());
+ builder.setWithDefault(val);
}
}
return builder.build();
* Read specific type of data from data store via transaction. Close {@link DOMTransactionChain} if any
* inside of object {@link RestconfStrategy} provided as a parameter.
*
- * @param valueOfContent type of data to read (config, state, all)
+ * @param content type of data to read (config, state, all)
* @param path the path to read
* @param strategy {@link RestconfStrategy} - object that perform the actual DS operations
* @param withDefa value of with-defaults parameter
* @param ctx schema context
* @return {@link NormalizedNode}
*/
- public static @Nullable NormalizedNode readData(final @NonNull String valueOfContent,
+ public static @Nullable NormalizedNode readData(final @NonNull ContentParameter content,
final @NonNull YangInstanceIdentifier path,
final @NonNull RestconfStrategy strategy,
- final String withDefa, final EffectiveModelContext ctx) {
- switch (valueOfContent) {
- case RestconfDataServiceConstant.ReadData.CONFIG:
+ final WithDefaultsParameter withDefa,
+ final EffectiveModelContext ctx) {
+ // FIXME: use a switch expression when they are available, removing source of RestconfDocumentedException
+ switch (content) {
+ case ALL:
+ return readAllData(strategy, path, withDefa, ctx);
+ case CONFIG:
final NormalizedNode read = readDataViaTransaction(strategy, LogicalDatastoreType.CONFIGURATION, path);
return withDefa == null ? read : prepareDataByParamWithDef(read, path, withDefa, ctx);
- case RestconfDataServiceConstant.ReadData.NONCONFIG:
+ case NONCONFIG:
return readDataViaTransaction(strategy, LogicalDatastoreType.OPERATIONAL, path);
- case RestconfDataServiceConstant.ReadData.ALL:
- return readAllData(strategy, path, withDefa, ctx);
default:
throw new RestconfDocumentedException(
new RestconfError(ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
- "Invalid content parameter: " + valueOfContent, null,
+ "Invalid content parameter: " + content.uriValue(), null,
"The content parameter value must be either config, nonconfig or all (default)"));
}
}
* Read specific type of data from data store via transaction with specified subtrees that should only be read.
* Close {@link DOMTransactionChain} inside of object {@link RestconfStrategy} provided as a parameter.
*
- * @param valueOfContent type of data to read (config, state, all)
+ * @param content type of data to read (config, state, all)
* @param path the parent path to read
* @param strategy {@link RestconfStrategy} - object that perform the actual DS operations
* @param withDefa value of with-defaults parameter
* @param fields paths to selected subtrees which should be read, relative to to the parent path
* @return {@link NormalizedNode}
*/
- public static @Nullable NormalizedNode readData(final @NonNull String valueOfContent,
+ public static @Nullable NormalizedNode readData(final @NonNull ContentParameter content,
final @NonNull YangInstanceIdentifier path, final @NonNull RestconfStrategy strategy,
- final @Nullable String withDefa, @NonNull final EffectiveModelContext ctx,
+ final @Nullable WithDefaultsParameter withDefa, @NonNull final EffectiveModelContext ctx,
final @NonNull List<YangInstanceIdentifier> fields) {
- switch (valueOfContent) {
- case RestconfDataServiceConstant.ReadData.CONFIG:
+ // FIXME: use a switch expression when they are available, removing source of RestconfDocumentedException
+ switch (content) {
+ case ALL:
+ return readAllData(strategy, path, withDefa, ctx, fields);
+ case CONFIG:
final NormalizedNode read = readDataViaTransaction(strategy, LogicalDatastoreType.CONFIGURATION, path,
fields);
return withDefa == null ? read : prepareDataByParamWithDef(read, path, withDefa, ctx);
- case RestconfDataServiceConstant.ReadData.NONCONFIG:
+ case NONCONFIG:
return readDataViaTransaction(strategy, LogicalDatastoreType.OPERATIONAL, path, fields);
- case RestconfDataServiceConstant.ReadData.ALL:
- return readAllData(strategy, path, withDefa, ctx, fields);
default:
throw new RestconfDocumentedException(new RestconfError(ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
- "Invalid content parameter: " + valueOfContent, null,
+ "Invalid content parameter: " + content.uriValue(), null,
"The content parameter value must be either config, nonconfig or all (default)"));
}
}
}
private static NormalizedNode prepareDataByParamWithDef(final NormalizedNode result,
- final YangInstanceIdentifier path, final String withDefa, final EffectiveModelContext ctx) {
+ final YangInstanceIdentifier path, final WithDefaultsParameter withDefa, final EffectiveModelContext ctx) {
boolean trim;
switch (withDefa) {
- case "trim":
+ case TRIM:
trim = true;
break;
- case "explicit":
+ case EXPLICIT:
trim = false;
break;
default:
- throw new RestconfDocumentedException("");
+ throw new RestconfDocumentedException("Unsupported with-defaults value " + withDefa.uriValue());
}
final DataSchemaContextTree baseSchemaCtxTree = DataSchemaContextTree.from(ctx);
* @return {@link NormalizedNode}
*/
private static @Nullable NormalizedNode readAllData(final @NonNull RestconfStrategy strategy,
- final YangInstanceIdentifier path, final String withDefa, final EffectiveModelContext ctx) {
+ final YangInstanceIdentifier path, final WithDefaultsParameter withDefa, final EffectiveModelContext ctx) {
// PREPARE STATE DATA NODE
final NormalizedNode stateDataNode = readDataViaTransaction(strategy, LogicalDatastoreType.OPERATIONAL, path);
// PREPARE CONFIG DATA NODE
* @return {@link NormalizedNode}
*/
private static @Nullable NormalizedNode readAllData(final @NonNull RestconfStrategy strategy,
- final @NonNull YangInstanceIdentifier path, final @Nullable String withDefa,
+ final @NonNull YangInstanceIdentifier path, final @Nullable WithDefaultsParameter withDefa,
final @NonNull EffectiveModelContext ctx, final @NonNull List<YangInstanceIdentifier> fields) {
// PREPARE STATE DATA NODE
final NormalizedNode stateDataNode = readDataViaTransaction(strategy, LogicalDatastoreType.OPERATIONAL, path,
+++ /dev/null
-/*
- * Copyright (c) 2016 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,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.restconf.nb.rfc8040.rests.utils;
-
-import static java.util.Objects.requireNonNull;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import java.util.Arrays;
-import java.util.Set;
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-/**
- * Constants for RestconfDataService.
- *
- */
-public final class RestconfDataServiceConstant {
- public static final QName NETCONF_BASE_QNAME = SchemaContext.NAME;
-
- private RestconfDataServiceConstant() {
- // Hidden on purpose
- }
-
- /**
- * Constants for read data.
- *
- */
- public static final class ReadData {
- // URI parameters
- public static final String CONTENT = "content";
- public static final String DEPTH = "depth";
- public static final String FIELDS = "fields";
-
- // content values
- public static final String CONFIG = "config";
- public static final String ALL = "all";
- public static final String NONCONFIG = "nonconfig";
-
- // depth values
- public static final String UNBOUNDED = "unbounded";
- public static final int MIN_DEPTH = 1;
- public static final int MAX_DEPTH = 65535;
-
- public static final String WITH_DEFAULTS = "with-defaults";
-
- /**
- * With-default values, as per
- * <a href="https://tools.ietf.org/html/rfc8040#section-4.8.9">RFC8040 section 4.8.9</a>.
- */
- enum WithDefaults {
- /**
- * All data nodes are reported.
- */
- REPORT_ALL("report-all"),
- /**
- * Data nodes set to the YANG default are not reported.
- */
- TRIM("trim"),
- /**
- * Data nodes set to the YANG default by the client are reported.
- */
- EXPLICIT("explicit"),
- /**
- * All data nodes are reported, and defaults are tagged.
- */
- REPORT_ALL_TAGGED("report-all-tagged");
-
- private static final ImmutableMap<String, WithDefaults> VALUES =
- Maps.uniqueIndex(Arrays.asList(values()), WithDefaults::value);
-
- private @NonNull String value;
-
- WithDefaults(final @NonNull String value) {
- this.value = value;
- }
-
- public @NonNull String value() {
- return value;
- }
-
- static @Nullable WithDefaults forValue(final String value) {
- return VALUES.get(requireNonNull(value));
- }
-
- static @Nullable Set<String> possibleValues() {
- return VALUES.keySet();
- }
- }
-
- private ReadData() {
- // Hidden on purpose
- }
- }
-
- /**
- * Common for PostData and PutData.
- */
- public static final class PostPutQueryParameters {
- public static final String INSERT = "insert";
- public static final String POINT = "point";
-
- /**
- * Insert values, as per <a href="https://tools.ietf.org/html/rfc8040#section-4.8.5">RFC8040 section 4.8.5</a>.
- */
- public enum Insert {
- /**
- * Insert the new data as the new first entry.
- */
- FIRST("first"),
- /**
- * Insert the new data as the new last entry.
- */
- LAST("last"),
- /**
- * Insert the new data before the insertion point, as specified by the value of the "point" parameter.
- */
- BEFORE("before"),
- /**
- * Insert the new data after the insertion point, as specified by the value of the "point" parameter.
- */
- AFTER("after");
-
- private static final ImmutableMap<String, Insert> VALUES =
- Maps.uniqueIndex(Arrays.asList(values()), Insert::value);
-
- private @NonNull String value;
-
- Insert(final @NonNull String value) {
- this.value = value;
- }
-
- public @NonNull String value() {
- return value;
- }
-
- public static @Nullable Insert forValue(final String value) {
- return VALUES.get(requireNonNull(value));
- }
- }
-
- private PostPutQueryParameters() {
- // Hidden on purpose
- }
- }
-}
import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
import org.opendaylight.restconf.common.errors.RestconfError;
+import org.opendaylight.restconf.nb.rfc8040.ContentParameter;
+import org.opendaylight.restconf.nb.rfc8040.DepthParameter;
+import org.opendaylight.restconf.nb.rfc8040.WithDefaultsParameter;
import org.opendaylight.restconf.nb.rfc8040.legacy.QueryParameters;
import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStrategy;
import org.opendaylight.restconf.nb.rfc8040.rests.transactions.NetconfRestconfStrategy;
import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy;
-import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfDataServiceConstant.ReadData;
-import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfDataServiceConstant.ReadData.WithDefaults;
import org.opendaylight.yangtools.yang.common.ErrorTag;
import org.opendaylight.yangtools.yang.common.ErrorType;
import org.opendaylight.yangtools.yang.common.QName;
doReturn(immediateFluentFuture(Optional.of(DATA.data3))).when(read)
.read(LogicalDatastoreType.CONFIGURATION, DATA.path);
doReturn(immediateFluentFuture(Optional.of(DATA.data3))).when(netconfService).getConfig(DATA.path);
- final String valueOfContent = RestconfDataServiceConstant.ReadData.CONFIG;
- NormalizedNode normalizedNode = readData(valueOfContent, DATA.path, mdsalStrategy);
+ NormalizedNode normalizedNode = readData(ContentParameter.CONFIG, DATA.path, mdsalStrategy);
assertEquals(DATA.data3, normalizedNode);
- normalizedNode = readData(valueOfContent, DATA.path, netconfStrategy);
+ normalizedNode = readData(ContentParameter.CONFIG, DATA.path, netconfStrategy);
assertEquals(DATA.data3, normalizedNode);
}
.read(LogicalDatastoreType.OPERATIONAL, DATA.path);
doReturn(immediateFluentFuture(Optional.of(DATA.data3))).when(netconfService).getConfig(DATA.path);
doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).get(DATA.path);
- final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
- NormalizedNode normalizedNode = readData(valueOfContent, DATA.path, mdsalStrategy);
+ NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.path, mdsalStrategy);
assertEquals(DATA.data3, normalizedNode);
- normalizedNode = readData(valueOfContent, DATA.path, netconfStrategy);
+ normalizedNode = readData(ContentParameter.ALL, DATA.path, netconfStrategy);
assertEquals(DATA.data3, normalizedNode);
}
.read(LogicalDatastoreType.CONFIGURATION, DATA.path2);
doReturn(immediateFluentFuture(Optional.of(DATA.data2))).when(netconfService).get(DATA.path2);
doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(DATA.path2);
- final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
- NormalizedNode normalizedNode = readData(valueOfContent, DATA.path2, mdsalStrategy);
+ NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.path2, mdsalStrategy);
assertEquals(DATA.data2, normalizedNode);
- normalizedNode = readData(valueOfContent, DATA.path2, netconfStrategy);
+ normalizedNode = readData(ContentParameter.ALL, DATA.path2, netconfStrategy);
assertEquals(DATA.data2, normalizedNode);
}
doReturn(immediateFluentFuture(Optional.of(DATA.data2))).when(read)
.read(LogicalDatastoreType.OPERATIONAL, DATA.path2);
doReturn(immediateFluentFuture(Optional.of(DATA.data2))).when(netconfService).get(DATA.path2);
- final String valueOfContent = RestconfDataServiceConstant.ReadData.NONCONFIG;
- NormalizedNode normalizedNode = readData(valueOfContent, DATA.path2, mdsalStrategy);
+ NormalizedNode normalizedNode = readData(ContentParameter.NONCONFIG, DATA.path2, mdsalStrategy);
assertEquals(DATA.data2, normalizedNode);
- normalizedNode = readData(valueOfContent, DATA.path2, netconfStrategy);
+ normalizedNode = readData(ContentParameter.NONCONFIG, DATA.path2, netconfStrategy);
assertEquals(DATA.data2, normalizedNode);
}
.read(LogicalDatastoreType.OPERATIONAL, DATA.path);
doReturn(immediateFluentFuture(Optional.of(DATA.data3))).when(netconfService).getConfig(DATA.path);
doReturn(immediateFluentFuture(Optional.of(DATA.data4))).when(netconfService).get(DATA.path);
- final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
final ContainerNode checkingData = Builders
.containerBuilder()
.withNodeIdentifier(NODE_IDENTIFIER)
.withChild(DATA.contentLeaf)
.withChild(DATA.contentLeaf2)
.build();
- NormalizedNode normalizedNode = readData(valueOfContent, DATA.path, mdsalStrategy);
+ NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.path, mdsalStrategy);
assertEquals(checkingData, normalizedNode);
- normalizedNode = readData(valueOfContent, DATA.path, netconfStrategy);
+ normalizedNode = readData(ContentParameter.ALL, DATA.path, netconfStrategy);
assertEquals(checkingData, normalizedNode);
}
.withChild(DATA.contentLeaf)
.withChild(DATA.contentLeaf2)
.build();
- NormalizedNode normalizedNode = readData(RestconfDataServiceConstant.ReadData.ALL, DATA.path, mdsalStrategy);
+ NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.path, mdsalStrategy);
assertEquals(checkingData, normalizedNode);
- normalizedNode = readData(RestconfDataServiceConstant.ReadData.ALL, DATA.path, netconfStrategy);
+ normalizedNode = readData(ContentParameter.ALL, DATA.path, netconfStrategy);
assertEquals(checkingData, normalizedNode);
}
.read(LogicalDatastoreType.CONFIGURATION, DATA.path3);
doReturn(immediateFluentFuture(Optional.of(DATA.listData))).when(netconfService).get(DATA.path3);
doReturn(immediateFluentFuture(Optional.of(DATA.listData2))).when(netconfService).getConfig(DATA.path3);
- final String valueOfContent = RestconfDataServiceConstant.ReadData.ALL;
final MapNode checkingData = Builders
.mapBuilder()
.withNodeIdentifier(new NodeIdentifier(QName.create("ns", "2016-02-28", "list")))
.withChild(DATA.checkData)
.build();
- NormalizedNode normalizedNode = readData(valueOfContent, DATA.path3, mdsalStrategy);
+ NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.path3, mdsalStrategy);
assertEquals(checkingData, normalizedNode);
- normalizedNode = readData(valueOfContent, DATA.path3, netconfStrategy);
+ normalizedNode = readData(ContentParameter.ALL, DATA.path3, netconfStrategy);
assertEquals(checkingData, normalizedNode);
}
.withNodeIdentifier(new NodeIdentifier(DATA.listQname))
.withChild(DATA.checkData)
.build();
- NormalizedNode normalizedNode = readData(RestconfDataServiceConstant.ReadData.ALL, DATA.path3,
+ NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.path3,
mdsalStrategy);
assertEquals(expectedData, normalizedNode);
- normalizedNode = readData(RestconfDataServiceConstant.ReadData.ALL, DATA.path3, netconfStrategy);
+ normalizedNode = readData(ContentParameter.ALL, DATA.path3, netconfStrategy);
assertEquals(expectedData, normalizedNode);
}
.withNodeIdentifier(new NodeIdentifier(DATA.listQname))
.withChild(DATA.unkeyedListEntryNode1.body().iterator().next())
.withChild(DATA.unkeyedListEntryNode2.body().iterator().next()).build()).build();
- NormalizedNode normalizedNode = readData(RestconfDataServiceConstant.ReadData.ALL, DATA.path3, mdsalStrategy);
+ NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.path3, mdsalStrategy);
assertEquals(expectedData, normalizedNode);
- normalizedNode = readData(RestconfDataServiceConstant.ReadData.ALL, DATA.path3, netconfStrategy);
+ normalizedNode = readData(ContentParameter.ALL, DATA.path3, netconfStrategy);
assertEquals(expectedData, normalizedNode);
}
.addAll(DATA.leafSetNode2.body())
.build())
.build();
- NormalizedNode normalizedNode = readData(RestconfDataServiceConstant.ReadData.ALL, DATA.leafSetNodePath,
+ NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.leafSetNodePath,
mdsalStrategy);
assertEquals(expectedData, normalizedNode);
- normalizedNode = readData(RestconfDataServiceConstant.ReadData.ALL, DATA.leafSetNodePath, netconfStrategy);
+ normalizedNode = readData(ContentParameter.ALL, DATA.leafSetNodePath, netconfStrategy);
assertEquals(expectedData, normalizedNode);
}
.addAll(DATA.orderedLeafSetNode2.body())
.build())
.build();
- NormalizedNode normalizedNode = readData(RestconfDataServiceConstant.ReadData.ALL, DATA.leafSetNodePath,
+ NormalizedNode normalizedNode = readData(ContentParameter.ALL, DATA.leafSetNodePath,
mdsalStrategy);
assertEquals(expectedData, normalizedNode);
- normalizedNode = readData(RestconfDataServiceConstant.ReadData.ALL, DATA.leafSetNodePath, netconfStrategy);
+ normalizedNode = readData(ContentParameter.ALL, DATA.leafSetNodePath, netconfStrategy);
assertEquals(expectedData, normalizedNode);
}
doReturn(immediateFluentFuture(Optional.empty())).when(read)
.read(LogicalDatastoreType.CONFIGURATION, DATA.path2);
doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(DATA.path2);
- final String valueOfContent = RestconfDataServiceConstant.ReadData.CONFIG;
- NormalizedNode normalizedNode = readData(valueOfContent, DATA.path2, mdsalStrategy);
+ NormalizedNode normalizedNode = readData(ContentParameter.CONFIG, DATA.path2, mdsalStrategy);
assertNull(normalizedNode);
- normalizedNode = readData(valueOfContent, DATA.path2, netconfStrategy);
- assertNull(normalizedNode);
- }
-
- @Test(expected = RestconfDocumentedException.class)
- public void readDataFailTest() {
- final String valueOfContent = "nonsense";
- NormalizedNode normalizedNode = readData(valueOfContent, null, mdsalStrategy);
- assertNull(normalizedNode);
-
- normalizedNode = readData(valueOfContent, null, netconfStrategy);
+ normalizedNode = readData(ContentParameter.CONFIG, DATA.path2, netconfStrategy);
assertNull(normalizedNode);
}
final QueryParameters parsedParameters = ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
- assertEquals("Not correctly parsed URI parameter",
- RestconfDataServiceConstant.ReadData.ALL, parsedParameters.getContent());
- assertNull("Not correctly parsed URI parameter",
- parsedParameters.getDepth());
- assertNull("Not correctly parsed URI parameter",
- parsedParameters.getFields());
+ assertEquals(ContentParameter.ALL, parsedParameters.getContent());
+ assertNull(parsedParameters.getDepth());
+ assertNull(parsedParameters.getFields());
}
/**
final UriInfo uriInfo = mock(UriInfo.class);
final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
- final String content = "config";
final String depth = "10";
final String fields = containerChildQName.getLocalName();
- parameters.put("content", List.of(content));
+ parameters.put("content", List.of("config"));
parameters.put("depth", List.of(depth));
parameters.put("fields", List.of(fields));
final QueryParameters parsedParameters = ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
// content
- assertEquals("Not correctly parsed URI parameter",
- content, parsedParameters.getContent());
+ assertEquals(ContentParameter.CONFIG, parsedParameters.getContent());
// depth
assertNotNull("Not correctly parsed URI parameter",
final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
// inserted value is too low
- parameters.put(
- "depth", List.of(String.valueOf(RestconfDataServiceConstant.ReadData.MIN_DEPTH - 1)));
+ parameters.put("depth", List.of("0"));
when(uriInfo.getQueryParameters()).thenReturn(parameters);
RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
// inserted value is too high
- parameters.put("depth", List.of(String.valueOf(RestconfDataServiceConstant.ReadData.MAX_DEPTH + 1)));
+ parameters.put("depth", List.of("65536"));
when(uriInfo.getQueryParameters()).thenReturn(parameters);
RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
// preparation of input data
final UriInfo uriInfo = mock(UriInfo.class);
final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
- parameters.put(RestconfDataServiceConstant.ReadData.WITH_DEFAULTS, List.of("explicit"));
+ parameters.put("with-defaults", List.of("explicit"));
when(uriInfo.getQueryParameters()).thenReturn(parameters);
final QueryParameters writerParameters = ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
- assertSame(WithDefaults.EXPLICIT.value(), writerParameters.getWithDefault());
+ assertSame(WithDefaultsParameter.EXPLICIT, writerParameters.getWithDefault());
assertFalse(writerParameters.isTagged());
}
// preparation of input data
final UriInfo uriInfo = mock(UriInfo.class);
final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
- parameters.put(RestconfDataServiceConstant.ReadData.WITH_DEFAULTS, List.of("invalid"));
+ parameters.put("with-defaults", List.of("invalid"));
when(uriInfo.getQueryParameters()).thenReturn(parameters);
final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
// preparation of input data
final UriInfo uriInfo = mock(UriInfo.class);
final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
- parameters.put(RestconfDataServiceConstant.ReadData.WITH_DEFAULTS,
- List.of(ReadData.WithDefaults.REPORT_ALL_TAGGED.value()));
+ parameters.put("with-defaults", List.of("report-all-tagged"));
when(uriInfo.getQueryParameters()).thenReturn(parameters);
final QueryParameters writerParameters = ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
// preparation of input data
final UriInfo uriInfo = mock(UriInfo.class);
final MultivaluedHashMap<String, String> parameters = new MultivaluedHashMap<>();
- parameters.put(RestconfDataServiceConstant.ReadData.WITH_DEFAULTS,
- List.of(ReadData.WithDefaults.REPORT_ALL.value()));
+ parameters.put("with-defaults", List.of("report-all"));
when(uriInfo.getQueryParameters()).thenReturn(parameters);
final QueryParameters writerParameters = ReadDataTransactionUtil.parseUriParameters(context, uriInfo);
*/
@Test
public void checkParameterCountTest() {
- ReadDataTransactionUtil.checkParameterCount(List.of("all"), RestconfDataServiceConstant.ReadData.CONTENT);
+ ReadDataTransactionUtil.checkParameterCount(List.of("all"), ContentParameter.uriName());
}
/**
public void checkParameterCountNegativeTest() {
final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
() -> ReadDataTransactionUtil.checkParameterCount(List.of("config", "nonconfig", "all"),
- RestconfDataServiceConstant.ReadData.CONTENT));
+ ContentParameter.uriName()));
final List<RestconfError> errors = ex.getErrors();
assertEquals(1, errors.size());
@Test
public void checkParametersTypesTest() {
ReadDataTransactionUtil.checkParametersTypes(Set.of("content"),
- Set.of(RestconfDataServiceConstant.ReadData.CONTENT, RestconfDataServiceConstant.ReadData.DEPTH));
+ Set.of(ContentParameter.uriName(), DepthParameter.uriName()));
}
/**
public void checkParametersTypesNegativeTest() {
final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
() -> ReadDataTransactionUtil.checkParametersTypes(Set.of("not-allowed-parameter"),
- Set.of(RestconfDataServiceConstant.ReadData.CONTENT, RestconfDataServiceConstant.ReadData.DEPTH)));
+ Set.of(ContentParameter.uriName(), DepthParameter.uriName())));
final List<RestconfError> errors = ex.getErrors();
assertEquals(1, errors.size());
/**
* Read specific type of data from data store via transaction.
*
- * @param valueOfContent type of data to read (config, state, all)
+ * @param content type of data to read (config, state, all)
* @param strategy {@link RestconfStrategy} - wrapper for variables
* @return {@link NormalizedNode}
*/
- private @Nullable NormalizedNode readData(final @NonNull String valueOfContent,
+ private @Nullable NormalizedNode readData(final @NonNull ContentParameter content,
final YangInstanceIdentifier path, final @NonNull RestconfStrategy strategy) {
- return ReadDataTransactionUtil.readData(valueOfContent, path, strategy, null, schemaContext);
+ return ReadDataTransactionUtil.readData(content, path, strategy, null, schemaContext);
}
}