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 | package Torello.Java.JSON; import Torello.Java.UnreachableError; import java.util.function.ObjIntConsumer; import java.util.function.IntConsumer; import java.util.function.Predicate; import java.util.function.Function; import javax.json.JsonValue; import javax.json.JsonString; import java.math.BigDecimal; // NOTE: This is not Rocket-Science. It just looks really complicated. // // Stuff with "Types" becomes so heinous to look at. I started this package in // 2022, and it is now 2025. The Package Torello.Java.JSON has more testing code than // literally any of the other packages in this Library. // // I'm still not done testing it. There is still more that I should do. // // The only purpose of making a "String-Handler" is so that the MAIN-PROCESSING-LOOP // which is in class "ProcessJsonArr" is short, simple & sweet. It just calls the handlers that // are saved inside of the "SettingsRec". The SettingsRec gets a String-Handler from this class! // // // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // 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 ChooseStringHandler { static <T> ObjIntConsumer<JsonString> useUserParser( final SettingsRec<T, ?> sr, final Class<T> CLASS, final ObjIntConsumer<T> ACCEPTOR, final Function<String, T> userParser, final IntConsumer handlerSPEX ) { return (final JsonString js, final int i) -> { try { ACCEPTOR.accept(userParser.apply(js.getString()), i); } catch (Exception e) { // 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). if (handlerSPEX != null) handlerSPEX.accept(i); else throw new JsonStrParseArrException(e, sr.ja, i, js, CLASS); } }; } static <T> ObjIntConsumer<JsonString> parseString( final SettingsRec<T, ?> sr, final Class<T> CLASS, final ObjIntConsumer<T> ACCEPTOR, final IntConsumer handlerSPEX, final IntConsumer handlerZLS, final Predicate<String> validStrTester, final Function<String, T> defaultParser ) { return (final JsonString js, final int i) -> { String s = js.getString(); if (s.length() == 0) { if (handlerZLS != null) handlerZLS.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 throw new JsonStrParseArrException( new IllegalArgumentException("Zero Length String"), sr.ja, i, js, CLASS ); } // StringParse.isInteger(s), isLong(String) **AND** s -> true (Double) else if (validStrTester.test(s)) // Integer.parseInt(String), Long.parseLong, Double.parseDouble ACCEPTOR.accept(defaultParser.apply(s), i); else if (handlerSPEX != null) handlerSPEX.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 throw new JsonStrParseArrException (getSPEX(s, defaultParser), sr.ja, i, js, CLASS); }; } // Small Internal, static, helper private static Exception getSPEX(final String s, final Function<String, ?> converter) { try { converter.apply(s); } catch (Exception e) { return e; } throw new UnreachableError(); } @SuppressWarnings("unchecked") static <T> ObjIntConsumer<JsonString> parseStringNUMBER( final SettingsRec<T, ?> sr, final Class<T> CLASS, final ObjIntConsumer<T> ACCEPTOR, final IntConsumer handlerSPEX, final IntConsumer handlerZLS ) { return (final JsonString js, final int i) -> { String s = js.getString(); if (s.length() == 0) { if (handlerZLS != null) handlerZLS.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 throw new JsonStrParseArrException( new IllegalArgumentException("Zero Length String"), sr.ja, i, js, CLASS ); return; } final BigDecimal bd; try { bd = new BigDecimal(s); } catch (Exception e) { if (handlerSPEX != null) handlerSPEX.accept(i); else throw new JsonStrParseArrException (e, sr.ja, i, js, Number.class); return; } ((ObjIntConsumer<Number>) ACCEPTOR).accept(RJInternal.convertToNumber(bd), i); }; } } |