001package Torello.JSON; 002 003import Torello.JavaDoc.Annotations.IntoHTMLTable; 004import static Torello.JavaDoc.Annotations.IntoHTMLTable.Background.GreenDither; 005import static Torello.JavaDoc.Annotations.IntoHTMLTable.Background.BlueDither; 006 007import javax.json.JsonArray; 008import javax.json.JsonObject; 009import javax.json.JsonValue; 010import javax.json.JsonNumber; 011import javax.json.JsonString; 012 013import static javax.json.JsonValue.ValueType.*; 014 015import java.math.BigDecimal; 016import java.util.function.Function; 017import java.util.function.ObjIntConsumer; 018 019/** 020 * This class is the "Central Artery" for all Json-Array Processing done in this package. 021 * These four FOR-LOOPS handle 100% of the array processors done by all of the "RJArr" 022 * classes offered. 023 * 024 * These four methods are extremely similar, but have a few minor subtleties that prevent 025 * them from being unified into a single handler for all types. 026 */ 027@Torello.JavaDoc.Annotations.StaticFunctional 028public class ProcessJsonArray 029{ 030 private ProcessJsonArray() { } 031 032 033 // ******************************************************************************************** 034 // ******************************************************************************************** 035 // Un-Synchronized Method Variants 036 // ******************************************************************************************** 037 // ******************************************************************************************** 038 039 040 /** 041 * Any and all Json-Array Processors that are intended to read an array of {@link JsonNumber} 042 * will invoke this method to do their Type-Conversions. 043 * 044 * @param <NUMERIC_DATA_TYPE> <EMBED CLASS='external-html' DATA-FILE-ID=PJA_NUM_DATA_TYPE> 045 * @param <RETURN_TYPE> <EMBED CLASS='external-html' DATA-FILE-ID=PJA_NUM_RETURN_TYPE> 046 * 047 * @param ja This should be any instance of {@link JsonArray}. It is expected that if this 048 * array does not contain explicit {@link JsonNumber} values, that is should at least contain 049 * values that are to converted or properly parsed into Java-Numbers. 050 * 051 * @param rec <EMBED CLASS='external-html' DATA-FILE-ID=PJA_REC_PARAM> 052 * 053 * @return An instance of the type specified by Type-Parameter {@code 'RETURN_TYPE'} 054 */ 055 public static <NUMERIC_DATA_TYPE extends Number, RETURN_TYPE> RETURN_TYPE numericToJava( 056 final JsonArray ja, 057 final SettingsRec<NUMERIC_DATA_TYPE, RETURN_TYPE> rec 058 ) 059 { 060 final int SIZE = ja.size(); 061 JsonValue jv = null; 062 rec.ja = ja; 063 064 rec.opener.run(); 065 rec.acceptor.reset(); 066 067 for (int i=0; i < SIZE; i++) 068 069 switch ((jv = ja.get(i)).getValueType()) 070 { 071 // javax.json.JsonValue.ValueType.NULL 072 case NULL: rec.handlerNull.accept(i); break; 073 074 // javax.json.JsonValue.ValueType.NUMBER 075 case NUMBER: rec.handlerNumber.accept((JsonNumber) jv, i); break; 076 077 // javax.json.JsonValue.ValueType.STRING 078 case STRING: rec.handlerJsonString.accept((JsonString) jv, i); break; 079 080 // OBJECT, ARRAY, TRUE, FALSE 081 default: 082 083 if (rec.handlerWrongType != null) 084 rec.handlerWrongType.accept(i); 085 else 086 throw new JsonTypeArrException(ja, i, NUMBER, jv, rec.CLASS); 087 } 088 089 return rec.closer.get(); 090 } 091 092 /** 093 * Any and all Json-Array Processors that are intended to read an array of Json-Boolean Values 094 * will invoke this method to do their Type-Conversions. 095 * 096 * @param <RETURN_TYPE> <EMBED CLASS='external-html' DATA-FILE-ID=PJA_BL_RETURN_TYPE> 097 * 098 * @param ja This should be any instance of {@link JsonArray}. It is expected that if this 099 * array does not contain explicit Json-Boolean values, that is should at least contain values 100 * that are to converted or properly parsed into Java-Booleans. 101 * 102 * @param rec <EMBED CLASS='external-html' DATA-FILE-ID=PJA_REC_PARAM> 103 * 104 * @return An instance of {@code Stream<Boolean>}. If the provided instance of 105 * {@code SettingsRec} has been constructed for a {@code Consumer}, then this method will 106 * return null. 107 */ 108 public static <RETURN_TYPE> RETURN_TYPE booleanToJava( 109 final JsonArray ja, 110 final SettingsRec<Boolean, RETURN_TYPE> rec 111 ) 112 { 113 final int SIZE = ja.size(); 114 JsonValue jv = null; 115 rec.ja = ja; 116 117 rec.opener.run(); 118 rec.acceptor.reset(); 119 120 for (int i=0; i < SIZE; i++) 121 122 switch ((jv = ja.get(i)).getValueType()) 123 { 124 // javax.json.JsonValue.ValueType.NULL, TRUE, FALSE & STRING 125 case NULL: rec.handlerNull.accept(i); break; 126 case TRUE: rec.acceptor.accept(true, i); break; 127 case FALSE: rec.acceptor.accept(false, i); break; 128 case STRING: rec.handlerJsonString.accept((JsonString) jv, i); break; 129 130 // javax.json.JsonValue.ValueType.NUMBER, OBJECT, ARRAY 131 default: 132 if (rec.handlerWrongType != null) rec.handlerWrongType.accept(i); 133 else throw new JsonTypeArrException(ja, i, TRUE, jv, Boolean.class); 134 } 135 136 return rec.closer.get(); 137 } 138 139 /** 140 * Used to convert {@code JsonObject}'s into Java-Objects 141 * 142 * @param <T> The Class / Type of the Objects to be extracted from the {@link JsonArray} 143 * @param <RETURN_TYPE> <EMBED CLASS='external-html' DATA-FILE-ID=PJA_T_RETURN_TYPE> 144 * 145 * @param ja This should be any instance of {@link JsonArray}. It is expected that this array 146 * contain explicit {@link JsonObject} values, that can be converted in.to {@code 'T'} 147 * 148 * @param rec <EMBED CLASS='external-html' DATA-FILE-ID=PJA_REC_PARAM> 149 * 150 * @return An instance of the type specified by Type-Parameter {@code 'RETURN_TYPE'}. 151 */ 152 public static <T, RETURN_TYPE> RETURN_TYPE objToJava( 153 final JsonArray ja, 154 final SettingsRec<T, RETURN_TYPE> rec 155 ) 156 { 157 final int SIZE = ja.size(); 158 JsonValue jv = null; 159 rec.ja = ja; 160 161 rec.opener.run(); 162 rec.acceptor.reset(); 163 164 for (int i=0; i < SIZE; i++) 165 166 switch ((jv = ja.get(i)).getValueType()) 167 { 168 // javax.json.JsonValue.ValueType.NULL 169 case NULL: 170 rec.handlerNull.accept(i); 171 break; 172 173 // javax.json.JsonValue.ValueType.OBJECT 174 case OBJECT: 175 final JsonObject jo = (JsonObject) jv; 176 177 try 178 { 179 final T POJO = rec.builder1Or2 180 ? rec.singleArgUserTypeBuilder.apply(jo) 181 : rec.tripleArgUserTypeBuilder.apply(i, jo); 182 183 rec.acceptor.accept(POJO, i); 184 } 185 186 catch (Exception e) 187 { throw new JsonBuildPOJOArrException(e, ja, i, jo, rec.CLASS); } 188 189 break; 190 191 // javax.json.JsonValue.ValueType.NUMBER, STRING, TRUE, FALSE, ARRAY 192 default: 193 if (rec.handlerWrongType != null) rec.handlerWrongType.accept(i); 194 else throw new JsonTypeArrException(ja, i, TRUE, jv, rec.CLASS); 195 } 196 197 return rec.closer.get(); 198 } 199 200 /** 201 * Any and all Json-Array Processors that are intended to read an array of {@link JsonString} 202 * Values will invoke this method to do their Type-Conversions. 203 * 204 * @param <RETURN_TYPE> <EMBED CLASS='external-html' DATA-FILE-ID=PJA_STR_RETURN_TYPE> 205 * 206 * @param ja This should be any instance of {@link JsonArray}. 207 * 208 * @param rec <EMBED CLASS='external-html' DATA-FILE-ID=PJA_REC_PARAM> 209 * 210 * @return An instance of {@code Stream<String>}. If the provided instance of 211 * {@code SettingsRec} has been constructed for a {@code Consumer}, then this method will 212 * return null. 213 */ 214 public static <RETURN_TYPE> RETURN_TYPE strToJava( 215 final JsonArray ja, 216 final SettingsRec<String, RETURN_TYPE> rec 217 ) 218 { 219 final int SIZE = ja.size(); 220 JsonValue jv = null; 221 rec.ja = ja; 222 223 rec.opener.run(); 224 rec.acceptor.reset(); 225 226 for (int i=0; i < SIZE; i++) 227 228 switch ((jv = ja.get(i)).getValueType()) 229 { 230 // javax.json.JsonValue.ValueType.NULL 231 case NULL: 232 rec.handlerNull.accept(i); 233 break; 234 235 // javax.json.JsonValue.ValueType.STRING 236 case STRING: 237 rec.acceptor.accept(((JsonString) jv).getString(), i); 238 break; 239 240 // OBJECT, ARRAY, TRUE, FALSE, NUMBER 241 default: 242 rec.jsonStringWrongTypeHandler.accept(jv, i); 243 } 244 245 return rec.closer.get(); 246 } 247 248 /** 249 * Invoke this method in order to read an array of {@link JsonObject JsonObject's} 250 * 251 * @param <RETURN_TYPE> <EMBED CLASS='external-html' DATA-FILE-ID=PJA_JO_RETURN_TYPE> 252 * 253 * @param ja This should be any instance of {@link JsonArray}. It is expected that the 254 * elements of this {@code JsonArray} are, themselves, {@code JsonObject's} 255 * 256 * @param rec <EMBED CLASS='external-html' DATA-FILE-ID=PJA_REC_PARAM> 257 * 258 * @return An instance of the type specified by Type-Parameter {@code 'RETURN_TYPE'} 259 * (explained above). 260 */ 261 public static <RETURN_TYPE> RETURN_TYPE joToJava( 262 final JsonArray ja, 263 final SettingsRec<JsonObject, RETURN_TYPE> rec 264 ) 265 { 266 final int SIZE = ja.size(); 267 JsonValue jv = null; 268 rec.ja = ja; 269 270 rec.opener.run(); 271 rec.acceptor.reset(); 272 273 for (int i=0; i < SIZE; i++) 274 275 switch ((jv = ja.get(i)).getValueType()) 276 { 277 // javax.json.JsonValue.ValueType.NULL 278 case NULL: rec.handlerNull.accept(i); break; 279 280 // javax.json.JsonValue.ValueType.OBJECT 281 case OBJECT: rec.acceptor.accept((JsonObject) jv, i); break; 282 283 // NUMBER, STRING, ARRAY, TRUE, FALSE 284 default: 285 286 if (rec.handlerWrongType != null) 287 rec.handlerWrongType.accept(i); 288 else 289 throw new JsonTypeArrException(ja, i, OBJECT, jv, rec.CLASS); 290 } 291 292 return rec.closer.get(); 293 } 294 295 /** 296 * Invoke this method in order to read an array of {@link JsonArray JsonArray's} 297 * 298 * @param <RETURN_TYPE> <EMBED CLASS='external-html' DATA-FILE-ID=PJA_JA_RETURN_TYPE> 299 * 300 * @param ja This should be any instance of {@link JsonArray}. It is expected that the 301 * elements of this {@code JsonArray} are, themselves, {@code JsonArray's} 302 * 303 * @param rec <EMBED CLASS='external-html' DATA-FILE-ID=PJA_REC_PARAM> 304 * 305 * @return An instance of the type specified by Type-Parameter {@code 'RETURN_TYPE'} 306 * (explained above). 307 */ 308 public static <RETURN_TYPE> RETURN_TYPE jaToJava( 309 final JsonArray ja, 310 final SettingsRec<JsonArray, RETURN_TYPE> rec 311 ) 312 { 313 final int SIZE = ja.size(); 314 JsonValue jv = null; 315 rec.ja = ja; 316 317 rec.opener.run(); 318 rec.acceptor.reset(); 319 320 for (int i=0; i < SIZE; i++) 321 322 switch ((jv = ja.get(i)).getValueType()) 323 { 324 // javax.json.JsonValue.ValueType.NULL 325 case NULL: rec.handlerNull.accept(i); break; 326 327 // javax.json.JsonValue.ValueType.OBJECT 328 case ARRAY: rec.acceptor.accept((JsonArray) jv, i); break; 329 330 // NUMBER, STRING, OBJECT, TRUE, FALSE 331 default: 332 333 if (rec.handlerWrongType != null) 334 rec.handlerWrongType.accept(i); 335 else 336 throw new JsonTypeArrException(ja, i, ARRAY, jv, rec.CLASS); 337 } 338 339 return rec.closer.get(); 340 } 341 342 343 // ******************************************************************************************** 344 // ******************************************************************************************** 345 // Synchronized Method Variants 346 // ******************************************************************************************** 347 // ******************************************************************************************** 348 349 350 /** 351 * <BR>Synchronized: Nothing More than a "Synchronized Wrapper" which can be used in a 352 * Multi-Threaded Programming-Environment. 353 * <BR>Wraps: Method {@link #numericToJava(JsonArray, SettingsRec)} 354 * <BR>Locking-Object: Input-Parameter {@code 'rec'}, the {@code SettingsRec} instance 355 * <BR>IMPORTANT: Synchronization <B><I>is only needed</I></B> when the {@code SettingsRec} 356 * instance shall be "re-used" in other threads. 357 * @see #numericToJava(JsonArray, SettingsRec) 358 */ 359 @IntoHTMLTable(background=BlueDither, title="Synchronized Variant of Method 'numericToJava'") 360 public static <NUMERIC_DATA_TYPE extends Number, RETURN_TYPE> RETURN_TYPE 361 numericToJavaSync( 362 final JsonArray ja, 363 final SettingsRec<NUMERIC_DATA_TYPE, RETURN_TYPE> rec 364 ) 365 { synchronized (rec) { return numericToJava(ja, rec); } } 366 367 /** 368 * <BR>Synchronized: Nothing More than a "Synchronized Wrapper" which can be used in a 369 * Multi-Threaded Programming-Environment. 370 * <BR>Wraps: Method {@link #booleanToJava(JsonArray, SettingsRec)} 371 * <BR>Locking-Object: Input-Parameter {@code 'rec'}, the {@code SettingsRec} instance 372 * <BR>IMPORTANT: Synchronizations <B><I>is only needed</I></B> when the {@code SettingsRec} 373 * instance shall be "re-used" in other threads. 374 * @see #booleanToJava(JsonArray, SettingsRec) 375 */ 376 @IntoHTMLTable(background=GreenDither, title="Synchronized Variant of Method 'booleanToJava'") 377 public static <RETURN_TYPE> RETURN_TYPE booleanToJavaSync( 378 final JsonArray ja, 379 final SettingsRec<Boolean, RETURN_TYPE> rec 380 ) 381 { synchronized (rec) { return booleanToJava(ja, rec); } } 382 383 /** 384 * <BR>Synchronized: Nothing More than a "Synchronized Wrapper" which can be used in a 385 * Multi-Threaded Programming-Environment. 386 * <BR>Wraps: Method {@link #objToJava(JsonArray, SettingsRec)} 387 * <BR>Locking-Object: Input-Parameter {@code 'rec'}, the {@code SettingsRec} instance 388 * <BR>IMPORTANT: Synchronizations <B><I>is only needed</I></B> when the {@code SettingsRec} 389 * instance shall be "re-used" in other threads. 390 * @see #objToJava(JsonArray, SettingsRec) 391 */ 392 @IntoHTMLTable(background=BlueDither, title="Synchronized Variant of Method 'objToJava'") 393 public static <T, RETURN_TYPE> RETURN_TYPE objToJavaSync( 394 final JsonArray ja, 395 final SettingsRec<T, RETURN_TYPE> rec 396 ) 397 { synchronized (rec) { return objToJava(ja, rec); } } 398 399 /** 400 * <BR>Synchronized: Nothing More than a "Synchronized Wrapper" which can be used in a 401 * Multi-Threaded Programming-Environment. 402 * <BR>Wraps: Method {@link #strToJava(JsonArray, SettingsRec)} 403 * <BR>Locking-Object: Input-Parameter {@code 'rec'}, the {@code SettingsRec} instance 404 * <BR>IMPORTANT: Synchronizations <B><I>is only needed</I></B> when the {@code SettingsRec} 405 * instance shall be "re-used" in other threads. 406 * @see #strToJava(JsonArray, SettingsRec) 407 */ 408 @IntoHTMLTable(background=GreenDither, title="Synchronized Variant of Method 'strToJava'") 409 public static <RETURN_TYPE> RETURN_TYPE strToJavaSync( 410 final JsonArray ja, 411 final SettingsRec<String, RETURN_TYPE> rec 412 ) 413 { synchronized (rec) { return strToJava(ja, rec); } } 414 415 /** 416 * <BR>Synchronized: Nothing More than a "Synchronized Wrapper" which can be used in a 417 * Multi-Threaded Programming-Environment. 418 * <BR>Wraps: Method {@link #joToJava(JsonArray, SettingsRec)} 419 * <BR>Locking-Object: Input-Parameter {@code 'rec'}, the {@code SettingsRec} instance 420 * <BR>IMPORTANT: Synchronizations <B><I>is only needed</I></B> when the {@code SettingsRec} 421 * instance shall be "re-used" in other threads. 422 * @see #joToJava(JsonArray, SettingsRec) 423 */ 424 @IntoHTMLTable(background=BlueDither, title="Synchronized Variant of Method 'joToJava'") 425 public static <RETURN_TYPE> RETURN_TYPE joToJavaSync( 426 final JsonArray ja, 427 final SettingsRec<JsonObject, RETURN_TYPE> rec 428 ) 429 { synchronized (rec) { return joToJava(ja, rec); } } 430 431 /** 432 * <BR>Synchronized: Nothing More than a "Synchronized Wrapper" which can be used in a 433 * Multi-Threaded Programming-Environment. 434 * <BR>Wraps: Method {@link #jaToJava(JsonArray, SettingsRec)} 435 * <BR>Locking-Object: Input-Parameter {@code 'rec'}, the {@code SettingsRec} instance 436 * <BR>IMPORTANT: Synchronizations <B><I>is only needed</I></B> when the {@code SettingsRec} 437 * instance shall be "re-used" in other threads. 438 * @see #jaToJava(JsonArray, SettingsRec) 439 */ 440 @IntoHTMLTable(background=GreenDither, title="Synchronized Variant of Method 'jaToJava'") 441 public static <RETURN_TYPE> RETURN_TYPE jaToJavaSync( 442 final JsonArray ja, 443 final SettingsRec<JsonArray, RETURN_TYPE> rec 444 ) 445 { synchronized (rec) { return jaToJava(ja, rec); } } 446 447 448}