Propagate WriteDataParams in utilities
[netconf.git] / restconf / restconf-nb-rfc8040 / src / main / java / org / opendaylight / restconf / nb / rfc8040 / WriteDataParams.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;
9
10 import static com.google.common.base.Verify.verifyNotNull;
11
12 import com.google.common.annotations.Beta;
13 import com.google.common.base.MoreObjects;
14 import org.eclipse.jdt.annotation.NonNull;
15 import org.eclipse.jdt.annotation.Nullable;
16 import org.opendaylight.yangtools.concepts.Immutable;
17
18 /**
19  * Parser and holder of query parameters from uriInfo for data and datastore modification operations.
20  */
21 // FIXME: this should be a record with JDK17+
22 public final class WriteDataParams implements Immutable {
23     private static final @NonNull WriteDataParams EMPTY = new WriteDataParams(null, null);
24
25     private final PointParam point;
26     private final InsertParam insert;
27
28     private WriteDataParams(final InsertParam insert, final PointParam point) {
29         this.insert = insert;
30         this.point = point;
31     }
32
33     public static @NonNull WriteDataParams empty() {
34         return EMPTY;
35     }
36
37     public static @NonNull WriteDataParams of(final InsertParam insert, final PointParam point) {
38         if (point == null) {
39             if (insert == null) {
40                 return empty();
41             }
42
43             // https://datatracker.ietf.org/doc/html/rfc8040#section-4.8.5:
44             //        If the values "before" or "after" are used, then a "point" query
45             //        parameter for the "insert" query parameter MUST also be present, or a
46             //        "400 Bad Request" status-line is returned.
47             if (insert == InsertParam.BEFORE || insert == InsertParam.AFTER) {
48                 throw new IllegalArgumentException(
49                     "Insert parameter " + insert.paramValue() + " cannot be used without a Point parameter.");
50             }
51         } else {
52             // https://datatracker.ietf.org/doc/html/rfc8040#section-4.8.6:
53             // [when "point" parameter is present and]
54             //        If the "insert" query parameter is not present or has a value other
55             //        than "before" or "after", then a "400 Bad Request" status-line is
56             //        returned.
57             if (insert != InsertParam.BEFORE && insert != InsertParam.AFTER) {
58                 throw new IllegalArgumentException(
59                     "Point parameter can be used only with 'after' or 'before' values of Insert parameter.");
60             }
61         }
62
63         return new WriteDataParams(insert, point);
64     }
65
66     public @Nullable InsertParam insert() {
67         return insert;
68     }
69
70     public @Nullable PointParam point() {
71         return point;
72     }
73
74     @Beta
75     // FIXME: it seems callers' structure should be able to cater with just point() and insert()
76     public @NonNull PointParam getPoint() {
77         return verifyNotNull(point);
78     }
79
80     @Override
81     public String toString() {
82         final var helper = MoreObjects.toStringHelper(this).omitNullValues();
83         if (insert != null) {
84             helper.add("insert", insert.paramValue());
85         }
86         if (point != null) {
87             helper.add("point", point.value());
88         }
89         return helper.toString();
90     }
91 }