Separate out ReadDataParams 11/98111/1
authorRobert Varga <robert.varga@pantheon.tech>
Sun, 24 Oct 2021 19:44:43 +0000 (21:44 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Sun, 24 Oct 2021 20:03:03 +0000 (22:03 +0200)
QueryParams has some filtering details stuck with normal UriInfo
parsing. Separate out ReadDataParams, so that we can easily discern
what is what.

JIRA: NETCONF-773
Change-Id: Idf3a46ec4978bc9a59ee062836a14dbb7413f505
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/FieldsParameter.java
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/FieldsParameterParser.java
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/ReadDataParams.java [new file with mode: 0644]
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/databind/jaxrs/QueryParams.java
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/JsonNormalizedNodeBodyWriter.java
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/jersey/providers/XmlNormalizedNodeBodyWriter.java
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/legacy/QueryParameters.java
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataServiceImpl.java
restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/databind/jaxrs/QueryParamsTest.java

index 3ef1531154993694aceaf9b0700ccdef686f9ea5..ab6623f3f575f8d666df8542a9ab942bf58e480d 100644 (file)
@@ -76,10 +76,12 @@ public final class FieldsParameter implements Immutable {
     private static final URI CAPABILITY = URI.create("urn:ietf:params:restconf:capability:fields:1.0");
 
     private final ImmutableList<NodeSelector> nodeSelectors;
+    private final String uriValue;
 
-    FieldsParameter(final ImmutableList<NodeSelector> nodeSelectors) {
+    private FieldsParameter(final ImmutableList<NodeSelector> nodeSelectors, final String uriValue) {
         this.nodeSelectors = requireNonNull(nodeSelectors);
         checkArgument(!nodeSelectors.isEmpty(), "At least one selector is required");
+        this.uriValue = requireNonNull(uriValue);
     }
 
     /**
@@ -90,7 +92,7 @@ public final class FieldsParameter implements Immutable {
      * @throws ParseException if {@code str} does not represent a valid {@code fields} parameter.
      */
     public static FieldsParameter parse(final String str) throws ParseException {
-        return new FieldsParameterParser().parse(str);
+        return new FieldsParameter(new FieldsParameterParser().parseNodeSelectors(str), str);
     }
 
     public static String uriName() {
@@ -110,6 +112,11 @@ public final class FieldsParameter implements Immutable {
         return nodeSelectors;
     }
 
+    // FIXME: for migration only
+    public String uriValue() {
+        return uriValue;
+    }
+
     @Override
     public String toString() {
         return MoreObjects.toStringHelper(this).add("nodeSelectors", nodeSelectors).toString();
index 1f98e429bec0150fdc77c235b2863420c4b3d5d2..d8eb31b5e8cc201b6e199652898871fdf1c878df 100644 (file)
@@ -66,7 +66,7 @@ final class FieldsParameterParser {
     // parsers instead of ten.
     private Deque<NodeSelectorParser> parsers;
 
-    @NonNull FieldsParameter parse(final String str) throws ParseException {
+    @NonNull ImmutableList<NodeSelector> parseNodeSelectors(final String str) throws ParseException {
         final var nodeSelectors = ImmutableList.<NodeSelector>builder();
 
         int idx = 0;
@@ -77,7 +77,7 @@ final class FieldsParameterParser {
 
             if (next == str.length()) {
                 // We have reached the end, we are done
-                return new FieldsParameter(nodeSelectors.build());
+                return nodeSelectors.build();
             }
 
             final char ch = str.charAt(next);
diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/ReadDataParams.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/ReadDataParams.java
new file mode 100644 (file)
index 0000000..31a8a2d
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * 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 com.google.common.base.MoreObjects;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.concepts.Immutable;
+
+/**
+ * Parser and holder of query parameters from uriInfo for data and datastore read operations.
+ */
+@Beta
+// FIXME: this should be a record once we have JDK17+
+public final class ReadDataParams implements Immutable {
+    private static final @NonNull ReadDataParams EMPTY =
+        new ReadDataParams(ContentParameter.ALL, null, null, null, false, false);
+
+    private final @NonNull ContentParameter content;
+    private final WithDefaultsParameter withDefaults;
+    private final FieldsParameter fields;
+    private final DepthParameter depth;
+    private final boolean prettyPrint;
+    private final boolean tagged;
+
+    private ReadDataParams(final ContentParameter content,  final DepthParameter depth, final FieldsParameter fields,
+            final WithDefaultsParameter withDefaults, final boolean tagged, final boolean prettyPrint) {
+        this.content = requireNonNull(content);
+        this.depth = depth;
+        this.fields = fields;
+        this.withDefaults = withDefaults;
+        this.tagged = tagged;
+        this.prettyPrint = prettyPrint;
+    }
+
+    public static @NonNull ReadDataParams empty() {
+        return EMPTY;
+    }
+
+    public static @NonNull ReadDataParams of(final ContentParameter content,  final DepthParameter depth,
+            final FieldsParameter fields, final WithDefaultsParameter withDefaults, final boolean tagged,
+            final boolean prettyPrint) {
+        return new ReadDataParams(content, depth, fields, withDefaults, tagged, prettyPrint);
+    }
+
+    public @NonNull ContentParameter content() {
+        return content;
+    }
+
+    public @Nullable DepthParameter depth() {
+        return depth;
+    }
+
+    public @Nullable FieldsParameter fields() {
+        return fields;
+    }
+
+    public @Nullable WithDefaultsParameter withDefaults() {
+        return withDefaults;
+    }
+
+    public boolean prettyPrint() {
+        return prettyPrint;
+    }
+
+    // FIXME: for migration only
+    public boolean tagged() {
+        return tagged;
+    }
+
+    @Override
+    public String toString() {
+        final var helper = MoreObjects.toStringHelper(this).add("content", content.uriValue());
+        if (depth != null) {
+            helper.add("depth", depth.value());
+        }
+        if (fields != null) {
+            helper.add("fields", fields.toString());
+        }
+        if (withDefaults != null) {
+            helper.add("withDefaults", withDefaults.uriValue());
+        }
+        return helper.add("tagged", tagged).add("prettyPrint", prettyPrint).toString();
+    }
+}
index d18b0435d80b40939840e37a69da9e301097d2a6..07152d1a106d33c329abf82ba38f21f019f52cd5 100644 (file)
@@ -13,6 +13,7 @@ import static org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserFieldsPara
 
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.VisibleForTesting;
+import java.text.ParseException;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map.Entry;
@@ -33,12 +34,12 @@ import org.opendaylight.restconf.nb.rfc8040.FilterParameter;
 import org.opendaylight.restconf.nb.rfc8040.InsertParameter;
 import org.opendaylight.restconf.nb.rfc8040.NotificationQueryParams;
 import org.opendaylight.restconf.nb.rfc8040.PointParameter;
+import org.opendaylight.restconf.nb.rfc8040.ReadDataParams;
 import org.opendaylight.restconf.nb.rfc8040.StartTimeParameter;
 import org.opendaylight.restconf.nb.rfc8040.StopTimeParameter;
 import org.opendaylight.restconf.nb.rfc8040.WithDefaultsParameter;
 import org.opendaylight.restconf.nb.rfc8040.WriteDataParams;
 import org.opendaylight.restconf.nb.rfc8040.legacy.QueryParameters;
-import org.opendaylight.restconf.nb.rfc8040.legacy.QueryParameters.Builder;
 import org.opendaylight.yangtools.yang.common.ErrorTag;
 import org.opendaylight.yangtools.yang.common.ErrorType;
 
@@ -94,52 +95,69 @@ public final class QueryParams {
         }
     }
 
+    public static QueryParameters newQueryParameters(final ReadDataParams params,
+            final InstanceIdentifierContext<?> identifier) {
+        final var fields = params.fields();
+        if (fields == null) {
+            return QueryParameters.of(params);
+        }
+
+        return identifier.getMountPoint() != null
+            ? QueryParameters.ofFieldPaths(params, parseFieldsPaths(identifier, fields.uriValue()))
+                : QueryParameters.ofFields(params, parseFieldsParameter(identifier, fields.uriValue()));
+    }
+
     /**
      * Parse parameters from URI request and check their types and values.
      *
-     * @param identifier {@link InstanceIdentifierContext}
      * @param uriInfo    URI info
-     * @return {@link QueryParameters}
+     * @return {@link ReadDataParams}
      */
-    public static QueryParameters newReadDataParams(final InstanceIdentifierContext<?> identifier,
-                                                    final UriInfo uriInfo) {
+    public static @NonNull ReadDataParams newReadDataParams(final UriInfo uriInfo) {
         // check only allowed parameters
         final MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
         checkParametersTypes(queryParams.keySet(), ALLOWED_PARAMETERS);
 
-        final Builder builder = QueryParameters.builder();
         // check and set content
         final String contentStr = getSingleParameter(queryParams, ContentParameter.uriName());
-        if (contentStr != null) {
-            builder.setContent(RestconfDocumentedException.throwIfNull(
-                ContentParameter.forUriValue(contentStr), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
-                "Invalid content parameter: %s, allowed values are %s", contentStr, POSSIBLE_CONTENT));
-        }
+        final ContentParameter content = contentStr == null ? ContentParameter.ALL
+            : RestconfDocumentedException.throwIfNull(ContentParameter.forUriValue(contentStr),
+                ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
+                "Invalid content parameter: %s, allowed values are %s", contentStr, POSSIBLE_CONTENT);
 
         // check and set depth
+        final DepthParameter depth;
         final String depthStr = getSingleParameter(queryParams, DepthParameter.uriName());
         if (depthStr != null) {
             try {
-                builder.setDepth(DepthParameter.forUriValue(depthStr));
+                depth = DepthParameter.forUriValue(depthStr);
             } catch (IllegalArgumentException e) {
                 throw new RestconfDocumentedException(e, new RestconfError(ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
                     "Invalid depth parameter: " + depthStr, null,
                     "The depth parameter must be an integer between 1 and 65535 or \"unbounded\""));
             }
+        } else {
+            depth = null;
         }
 
         // check and set fields
+        final FieldsParameter fields;
         final String fieldsStr = getSingleParameter(queryParams, FieldsParameter.uriName());
         if (fieldsStr != null) {
-            // FIXME: parse a FieldsParameter instead
-            if (identifier.getMountPoint() != null) {
-                builder.setFieldPaths(parseFieldsPaths(identifier, fieldsStr));
-            } else {
-                builder.setFields(parseFieldsParameter(identifier, fieldsStr));
+            try {
+                fields = FieldsParameter.parse(fieldsStr);
+            } catch (ParseException e) {
+                throw new RestconfDocumentedException(e, new RestconfError(ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
+                    "Invalid filds parameter: " + fieldsStr));
             }
+        } else {
+            fields = null;
         }
 
         // check and set withDefaults parameter
+        final WithDefaultsParameter withDefaults;
+        final boolean tagged;
+
         final String withDefaultsStr = getSingleParameter(queryParams, WithDefaultsParameter.uriName());
         if (withDefaultsStr != null) {
             final WithDefaultsParameter val = WithDefaultsParameter.forUriValue(withDefaultsStr);
@@ -151,16 +169,24 @@ public final class QueryParams {
 
             switch (val) {
                 case REPORT_ALL:
+                    withDefaults = null;
+                    tagged = false;
                     break;
                 case REPORT_ALL_TAGGED:
-                    builder.setTagged(true);
+                    withDefaults = null;
+                    tagged = true;
                     break;
                 default:
-                    builder.setWithDefault(val);
+                    withDefaults = val;
+                    tagged = false;
             }
+        } else {
+            withDefaults = null;
+            tagged = false;
         }
 
-        return builder.build();
+        // FIXME: recognize pretty-print here
+        return ReadDataParams.of(content, depth, fields, withDefaults, tagged, false);
     }
 
     public static @NonNull WriteDataParams newWriteDataParams(final UriInfo uriInfo) {
index fd4b6a8f3f94bcae741293c7ee48ca7257b69696..a37a9a86cddb4d62188157122aa22a0adfcdb65d 100644 (file)
@@ -68,10 +68,10 @@ public class JsonNormalizedNodeBodyWriter extends AbstractNormalizedNodeBodyWrit
                 (InstanceIdentifierContext<SchemaNode>) context.getInstanceIdentifierContext();
         final SchemaPath path = identifierCtx.getSchemaNode().getPath();
 
-        try (JsonWriter jsonWriter = createJsonWriter(entityStream, context.getWriterParameters().isPrettyPrint())) {
+        try (JsonWriter jsonWriter = createJsonWriter(entityStream, context.getWriterParameters().prettyPrint())) {
             jsonWriter.beginObject();
             writeNormalizedNode(jsonWriter, path, identifierCtx, data,
-                    context.getWriterParameters().getDepth(), context.getWriterParameters().getFields());
+                    context.getWriterParameters().depth(), context.getWriterParameters().fields());
             jsonWriter.endObject();
             jsonWriter.flush();
         }
index fb3d4e979c44bdd7ff75d427eacef914f2aba88e..0baa199d7ae1e4b394c0e9ca77cb06e84a887ecb 100644 (file)
@@ -74,7 +74,7 @@ public class XmlNormalizedNodeBodyWriter extends AbstractNormalizedNodeBodyWrite
         XMLStreamWriter xmlWriter;
         try {
             xmlWriter = XML_FACTORY.createXMLStreamWriter(entityStream, StandardCharsets.UTF_8.name());
-            if (context.getWriterParameters().isPrettyPrint()) {
+            if (context.getWriterParameters().prettyPrint()) {
                 xmlWriter = new IndentingXMLStreamWriter(xmlWriter);
             }
         } catch (final XMLStreamException | FactoryConfigurationError e) {
@@ -83,8 +83,8 @@ public class XmlNormalizedNodeBodyWriter extends AbstractNormalizedNodeBodyWrite
         final NormalizedNode data = context.getData();
         final SchemaPath schemaPath = pathContext.getSchemaNode().getPath();
 
-        writeNormalizedNode(xmlWriter, schemaPath, pathContext, data, context.getWriterParameters().getDepth(),
-                context.getWriterParameters().getFields());
+        writeNormalizedNode(xmlWriter, schemaPath, pathContext, data, context.getWriterParameters().depth(),
+                context.getWriterParameters().fields());
     }
 
     private static void writeNormalizedNode(final XMLStreamWriter xmlWriter, final SchemaPath path,
index 4fa5a521da8bee65ecf6a62d904b4cdd734a6ba7..762a614a67b7acdee1eea79e1caeb50a3ff1fc61 100644 (file)
@@ -9,13 +9,13 @@ package org.opendaylight.restconf.nb.rfc8040.legacy;
 
 import static java.util.Objects.requireNonNull;
 
+import com.google.common.annotations.Beta;
 import java.util.List;
 import java.util.Set;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
-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.ReadDataParams;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 
@@ -24,114 +24,57 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
  * sense of it, as parts of it pertain to how a {@link NormalizedNodePayload} should be created while others how it
  * needs to be processed (for example filtered).
  */
+@Beta
+// FIXME: this probably needs to be renamed back to WriterParams, or somesuch
 public final class QueryParameters {
-    public static final class Builder {
-        private @NonNull ContentParameter content = ContentParameter.ALL;
-        private List<YangInstanceIdentifier> fieldPaths;
-        private List<Set<QName>> fields;
-        private WithDefaultsParameter withDefault;
-        private DepthParameter depth;
-        private boolean prettyPrint;
-        private boolean tagged;
-
-        Builder() {
-            // Hidden on purpose
-        }
-
-        public Builder setContent(final ContentParameter content) {
-            this.content = requireNonNull(content);
-            return this;
-        }
-
-        public Builder setDepth(final DepthParameter depth) {
-            this.depth = depth;
-            return this;
-        }
-
-        public Builder setFields(final List<Set<QName>> fields) {
-            this.fields = fields;
-            return this;
-        }
-
-        public Builder setFieldPaths(final List<YangInstanceIdentifier> fieldPaths) {
-            this.fieldPaths = fieldPaths;
-            return this;
-        }
-
-        // FIXME: this is not called from anywhere. Create a PrettyPrintParameter or similar to hold it
-        public Builder setPrettyPrint(final boolean prettyPrint) {
-            this.prettyPrint = prettyPrint;
-            return this;
-        }
-
-        public Builder setTagged(final boolean tagged) {
-            this.tagged = tagged;
-            return this;
-        }
-
-        public Builder setWithDefault(final WithDefaultsParameter withDefault) {
-            this.withDefault = withDefault;
-            return this;
-        }
-
-        public @NonNull QueryParameters build() {
-            return new QueryParameters(this);
-        }
-    }
-
-    private static final @NonNull QueryParameters EMPTY = new Builder().build();
+    private static final @NonNull QueryParameters EMPTY = of(ReadDataParams.empty());
 
+    private final @NonNull ReadDataParams params;
     private final List<YangInstanceIdentifier> fieldPaths;
     private final List<Set<QName>> fields;
-    private final WithDefaultsParameter withDefault;
-    private final @NonNull ContentParameter content;
-    private final DepthParameter depth;
-    private final boolean prettyPrint;
-    private final boolean tagged;
 
-    private QueryParameters(final Builder builder) {
-        content = builder.content;
-        depth = builder.depth;
-        fields = builder.fields;
-        fieldPaths = builder.fieldPaths;
-        tagged = builder.tagged;
-        prettyPrint = builder.prettyPrint;
-        withDefault = builder.withDefault;
+    private QueryParameters(final ReadDataParams params, final List<Set<QName>> fields,
+            final List<YangInstanceIdentifier> fieldPaths) {
+        this.params = requireNonNull(params);
+        this.fields = fields;
+        this.fieldPaths = fieldPaths;
     }
 
     public static @NonNull QueryParameters empty() {
         return EMPTY;
     }
 
-    public static @NonNull Builder builder() {
-        return new Builder();
+    public static @NonNull QueryParameters of(final ReadDataParams params) {
+        return new QueryParameters(params, null, null);
     }
 
-    public @NonNull ContentParameter getContent() {
-        return content;
+    public static @NonNull QueryParameters ofFields(final ReadDataParams params, final List<Set<QName>> fields) {
+        return new QueryParameters(params, fields, null);
     }
 
-    public @Nullable DepthParameter getDepth() {
-        return depth;
+    public static @NonNull QueryParameters ofFieldPaths(final ReadDataParams params,
+            final List<YangInstanceIdentifier> fieldPaths) {
+        return new QueryParameters(params, null, fieldPaths);
     }
 
-    public List<Set<QName>> getFields() {
-        return fields;
+    public @NonNull ReadDataParams params() {
+        return params;
     }
 
-    public List<YangInstanceIdentifier> getFieldPaths() {
-        return fieldPaths;
+    public @Nullable DepthParameter depth() {
+        return params.depth();
     }
 
-    public WithDefaultsParameter getWithDefault() {
-        return withDefault;
+
+    public @Nullable List<Set<QName>> fields() {
+        return fields;
     }
 
-    public boolean isPrettyPrint() {
-        return prettyPrint;
+    public @Nullable List<YangInstanceIdentifier> fieldPaths() {
+        return fieldPaths;
     }
 
-    public boolean isTagged() {
-        return tagged;
+    public boolean prettyPrint() {
+        return params.prettyPrint();
     }
 }
index 4891a5b96a863f6d458bdf79b9ee42fe8cf7a5be..b3375a8c340b5466c37cdd53c9111d032c34b1af 100644 (file)
@@ -49,6 +49,7 @@ import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
 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.ReadDataParams;
 import org.opendaylight.restconf.nb.rfc8040.Rfc8040;
 import org.opendaylight.restconf.nb.rfc8040.WriteDataParams;
 import org.opendaylight.restconf.nb.rfc8040.databind.jaxrs.QueryParams;
@@ -130,11 +131,11 @@ public class RestconfDataServiceImpl implements RestconfDataService {
 
     @Override
     public Response readData(final String identifier, final UriInfo uriInfo) {
+        final ReadDataParams readParams = QueryParams.newReadDataParams(uriInfo);
+
         final EffectiveModelContext schemaContextRef = schemaContextHandler.get();
         final InstanceIdentifierContext<?> instanceIdentifier = ParserIdentifier.toInstanceIdentifier(
                 identifier, schemaContextRef, Optional.of(mountPointService));
-        final QueryParameters parameters = QueryParams.newReadDataParams(instanceIdentifier, uriInfo);
-
         final DOMMountPoint mountPoint = instanceIdentifier.getMountPoint();
 
         // FIXME: this looks quite crazy, why do we even have it?
@@ -143,15 +144,16 @@ public class RestconfDataServiceImpl implements RestconfDataService {
             createAllYangNotificationStreams(schemaContextRef, uriInfo);
         }
 
-        final List<YangInstanceIdentifier> fieldPaths = parameters.getFieldPaths();
+        final QueryParameters queryParams = QueryParams.newQueryParameters(readParams, instanceIdentifier);
+        final List<YangInstanceIdentifier> fieldPaths = queryParams.fieldPaths();
         final RestconfStrategy strategy = getRestconfStrategy(mountPoint);
         final NormalizedNode node;
         if (fieldPaths != null && !fieldPaths.isEmpty()) {
-            node = ReadDataTransactionUtil.readData(parameters.getContent(), instanceIdentifier.getInstanceIdentifier(),
-                    strategy, parameters.getWithDefault(), schemaContextRef, fieldPaths);
+            node = ReadDataTransactionUtil.readData(readParams.content(), instanceIdentifier.getInstanceIdentifier(),
+                    strategy, readParams.withDefaults(), schemaContextRef, fieldPaths);
         } else {
-            node = ReadDataTransactionUtil.readData(parameters.getContent(), instanceIdentifier.getInstanceIdentifier(),
-                    strategy, parameters.getWithDefault(), schemaContextRef);
+            node = ReadDataTransactionUtil.readData(readParams.content(), instanceIdentifier.getInstanceIdentifier(),
+                    strategy, readParams.withDefaults(), schemaContextRef);
         }
 
         // FIXME: this is utter craziness, refactor it properly!
@@ -167,19 +169,19 @@ public class RestconfDataServiceImpl implements RestconfDataService {
                     ErrorType.PROTOCOL, ErrorTag.DATA_MISSING);
         }
 
-        switch (parameters.getContent()) {
+        switch (readParams.content()) {
             case ALL:
             case CONFIG:
                 final QName type = node.getIdentifier().getNodeType();
                 return Response.status(Status.OK)
-                    .entity(NormalizedNodePayload.ofReadData(instanceIdentifier, node, parameters))
+                    .entity(NormalizedNodePayload.ofReadData(instanceIdentifier, node, queryParams))
                     .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(NormalizedNodePayload.ofReadData(instanceIdentifier, node, parameters))
+                    .entity(NormalizedNodePayload.ofReadData(instanceIdentifier, node, queryParams))
                     .build();
         }
     }
index 97f8b1fe23af70acce861638f7185e79011acd52..1cc2cd47979c721e5e251de58a5fe63f1a1f5c68 100644 (file)
@@ -30,6 +30,7 @@ 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.ReadDataParams;
 import org.opendaylight.restconf.nb.rfc8040.WithDefaultsParameter;
 import org.opendaylight.restconf.nb.rfc8040.legacy.QueryParameters;
 import org.opendaylight.yangtools.yang.common.ErrorTag;
@@ -113,11 +114,10 @@ public class QueryParamsTest {
         // no parameters, default values should be used
         mockQueryParameters(new MultivaluedHashMap<String, String>());
 
-        final QueryParameters parsedParameters = QueryParams.newReadDataParams(context, uriInfo);
-
-        assertEquals(ContentParameter.ALL, parsedParameters.getContent());
-        assertNull(parsedParameters.getDepth());
-        assertNull(parsedParameters.getFields());
+        final var parsedParameters = QueryParams.newReadDataParams(uriInfo);
+        assertEquals(ContentParameter.ALL, parsedParameters.content());
+        assertNull(parsedParameters.depth());
+        assertNull(parsedParameters.fields());
     }
 
     /**
@@ -129,7 +129,7 @@ public class QueryParamsTest {
         mockQueryParameter("with-defaults", "invalid");
 
         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
-            () -> QueryParams.newReadDataParams(context, uriInfo));
+            () -> QueryParams.newReadDataParams(uriInfo));
         final List<RestconfError> errors = ex.getErrors();
         assertEquals(1, errors.size());
         assertEquals(ErrorTag.INVALID_VALUE, errors.get(0).getErrorTag());
@@ -144,7 +144,7 @@ public class QueryParamsTest {
         mockQueryParameter("depth", "bounded");
 
         RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
-            () -> QueryParams.newReadDataParams(context, uriInfo));
+            () -> QueryParams.newReadDataParams(uriInfo));
         // Bad request
         assertEquals("Error type is not correct", ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
         assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
@@ -158,7 +158,7 @@ public class QueryParamsTest {
         mockQueryParameter("content", "not-allowed-parameter-value");
 
         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
-            () -> QueryParams.newReadDataParams(context, uriInfo));
+            () -> QueryParams.newReadDataParams(uriInfo));
         // Bad request
         assertEquals("Error type is not correct", ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
         assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
@@ -173,7 +173,7 @@ public class QueryParamsTest {
         mockQueryParameter("depth", "65536");
 
         RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
-            () -> QueryParams.newReadDataParams(context, uriInfo));
+            () -> QueryParams.newReadDataParams(uriInfo));
         // Bad request
         assertEquals("Error type is not correct", ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
         assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
@@ -188,7 +188,7 @@ public class QueryParamsTest {
         mockQueryParameter("depth", "0");
 
         RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
-            () -> QueryParams.newReadDataParams(context, uriInfo));
+            () -> QueryParams.newReadDataParams(uriInfo));
         // Bad request
         assertEquals("Error type is not correct", ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
         assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
@@ -203,9 +203,9 @@ public class QueryParamsTest {
         // preparation of input data
         mockQueryParameter("with-defaults", "report-all-tagged");
 
-        final QueryParameters writerParameters = QueryParams.newReadDataParams(context, uriInfo);
-        assertNull(writerParameters.getWithDefault());
-        assertTrue(writerParameters.isTagged());
+        final var parsedParameters = QueryParams.newReadDataParams(uriInfo);
+        assertNull(parsedParameters.withDefaults());
+        assertTrue(parsedParameters.tagged());
     }
 
     /**
@@ -217,9 +217,9 @@ public class QueryParamsTest {
         // preparation of input data
         mockQueryParameter("with-defaults", "report-all");
 
-        final QueryParameters writerParameters = QueryParams.newReadDataParams(context, uriInfo);
-        assertNull(writerParameters.getWithDefault());
-        assertFalse(writerParameters.isTagged());
+        final var parsedParameters = QueryParams.newReadDataParams(uriInfo);
+        assertNull(parsedParameters.withDefaults());
+        assertFalse(parsedParameters.tagged());
     }
 
     /**
@@ -231,9 +231,9 @@ public class QueryParamsTest {
         // preparation of input data
         mockQueryParameter("with-defaults", "explicit");
 
-        final QueryParameters writerParameters = QueryParams.newReadDataParams(context, uriInfo);
-        assertSame(WithDefaultsParameter.EXPLICIT, writerParameters.getWithDefault());
-        assertFalse(writerParameters.isTagged());
+        final var parsedParameters = QueryParams.newReadDataParams(uriInfo);
+        assertSame(WithDefaultsParameter.EXPLICIT, parsedParameters.withDefaults());
+        assertFalse(parsedParameters.tagged());
     }
 
     /**
@@ -249,28 +249,30 @@ public class QueryParamsTest {
         parameters.putSingle("fields", "container-child");
         mockQueryParameters(parameters);
 
-        doReturn(QName.create(containerChild, "container")).when(containerSchema).getQName();
-        doReturn(containerChildSchema).when(containerSchema).dataChildByName(containerChild);
-        doReturn(containerChild).when(containerChildSchema).getQName();
-
-        doReturn(modelContext).when(context).getSchemaContext();
-        doReturn(containerSchema).when(context).getSchemaNode();
-
-        final QueryParameters parsedParameters = QueryParams.newReadDataParams(context, uriInfo);
-
+        final ReadDataParams parsedParameters = QueryParams.newReadDataParams(uriInfo);
         // content
-        assertEquals(ContentParameter.CONFIG, parsedParameters.getContent());
+        assertEquals(ContentParameter.CONFIG, parsedParameters.content());
 
         // depth
-        final DepthParameter depth = parsedParameters.getDepth();
+        final DepthParameter depth = parsedParameters.depth();
         assertNotNull(depth);
         assertEquals(10, depth.value());
 
         // fields
-        assertNotNull(parsedParameters.getFields());
-        assertEquals(1, parsedParameters.getFields().size());
-        assertEquals(1, parsedParameters.getFields().get(0).size());
-        assertEquals(containerChild, parsedParameters.getFields().get(0).iterator().next());
+        assertNotNull(parsedParameters.fields());
+
+        // fields for write filtering
+        doReturn(QName.create(containerChild, "container")).when(containerSchema).getQName();
+        doReturn(containerChildSchema).when(containerSchema).dataChildByName(containerChild);
+        doReturn(containerChild).when(containerChildSchema).getQName();
+        doReturn(modelContext).when(context).getSchemaContext();
+        doReturn(containerSchema).when(context).getSchemaNode();
+
+        final QueryParameters queryParameters = QueryParams.newQueryParameters(parsedParameters, context);
+        final List<Set<QName>> fields = queryParameters.fields();
+        assertNotNull(fields);
+        assertEquals(1, fields.size());
+        assertEquals(Set.of(containerChild), fields.get(0));
     }
 
     private void mockQueryParameter(final String name, final String value) {