001package Torello.Java.JSON; 002 003import Torello.JavaDoc.IntoHTMLTable; 004import static Torello.JavaDoc.IntoHTMLTable.Background.*; 005 006import javax.json.JsonArray; 007import javax.json.JsonObject; 008import javax.json.JsonValue; 009import javax.json.JsonNumber; 010import javax.json.JsonString; 011 012import static javax.json.JsonValue.ValueType.*; 013 014import java.math.BigDecimal; 015import java.util.function.Function; 016import java.util.function.ObjIntConsumer; 017 018/** 019 * This class is the "Central Artery" for all Json-Array Processing done in this package. 020 * These four FOR-LOOPS handle 100% of the array processors done by all of the "RJArr" 021 * classes offered. 022 * 023 * These four methods are extremely similar, but have a few minor subtleties that prevent 024 * them from being unified into a single handler for all types. 025 */ 026public class ProcessJsonArray 027{ 028 private ProcessJsonArray() { } 029 030 031 // ******************************************************************************************** 032 // ******************************************************************************************** 033 // Un-Synchronized Method Variants 034 // ******************************************************************************************** 035 // ******************************************************************************************** 036 037 038 /** 039 * Any and all Json-Array Processors that are intended to read an array of {@link JsonNumber} 040 * will invoke this method to do their Type-Conversions. 041 * 042 * @param <NUMERIC_DATA_TYPE> <EMBED CLASS='external-html' DATA-FILE-ID=PJA_NUM_DATA_TYPE> 043 * @param <RETURN_TYPE> <EMBED CLASS='external-html' DATA-FILE-ID=PJA_NUM_RETURN_TYPE> 044 * 045 * @param ja This should be any instance of {@link JsonArray}. It is expected that if this 046 * array does not contain explicit {@link JsonNumber} values, that is should at least contain 047 * values that are to converted or properly parsed into Java-Numbers. 048 * 049 * @param rec <EMBED CLASS='external-html' DATA-FILE-ID=PJA_REC_PARAM> 050 * 051 * @return An instance of the type specified by Type-Parameter {@code 'RETURN_TYPE'} 052 */ 053 public static <NUMERIC_DATA_TYPE extends Number, RETURN_TYPE> RETURN_TYPE numericToJava( 054 final JsonArray ja, 055 final SettingsRec<NUMERIC_DATA_TYPE, RETURN_TYPE> rec 056 ) 057 { 058 rec.ja = ja; 059 060 final int SIZE = ja.size(); 061 062 JsonValue jv; 063 064 065 // If 'RETURN_TYPE' is a Stream, this builds a new Stream, and saves it to the 066 // internally-used "EffectivelyFinal" instance. It's quite simple, actually. 067 // 068 // If 'RETURN_TYPE' is a Consumer, this is a simple "No-Op" 069 070 rec.constructNewBuilder.run(); 071 072 for (int i=0; i < SIZE; i++) 073 074 switch ((jv = ja.get(i)).getValueType()) 075 { 076 // javax.json.JsonValue.ValueType.NULL 077 case NULL: rec.handlerNull.accept(i); break; 078 079 // javax.json.JsonValue.ValueType.NUMBER 080 case NUMBER: rec.handlerNumber.accept((JsonNumber) jv, i); break; 081 082 // javax.json.JsonValue.ValueType.STRING 083 case STRING: rec.handlerJsonString.accept((JsonString) jv, i); break; 084 085 // OBJECT, ARRAY, TRUE, FALSE 086 default: 087 088 if (rec.handlerWrongType != null) 089 rec.handlerWrongType.accept(i); 090 else 091 throw new JsonTypeArrException(ja, i, NUMBER, jv, rec.CLASS); 092 } 093 094 // Run Stream.Builder.build() 095 return rec.runBuilderDotBuild.get(); 096 } 097 098 /** 099 * Any and all Json-Array Processors that are intended to read an array of Json-Boolean Values 100 * will invoke this method to do their Type-Conversions. 101 * 102 * @param <RETURN_TYPE> <EMBED CLASS='external-html' DATA-FILE-ID=PJA_BL_RETURN_TYPE> 103 * 104 * @param ja This should be any instance of {@link JsonArray}. It is expected that if this 105 * array does not contain explicit Json-Boolean values, that is should at least contain values 106 * that are to converted or properly parsed into Java-Booleans. 107 * 108 * @param rec <EMBED CLASS='external-html' DATA-FILE-ID=PJA_REC_PARAM> 109 * 110 * @return An instance of {@code Stream<Boolean>}. If the provided instance of 111 * {@code SettingsRec} has been constructed for a {@code Consumer}, then this method will 112 * return null. 113 */ 114 public static <RETURN_TYPE> RETURN_TYPE booleanToJava( 115 final JsonArray ja, 116 final SettingsRec<Boolean, RETURN_TYPE> rec 117 ) 118 { 119 final int SIZE = ja.size(); 120 121 JsonValue jv = null; 122 123 rec.ja = ja; 124 125 // If 'RETURN_TYPE' is a Consumer, this is a simple "No-Op" 126 rec.constructNewBuilder.run(); 127 128 for (int i=0; i < SIZE; i++) 129 130 switch ((jv = ja.get(i)).getValueType()) 131 { 132 // javax.json.JsonValue.ValueType.NULL, TRUE, FALSE & STRING 133 case NULL: rec.handlerNull.accept(i); break; 134 case TRUE: rec.ACCEPTOR.accept(true, i); break; 135 case FALSE: rec.ACCEPTOR.accept(false, i); break; 136 case STRING: rec.handlerJsonString.accept((JsonString) jv, i); break; 137 138 // javax.json.JsonValue.ValueType.NUMBER, OBJECT, ARRAY 139 default: 140 if (rec.handlerWrongType != null) rec.handlerWrongType.accept(i); 141 else throw new JsonTypeArrException(ja, i, TRUE, jv, Boolean.class); 142 } 143 144 145 // Run Stream.Builder.build() - IF NEEDED 146 // 'get()' simply returns null if the SettingsRec<T, U> had a "consumer" 147 // for it's 'U' Type, rather than a Stream. 148 149 return rec.runBuilderDotBuild.get(); 150 } 151 152 /** 153 * Used to convert {@code JsonObject}'s into Java-Objects 154 * 155 * @param <T> The Class / Type of the Objects to be extracted from the {@link JsonArray} 156 * @param <RETURN_TYPE> <EMBED CLASS='external-html' DATA-FILE-ID=PJA_T_RETURN_TYPE> 157 * 158 * @param ja This should be any instance of {@link JsonArray}. It is expected that this array 159 * contain explicit {@link JsonObject} values, that can be converted in.to {@code 'T'} 160 * 161 * @param rec <EMBED CLASS='external-html' DATA-FILE-ID=PJA_REC_PARAM> 162 * 163 * @return An instance of the type specified by Type-Parameter {@code 'RETURN_TYPE'}. 164 */ 165 public static <T, RETURN_TYPE> RETURN_TYPE objToJava( 166 final JsonArray ja, 167 final SettingsRec<T, RETURN_TYPE> rec 168 ) 169 { 170 final int SIZE = ja.size(); 171 172 JsonValue jv = null; 173 174 rec.ja = ja; 175 176 177 // For Stream<T>, this builds a new Stream.Builder 178 // for Consumer<T>, this is a "No-Op" 179 180 rec.constructNewBuilder.run(); 181 182 for (int i=0; i < SIZE; i++) 183 184 switch ((jv = ja.get(i)).getValueType()) 185 { 186 // javax.json.JsonValue.ValueType.NULL 187 case NULL: 188 rec.handlerNull.accept(i); 189 break; 190 191 // javax.json.JsonValue.ValueType.OBJECT 192 case OBJECT: 193 T obj = rec.builder1Or2 194 ? rec.objBuilder.apply((JsonObject) jv) 195 : rec.objBuilder2.apply(i, (JsonObject) jv); 196 197 rec.ACCEPTOR.accept(obj, i); 198 break; 199 200 // javax.json.JsonValue.ValueType.NUMBER, STRING, TRUE, FALSE, ARRAY 201 default: 202 if (rec.handlerWrongType != null) rec.handlerWrongType.accept(i); 203 else throw new JsonTypeArrException(ja, i, TRUE, jv, rec.CLASS); 204 } 205 206 207 // For Stream<T>, this runs Stream.Builder.build() 208 // For Consumer<T>, this automatically returns null 209 210 return rec.runBuilderDotBuild.get(); 211 } 212 213 /** 214 * Any and all Json-Array Processors that are intended to read an array of {@link JsonString} 215 * Values will invoke this method to do their Type-Conversions. 216 * 217 * @param <RETURN_TYPE> <EMBED CLASS='external-html' DATA-FILE-ID=PJA_STR_RETURN_TYPE> 218 * 219 * @param ja This should be any instance of {@link JsonArray}. 220 * 221 * @param rec <EMBED CLASS='external-html' DATA-FILE-ID=PJA_REC_PARAM> 222 * 223 * @return An instance of {@code Stream<String>}. If the provided instance of 224 * {@code SettingsRec} has been constructed for a {@code Consumer}, then this method will 225 * return null. 226 */ 227 public static <RETURN_TYPE> RETURN_TYPE strToJava( 228 final JsonArray ja, 229 final SettingsRec<String, RETURN_TYPE> rec 230 ) 231 { 232 final int SIZE = ja.size(); 233 234 JsonValue jv = null; 235 236 rec.ja = ja; 237 238 if (rec.constructNewBuilder != null) rec.constructNewBuilder.run(); 239 240 for (int i=0; i < SIZE; i++) 241 242 switch ((jv = ja.get(i)).getValueType()) 243 { 244 // javax.json.JsonValue.ValueType.NULL 245 case NULL: 246 rec.handlerNull.accept(i); 247 break; 248 249 // javax.json.JsonValue.ValueType.STRING 250 case STRING: 251 rec.ACCEPTOR.accept(((JsonString) jv).getString(), i); 252 break; 253 254 // OBJECT, ARRAY, TRUE, FALSE, NUMBER 255 default: 256 rec.jsonStringWrongTypeHandler.accept(jv, i); 257 } 258 259 260 // Returns the Built-Stream, for Streams. 261 // Returns 'null' for Consumer's 262 263 return rec.runBuilderDotBuild.get(); 264 } 265 266 267 // ******************************************************************************************** 268 // ******************************************************************************************** 269 // Synchronized Method Variants 270 // ******************************************************************************************** 271 // ******************************************************************************************** 272 273 274 /** 275 * <BR>Synchronized: Nothing More than a "Synchronized Wrapper" which can be used in a 276 * Multi-Threaded Programming-Environment. 277 * <BR>Wraps: Method {@link #numericToJava(JsonArray, SettingsRec)} 278 * <BR>Locking-Object: Input-Parameter {@code 'rec'}, the {@code SettingsRec} instance 279 * <BR>IMPORTANT: Synchronization <B><I>is only needed</I></B> when the {@code SettingsRec} 280 * instance shall be "re-used" in other threads. 281 */ 282 @IntoHTMLTable(background=BlueDither, title="Synchronized Variant of Method 'numericToJava'") 283 public static <NUMERIC_DATA_TYPE extends Number, RETURN_TYPE> RETURN_TYPE 284 numericToJavaSync( 285 final JsonArray ja, 286 final SettingsRec<NUMERIC_DATA_TYPE, RETURN_TYPE> rec 287 ) 288 { synchronized (rec) { return numericToJava(ja, rec); } } 289 290 /** 291 * <BR>Synchronized: Nothing More than a "Synchronized Wrapper" which can be used in a 292 * Multi-Threaded Programming-Environment. 293 * <BR>Wraps: Method {@link #booleanToJava(JsonArray, SettingsRec)} 294 * <BR>Locking-Object: Input-Parameter {@code 'rec'}, the {@code SettingsRec} instance 295 * <BR>IMPORTANT: Synchronizations <B><I>is only needed</I></B> when the {@code SettingsRec} 296 * instance shall be "re-used" in other threads. 297 */ 298 @IntoHTMLTable(background=GreenDither, title="Synchronized Variant of Method 'booleanToJava'") 299 public static <RETURN_TYPE> RETURN_TYPE booleanToJavaSync( 300 final JsonArray ja, 301 final SettingsRec<Boolean, RETURN_TYPE> rec 302 ) 303 { synchronized (rec) { return booleanToJava(ja, rec); } } 304 305 /** 306 * <BR>Synchronized: Nothing More than a "Synchronized Wrapper" which can be used in a 307 * Multi-Threaded Programming-Environment. 308 * <BR>Wraps: Method {@link #objToJava(JsonArray, SettingsRec)} 309 * <BR>Locking-Object: Input-Parameter {@code 'rec'}, the {@code SettingsRec} instance 310 * <BR>IMPORTANT: Synchronizations <B><I>is only needed</I></B> when the {@code SettingsRec} 311 * instance shall be "re-used" in other threads. 312 */ 313 @IntoHTMLTable(background=BlueDither, title="Synchronized Variant of Method 'objToJava'") 314 public static <T, RETURN_TYPE> RETURN_TYPE objToJavaSync( 315 final JsonArray ja, 316 final SettingsRec<T, RETURN_TYPE> rec 317 ) 318 { synchronized (rec) { return objToJava(ja, rec); } } 319 320 /** 321 * <BR>Synchronized: Nothing More than a "Synchronized Wrapper" which can be used in a 322 * Multi-Threaded Programming-Environment. 323 * <BR>Wraps: Method {@link #strToJava(JsonArray, SettingsRec)} 324 * <BR>Locking-Object: Input-Parameter {@code 'rec'}, the {@code SettingsRec} instance 325 * <BR>IMPORTANT: Synchronizations <B><I>is only needed</I></B> when the {@code SettingsRec} 326 * instance shall be "re-used" in other threads. 327 */ 328 @IntoHTMLTable(background=GreenDither, title="Synchronized Variant of Method 'strToJava'") 329 public static <RETURN_TYPE> RETURN_TYPE strToJavaSync( 330 final JsonArray ja, 331 final SettingsRec<String, RETURN_TYPE> rec 332 ) 333 { synchronized (rec) { return strToJava(ja, rec); } } 334 335}