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