001package Torello.JSON; 002 003import java.lang.reflect.Constructor; 004import java.lang.reflect.Modifier; 005import java.util.Objects; 006 007import javax.json.JsonObject; 008 009/** 010 * Used for Read Json method that attempt to build a Java POJO, but fail due to an inability to 011 * extract a valid constructor from the object. When using a class' constructor as a builder, 012 * the required constructor must be one which accepts only one parameter. That parameter must be 013 * of type {@link javax.json.JsonObject}. 014 */ 015public class InvalidClassException extends RuntimeException 016{ 017 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUIDEX> */ 018 public static final long serialVersionUID = 1; 019 020 /** Constructs a {@code InvalidClassException} with no detail message. */ 021 public InvalidClassException() 022 { super(); } 023 024 /** 025 * Constructs a {@code InvalidClassException} with the specified detail message. 026 * @param message the detail message. 027 */ 028 public InvalidClassException(String message) 029 { super(message); } 030 031 /** 032 * Constructs a new {@code InvalidClassException} with the specified detail message 033 * and cause. 034 * 035 * <BR /><BR /><DIV CLASS=JDHint> 036 * <B STYLE='color:red;'>Note:</B> The detail message associated with cause is not 037 * automatically incorporated into this exception's detail message. 038 * </DIV> 039 * 040 * @param message The detail message (which is saved for later retrieval by the 041 * {@code Throwable.getMessage()} method). 042 * 043 * @param cause the cause (which is saved for later retrieval by the 044 * {@code Throwable.getCause()} method). (A null value is permitted, and indicates that the 045 * cause is nonexistent or unknown.) 046 */ 047 public InvalidClassException(String message, Throwable cause) 048 { super(message, cause); } 049 050 /** 051 * Constructs a new {@code InvalidClassException} with the specified cause and a detail 052 * message of {@code (cause==null ? null : cause.toString())} (which typically contains the 053 * class and detail message of cause). This constructor is useful for exceptions that are 054 * little more than wrappers for other throwables. 055 * 056 * @param cause The cause (which is saved for later retrieval by the 057 * {@code Throwable.getCause()} method). (A null value is permitted, and indicates that the 058 * cause is nonexistent or unknown.) 059 */ 060 public InvalidClassException(Throwable cause) 061 { super(cause); } 062 063 /** 064 * Extracts a valid {@code java.lang.reflect.Constructor} instance for a constructor that 065 * accepts one arguement of type {@code JsonObject}. 066 * 067 * <BR /><BR />Throws if such an instance of {@code Constructor} cannot be found. 068 * 069 * @throws NullPointerException throws if parameter {@code 'c'} is null 070 * 071 * @throws InvalidClassException throws if any errors occur when extracting the instance of 072 * {@code java.lang.reflect.Constructor}. This method excepts & attempts to extract a one 073 * argument constructor whose sole arguement is of type {@link JsonObject}. 074 */ 075 public static <T> Constructor<T> check(Class<T> c) 076 { 077 final Constructor<T> ctor; 078 079 Objects.requireNonNull(c, "The Class<T> parameter 'c' has been passed null"); 080 081 try 082 { 083 // This just gets a "Constructor" using Reflection. The main point is that the 084 // Constructor must have exactly one parameter - and that parameter must have a 085 // type "JsonObject" (basic java.lang.reflect stuff) 086 // 087 //System.out.println("c.getName:():" + c.getName()); 088 089 ctor = c.getDeclaredConstructor(JsonObject.class); 090 } 091 092 catch (Exception e) 093 { 094 if (c.getEnclosingClass() != null) 095 { 096 int modifiers = c.getModifiers(); 097 098 if ((! Modifier.isStatic(modifiers)) || (! Modifier.isPublic(modifiers))) 099 100 throw new InvalidClassException( 101 "Unable to retrieve POJO Constructor for class: " + 102 "[" + c.getName() + "]\n" + 103 "Your class appears to be a Nested-Class, however it has not been " + 104 "declared public and static. There is no way to retrieve a " + 105 "1-Argument JsonObject Constructor for Nested-Type's unless the " + 106 "type has been declared BOTH static AND public.\n" + 107 "See Exception.getCause() for details.", 108 e 109 ); 110 111 else throw new InvalidClassException( 112 "There was a problem retrieving a one-argument, public, constructor for the " + 113 "class you wish to instantiate. See Exception.getCause() for details.", 114 e 115 ); 116 } 117 118 else throw new InvalidClassException( 119 "Unable to retrieve POJO Constructor for class: [" + c.getName() + "]\n" + 120 "Do you have a one-argument, public, constructor for this class?\n" + 121 "Does it accept a JsonObject in its parameter list?\n" + 122 "See Exception.getCause() for details.", 123 e 124 ); 125 } 126 127 128 // If the user has requested a class that doesn't have that kind of constructor, then 129 // there is no way to build the object. Throw an exception. 130 131 if (ctor == null) throw new InvalidClassException( 132 "The class which was passed to parameter 'c' [" + c.getName() + "] does not " + 133 "appear to have a constructor with precisely one parameter of type JsonObject. " + 134 "c.getDeclaredConstructor(JsonObject.class) has returned null." 135 ); 136 137 return ctor; 138 } 139}