1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package Torello.JSON;

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.Objects;

import javax.json.JsonObject;

/** 
 * Used for Read Json method that attempt to build a Java POJO, but fail due to an inability to
 * extract a valid constructor from the object.  When using a class' constructor as a builder,
 * the required constructor must be one which accepts only one parameter.  That parameter must be 
 * of type {@link javax.json.JsonObject}.
 */
public class InvalidClassException extends RuntimeException
{
    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUIDEX>  */
    public static final long serialVersionUID = 1;

    /** Constructs a {@code InvalidClassException} with no detail message. */
    public InvalidClassException()
    { super(); }

    /**
     * Constructs a {@code InvalidClassException} with the specified detail message.
     * @param message the detail message.
     */
    public InvalidClassException(String message)
    { super(message); }

    /**
     * Constructs a new {@code InvalidClassException} with the specified detail message
     * and cause.
     * 
     * <BR /><BR /><DIV CLASS=JDHint>
     * <B STYLE='color:red;'>Note:</B> The detail message associated with cause is not
     * automatically incorporated into this exception's detail message.
     * </DIV>
     * 
     * @param message The detail message (which is saved for later retrieval by the
     * {@code Throwable.getMessage()} method).
     * 
     * @param cause the cause (which is saved for later retrieval by the
     * {@code Throwable.getCause()} method).  (A null value is permitted, and indicates that the
     * cause is nonexistent or unknown.)
     */
    public InvalidClassException(String message, Throwable cause)
    { super(message, cause); }

    /**
     * Constructs a new {@code InvalidClassException} with the specified cause and a detail
     * message of {@code (cause==null ? null : cause.toString())} (which typically contains the
     * class and detail message of cause).  This constructor is useful for exceptions that are
     * little more than wrappers for other throwables.
     * 
     * @param cause The cause (which is saved for later retrieval by the
     * {@code Throwable.getCause()} method).  (A null value is permitted, and indicates that the
     * cause is nonexistent or unknown.)
     */
    public InvalidClassException(Throwable cause)
    { super(cause); }

    /**
     * Extracts a valid {@code java.lang.reflect.Constructor} instance for a constructor that
     * accepts one arguement of type {@code JsonObject}.
     *
     * <BR /><BR />Throws if such an instance of {@code Constructor} cannot be found.
     *
     * @throws NullPointerException throws if parameter {@code 'c'} is null
     * 
     * @throws InvalidClassException throws if any errors occur when extracting the instance of
     * {@code java.lang.reflect.Constructor}.  This method excepts &amp; attempts to extract a one
     * argument constructor whose sole arguement is of type {@link JsonObject}.
     */
    public static <T> Constructor<T> check(Class<T> c)
    {
        final Constructor<T> ctor;

        Objects.requireNonNull(c, "The Class<T> parameter 'c' has been passed null");

        try
        {
            // This just gets a "Constructor" using Reflection.  The main point is that the
            // Constructor must have exactly one parameter - and that parameter must have a
            // type "JsonObject"  (basic java.lang.reflect stuff)
            //
            //System.out.println("c.getName:():" + c.getName());

            ctor = c.getDeclaredConstructor(JsonObject.class);
        }

        catch (Exception e)
        {
            if (c.getEnclosingClass() != null)
            {
                int modifiers = c.getModifiers();

                if ((! Modifier.isStatic(modifiers)) ||  (! Modifier.isPublic(modifiers)))

                    throw new InvalidClassException(
                        "Unable to retrieve POJO Constructor for class: " +
                        "[" + c.getName() + "]\n" +
                        "Your class appears to be a Nested-Class, however it has not been " +
                        "declared public and static.  There is no way to retrieve a " +
                        "1-Argument JsonObject Constructor for Nested-Type's unless the " +
                        "type has been declared BOTH static AND public.\n" +
                        "See Exception.getCause() for details.",
                        e
                    );

                else throw new InvalidClassException(
                    "There was a problem retrieving a one-argument, public, constructor for the " +
                    "class you wish to instantiate.  See Exception.getCause() for details.",
                    e
                );
            }

            else throw new InvalidClassException(
                "Unable to retrieve POJO Constructor for class: [" + c.getName() + "]\n" +
                "Do you have a one-argument, public, constructor for this class?\n" +
                "Does it accept a JsonObject in its parameter list?\n" +
                "See Exception.getCause() for details.",
                e
            );
        }


        // If the user has requested a class that doesn't have that kind of constructor, then
        // there is no way to build the object.  Throw an exception.

        if (ctor == null) throw new InvalidClassException(
            "The class which was passed to parameter 'c' [" + c.getName() + "] does not " +
            "appear to have a constructor with precisely one parameter of type JsonObject.  " +
            "c.getDeclaredConstructor(JsonObject.class) has returned null."
        );

        return ctor;
    }
}