001package com.thetransactioncompany.jsonrpc2;
002
003
004import net.minidev.json.JSONObject;
005
006
007/** 
008 * Represents a JSON-RPC 2.0 error that occurred during the processing of a 
009 * request. This class is immutable.
010 *
011 * <p>The protocol expects error objects to be structured like this:
012 *
013 * <ul>
014 *     <li>{@code code} An integer that indicates the error type.
015 *     <li>{@code message} A string providing a short description of the 
016 *         error. The message should be limited to a concise single sentence.
017 *     <li>{@code data} Additional information, which may be omitted. Its 
018 *         contents is entirely defined by the application.
019 * </ul>
020 * 
021 * <p>Note that the "Error" word in the class name was put there solely to
022 * comply with the parlance of the JSON-RPC spec. This class doesn't inherit 
023 * from {@code java.lang.Error}. It's a regular subclass of 
024 * {@code java.lang.Exception} and, if thrown, it's to indicate a condition 
025 * that a reasonable application might want to catch.
026 *
027 * <p>This class also includes convenient final static instances for all 
028 * standard JSON-RPC 2.0 errors:
029 *
030 * <ul>
031 *     <li>{@link #PARSE_ERROR} JSON parse error (-32700)
032 *     <li>{@link #INVALID_REQUEST} Invalid JSON-RPC 2.0 Request (-32600)
033 *     <li>{@link #METHOD_NOT_FOUND} Method not found (-32601)
034 *     <li>{@link #INVALID_PARAMS} Invalid parameters (-32602)
035 *     <li>{@link #INTERNAL_ERROR} Internal error (-32603)
036 * </ul>
037 *
038 * <p>Note that the range -32099..-32000 is reserved for additional server 
039 * errors.
040 *
041 * <p id="map">The mapping between JSON and Java entities (as defined by the 
042 * underlying JSON Smart library): 
043 * <pre>
044 *     true|false  <--->  java.lang.Boolean
045 *     number      <--->  java.lang.Number
046 *     string      <--->  java.lang.String
047 *     array       <--->  java.util.List
048 *     object      <--->  java.util.Map
049 *     null        <--->  null
050 * </pre>
051 *
052 * @author Vladimir Dzhuvinov
053 */
054public class JSONRPC2Error extends Exception {
055        
056        
057        /**
058         * Serial version UID.
059         */
060        private static final long serialVersionUID = 4682571044532698806l;
061
062
063        /** 
064         * JSON parse error (-32700).
065         */
066        public static final JSONRPC2Error PARSE_ERROR = new JSONRPC2Error(-32700, "JSON parse error");
067        
068        
069        /** 
070         * Invalid JSON-RPC 2.0 request error (-32600).
071         */
072        public static final JSONRPC2Error INVALID_REQUEST = new JSONRPC2Error(-32600, "Invalid request");
073        
074        
075        /** 
076         * Method not found error (-32601). 
077         */
078        public static final JSONRPC2Error METHOD_NOT_FOUND = new JSONRPC2Error(-32601, "Method not found");
079        
080        
081        /** 
082         * Invalid parameters error (-32602).
083         */
084        public static final JSONRPC2Error INVALID_PARAMS = new JSONRPC2Error(-32602, "Invalid parameters");
085        
086        
087        /** 
088         * Internal JSON-RPC 2.0 error (-32603).
089         */
090        public static final JSONRPC2Error INTERNAL_ERROR = new JSONRPC2Error(-32603, "Internal error");
091        
092        
093        /**
094         * The error code.
095         */
096        private final int code;
097        
098        
099        /**
100         * The optional error data.
101         */
102        private final Object data;
103
104
105        /**
106         * Appends the specified string to the message of a JSON-RPC 2.0 error.
107         *
108         * @param err The JSON-RPC 2.0 error. Must not be {@code null}.
109         * @param apx The string to append to the original error message.
110         *
111         * @return A new JSON-RPC 2.0 error with the appended message.
112         */
113        @Deprecated
114        public static JSONRPC2Error appendMessage(final JSONRPC2Error err, final String apx) {
115
116                return new JSONRPC2Error(err.getCode(), err.getMessage() + apx, err.getData());
117        }
118
119
120        /**
121         * Sets the specified data to a JSON-RPC 2.0 error.
122         *
123         * @param err  The JSON-RPC 2.0 error to have its data field set. Must
124         *             not be {@code null}.
125         * @param data Optional error data, must <a href="#map">map</a> to a 
126         *             valid JSON type.
127         *
128         * @return A new JSON-RPC 2.0 error with the set data.
129         */
130        @Deprecated
131        public static JSONRPC2Error setData(final JSONRPC2Error err, final Object data) {
132
133                return new JSONRPC2Error(err.getCode(), err.getMessage(), data);
134        }
135        
136        
137        /** 
138         * Creates a new JSON-RPC 2.0 error with the specified code and 
139         * message. The optional data is omitted.
140         * 
141         * @param code    The error code (standard pre-defined or
142         *                application-specific).
143         * @param message The error message.
144         */
145        public JSONRPC2Error(int code, String message) {
146                
147                this(code, message, null);
148        }
149        
150        
151        /** 
152         * Creates a new JSON-RPC 2.0 error with the specified code,
153         * message and data.
154         * 
155         * @param code    The error code (standard pre-defined or
156         *                application-specific).
157         * @param message The error message.
158         * @param data    Optional error data, must <a href="#map">map</a>
159         *                to a valid JSON type.
160         */
161        public JSONRPC2Error(int code, String message, Object data) {
162                
163                super(message);
164                this.code = code;
165                this.data = data;
166        }
167        
168        
169        /** 
170         * Gets the JSON-RPC 2.0 error code.
171         *
172         * @return The error code.
173         */
174        public int getCode() {
175                
176                return code;
177        }
178        
179        
180        /**
181         * Gets the JSON-RPC 2.0 error data.
182         *
183         * @return The error data, {@code null} if none was specified.
184         */
185        public Object getData() {
186                
187                return data;    
188        }
189
190
191        /**
192         * Sets the specified data to a JSON-RPC 2.0 error.
193         *
194         * @param data Optional error data, must <a href="#map">map</a> to a 
195         *             valid JSON type.
196         *
197         * @return A new JSON-RPC 2.0 error with the set data.
198         */
199        public JSONRPC2Error setData(final Object data) {
200
201                return new JSONRPC2Error(code, getMessage(), data);
202        }
203
204
205        /**
206         * Appends the specified string to the message of this JSON-RPC 2.0 
207         * error.
208         *
209         * @param apx The string to append to the original error message.
210         *
211         * @return A new JSON-RPC 2.0 error with the appended message.
212         */
213        public JSONRPC2Error appendMessage(final String apx) {
214
215                return new JSONRPC2Error(code, getMessage() + apx, data);
216        }
217        
218        
219        /** 
220         * @see #toJSONObject
221         */
222        @Deprecated
223        public JSONObject toJSON() {
224        
225                return toJSONObject();
226        }
227        
228        
229        /** 
230         * Returns a JSON object representation of this JSON-RPC 2.0 error.
231         *
232         * @return A JSON object representing this error object.
233         */
234        public JSONObject toJSONObject() {
235        
236                JSONObject out = new JSONObject();
237                
238                out.put("code", code);
239                out.put("message", super.getMessage());
240                if (data != null)
241                        out.put("data", data);
242                                
243                return out;
244        }
245        
246        
247        /** 
248         * Serialises the error object to a JSON string.
249         *
250         * @return A JSON-encoded string representing this error object.
251         */
252        @Override
253        public String toString() {
254                
255                return toJSON().toString();
256        }
257        
258        
259        /**
260         * Overrides {@code Object.equals()}.
261         *
262         * @param object The object to compare to.
263         *
264         * @return {@code true} if both objects are instances if this class and
265         *         their error codes are identical, {@code false} if not.
266         */
267        @Override
268        public boolean equals(Object object) {
269        
270                return object != null &&
271                       object instanceof JSONRPC2Error && 
272                       code == ((JSONRPC2Error)object).getCode();
273        }
274}