001package Torello.Java.JSON;
002
003import javax.json.*;
004import Torello.Java.StrPrint;
005
006/**
007 * The parent class of all Json Exceptions in this package.  This class contains several
008 * convenience fields that will be auto-populated by any method inside Java HTML that would throw
009 * this exception, or any of this exception's descendant classes.
010 * 
011 * <BR /><BR /><B>NOTE:</B> This class is abstract, and cannot be instantiated.
012 * 
013 * <EMBED CLASS=globalDefs DATA-STRUCT=JsonArray>
014 * <EMBED CLASS='external-html' DATA-FILE-ID=JE_FIELD_BIND>
015 */
016@Torello.JavaDoc.CSSLinks(FileNames="JSONExceptions.css")
017public abstract class JsonBindingException extends JsonException
018{
019    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUIDEX>  */
020    public static final long serialVersionUID = 1;
021
022    /**
023     * <EMBED CLASS='external-html' DATA-FILE-ID=EXPF>
024     * 
025     * <BR /><BR />This contains the actual {@link JsonStructure} (which should either be an
026     * instance of <B>{@link JsonObject}</B> or <B>{@link JsonArray}</B>) which contained the
027     * array-element or object-property that has caused this exception throw.
028     */
029    public final JsonStructure errorSourceJsonStruct;
030
031    /**
032     * <EMBED CLASS='external-html' DATA-FILE-ID=EXPF>
033     * 
034     * <BR /><BR />This contains the <B STYLE='color: red;'>expected type</B> which ought to have
035     * been found at the user-specified <B>{@link JsonArray}</B> or <B>{@link JsonObject}</B>
036     * location.  Since both of these kinds of <B>{@link JsonStructure}</B> are only allowed to
037     * have <B STYLE='color: red;'>Json-Type's</B>; therefore this field's declared type is 
038     * <B>{@link JsonValue.ValueType}</B>.
039     * 
040     * <BR /><BR /><B STYLE='color: red;'>ASIDE:</B> The enum <B>{@link JsonValue.ValueType}</B>
041     * has two enum-constants which represent the <B STYLE='color: red'>Json-Type</B>
042     * 'Boolean'.  As a result, there are two possible values to which this field could be
043     * assigned to symbolize a <B>Json Boolean Type</B> ({@link JsonValue.ValueType#FALSE} and
044     * {@link JsonValue.ValueType#TRUE}).  However, in Java HTML, a Json-Boolean Type will always
045     * be represented using the {@code TRUE} enum-constant.
046     */
047    public final JsonValue.ValueType expectedJsonType;
048
049    /**
050     * <EMBED CLASS='external-html' DATA-FILE-ID=EXPF>
051     * 
052     * <BR /><BR />This is the value retrieved from the <B>{@link JsonArray}</B> or
053     * <B>{@link JsonObject}</B>.  If the value was not present or unavailable, then this parameter
054     * will, indeed, evaulated to <B STYLE='color: red;'>Java-Null</B>.
055     * If <B STYLE='color: red;'>Json-Null</B> was retrieved, then this parameter will contain
056     * <B>{@link JsonValue#NULL}</B>.
057     */
058    public final JsonValue valueRetrieved;
059
060    /**
061     * <EMBED CLASS='external-html' DATA-FILE-ID=EXPF>
062     * 
063     * <BR /><BR />This specifies <B STYLE='color: red;'>return type</B> (as an instance of
064     * <B>{@code java.lang.Class<T>}</B> that is used by the method which has thrown this
065     * exception.  This is the <B STYLE='color:red'>Java-Type</B> to which the 
066     * <B STYLE='color:red'>Json-Type</B> was going to be assigned.
067     */
068    public final Class<?> methodReturnJavaType;
069
070    /**
071     * Constructs a {@code JsonBindingException} with no specified detail messsage,
072     * and the user-provided convenience-field values.
073     * 
074     * @param errorSourceJsonStruct <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_ESJS>
075     * @param expectedJsonType      <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_EJT>
076     * @param valueRetrieved        <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_VR>
077     * @param methodReturnJavaType  <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_MRJT>
078     */
079    /** Constructs a {@code JsonBindingException} with no detail message. */
080    public JsonBindingException(
081            JsonStructure       errorSourceJsonStruct,
082            JsonValue.ValueType expectedJsonType,
083            JsonValue           valueRetrieved,
084            Class<?>            methodReturnJavaType
085        )
086    {
087        super(
088            BASE_MESSAGE(
089                errorSourceJsonStruct, expectedJsonType, valueRetrieved,
090                methodReturnJavaType
091            ));
092
093        this.errorSourceJsonStruct  = errorSourceJsonStruct;
094        this.expectedJsonType       = expectedJsonType;
095        this.valueRetrieved         = valueRetrieved;
096        this.methodReturnJavaType   = methodReturnJavaType;
097    }
098
099    /**
100     * Constructs a {@code JsonBindingException} with the specified detail message, and
101     * user-provided convenience-field values.
102     * 
103     * @param message the detail message.
104     * @param errorSourceJsonStruct <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_ESJS>
105     * @param expectedJsonType      <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_EJT>
106     * @param valueRetrieved        <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_VR>
107     * @param methodReturnJavaType  <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_MRJT>
108     */
109    public JsonBindingException(
110            String              message,
111            JsonStructure       errorSourceJsonStruct,
112            JsonValue.ValueType expectedJsonType,
113            JsonValue           valueRetrieved,
114            Class<?>            methodReturnJavaType
115        )
116    {
117        super(message);
118
119        this.errorSourceJsonStruct  = errorSourceJsonStruct;
120        this.expectedJsonType       = expectedJsonType;
121        this.valueRetrieved         = valueRetrieved;
122        this.methodReturnJavaType   = methodReturnJavaType;
123    }
124
125    /**
126     * Constructs a new {@code JsonBindingException} with the specified detail message and cause.
127     * 
128     * <BR /><BR /><B CLASS=JDDescLabel>NOTE:</B>
129     * 
130     * <BR /><BR />The detail message associated with cause is not automatically incorporated into
131     * this exception's detail message.
132     * 
133     * @param message The detail message (which is saved for later retrieval by the
134     * {@code Throwable.getMessage()} method).
135     * 
136     * @param cause the cause (which is saved for later retrieval by the
137     * {@code Throwable.getCause()} method).  (A null value is permitted, and indicates that the
138     * cause is nonexistent or unknown.)
139     * 
140     * @param errorSourceJsonStruct <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_ESJS>
141     * @param expectedJsonType      <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_EJT>
142     * @param valueRetrieved        <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_VR>
143     * @param methodReturnJavaType  <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_MRJT>
144     */
145    public JsonBindingException(
146            String              message,
147            Throwable           cause,
148            JsonStructure       errorSourceJsonStruct,
149            JsonValue.ValueType expectedJsonType,
150            JsonValue           valueRetrieved,
151            Class<?>            methodReturnJavaType
152        )
153    {
154        super(message, cause);
155
156        this.errorSourceJsonStruct  = errorSourceJsonStruct;
157        this.expectedJsonType       = expectedJsonType;
158        this.valueRetrieved         = valueRetrieved;
159        this.methodReturnJavaType   = methodReturnJavaType;
160    }
161
162    /**
163     * Constructs a new {@code JsonBindingException} with the specified cause and a detail message of
164     * {@code (cause==null ? null : cause.toString())} (which typically contains the class and
165     * detail message of cause).
166     * 
167     * <BR /><BR />This constructor is useful for exceptions that are little more than wrappers for
168     * other throwables.
169     * 
170     * @param cause The cause (which is saved for later retrieval by the
171     * {@code Throwable.getCause()} method).  (A null value is permitted, and indicates that the
172     * cause is nonexistent or unknown.)
173     * 
174     * @param errorSourceJsonStruct <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_ESJS>
175     * @param expectedJsonType      <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_EJT>
176     * @param valueRetrieved        <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_VR>
177     * @param methodReturnJavaType  <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_MRJT>
178     */
179    public JsonBindingException(
180            Throwable           cause,
181            JsonStructure       errorSourceJsonStruct,
182            JsonValue.ValueType expectedJsonType,
183            JsonValue           valueRetrieved,
184            Class<?>            methodReturnJavaType
185        )
186    {
187        super(
188            BASE_MESSAGE(
189                errorSourceJsonStruct, expectedJsonType, valueRetrieved,
190                methodReturnJavaType, cause
191            ),
192            cause
193        );
194
195        this.errorSourceJsonStruct  = errorSourceJsonStruct;
196        this.expectedJsonType       = expectedJsonType;
197        this.valueRetrieved         = valueRetrieved;
198        this.methodReturnJavaType   = methodReturnJavaType;
199    }
200
201    // Package Visible Exception Message Helper
202    static String ABBREV_STRUCT(JsonStructure js)
203    {
204        return (js != null) 
205            ? StrPrint.abbrevEnd(js.toString().trim(), true, MAX_STR_LEN)
206            : "Null Was Passed";
207    }
208
209    private static final String JVVT_NAME = "JsonValue.ValueType.";
210    private static int MAX_STR_LEN = 70;
211
212    // Package Visible Exception Message Helper
213    static String JT_STR(JsonValue.ValueType jt)
214    {
215        if (jt == null) return "Json-Type Not Available";
216
217        switch (jt)
218        {
219            case ARRAY:     return JVVT_NAME + "ARRAY";
220            case FALSE:     return JVVT_NAME + "FALSE";
221            case NULL:      return JVVT_NAME + "NULL";
222            case NUMBER:    return JVVT_NAME + "NUMBER";
223            case OBJECT:    return JVVT_NAME + "OBJECT";
224            case STRING:    return JVVT_NAME + "STRING";
225            case TRUE:      return JVVT_NAME + "TRUE";
226            default:        throw new Torello.Java.UnreachableError();
227        }
228    }
229
230    // Package Visible Exception Message Helper
231    static String ABBREV_VAL(JsonValue valueRetrieved)
232    {
233        if (valueRetrieved == null) return "Java-Null (Not Present)";
234
235        if (valueRetrieved.getValueType() == JsonValue.ValueType.NULL)
236            return "JsonValue.NULL (Json-Null)";
237
238        return StrPrint.abbrevEnd(valueRetrieved.toString().trim(), true, MAX_STR_LEN);
239    }
240
241    static String CAUSE_MESSAGE(Throwable[] causes)
242    {
243        if ((causes == null) || (causes.length == 0)) return "";
244
245        String temp = causes[0].getMessage().trim();
246
247        String seeDetailsMessage = ((temp.length() > MAX_STR_LEN) || (temp.indexOf('\n') != -1))
248            ? "\tSee Throwable.cause():    [The message has been abbreviated]\n"
249            : "";
250
251        return
252            "\tCause-Exception Class:    " + causes[0].getClass().getName() + "\n" +
253            "\tCause-Exception Message:  " +
254                StrPrint.abbrevEnd(temp, true, MAX_STR_LEN) + "\n" +
255            seeDetailsMessage;
256    }
257
258    /**
259     * A simple helper method for printing a consistent error messge using the input-data
260     * convenience fields.
261     * 
262     * @param errorSourceJsonStruct <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_ESJS>
263     * @param expectedJsonType      <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_EJT>
264     * @param valueRetrieved        <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_VR>
265     * @param methodReturnJavaType  <EMBED CLASS='external-html' DATA-FILE-ID=JBEX_MRJT>
266     * @param causes                Optional Parameter.  At most 1 cause is printed.
267     * 
268     * @return The error message {@code String}.
269     */
270    protected static String BASE_MESSAGE(
271            JsonStructure       errorSourceJsonStruct,
272            JsonValue.ValueType expectedJsonType,
273            JsonValue           valueRetrieved,
274            Class<?>            methodReturnJavaType,
275            Throwable...        causes
276        )
277    {
278        return
279            "Problems Binding Json\n" +
280            CAUSE_MESSAGE(causes) +
281            "\tFound In JsonStructure:   " + ABBREV_STRUCT(errorSourceJsonStruct) + "\n" +
282            "\tJsonStructure SubClass:   " + errorSourceJsonStruct.getClass().getSimpleName() + "\n" +
283            "\tExpected Json-Type:       " + JT_STR(expectedJsonType) + "\n" +
284            "\tContained JsonValue:      " + ABBREV_VAL(valueRetrieved) + "\n" +
285            "\tHaving Actual Json-Type:  " + JT_STR((valueRetrieved != null)
286                    ? valueRetrieved.getValueType()
287                    : null
288                ) + "\n" +
289            "\tConverting To Java-Type: " + ((methodReturnJavaType != null)
290                    ? methodReturnJavaType.getCanonicalName()
291                    : "Java-Type Unknown"
292                );
293    }
294}