b2d892c51773e89f33d20347131101e59bc50dd4
[netconf.git] / restconf / restconf-nb-rfc8040 / src / main / java / org / opendaylight / restconf / nb / rfc8040 / databind / jaxrs / UriInfoSupport.java
1 /*
2  * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.restconf.nb.rfc8040.databind.jaxrs;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.annotations.Beta;
13 import java.util.List;
14 import java.util.Map.Entry;
15 import java.util.function.Function;
16 import javax.ws.rs.core.MultivaluedMap;
17 import javax.ws.rs.core.UriInfo;
18 import org.eclipse.jdt.annotation.NonNull;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
21 import org.opendaylight.restconf.nb.rfc8040.FilterParameter;
22 import org.opendaylight.restconf.nb.rfc8040.NotificationQueryParams;
23 import org.opendaylight.restconf.nb.rfc8040.StartTimeParameter;
24 import org.opendaylight.restconf.nb.rfc8040.StopTimeParameter;
25 import org.opendaylight.yangtools.yang.common.ErrorTag;
26 import org.opendaylight.yangtools.yang.common.ErrorType;
27
28 @Beta
29 public final class UriInfoSupport {
30     private UriInfoSupport() {
31         // Utility class
32     }
33
34     public static @NonNull NotificationQueryParams newNotificationQueryParams(final UriInfo uriInfo) {
35         StartTimeParameter startTime = null;
36         StopTimeParameter stopTime = null;
37         FilterParameter filter = null;
38         boolean skipNotificationData = false;
39
40         for (final Entry<String, List<String>> entry : uriInfo.getQueryParameters().entrySet()) {
41             final String paramName = entry.getKey();
42             final List<String> paramValues = entry.getValue();
43
44             try {
45                 if (paramName.equals(StartTimeParameter.uriName())) {
46                     startTime = optionalParam(StartTimeParameter::forUriValue, paramName, paramValues);
47                     break;
48                 } else if (paramName.equals(StopTimeParameter.uriName())) {
49                     stopTime = optionalParam(StopTimeParameter::forUriValue, paramName, paramValues);
50                     break;
51                 } else if (paramName.equals(FilterParameter.uriName())) {
52                     filter = optionalParam(FilterParameter::forUriValue, paramName, paramValues);
53                 } else if (paramName.equals("odl-skip-notification-data")) {
54                     // FIXME: this should be properly encapsulated in SkipNotificatioDataParameter
55                     skipNotificationData = Boolean.parseBoolean(optionalParam(paramName, paramValues));
56                 } else {
57                     throw new RestconfDocumentedException("Bad parameter used with notifications: " + paramName);
58                 }
59             } catch (IllegalArgumentException e) {
60                 throw new RestconfDocumentedException("Invalid " + paramName + " value: " + e.getMessage(), e);
61             }
62         }
63
64         try {
65             return NotificationQueryParams.of(startTime, stopTime, filter, skipNotificationData);
66         } catch (IllegalArgumentException e) {
67             throw new RestconfDocumentedException("Invalid query parameters: " + e.getMessage(), e);
68         }
69     }
70
71     public static @Nullable String getSingleParameter(final MultivaluedMap<String, String> params, final String name) {
72         final var values = params.get(name);
73         return values == null ? null : optionalParam(name, values);
74     }
75
76     public static @Nullable String optionalParam(final String name, final List<String> values) {
77         switch (values.size()) {
78             case 0:
79                 return null;
80             case 1:
81                 return requireNonNull(values.get(0));
82             default:
83                 throw new RestconfDocumentedException("Parameter " + name + " can appear at most once in request URI",
84                     ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
85         }
86     }
87
88     private static <T> @Nullable T optionalParam(final Function<String, @NonNull T> factory, final String name,
89             final List<String> values) {
90         final String str = optionalParam(name, values);
91         return str == null ? null : factory.apply(str);
92     }
93 }