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 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | package Torello.Java.JSON; import java.util.function.Predicate; import java.util.function.Function; import java.util.function.ObjIntConsumer; import java.util.function.IntConsumer; import javax.json.JsonString; import javax.json.JsonValue; import static javax.json.JsonValue.ValueType.NUMBER; import static javax.json.JsonValue.ValueType.STRING; import static Torello.Java.JSON.JFlag.*; // An (extremely) temporary class. This is created in the SettingsRec Constructor, and then it is // GC'ed as soon as that Constructor finishes. // // IMPORTANT NOTE: These booleans are used to decide WHICH Lambda to return. These boolean's // ARE NEVER used inside of a Lambda - which (if you try really had to think about // it) means the GC will not retain or keep these once the SettingsRec Constructor // has finished. // // // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // The 'ja' instance declared in class "SettingsRec" **IS NOT** declared final. It can be reset ! // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // // IMPORTANT NOTE: The 'ja' that is passed to the Functional-Interface Implementatons which are // constructed in this method is "de-referenced" from the SettingsRec -- It **IS NOT** passed as // a parameter to this method. If it **WERE NOT** retrieved from the 'SettingsRec', then 'sr' // instance, then the 'ja' that would be used would be permanently-solidified to the 'ja' // referenced that were passed right at the beginning, upon construction of the SettingsRec // instance. class TempFlags { // Internally used flags. These are actually only used during the construction phase, and // therefore these don't have to be "instance fields" at all, they could easily just be final // variables that are used (and then discarded) inside of the constructor only. However, since // there has been a recent "Breaking up the Monolithic Constructor" into smaller pieces, these // were moved here. // // These could also, EASILY, be final-variables that are passed as parameters into the methods // that use them, but this seems OK. The garbage collector really won't know the difference, // because these are primitives. private final boolean NULLS, RN_AA, RD_AA, S_AA; // Some of the FLAGS. private final boolean RTS_WT, RJA_AEX, IN_NSAT, S_NSAT; // A Quick Getter for three of the above private fields boolean RJA_AEX() { return this.RJA_AEX; } boolean IN_NSAT() { return this.IN_NSAT; } boolean S_NSAT() { return this.S_NSAT; } // Save the actual-complete FLAGS Mask private final int FLAGS; @SuppressWarnings("rawtypes") private final Lambdas lambdas; TempFlags( final int FLAGS, final boolean NULLS, @SuppressWarnings("rawtypes") final Lambdas lambdas ) { this.RJA_AEX = (FLAGS & RETURN_JAPPROX_ON_AEX) > 0; this.RTS_WT = (FLAGS & RETURN_TOSTRING_ON_WRONGTYPE) > 0; this.IN_NSAT = (FLAGS & INSERT_NULL_ON_NON_SUBARRAY_TYPE) > 0; this.S_NSAT = (FLAGS & SKIP_ON_NON_SUBARRAY_TYPE) > 0; // Fields which are (only) used in the "Handler Selector Methods" below // These could be converted into Final-Variables that are passed as parameters into the // Selector-Methods below, but I chose not too. I don't have a good reason. The way it is // being done, now, is a tiny bit wasteful since they are now saved as Final / Constant // Fields in this class, but they are private and aren't ever used after this constructor // finishes! // // Passing them as a long list of parameters to each of the selector methods would also be // a "Tiny Bit" slower! this.NULLS = NULLS; this.RN_AA = NULLS && ((FLAGS & RETURN_NULL_ON_ANY_ALL) > 0); this.RD_AA = (FLAGS & RETURN_DEFVAL_ON_ANY_ALL) > 0; this.S_AA = (FLAGS & SKIP_ON_ANY_ALL) > 0; this.FLAGS = FLAGS; this.lambdas = lambdas; } // Used when Json-Null is encountered in a Json-Array IntConsumer selectNullHandler(final SettingsRec<?, ?> sr) { if (NULLS && ((FLAGS & RETURN_NULL_ON_NULL) > 0)) return lambdas::AN; else if ((FLAGS & RETURN_DEFVAL_ON_NULL) > 0) return lambdas::AD; else if ((FLAGS & SKIP_ON_NULL) > 0) return lambdas::NOOP; else if (NULLS && RN_AA) return lambdas::AN; else if (RD_AA) return lambdas::AD; else if (S_AA) return lambdas::NOOP; else if (NULLS) return lambdas::AN; // IMPORTANT NOTE: See the comment at the top of this class regarding the 'sr.ja' // versus 'ja' (being passed as a parameter to this method). else return (int i) -> { throw new JsonNullPrimitiveArrException(sr.ja, i, NUMBER, sr.CLASS); }; } // AEX Handler (ArithmeticException) IntConsumer selectAEXHandler() { if (NULLS && ((FLAGS & RETURN_NULL_ON_AEX) > 0)) return lambdas::AN; else if ((FLAGS & RETURN_DEFVAL_ON_AEX) > 0) return lambdas::AD; else if ((FLAGS & SKIP_ON_AEX) > 0) return lambdas::NOOP; else if (NULLS && RN_AA) return lambdas::AN; else if (RD_AA) return lambdas::AD; else if (S_AA) return lambdas::NOOP; return null; } // SPEX Handler (Exception while parsing a String into the Java-Type) private IntConsumer selectSPEXHandler() { if (NULLS && ((FLAGS & RETURN_NULL_ON_SPEX) > 0)) return lambdas::AN; else if ((FLAGS & RETURN_DEFVAL_ON_SPEX) > 0) return lambdas::AD; else if ((FLAGS & SKIP_ON_SPEX) > 0) return lambdas::NOOP; else if (NULLS && RN_AA) return lambdas::AN; else if (RD_AA) return lambdas::AD; else if (S_AA) return lambdas::NOOP; return null; } // ZLS Handler (A Zero-Length String was in the JsonArray) private IntConsumer selectZLSHandler() { if (NULLS && ((FLAGS & RETURN_NULL_ON_0LEN_STR) > 0)) return lambdas::AN; else if ((FLAGS & RETURN_DEFVAL_ON_0LEN_STR) > 0) return lambdas::AD; else if ((FLAGS & SKIP_ON_0LEN_STR) > 0) return lambdas::NOOP; else if (NULLS && RN_AA) return lambdas::AN; else if (RD_AA) return lambdas::AD; else if (S_AA) return lambdas::NOOP; return null; } // Wrong-Type Handler (A JsonObject or a nested-JsonArray was in an array position) IntConsumer selectWrongTypeHandler() { if (NULLS && ((FLAGS & RN_WT) > 0)) return lambdas::AN; else if ((FLAGS & RD_WT) > 0) return lambdas::AD; else if ((FLAGS & SKIP_ON_WRONG_JSONTYPE) > 0) return lambdas::NOOP; else if (NULLS && RN_AA) return lambdas::AN; else if (RD_AA) return lambdas::AD; else if (S_AA) return lambdas::NOOP; return null; } // JsonString Handler: **ONLY USED BY** ProcessJsonArray.numericToJava <T> ObjIntConsumer<JsonString> selectJsonStringHandler( final SettingsRec<T, ?> sr, final Function<String, T> userParser, // BASIC_TYPES: bt.whichType, final byte whichType, // BASIC_TYPES: bt.validStrTester, final Predicate<String> validStrTester, // BASIC_TYPES: bt.defaultParser final Function<String, T> defaultParser ) { final IntConsumer handlerSPEX = this.selectSPEXHandler(); final IntConsumer handlerZLS = this.selectZLSHandler(); if (userParser != null) return ChooseStringHandler.useUserParser (sr, sr.CLASS, sr.ACCEPTOR, userParser, handlerSPEX); else if ((FLAGS & RP_S) > 0) return (whichType == BASIC_TYPES.NUMBER) ? ChooseStringHandler.parseStringNUMBER (sr, sr.CLASS, sr.ACCEPTOR, handlerSPEX, handlerZLS) : ChooseStringHandler.parseString( sr, sr.CLASS, sr.ACCEPTOR, handlerSPEX, handlerZLS, validStrTester, defaultParser ); else if (NULLS && ((FLAGS & RETURN_NULL_ON_STR) > 0)) return lambdas::AN; else if ((FLAGS & RETURN_DEFVAL_ON_STR) > 0) return lambdas::AD; else if ((FLAGS & SKIP_ON_STR) > 0) return lambdas::NOOP; else if (NULLS && RN_AA) return lambdas::AN; else if (RD_AA) return lambdas::AD; else if (S_AA) return lambdas::NOOP; // Thanksgiving 2024 else if (sr.handlerWrongType != null) return (JsonString js, int i) -> sr.handlerWrongType.accept(i); // IMPORTANT NOTE: See the comment at the top of this class regarding the 'sr.ja' // versus 'ja' (being passed as a parameter to this method). else return (JsonString js, int i) -> { throw new JsonTypeArrException (sr.ja, i, NUMBER, js, sr.CLASS); }; } <T> ObjIntConsumer<JsonValue> selectJsonStringWrongTypeHandler (final SettingsRec<String, ?> sr) { if (this.RTS_WT) return (JsonValue jv, int i) -> sr.ACCEPTOR.accept(jv.toString(), i); else if (sr.handlerWrongType != null) return (JsonValue jv, int i) -> sr.handlerWrongType.accept(i); // IMPORTANT NOTE: See the comment at the top of this class regarding the 'sr.ja' // versus 'ja' (being passed as a parameter to this method). else return (JsonValue jv, int i) -> { throw new JsonTypeArrException(sr.ja, i, STRING, jv, String.class); }; } } |