001package Torello.JSON; 002 003import Torello.Java.UnreachableError; 004 005import java.util.function.ObjIntConsumer; 006import java.util.function.IntConsumer; 007import java.util.function.Predicate; 008import java.util.function.Function; 009 010import javax.json.JsonValue; 011import javax.json.JsonString; 012 013import java.math.BigDecimal; 014 015 016// NOTE: This is not Rocket-Science. It just looks really complicated. 017// 018// Stuff with "Types" becomes so heinous to look at. I started this package in 019// 2022, and it is now 2025. The Package Torello.JSON has more testing code than 020// literally any of the other packages in this Library. 021// 022// I'm still not done testing it. There is still more that I should do. 023// 024// The only purpose of making a "String-Handler" is so that the MAIN-PROCESSING-LOOP 025// which is in class "ProcessJsonArr" is short, simple & sweet. It just calls the handlers that 026// are saved inside of the "SettingsRec". The SettingsRec gets a String-Handler from this class! 027// 028// 029// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 030// The 'ja' instance declared in class "SettingsRec" **IS NOT** declared final. It can be reset ! 031// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 032// 033// IMPORTANT NOTE: The 'ja' that is passed to the Functional-Interface Implementatons which are 034// constructed in this method is "de-referenced" from the SettingsRec -- It **IS NOT** passed as 035// a parameter to this method. If it **WERE NOT** retrieved from the 'SettingsRec', then 'sr' 036// instance, then the 'ja' that would be used would be permanently-solidified to the 'ja' 037// referenced that were passed right at the beginning, upon construction of the SettingsRec 038// instance. 039 040@Torello.JavaDoc.Annotations.StaticFunctional 041public class ChooseStringHandler 042{ 043 private ChooseStringHandler() {} 044 045 046 static <T> ObjIntConsumer<JsonString> useUserParser( 047 final SettingsRec<T, ?> sr, 048 final Class<T> CLASS, 049 final ACCEPTOR<T> acceptor, 050 final Function<String, T> userParser, 051 final IntConsumer handlerSPEX 052 ) 053 { 054 return (final JsonString js, final int i) -> 055 { 056 try 057 { acceptor.accept(userParser.apply(js.getString()), i); } 058 059 catch (Exception e) 060 { 061 // IMPORTANT NOTE: See the comment at the top of this class regarding the 'sr.ja' 062 // versus 'ja' (being passed as a parameter to this method). 063 064 if (handlerSPEX != null) handlerSPEX.accept(i); 065 else throw new JsonStrParseArrException(e, sr.ja, i, js, CLASS); 066 } 067 }; 068 } 069 070 static <T> ObjIntConsumer<JsonString> parseString( 071 final SettingsRec<T, ?> sr, 072 final Class<T> CLASS, 073 final ACCEPTOR<T> acceptor, 074 final IntConsumer handlerSPEX, 075 final IntConsumer handlerZLS, 076 final Predicate<String> validStrTester, 077 final Function<String, T> defaultParser 078 ) 079 { 080 return (final JsonString js, final int i) -> 081 { 082 String s = js.getString(); 083 084 if (s.length() == 0) 085 { 086 if (handlerZLS != null) handlerZLS.accept(i); 087 088 089 // IMPORTANT NOTE: See the comment at the top of this class regarding the 'sr.ja' 090 // versus 'ja' (being passed as a parameter to this method). 091 092 else throw new JsonStrParseArrException( 093 new IllegalArgumentException("Zero Length String"), 094 sr.ja, i, js, CLASS 095 ); 096 } 097 098 // StringParse.isInteger(s), isLong(String) **AND** s -> true (Double) 099 else if (validStrTester.test(s)) 100 101 // Integer.parseInt(String), Long.parseLong, Double.parseDouble 102 acceptor.accept(defaultParser.apply(s), i); 103 104 else if (handlerSPEX != null) handlerSPEX.accept(i); 105 106 107 // IMPORTANT NOTE: See the comment at the top of this class regarding the 'sr.ja' 108 // versus 'ja' (being passed as a parameter to this method). 109 110 else throw new JsonStrParseArrException 111 (getSPEX(s, defaultParser), sr.ja, i, js, CLASS); 112 }; 113 } 114 115 // Small Internal, static, helper 116 private static Exception getSPEX(final String s, final Function<String, ?> converter) 117 { 118 try 119 { converter.apply(s); } 120 121 catch (Exception e) 122 { return e; } 123 124 throw new UnreachableError(); 125 } 126 127 @SuppressWarnings("unchecked") 128 static <T> ObjIntConsumer<JsonString> parseStringNUMBER( 129 final SettingsRec<T, ?> sr, 130 final Class<T> CLASS, 131 final ACCEPTOR<T> acceptor, 132 final IntConsumer handlerSPEX, 133 final IntConsumer handlerZLS 134 ) 135 { 136 return (final JsonString js, final int i) -> 137 { 138 String s = js.getString(); 139 140 if (s.length() == 0) 141 { 142 if (handlerZLS != null) handlerZLS.accept(i); 143 144 145 // IMPORTANT NOTE: See the comment at the top of this class regarding the 'sr.ja' 146 // versus 'ja' (being passed as a parameter to this method). 147 148 else throw new JsonStrParseArrException( 149 new IllegalArgumentException("Zero Length String"), 150 sr.ja, i, js, CLASS 151 ); 152 153 return; 154 } 155 156 final BigDecimal bd; 157 158 try 159 { bd = new BigDecimal(s); } 160 161 catch (Exception e) 162 { 163 if (handlerSPEX != null) handlerSPEX.accept(i); 164 165 else throw new JsonStrParseArrException 166 (e, sr.ja, i, js, Number.class); 167 168 return; 169 } 170 171 // ((ObjIntConsumer<Number>) ACCEPTOR).accept(ReadNumberJSON.convertToNumber(bd), i); 172 ((ACCEPTOR<Number>) acceptor).accept(ReadNumberJSON.convertToNumber(bd), i); 173 }; 174 } 175}