blob: 61c7144c1718bd127bb1aaafc7a1d3f68fd0a6b8 [file] [log] [blame]
Sean Condon13b16812018-01-25 10:31:49 +00001/*
2 * Copyright 2017-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.restconf.api;
17
18import com.fasterxml.jackson.databind.ObjectMapper;
19import com.fasterxml.jackson.databind.node.ArrayNode;
20import com.fasterxml.jackson.databind.node.ObjectNode;
21
22import java.util.List;
23
24/**
25 * Restconf error structured as in "ietf-restconf@2017-01-26.yang".
26 * An entry containing information about one specific error that occurred while
27 * processing a RESTCONF request.
28 */
29public final class RestconfError {
30 private final ErrorType errorType;
31 private final ErrorTag errorTag;
32 private String errorAppTag;
33 private String errorPath;
34 private String errorMessage;
35 private String errorInfo;
36
37 private RestconfError(ErrorType errorType, ErrorTag errorTag) {
38 this.errorType = errorType;
39 this.errorTag = errorTag;
40 }
41
42 /**
43 * The protocol layer where the error occurred.
44 * @return The error type
45 */
46 public ErrorType getErrorType() {
47 return errorType;
48 }
49
50 /**
51 * The enumerated error-tag.
52 * @return The enumerated error-tag
53 */
54 public ErrorTag getErrorTag() {
55 return errorTag;
56 }
57
58 /**
59 * The application-specific error-tag.
60 * @return The application-specific error-tag
61 */
62 public String getErrorAppTag() {
63 return errorAppTag;
64 }
65
66 /**
67 * The YANG instance identifier associated with the error node.
68 * @return A yang instance represented in XPath
69 */
70 public String getErrorPath() {
71 return errorPath;
72 }
73
74 /**
75 * A message describing the error.
76 * @return A message describing the error
77 */
78 public String getErrorMessage() {
79 return errorMessage;
80 }
81
82 /**
83 * A container with zero or more data nodes representing additional error information.
84 * @return A string serialization of datanodes e.g. a stack trace
85 */
86 public String getErrorInfo() {
87 return errorInfo;
88 }
89
90 /**
91 * Convert the restconf error to Json - this is for one error - many may be included in a response.
92 * @return A JSON object containing the details of one error
93 */
94 public ObjectNode toJson() {
95 ObjectMapper mapper = new ObjectMapper();
96 ObjectNode errorTags = (ObjectNode) mapper.createObjectNode();
97 errorTags.put("error-type", errorType.name().toLowerCase());
98 errorTags.put("error-tag", errorTag.text());
99
100 if (errorAppTag != null) {
101 errorTags.put("error-app-tag", errorAppTag);
102 }
103
104 if (errorPath != null) {
105 errorTags.put("error-path", errorPath);
106 }
107
108 if (errorMessage != null) {
109 errorTags.put("error-message", errorMessage);
110 }
111
112 if (errorInfo != null) {
113 errorTags.put("error-info", errorInfo);
114 }
115
116 ObjectNode errorNode = (ObjectNode) mapper.createObjectNode();
117 errorNode.put("error", errorTags);
118 return errorNode;
119 }
120
121 /**
122 * An enumerated set of the protocol layer involved in a RESTCONF request.
123 */
124 public enum ErrorType {
125 //The transport layer
126 TRANSPORT,
127 //The rpc or notification layer
128 RPC,
129 //The protocol operation layer
130 PROTOCOL,
131 //The server application layer
132 APPLICATION
133 }
134
135 /**
136 * An enumerated set of error 'tags' - consistent labels for error causes.
137 * See <a href="https://tools.ietf.org/html/rfc8040#section-7">Section 7 of RFC 8040</a>
138 * for a list of HTTP status codes associated with these
139 * error tags. Developers should ensure that suitable HTTP status codes are used
140 * when raising RESTCONF errors
141 */
142 public enum ErrorTag {
143 /**
144 * Use with Response 409 {@link javax.ws.rs.core.Response.Status#CONFLICT}.
145 */
146 IN_USE("in-use"),
147 /**
148 * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST},
149 * 404 {@link javax.ws.rs.core.Response.Status#NOT_FOUND} or
150 * 406 {@link javax.ws.rs.core.Response.Status#NOT_ACCEPTABLE}.
151 */
152 INVALID_VALUE("invalid-value"),
153 /**
154 * Use with Response 413 {@link javax.ws.rs.core.Response.Status#REQUEST_ENTITY_TOO_LARGE}.
155 */
156 REQUEST_TOO_BIG("too-big"),
157 /**
158 * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST}.
159 */
160 RESPONSE_TOO_BIG("too-big"),
161 /**
162 * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST}.
163 */
164 MISSING_ATTRIBUTE("missing-attribute"),
165 /**
166 * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST}.
167 */
168 BAD_ATTRIBUTE("bad-attribute"),
169 /**
170 * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST}.
171 */
172 UNKNOWN_ATTRIBUTE("unknown-attribute"),
173 /**
174 * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST}.
175 */
176 BAD_ELEMENT("bad-element"),
177 /**
178 * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST}.
179 */
180 UNKNOWN_ELEMENT("unknown-element"),
181 /**
182 * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST}.
183 */
184 UNKNOWN_NAMESPACE("unknown-namespace"),
185 /**
186 * Use with Response 401 {@link javax.ws.rs.core.Response.Status#UNAUTHORIZED},
187 * or 403 {@link javax.ws.rs.core.Response.Status#FORBIDDEN}.
188 */
189 ACCESS_DENIED("access-denied"),
190 /**
191 * Use with Response 409 {@link javax.ws.rs.core.Response.Status#CONFLICT}.
192 */
193 LOCK_DENIED("lock-denied"),
194 /**
195 * Use with Response 409 {@link javax.ws.rs.core.Response.Status#CONFLICT}.
196 */
197 RESOURCE_DENIED("resource-denied"),
198 /**
199 * Use with Response 500 {@link javax.ws.rs.core.Response.Status#INTERNAL_SERVER_ERROR}.
200 */
201 ROLLBACK_FAILED("rollback-failed"),
202 /**
203 * Use with Response 409 {@link javax.ws.rs.core.Response.Status#CONFLICT}.
204 */
205 DATA_EXISTS("data-exists"),
206 /**
207 * Use with Response 409 {@link javax.ws.rs.core.Response.Status#CONFLICT}.
208 */
209 DATA_MISSING("data-missing"),
210 /**
211 * Use with Response 405 {@link javax.ws.rs.core.Response.Status#METHOD_NOT_ALLOWED},
212 * or 501 {@link javax.ws.rs.core.Response.Status#NOT_IMPLEMENTED}.
213 */
214 OPERATION_NOT_SUPPORTED("operation-not-supported"),
215 /**
216 * Use with Response 412 {@link javax.ws.rs.core.Response.Status#PRECONDITION_FAILED},
217 * or 500 {@link javax.ws.rs.core.Response.Status#INTERNAL_SERVER_ERROR}.
218 */
219 OPERATION_FAILED("operation-failed"),
220 /**
221 * Use with Response 500 {@link javax.ws.rs.core.Response.Status#INTERNAL_SERVER_ERROR}.
222 */
223 PARTIAL_OPERATION("partial-operation"),
224 /**
225 * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST}.
226 */
227 MALFORMED_MESSAGE("malformed-message");
228
229 private String text;
230
231 ErrorTag(String text) {
232 this.text = text;
233 }
234
235 /**
236 * Lowercase version of the error tag compliant with the standard.
237 * @return the associated lowercase version
238 */
239 public String text() {
240 return text;
241 }
242 }
243
244 /**
245 * Build a new RestconfError. ErrorTag and ErrorType are mandatory parameters.
246 * @param errorType The error type
247 * @param errorTag The error Tag
248 * @return A build which an be used to create the RestconfError
249 */
250 public static RestconfError.Builder builder(ErrorType errorType, ErrorTag errorTag) {
251 return new Builder(errorType, errorTag);
252 }
253
254 /**
255 * Create the complete JSON representation of the errors for the Response.
256 * Note this can contain many individual RestconfErrors
257 * @param restconfErrors A list of {@link RestconfError}s
258 * @return A JSON node which can be used in a response
259 */
260 public static ObjectNode wrapErrorAsJson(List<RestconfError> restconfErrors) {
261 ObjectMapper mapper = new ObjectMapper();
262 ArrayNode errorArray = mapper.createArrayNode();
263 restconfErrors.forEach(error -> errorArray.add(error.toJson()));
264 ObjectNode errorsNode = (ObjectNode) mapper.createObjectNode();
265 errorsNode.put("ietf-restconf:errors", errorArray);
266 return errorsNode;
267 }
268
269 /**
270 * A builder for the Restconf Error. ErrorTag and ErrorType are mandatory parameters.
271 */
272 public static final class Builder {
273 private RestconfError restconfError;
274
275 /**
276 * ErrorTag and ErrorType are mandatory parameters of the error.
277 * @param errorType The error-type
278 * @param errorTag The error-tag
279 */
280 private Builder(ErrorType errorType, ErrorTag errorTag) {
281 restconfError = new RestconfError(errorType, errorTag);
282 }
283
284 /**
285 * Set an error-app-tag on the error.
286 * @param errorAppTag a tag relevant to the error in the application
287 * @return The builder
288 */
289 public Builder errorAppTag(String errorAppTag) {
290 this.restconfError.errorAppTag = errorAppTag;
291 return this;
292 }
293
294 /**
295 * Set an error-path on the error.
296 * @param errorPath A path to the resource that caused the error
297 * @return The builder
298 */
299 public Builder errorPath(String errorPath) {
300 this.restconfError.errorPath = errorPath;
301 return this;
302 }
303
304 /**
305 * Set an error-message on the error.
306 * @param errorMessage an explaination of the error
307 * @return The builder
308 */
309 public Builder errorMessage(String errorMessage) {
310 this.restconfError.errorMessage = errorMessage;
311 return this;
312 }
313
314 /**
315 * Set an error-info on the error.
316 * @param errorInfo Any additional infor about the error
317 * @return The builder
318 */
319 public Builder errorInfo(String errorInfo) {
320 this.restconfError.errorInfo = errorInfo;
321 return this;
322 }
323
324 /**
325 * Build the contents of the builder in to a {@link RestconfError}.
326 * @return A RestconfError
327 */
328 public RestconfError build() {
329 return restconfError;
330 }
331 }
332}