View Javadoc
1   /*
2    * The contents of this file are subject to the terms of the Common Development and
3    * Distribution License (the License). You may not use this file except in compliance with the
4    * License.
5    *
6    * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
7    * specific language governing permission and limitations under the License.
8    *
9    * When distributing Covered Software, include this CDDL Header Notice in each file and include
10   * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
11   * Header, with the fields enclosed by brackets [] replaced by your own identifying
12   * information: "Portions copyright [year] [name of copyright owner]".
13   *
14   * Copyright 2016 ForgeRock AS.
15   */
16  
17  package org.forgerock.api.models;
18  
19  import static org.forgerock.api.util.ValidationUtil.*;
20  
21  import java.util.HashMap;
22  import java.util.Map;
23  import java.util.Objects;
24  import java.util.Set;
25  
26  import com.fasterxml.jackson.annotation.JsonAnySetter;
27  import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
28  import org.forgerock.api.util.PathUtil;
29  import org.forgerock.util.Reject;
30  
31  import com.fasterxml.jackson.annotation.JsonIgnore;
32  import com.fasterxml.jackson.annotation.JsonValue;
33  
34  /**
35   * Sub-resources of a resource are declared here.
36   */
37  @JsonDeserialize(builder = SubResources.Builder.class)
38  public final class SubResources {
39      private final Map<String, Resource> subResources;
40  
41      private SubResources(Builder builder) {
42          this.subResources = builder.subResources;
43      }
44  
45      /**
46       * Gets a {@code Map} of paths to {@link Resource}s.
47       *
48       * @return The {@code Map}.
49       */
50      @JsonValue
51      public Map<String, Resource> getSubResources() {
52          return subResources;
53      }
54  
55      /**
56       * Gets the {@link Resource} for a given sub-resource name.
57       *
58       * @param name Sub-resource name
59       * @return {@link Resource} or {@code null} if does-not-exist.
60       */
61      @JsonIgnore
62      public Resource get(String name) {
63          return subResources.get(name);
64      }
65  
66      /**
67       * Returns all sub-resource names.
68       *
69       * @return The names.
70       */
71      @JsonIgnore
72      public Set<String> getNames() {
73          return subResources.keySet();
74      }
75  
76      @Override
77      public boolean equals(Object o) {
78          if (this == o) {
79              return true;
80          }
81          if (o == null || getClass() != o.getClass()) {
82              return false;
83          }
84          SubResources that = (SubResources) o;
85          return Objects.equals(subResources, that.subResources);
86      }
87  
88      @Override
89      public int hashCode() {
90          return Objects.hash(subResources);
91      }
92  
93      /**
94       * Create a new Builder for sub-resources.
95       *
96       * @return Builder
97       */
98      public static Builder subresources() {
99          return new Builder();
100     }
101 
102     /**
103      * Builder to help construct the SubResources.
104      */
105     public static final class Builder {
106 
107         private final Map<String, Resource> subResources = new HashMap<>();
108 
109         /**
110          * Private default constructor.
111          */
112         private Builder() {
113         }
114 
115         /**
116          * Adds a sub-resource.
117          *
118          * @param path Sub-resource path
119          * @param resource {@link Resource}
120          * @return Builder
121          */
122         @JsonAnySetter
123         public Builder put(String path, Resource resource) {
124             if (path == null || containsWhitespace(path)) {
125                 throw new IllegalArgumentException("path required and may not contain whitespace");
126             }
127             if (!path.isEmpty()) {
128                 // paths must start with a slash (OpenAPI spec) and not end with one
129                 path = PathUtil.buildPath(path);
130             }
131             if (subResources.containsKey(path)) {
132                 throw new IllegalStateException("path not unique");
133             }
134             subResources.put(path, Reject.checkNotNull(resource));
135             return this;
136         }
137 
138         /**
139          * Builds the {@link SubResources} instance.
140          *
141          * @return {@link SubResources} instance
142          */
143         public SubResources build() {
144             return new SubResources(this);
145         }
146     }
147 
148 }