Fix findbugs violations in restconf-common
[netconf.git] / restconf / restconf-common / src / main / java / org / opendaylight / restconf / common / errors / RestconfError.java
1 /*
2  * Copyright (c) 2014 Brocade Communications Systems, Inc. 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
9 package org.opendaylight.restconf.common.errors;
10
11 import com.google.common.base.Preconditions;
12 import com.google.common.base.Throwables;
13 import java.io.Serializable;
14 import java.util.Locale;
15 import org.opendaylight.yangtools.yang.common.RpcError;
16 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
17
18 /**
19  * Encapsulates a restconf error as defined in the ietf restconf draft.
20  *
21  * <br>
22  * <br>
23  * <b>Note:</b> Enumerations defined within are provided by the ietf restconf draft.
24  *
25  * @author Devin Avery
26  *     See also <a href="https://tools.ietf.org/html/draft-bierman-netconf-restconf-02">RESTCONF</a>.
27  */
28 public class RestconfError implements Serializable {
29     private static final long serialVersionUID = 1L;
30
31     public enum ErrorType {
32         /**
33          * Errors relating to the transport layer.
34          */
35         TRANSPORT,
36         /**
37          * Errors relating to the RPC or notification layer.
38          */
39         RPC,
40         /**
41          * Errors relating to the protocol operation layer.
42          */
43         PROTOCOL,
44         /**
45          * Errors relating to the server application layer.
46          */
47         APPLICATION;
48
49         public String getErrorTypeTag() {
50             return name().toLowerCase(Locale.ROOT);
51         }
52
53         public static ErrorType valueOfCaseInsensitive(final String value) {
54             try {
55                 return ErrorType.valueOf(ErrorType.class, value.toUpperCase(Locale.ROOT));
56             } catch (IllegalArgumentException e) {
57                 return APPLICATION;
58             }
59         }
60     }
61
62     public enum ErrorTag {
63         IN_USE("in-use", 409 /* Conflict */),
64         INVALID_VALUE("invalid-value", 400 /* Bad Request */),
65         TOO_BIG("too-big", 413 /* Request Entity Too Large */),
66         MISSING_ATTRIBUTE("missing-attribute", 400 /* Bad Request */),
67         BAD_ATTRIBUTE("bad-attribute", 400 /* Bad Request */),
68         UNKNOWN_ATTRIBUTE("unknown-attribute", 400 /* Bad Request */),
69         MISSING_ELEMENT("missing-element", 400 /* Bad Request */),
70         BAD_ELEMENT("bad-element", 400 /* Bad Request */),
71         UNKNOWN_ELEMENT("unknown-element", 400 /* Bad Request */),
72         UNKNOWN_NAMESPACE("unknown-namespace", 400 /* Bad Request */),
73         ACCESS_DENIED("access-denied", 403 /* Forbidden */),
74         LOCK_DENIED("lock-denied", 409 /* Conflict */),
75         RESOURCE_DENIED("resource-denied", 409 /* Conflict */),
76         ROLLBACK_FAILED("rollback-failed", 500 /* INTERNAL_SERVER_ERROR */),
77         DATA_EXISTS("data-exists", 409 /* Conflict */),
78         DATA_MISSING("data-missing", 404 /* Resource Not Found */),
79         OPERATION_NOT_SUPPORTED("operation-not-supported", 501 /* Not Implemented */),
80         OPERATION_FAILED("operation-failed", 500 /* INTERNAL_SERVER_ERROR */),
81         PARTIAL_OPERATION("partial-operation", 500 /* INTERNAL_SERVER_ERROR */),
82         MALFORMED_MESSAGE("malformed-message", 400 /* Bad Request */),
83         RESOURCE_DENIED_TRANSPORT("resource-denied-transport", 503 /* Service Unavailable */);
84
85         private final String tagValue;
86         private final int statusCode;
87
88         ErrorTag(final String tagValue, final int statusCode) {
89             this.tagValue = tagValue;
90             this.statusCode = statusCode;
91         }
92
93         public String getTagValue() {
94             return this.tagValue.toLowerCase(Locale.ROOT);
95         }
96
97         public static ErrorTag valueOfCaseInsensitive(final String value) {
98             try {
99                 return ErrorTag.valueOf(ErrorTag.class, value.toUpperCase(Locale.ROOT).replaceAll("-", "_"));
100             } catch (IllegalArgumentException e) {
101                 return OPERATION_FAILED;
102             }
103         }
104
105         public int getStatusCode() {
106             return statusCode;
107         }
108     }
109
110     private final ErrorType errorType;
111     private final ErrorTag errorTag;
112     private final String errorInfo;
113     private final String errorAppTag;
114     private final String errorMessage;
115     private final YangInstanceIdentifier errorPath;
116
117     /**
118      * Constructs a RestConfError.
119      *
120      * @param errorType
121      *            The enumerated type indicating the layer where the error occurred.
122      * @param errorTag
123      *            The enumerated tag representing a more specific error cause.
124      * @param errorMessage
125      *            A string which provides a plain text string describing the error.
126      */
127     public RestconfError(final ErrorType errorType, final ErrorTag errorTag, final String errorMessage) {
128         this(errorType, errorTag, errorMessage, null, null, null);
129     }
130
131     /**
132      * Constructs a RestConfError object.
133      *
134      * @param errorType
135      *            The enumerated type indicating the layer where the error occurred.
136      * @param errorTag
137      *            The enumerated tag representing a more specific error cause.
138      * @param errorMessage
139      *            A string which provides a plain text string describing the error.
140      * @param errorAppTag
141      *            A string which represents an application-specific error tag that further specifies the error cause.
142      */
143     public RestconfError(final ErrorType errorType, final ErrorTag errorTag, final String errorMessage,
144                          final String errorAppTag) {
145         this(errorType, errorTag, errorMessage, errorAppTag, null, null);
146     }
147
148     /**
149      * Constructs a RestConfError object.
150      *
151      * @param errorType
152      *            The enumerated type indicating the layer where the error occurred.
153      * @param errorTag
154      *            The enumerated tag representing a more specific error cause.
155      * @param errorMessage
156      *            A string which provides a plain text string describing the error.
157      * @param errorPath
158      *            An instance identifier which contains error path
159      */
160     public RestconfError(final ErrorType errorType, final ErrorTag errorTag, final String errorMessage,
161                          final YangInstanceIdentifier errorPath) {
162         this(errorType, errorTag, errorMessage, null, null, errorPath);
163     }
164
165     /**
166      * Constructs a RestConfError object.
167      *
168      * @param errorType
169      *            The enumerated type indicating the layer where the error occurred.
170      * @param errorTag
171      *            The enumerated tag representing a more specific error cause.
172      * @param errorMessage
173      *            A string which provides a plain text string describing the error.
174      * @param errorAppTag
175      *            A string which represents an application-specific error tag that further specifies the error cause.
176      * @param errorInfo
177      *            A string, <b>formatted as XML</b>, which contains additional error information.
178      */
179     public RestconfError(final ErrorType errorType, final ErrorTag errorTag, final String errorMessage,
180                          final String errorAppTag, final String errorInfo) {
181         this(errorType, errorTag, errorMessage, errorAppTag, errorInfo, null);
182     }
183
184     /**
185      * Constructs a RestConfError object.
186      *
187      * @param errorType
188      *            The enumerated type indicating the layer where the error occurred.
189      * @param errorTag
190      *            The enumerated tag representing a more specific error cause.
191      * @param errorMessage
192      *            A string which provides a plain text string describing the error.
193      * @param errorAppTag
194      *            A string which represents an application-specific error tag that further specifies the error cause.
195      * @param errorInfo
196      *            A string, <b>formatted as XML</b>, which contains additional error information.
197      * @param errorPath
198      *            An instance identifier which contains error path
199      */
200     public RestconfError(final ErrorType errorType, final ErrorTag errorTag, final String errorMessage,
201                          final String errorAppTag, final String errorInfo, final YangInstanceIdentifier errorPath) {
202         Preconditions.checkNotNull(errorType, "Error type is required for RestConfError");
203         Preconditions.checkNotNull(errorTag, "Error tag is required for RestConfError");
204         this.errorType = errorType;
205         this.errorTag = errorTag;
206         this.errorMessage = errorMessage;
207         this.errorAppTag = errorAppTag;
208         this.errorInfo = errorInfo;
209         this.errorPath = errorPath;
210     }
211
212     /**
213      * Constructs a RestConfError object from an RpcError.
214      */
215     public RestconfError(final RpcError rpcError) {
216
217         this.errorType = rpcError.getErrorType() == null ? ErrorType.APPLICATION : ErrorType
218                 .valueOfCaseInsensitive(rpcError.getErrorType().name());
219
220         this.errorTag = rpcError.getTag() == null ? ErrorTag.OPERATION_FAILED : ErrorTag
221                 .valueOfCaseInsensitive(rpcError.getTag());
222
223         this.errorMessage = rpcError.getMessage();
224         this.errorAppTag = rpcError.getApplicationTag();
225
226         String localErrorInfo = null;
227         if (rpcError.getInfo() == null) {
228             if (rpcError.getCause() != null) {
229                 localErrorInfo = Throwables.getStackTraceAsString(rpcError.getCause());
230             } else if (rpcError.getSeverity() != null) {
231                 localErrorInfo = "<severity>" + rpcError.getSeverity().toString().toLowerCase(Locale.ROOT)
232                         + "</severity>";
233             }
234         } else {
235             localErrorInfo = rpcError.getInfo();
236         }
237
238         this.errorInfo = localErrorInfo;
239         this.errorPath = null;
240     }
241
242     public ErrorType getErrorType() {
243         return errorType;
244     }
245
246     public ErrorTag getErrorTag() {
247         return errorTag;
248     }
249
250     public String getErrorInfo() {
251         return errorInfo;
252     }
253
254     public String getErrorAppTag() {
255         return errorAppTag;
256     }
257
258     public String getErrorMessage() {
259         return errorMessage;
260     }
261
262     public YangInstanceIdentifier getErrorPath() {
263         return errorPath;
264     }
265
266     @Override
267     public String toString() {
268         return "RestconfError ["
269                 + "error-type: " + errorType.getErrorTypeTag() + ", error-tag: " + errorTag.getTagValue()
270                 + (errorAppTag != null ? ", error-app-tag: " + errorAppTag : "")
271                 + (errorMessage != null ? ", error-message: " + errorMessage : "")
272                 + (errorInfo != null ? ", error-info: " + errorInfo : "")
273                 + (errorPath != null ? ", error-path: " + errorPath.toString() : "")
274                 + "]";
275     }
276 }