001package Torello.Java.JSON; 002 003import Torello.Java.StringParse; 004 005import java.util.Vector; 006import java.lang.reflect.Parameter; 007import java.io.StringWriter; 008import javax.json.Json; 009import javax.json.stream.JsonGenerator; 010 011/** 012 * Generates JSON Requests from lists of Parameter-Names, Parameter-Types and Parameter-Values. 013 * 014 * <BR /><BR /><EMBED CLASS='external-html' DATA-FILE-ID=WRITE_JSON> 015 */ 016@Torello.JavaDoc.StaticFunctional 017@Torello.JavaDoc.JDHeaderBackgroundImg(EmbedTagFileID="JSON_SERIALIZER_JDHBI") 018public class WriteJSON 019{ 020 // This is a "Static" class (static functional) 021 private WriteJSON() { } 022 023 /** 024 * Converts a list of class types, names & values into a Json Request, as a {@code String} 025 * 026 * @param paramTypes These are the types being passed to the JSON Request. 027 * 028 * @param paramNames These are the names of the parameters, and these are used for the names 029 * of the JSON parameters passed. 030 * 031 * @param optionals This is a boolean array that indicates which parameter-values are allowed 032 * to be null. 033 * 034 * @param methodName The name of the command being passed over the Web-Socket Connection. 035 * 036 * @return Returns the JSON Web-Socket Request as a {@code java.lang.String} 037 */ 038 public static String get( 039 Vector<Class<?>> paramTypes, Vector<String> paramNames, boolean[] optionals, 040 int webSocketID, String methodName, Object... paramValues 041 ) 042 { 043 StringWriter strW = new StringWriter(); 044 JsonGenerator jGen = Json.createGenerator(strW); 045 046 jGen.writeStartObject() 047 .write("id", webSocketID) 048 .write("method", methodName); 049 050 if (paramTypes.size() > 0) 051 { 052 Vector<Object> oVec = new Vector<>(); 053 for (Object o : paramValues) oVec.add(o); 054 055 jGen.writeStartObject("params"); 056 get(jGen, paramTypes, paramNames, oVec, optionals); 057 jGen.writeEnd(); 058 } 059 // else jGen.writeNull("params"); // Is this the right idea? 060 061 jGen.writeEnd(); 062 jGen.close(); 063 064 return strW.toString(); 065 } 066 067 /** 068 * Converts a list of class types, names & values into a series of Json-Generator commands. 069 * 070 * @param jGen Because this method may be used recursively, the current generator that is being 071 * used must be passed to this method. 072 * 073 * @param cVec The list of types for each entity being converted to a Json Request. 074 * @param nVec The list of names for each entity being converted to a Json Request. 075 * @param oVec The list of values for each entity being converted to a Json Request. 076 * @param optArr A {@code boolean[]} array indicating which parameters may be null. 077 */ 078 public static void get( 079 JsonGenerator jGen, Vector<Class<?>> cVec, Vector<String> nVec, Vector<Object> oVec, 080 boolean[] optArr 081 ) 082 { 083 for (int k=0; k < nVec.size(); k++) 084 { 085 boolean opt = optArr[k]; 086 Class<?> c = cVec.elementAt(k); 087 String n = nVec.elementAt(k); 088 Object o = oVec.elementAt(k); 089 090 if (o == null) 091 { 092 if (! opt) throw new Error( 093 "The Operating Assertion is that if a Field is null in this class, it must " + 094 "have been declared 'optional.' Field [" + n + "] is null, but not optional." 095 ); 096 097 else continue; // Just leave off of the JSON Completely! 098 } 099 100 switch (c.getSimpleName()) 101 { 102 case "int" : 103 case "Integer" : jGen.write(n, ((Integer) o).intValue()); break; 104 case "boolean" : 105 case "Boolean" : jGen.write(n, ((Boolean) o).booleanValue()); break; 106 case "String" : jGen.write(n, (String) o); break; 107 108 case "Number" : 109 if (o instanceof Long) jGen.write(n, ((Long) o).longValue()); 110 else jGen.write(n, ((Double) o).doubleValue()); 111 break; 112 113 case "int[]" : 114 jGen.writeStartArray(n); 115 for (int i : (int[]) o) jGen.write(i); 116 jGen.writeEnd(); 117 break; 118 119 case "boolean[]" : 120 jGen.writeStartArray(n); 121 for (boolean b : (boolean[]) o) jGen.write(b); 122 jGen.writeEnd(); 123 break; 124 125 case "String[]" : 126 jGen.writeStartArray(n); 127 for (String s : (String[]) o) 128 if (s == null) jGen.writeNull(); 129 else jGen.write(s); 130 jGen.writeEnd(); 131 break; 132 133 case "Number[]" : 134 jGen.writeStartArray(n); 135 for (Number num : (Number[]) o) 136 if (num == null) jGen.writeNull(); 137 else if (num instanceof Long) jGen.write(n, ((Long) num).longValue()); 138 else jGen.write(n, ((Double) num).doubleValue()); 139 jGen.writeEnd(); 140 break; 141 142 case "int[][]" : 143 jGen.writeStartArray(n); 144 for (int[] iArr : (int[][]) o) 145 { 146 jGen.writeStartArray(); 147 for (boolean b : (boolean[]) o) jGen.write(b); 148 jGen.writeEnd(); 149 } 150 jGen.writeEnd(); 151 break; 152 153 case "boolean[][]" : 154 jGen.writeStartArray(n); 155 for (int[] iArr : (int[][]) o) 156 { 157 jGen.writeStartArray(); 158 for (boolean b : (boolean[]) o) jGen.write(b); 159 jGen.writeEnd(); 160 } 161 jGen.writeEnd(); 162 break; 163 164 case "String[][]" : 165 jGen.writeStartArray(n); 166 for (String[] sArr : (String[][]) o) 167 { 168 jGen.writeStartArray(); 169 for (String s : (String[]) o) 170 if (s == null) jGen.writeNull(); 171 else jGen.write(s); 172 jGen.writeEnd(); 173 } 174 jGen.writeEnd(); 175 break; 176 177 178 case "Number[][]" : 179 jGen.writeStartArray(n); 180 NUM_ARR: 181 for (Number[] sArr : (Number[][]) o) 182 { 183 if (sArr == null) 184 { jGen.writeNull(); continue NUM_ARR; } 185 186 jGen.writeStartArray(); 187 for (Number num : (Number[]) o) 188 if (num == null) jGen.writeNull(); 189 else if (num instanceof Long) jGen.write(n, ((Long) num).longValue()); 190 else jGen.write(n, ((Double) num).doubleValue()); 191 jGen.writeEnd(); 192 } 193 jGen.writeEnd(); 194 break; 195 196 default: 197 if (c.isArray()) 198 { 199 if (! BaseType.class.isAssignableFrom(c.getComponentType())) 200 throw new Error( 201 "One of the Fields [" + n + "] is declared an array, " + 202 "(type " + c.getSimpleName() + "), but the Array Elements do " + 203 "not implement the interface 'BaseType'" 204 ); 205 206 if (StringParse.countCharacters(c.getSimpleName(), '[') > 1) 207 throw new Error( 208 "One of the Fields [" + n + "] is declared an array, " + 209 "(type " + c.getSimpleName() + "), but the Array has a dimension " + 210 "greater than 1. This was agreed, impossible." 211 ); 212 213 jGen.writeStartArray(n); 214 for (BaseType bt : (BaseType[]) o) 215 if (bt == null) jGen.writeNull(); 216 else bt.toJSON(null, jGen); 217 jGen.writeEnd(); 218 } 219 else 220 { 221 if (! BaseType.class.isAssignableFrom(c)) throw new Error( 222 "Field [" + n +"] has a class / type [" + c.getSimpleName() + "], " + 223 "but this class does not implement the interface BaseType!" 224 ); 225 226 else ((BaseType) o).toJSON(n, jGen); 227 } 228 } 229 } 230 } 231}