001package Torello.JSON; 002 003import Torello.Java.StringParse; 004import Torello.Java.UnreachableError; 005 006import Torello.Java.Additional.Counter; 007 008import java.lang.reflect.Array; 009 010import java.util.function.Function; 011import java.util.function.ObjIntConsumer; 012 013import java.util.stream.Stream; 014import java.util.stream.IntStream; 015import java.util.stream.LongStream; 016import java.util.stream.DoubleStream; 017 018import javax.json.JsonArray; 019import javax.json.JsonValue; 020 021import static javax.json.JsonValue.ValueType.*; 022 023@Torello.JavaDoc.Annotations.StaticFunctional 024public class GENERATE_1DARRAY 025{ 026 private GENERATE_1DARRAY() { } 027 028 029 // @SuppressWarnings({"unchecked", "rawtypes"}) 030 @SuppressWarnings("unchecked") 031 static <T> Function<JsonArray, Object> retrieveAppropriateGenerator( 032 final SettingsRec<?, ?> rec, 033 final BASIC_TYPES<T> bt, 034 final boolean boxedOrPrimitive 035 ) 036 { 037 switch (bt.whichType) 038 { 039 case BASIC_TYPES.INTEGER: return boxedOrPrimitive 040 041 ? (JsonArray ja) -> ProcessJsonArray 042 .numericToJava(ja, (SettingsRec<Integer, Stream<Integer>>) rec) 043 .toArray(Integer[]::new) 044 045 : (JsonArray ja) -> ProcessJsonArray 046 .numericToJava(ja, (SettingsRec<Integer, IntStream>) rec) 047 .toArray(); 048 049 050 case BASIC_TYPES.SHORT: return boxedOrPrimitive 051 052 ? (JsonArray ja) -> ProcessJsonArray 053 .numericToJava(ja, (SettingsRec<Short, Stream<Short>>) rec) 054 .toArray(Short[]::new) 055 056 : (JsonArray ja) -> 057 array1DGeneratorShort(ja, (SettingsRec<Short, Stream<Short>>) rec); 058 059 060 case BASIC_TYPES.BYTE: return boxedOrPrimitive 061 062 ? (JsonArray ja) -> ProcessJsonArray 063 .numericToJava(ja, (SettingsRec<Byte, Stream<Byte>>) rec) 064 .toArray(Byte[]::new) 065 066 : (JsonArray ja) -> 067 array1DGeneratorByte(ja, (SettingsRec<Byte, Stream<Byte>>) rec); 068 069 070 case BASIC_TYPES.LONG: return boxedOrPrimitive 071 072 ? (JsonArray ja) -> ProcessJsonArray 073 .numericToJava(ja, (SettingsRec<Long, Stream<Long>>) rec) 074 .toArray(Long[]::new) 075 076 : (JsonArray ja) -> ProcessJsonArray 077 .numericToJava(ja, (SettingsRec<Long, LongStream>) rec) 078 .toArray(); 079 080 081 case BASIC_TYPES.DOUBLE: return boxedOrPrimitive 082 083 ? (JsonArray ja) -> ProcessJsonArray 084 .numericToJava(ja, (SettingsRec<Double, Stream<Double>>) rec) 085 .toArray(Double[]::new) 086 087 : (JsonArray ja) -> ProcessJsonArray 088 .numericToJava(ja, (SettingsRec<Double, DoubleStream>) rec) 089 .toArray(); 090 091 092 case BASIC_TYPES.FLOAT: return boxedOrPrimitive 093 094 ? (JsonArray ja) -> ProcessJsonArray 095 .numericToJava(ja, (SettingsRec<Float, Stream<Float>>) rec) 096 .toArray(Float[]::new) 097 098 : (JsonArray ja) -> 099 array1DGeneratorFloat(ja, (SettingsRec<Float, Stream<Float>>) rec); 100 101 102 case BASIC_TYPES.BOOLEAN: return boxedOrPrimitive 103 104 ? (JsonArray ja) -> ProcessJsonArray 105 .booleanToJava(ja, (SettingsRec<Boolean, Stream<Boolean>>) rec) 106 .toArray(Boolean[]::new) 107 108 : (JsonArray ja) -> 109 array1DGeneratorBoolean(ja, (SettingsRec<Boolean, Stream<Boolean>>) rec); 110 111 112 case BASIC_TYPES.NUMBER: 113 114 return (JsonArray ja) -> ProcessJsonArray 115 .numericToJava(ja, (SettingsRec<Number, Stream<Number>>) rec) 116 .toArray(Number[]::new); 117 118 119 case BASIC_TYPES.STRING: 120 121 return (JsonArray ja) -> ProcessJsonArray 122 .strToJava(ja, (SettingsRec<String, Stream<String>>) rec) 123 .toArray(String[]::new); 124 125 126 case BASIC_TYPES.EXTENDED_OBJ: 127 128 return (JsonArray ja) -> ProcessJsonArray 129 .objToJava(ja, (SettingsRec<T, Stream<T>>) rec) 130 .toArray((int length) -> (T[]) Array.newInstance(rec.CLASS, length)); 131 132 default: throw new UnreachableError(); 133 } 134 } 135 136 137 // Converts a Java Boxed Stream to a Primitive Array. 138 static <T, U> U boxedStreamToPrimitiveArray( 139 final Stream<T> boxedStream, 140 final JsonArray ja, 141 final Class<T> returnClass, 142 final ObjIntConsumer<T> arrayBuilder, 143 final U retArr 144 ) 145 { 146 // Since the array-index is used inside of a LAMBDA, this "EffectivelyFinal" counter 147 // class becomes necessary. 148 149 final Counter counter = new Counter(-1); 150 151 152 // Don't forget, Stream's are not guaranteed to be processed in order, unless an 153 // explicit request is made using something like 'forEachOrdered' 154 155 boxedStream.forEachOrdered((T boxedPrimitive) -> 156 { 157 final int i = counter.addOne(); // "Final, or Effectively Final" 158 159 // A Primitive-Array (like int[], long[], boolean[] etc...) may not have null 160 if (boxedPrimitive == null) 161 throw new JsonNullPrimitiveArrException(ja, i, NUMBER, returnClass); 162 163 // The 'arrayBuilder' just assigns the value to the array[i] 164 arrayBuilder.accept(boxedPrimitive, i); 165 }); 166 167 return retArr; 168 } 169 170 171 // REMEMBER: The 1-D Arrays ==> int[], long[], double[] are built directly from a 172 // PrimitiveStream using PrimStream.toArray, they don't need a "helper" 173 174 175 // @SuppressWarnings({"rawtypes", "unchecked"}) 176 private static short[] array1DGeneratorShort( 177 final JsonArray ja, 178 final SettingsRec<Short, Stream<Short>> rec 179 ) 180 { 181 final short[] retArrShort = new short[ja.size()]; 182 183 return boxedStreamToPrimitiveArray( 184 ProcessJsonArray.numericToJava(ja, rec), 185 ja, 186 short.class, 187 (Short s, int i) -> retArrShort[i] = s.shortValue(), 188 retArrShort 189 ); 190 } 191 192 193 // @SuppressWarnings({"rawtypes", "unchecked"}) 194 private static byte[] array1DGeneratorByte( 195 final JsonArray ja, 196 final SettingsRec<Byte, Stream<Byte>> rec 197 ) 198 { 199 final byte[] retArrByte = new byte[ja.size()]; 200 201 return boxedStreamToPrimitiveArray( 202 ProcessJsonArray.numericToJava(ja, rec), 203 ja, 204 byte.class, 205 (Byte s, int i) -> retArrByte[i] = s.byteValue(), 206 retArrByte 207 ); 208 } 209 210 211 // @SuppressWarnings({"rawtypes", "unchecked"}) 212 private static float[] array1DGeneratorFloat( 213 final JsonArray ja, 214 final SettingsRec<Float, Stream<Float>> rec 215 ) 216 { 217 final float[] retArrFloat = new float[ja.size()]; 218 219 return boxedStreamToPrimitiveArray( 220 ProcessJsonArray.numericToJava(ja, rec), 221 ja, 222 float.class, 223 (Float s, int i) -> retArrFloat[i] = s.floatValue(), 224 retArrFloat 225 ); 226 } 227 228 229 // @SuppressWarnings({"rawtypes", "unchecked"}) 230 private static boolean[] array1DGeneratorBoolean( 231 final JsonArray ja, 232 final SettingsRec<Boolean, Stream<Boolean>> rec 233 ) 234 { 235 final boolean[] retArrBoolean = new boolean[ja.size()]; 236 237 return boxedStreamToPrimitiveArray( 238 ProcessJsonArray.booleanToJava(ja, rec), 239 ja, 240 boolean.class, 241 (Boolean s, int i) -> retArrBoolean[i] = s.booleanValue(), 242 retArrBoolean 243 ); 244 } 245 246}