2 * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.restconf.api.query;
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.base.MoreObjects;
14 import com.google.common.collect.ImmutableList;
16 import java.text.ParseException;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.opendaylight.restconf.api.ApiPath.ApiIdentifier;
19 import org.opendaylight.yangtools.concepts.Immutable;
22 * This class represents a {@code fields} parameter as defined in
23 * <a href="https://www.rfc-editor.org/rfc/rfc8040#section-4.8.3">RFC8040 section 4.8.3</a>.
26 public final class FieldsParam implements RestconfQueryParam<FieldsParam> {
28 * A selector for a single node as identified by {@link #path()}. Individual child nodes are subject to further
29 * filtering based on {@link #subSelectors()}.
31 public static final class NodeSelector implements Immutable {
32 private final ImmutableList<ApiIdentifier> path;
33 private final ImmutableList<NodeSelector> subSelectors;
35 NodeSelector(final ImmutableList<ApiIdentifier> path, final ImmutableList<NodeSelector> subSelectors) {
36 this.path = requireNonNull(path);
37 this.subSelectors = requireNonNull(subSelectors);
38 checkArgument(!path.isEmpty(), "At least path segment is required");
42 * Return the path to the selected node. Guaranteed to have at least one element.
44 * @return path to the selected node
46 public ImmutableList<ApiIdentifier> path() {
51 * Selectors for single nodes which should be selected from the node found by interpreting {@link #path}. If
52 * there are no selectors, i.e. {@code subSelectors().isEmpty())}, all child nodes are meant to be selected.
54 * @return Selectors for nested nodes.
56 public ImmutableList<NodeSelector> subSelectors() {
61 public String toString() {
62 final var helper = MoreObjects.toStringHelper(this).add("path", path);
63 if (!subSelectors.isEmpty()) {
64 helper.add("subSelectors", subSelectors);
66 return helper.toString();
69 void appendTo(final StringBuilder sb) {
70 final var it = path.iterator();
71 appendStep(sb, it.next());
72 while (it.hasNext()) {
73 appendStep(sb.append('/'), it.next());
76 if (!subSelectors.isEmpty()) {
77 appendSelectors(sb.append('('), subSelectors).append(')');
81 private static void appendStep(final StringBuilder sb, final ApiIdentifier step) {
82 final var mod = step.module();
84 sb.append(mod).append(':');
86 sb.append(step.identifier().getLocalName());
90 // API consistency: must not be confused with enum constants
91 @SuppressWarnings("checkstyle:ConstantName")
92 public static final String uriName = "fields";
93 private static final URI CAPABILITY = URI.create("urn:ietf:params:restconf:capability:fields:1.0");
95 private final ImmutableList<NodeSelector> nodeSelectors;
97 FieldsParam(final ImmutableList<NodeSelector> nodeSelectors) {
98 this.nodeSelectors = requireNonNull(nodeSelectors);
99 checkArgument(!nodeSelectors.isEmpty(), "At least one selector is required");
103 * Parse a {@code fields} parameter.
105 * @param str Unescaped URL string
106 * @return The contents of parameter
107 * @throws ParseException if {@code str} does not represent a valid {@code fields} parameter.
109 public static FieldsParam parse(final String str) throws ParseException {
110 return new FieldsParameterParser().parse(str);
113 public static FieldsParam forUriValue(final String uriValue) {
115 return parse(uriValue);
116 } catch (ParseException e) {
117 throw new IllegalArgumentException(e.getMessage() + " [at offset " + e.getErrorOffset() + "]", e);
122 public Class<FieldsParam> javaClass() {
123 return FieldsParam.class;
127 public String paramName() {
131 public static URI capabilityUri() {
136 * Selectors for nodes which should be reported. Guaranteed to have at least one element.
138 * @return selectors for nodes to be reported
140 public ImmutableList<NodeSelector> nodeSelectors() {
141 return nodeSelectors;
145 public String paramValue() {
146 return appendSelectors(new StringBuilder(), nodeSelectors).toString();
150 public String toString() {
151 return MoreObjects.toStringHelper(this).add("nodeSelectors", nodeSelectors).toString();
154 private static StringBuilder appendSelectors(final StringBuilder sb, final ImmutableList<NodeSelector> selectors) {
155 final var it = selectors.iterator();
156 it.next().appendTo(sb);
157 while (it.hasNext()) {
158 it.next().appendTo(sb.append(';'));