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.containsWhitespace;
20  import static org.forgerock.api.util.ValidationUtil.isEmpty;
21  
22  import java.lang.reflect.Method;
23  import java.util.Objects;
24  
25  import com.fasterxml.jackson.annotation.JsonInclude;
26  import com.fasterxml.jackson.annotation.JsonProperty;
27  import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
28  import org.wrensecurity.guava.common.base.Strings;
29  
30  import org.forgerock.api.ApiValidationException;
31  
32  /**
33   * Class that represents the Action operation type in API descriptor.
34   */
35  @JsonDeserialize(builder = Action.Builder.class)
36  @JsonInclude(JsonInclude.Include.NON_NULL)
37  public final class Action extends Operation implements Comparable<Action> {
38  
39      private final String name;
40      private final Schema request;
41      private final Schema response;
42  
43      /**
44       * Protected contstructor of the Action.
45       *
46       * @param builder Action Builder
47       */
48      private Action(Builder builder) {
49          super(builder);
50          this.name = builder.name;
51          this.request = builder.request;
52          this.response = builder.response;
53  
54          if (isEmpty(name)) {
55              throw new ApiValidationException("name is required");
56          }
57          if (containsWhitespace(name)) {
58              throw new ApiValidationException("name contains whitespace");
59          }
60      }
61  
62      /**
63       * Getter of the ID.
64       *
65       * @return Id
66       */
67      public String getName() {
68          return name;
69      }
70  
71      /**
72       * Getter of the request.
73       *
74       * @return Request
75       */
76      public Schema getRequest() {
77          return request;
78      }
79  
80      /**
81       * Getter of the response.
82       *
83       * @return Response
84       */
85      public Schema getResponse() {
86          return response;
87      }
88  
89      @Override
90      public boolean equals(Object o) {
91          if (this == o) {
92              return true;
93          }
94          if (o == null || getClass() != o.getClass()) {
95              return false;
96          }
97          if (!super.equals(o)) {
98              return false;
99          }
100         Action action = (Action) o;
101         return super.equals(o)
102                 && Objects.equals(name, action.name)
103                 && Objects.equals(request, action.request)
104                 && Objects.equals(response, action.response);
105     }
106 
107     @Override
108     public int hashCode() {
109         return Objects.hash(super.hashCode(), name, request, response);
110     }
111 
112     /**
113      * Creates a new builder for Action.
114      *
115      * @return New builder instance
116      */
117     public static final Builder action() {
118         return new Builder();
119     }
120 
121     /**
122      * Allocates the Action operation type to the given Resource Builder.
123      *
124      * @param resourceBuilder - Resource Builder to add the operation
125      */
126     @Override
127     protected void allocateToResource(Resource.Builder resourceBuilder) {
128         resourceBuilder.action(this);
129     }
130 
131     /**
132      * Builds an Action object using the data in the annotation.
133      * @param action The annotation that holds the data for the built object.
134      * @param annotated The action method.
135      * @param descriptor The root descriptor to add definitions to.
136      * @param relativeType The type relative to which schema resources should be resolved.
137      * @return Action instance.
138      */
139     public static Action fromAnnotation(org.forgerock.api.annotations.Action action, Method annotated,
140             ApiDescription descriptor, Class<?> relativeType) {
141         Builder builder = action();
142         String specifiedName = action.name();
143         if (Strings.isNullOrEmpty(specifiedName)) {
144             if (annotated == null) {
145                 throw new IllegalArgumentException("Action does not have a name: " + action);
146             }
147             specifiedName = annotated.getName();
148         }
149         return builder.name(specifiedName)
150                 .request(Schema.fromAnnotation(action.request(), descriptor, relativeType))
151                 .response(Schema.fromAnnotation(action.response(), descriptor, relativeType))
152                 .detailsFromAnnotation(action.operationDescription(), descriptor, relativeType)
153                 .build();
154     }
155 
156     /**
157      * Compares two strings lexicographically.
158      * @param action Action to compare to
159      * @return  the value {@code 0} if the argument string is equal to
160      *          this string; a value less than {@code 0} if this string
161      *          is lexicographically less than the string argument; and a
162      *          value greater than {@code 0} if this string is
163      *          lexicographically greater than the string argument.
164      */
165     @Override
166     public int compareTo(Action action) {
167         return this.name.compareTo(action.getName());
168     }
169 
170     /**
171      * Builder class for creating the Action.
172      */
173     public static final class Builder extends Operation.Builder<Builder> {
174 
175         private String name;
176         private Schema request;
177         private Schema response;
178 
179         @Override
180         protected Builder self() {
181             return this;
182         }
183 
184         /**
185          * Set the Id.
186          *
187          * @param name Action name
188          * @return Builder
189          */
190         @JsonProperty("name")
191         public Builder name(String name) {
192             this.name = name;
193             return this;
194         }
195 
196         /**
197          * Set the request.
198          *
199          * @param request Action request
200          * @return Builder
201          */
202         @JsonProperty("request")
203         public Builder request(Schema request) {
204             this.request = request;
205             return this;
206         }
207 
208         /**
209          * Set the response.
210          *
211          * @param response Action resopnse
212          * @return Builder
213          */
214         @JsonProperty("response")
215         public Builder response(Schema response) {
216             this.response = response;
217             return this;
218         }
219 
220         /**
221          * Builds the Action instance.
222          *
223          * @return Action instance
224          */
225         public Action build() {
226             return new Action(this);
227         }
228     }
229 
230 }