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         * Creates a new JSON-RPC 2.0 error with the specified code and 
107         * message. The optional data is omitted.
108         * 
109         * @param code    The error code (standard pre-defined or
110         *                application-specific).
111         * @param message The error message.
112         */
113        public JSONRPC2Error(int code, String message) {
114                
115                this(code, message, null);
116        }
117        
118        
119        /** 
120         * Creates a new JSON-RPC 2.0 error with the specified code,
121         * message and data.
122         * 
123         * @param code    The error code (standard pre-defined or
124         *                application-specific).
125         * @param message The error message.
126         * @param data    Optional error data, must <a href="#map">map</a>
127         *                to a valid JSON type.
128         */
129        public JSONRPC2Error(int code, String message, Object data) {
130                
131                super(message);
132                this.code = code;
133                this.data = data;
134        }
135        
136        
137        /** 
138         * Gets the JSON-RPC 2.0 error code.
139         *
140         * @return The error code.
141         */
142        public int getCode() {
143                
144                return code;
145        }
146        
147        
148        /**
149         * Gets the JSON-RPC 2.0 error data.
150         *
151         * @return The error data, {@code null} if none was specified.
152         */
153        public Object getData() {
154                
155                return data;    
156        }
157
158
159        /**
160         * Sets the specified data to a JSON-RPC 2.0 error.
161         *
162         * @param data Optional error data, must <a href="#map">map</a> to a 
163         *             valid JSON type.
164         *
165         * @return A new JSON-RPC 2.0 error with the set data.
166         */
167        public JSONRPC2Error setData(final Object data) {
168
169                return new JSONRPC2Error(code, getMessage(), data);
170        }
171
172
173        /**
174         * Appends the specified string to the message of this JSON-RPC 2.0 
175         * error.
176         *
177         * @param apx The string to append to the original error message.
178         *
179         * @return A new JSON-RPC 2.0 error with the appended message.
180         */
181        public JSONRPC2Error appendMessage(final String apx) {
182
183                return new JSONRPC2Error(code, getMessage() + apx, data);
184        }
185        
186        
187        /** 
188         * Returns a JSON object representation of this JSON-RPC 2.0 error.
189         *
190         * @return A JSON object representing this error object.
191         */
192        public JSONObject toJSONObject() {
193        
194                JSONObject out = new JSONObject();
195                
196                out.put("code", code);
197                out.put("message", super.getMessage());
198                if (data != null)
199                        out.put("data", data);
200                                
201                return out;
202        }
203        
204        
205        /** 
206         * Serialises the error object to a JSON string.
207         *
208         * @return A JSON-encoded string representing this error object.
209         */
210        @Override
211        public String toString() {
212                
213                return toJSONObject().toString();
214        }
215        
216        
217        /**
218         * Overrides {@code Object.equals()}.
219         *
220         * @param object The object to compare to.
221         *
222         * @return {@code true} if both objects are instances if this class and
223         *         their error codes are identical, {@code false} if not.
224         */
225        @Override
226        public boolean equals(Object object) {
227        
228                return object instanceof JSONRPC2Error && code == ((JSONRPC2Error) object).getCode();
229        }
230}