BUG-614: introduce AbstractRuntimeCodeGenerator
[controller.git] / opendaylight / md-sal / sal-rest-connector / src / main / java / org / opendaylight / controller / 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 package org.opendaylight.controller.sal.restconf.impl;
9
10 import java.io.PrintWriter;
11 import java.io.StringWriter;
12
13 import org.opendaylight.yangtools.yang.common.RpcError;
14
15 import com.google.common.base.Preconditions;
16
17 /**
18  * Encapsulates a restconf error as defined in the ietf restconf draft.
19  *
20  * <br><br><b>Note:</b> Enumerations defined within are provided by the ietf restconf draft.
21  *
22  * @author Devin Avery
23  * @see {@link https://tools.ietf.org/html/draft-bierman-netconf-restconf-02}
24  */
25 public class RestconfError {
26
27     public static enum ErrorType {
28         /** Errors relating to the transport layer */
29         TRANSPORT,
30         /** Errors relating to the RPC or notification layer */
31         RPC,
32         /** Errors relating to the protocol operation layer. */
33         PROTOCOL,
34         /** Errors relating to the server application layer. */
35         APPLICATION;
36
37         public String getErrorTypeTag() {
38             return name().toLowerCase();
39         }
40
41         public static ErrorType valueOfCaseInsensitive( String value )
42         {
43             try {
44                 return ErrorType.valueOf( ErrorType.class, value.toUpperCase() );
45             }
46             catch( IllegalArgumentException e ) {
47                 return APPLICATION;
48             }
49         }
50     }
51
52     public static enum ErrorTag {
53         IN_USE( "in-use", 409 /*Conflict*/ ),
54         INVALID_VALUE( "invalid-value", 400 /*Bad Request*/ ),
55         TOO_BIG( "too-big", 413 /*Request Entity Too Large*/ ),
56         MISSING_ATTRIBUTE( "missing-attribute", 400 /*Bad Request*/ ),
57         BAD_ATTRIBUTE( "bad-attribute", 400 /*Bad Request*/ ),
58         UNKNOWN_ATTRIBUTE( "unknown-attribute", 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", 409 /*Conflict*/ ),
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( String value )
86         {
87             try {
88                 return ErrorTag.valueOf( ErrorTag.class, value.toUpperCase().replaceAll( "-","_" ) );
89             }
90             catch( IllegalArgumentException e ) {
91                 return OPERATION_FAILED;
92             }
93         }
94
95         public int getStatusCode() {
96             return statusCode;
97         }
98     }
99
100     private final ErrorType errorType;
101     private final ErrorTag errorTag;
102     private final String errorInfo;
103     private final String errorAppTag;
104     private final String errorMessage;
105     //TODO: Add in the error-path concept as defined in the ietf draft.
106
107     static String toErrorInfo( Throwable cause ) {
108         StringWriter writer = new StringWriter();
109         cause.printStackTrace( new PrintWriter( writer ) );
110         return writer.toString();
111     }
112
113     /**
114      * Constructs a RestConfError
115      *
116      * @param errorType The enumerated type indicating the layer where the error occurred.
117      * @param errorTag The enumerated tag representing a more specific error cause.
118      * @param errorMessage A string which provides a plain text string describing the error.
119      */
120     public RestconfError(ErrorType errorType, ErrorTag errorTag, String errorMessage) {
121         this( errorType, errorTag, errorMessage, null );
122     }
123
124     /**
125      * Constructs a RestConfError object.
126      *
127      * @param errorType The enumerated type indicating the layer where the error occurred.
128      * @param errorTag The enumerated tag representing a more specific error cause.
129      * @param errorMessage A string which provides a plain text string describing the error.
130      * @param errorAppTag A string which represents an application-specific error tag that further
131      *                    specifies the error cause.
132      */
133     public RestconfError(ErrorType errorType, ErrorTag errorTag, String errorMessage,
134                          String errorAppTag) {
135         this( errorType, errorTag, errorMessage, errorAppTag, null );
136     }
137
138     /**
139      * Constructs a RestConfError object.
140      *
141      * @param errorType The enumerated type indicating the layer where the error occurred.
142      * @param errorTag The enumerated tag representing a more specific error cause.
143      * @param errorMessage A string which provides a plain text string describing the error.
144      * @param errorAppTag A string which represents an application-specific error tag that further
145      *                    specifies the error cause.
146      * @param errorInfo A string, <b>formatted as XML</b>, which contains additional error information.
147      */
148     public RestconfError(ErrorType errorType, ErrorTag errorTag, String errorMessage,
149                          String errorAppTag, String errorInfo) {
150         Preconditions.checkNotNull( errorType, "Error type is required for RestConfError" );
151         Preconditions.checkNotNull( errorTag, "Error tag is required for RestConfError");
152         this.errorType = errorType;
153         this.errorTag = errorTag;
154         this.errorMessage = errorMessage;
155         this.errorAppTag = errorAppTag;
156         this.errorInfo = errorInfo;
157     }
158
159     /**
160      * Constructs a RestConfError object from an RpcError.
161      */
162     public RestconfError( RpcError rpcError ) {
163
164         this.errorType = rpcError.getErrorType() == null ? ErrorType.APPLICATION :
165                                ErrorType.valueOfCaseInsensitive( rpcError.getErrorType().name() );
166
167         this.errorTag = rpcError.getTag() == null ? ErrorTag.OPERATION_FAILED :
168                                     ErrorTag.valueOfCaseInsensitive( rpcError.getTag().toString() );
169
170         this.errorMessage = rpcError.getMessage();
171         this.errorAppTag = rpcError.getApplicationTag();
172
173         String errorInfo = null;
174         if( rpcError.getInfo() == null ) {
175             if( rpcError.getCause() != null ) {
176                 errorInfo = toErrorInfo( rpcError.getCause() );
177             }
178             else if( rpcError.getSeverity() != null ) {
179                 errorInfo = "<severity>" + rpcError.getSeverity().toString().toLowerCase() +
180                             "</severity>";
181             }
182         }
183         else {
184             errorInfo = rpcError.getInfo();
185         }
186
187         this.errorInfo = errorInfo;
188     }
189
190     public ErrorType getErrorType() {
191         return errorType;
192     }
193
194     public ErrorTag getErrorTag() {
195         return errorTag;
196     }
197
198     public String getErrorInfo() {
199         return errorInfo;
200     }
201
202     public String getErrorAppTag() {
203         return errorAppTag;
204     }
205
206     public String getErrorMessage() {
207         return errorMessage;
208     }
209
210     @Override
211     public String toString() {
212         return "error-type: " + errorType.getErrorTypeTag()
213                 + ", error-tag: " + errorTag.getTagValue() + ", "
214                 + (errorAppTag != null ? "error-app-tag: " + errorAppTag + ", " : "")
215                 + (errorMessage != null ? "error-message: " + errorMessage : "")
216                 + (errorInfo != null ? "error-info: " + errorInfo + ", " : "") + "]";
217     }
218
219 }