001package Torello.Browser.JsonAST; 002 003import Torello.JSON.ReadJSON; 004 005import Torello.Java.Additional.Ret2; 006 007import javax.json.JsonObject; 008 009/** 010 * Extracts the Json Property {@code "type"} from the {@link JsonObject} which defines an 011 * {@link Entity} instance, and converts that {@code String} into an instance of {@link TypeProp}. 012 * This class also extracts, if present, the {@code "type"} property from within an {@code "items"} 013 * {@code JsonObject}. These (the second) {@code "type"} are used <B STYLE='color:red;'><I>if and 014 * only if</B></I> the first {@code "type"} has a value of {@link TypeProp#ARRAY "array"}, and 015 * subsequently requires a definition for the Array's Base-Component Class. 016 * 017 * <BR /><BR />The only values which are ever assigned to the Json {@code "type"} property will 018 * directly correspond to one of the enum constants listed inside the {@link TypeProp} enum. 019 * It is of utmost important to remember, that if a {@link PPR} has a "Type" that is actually one 020 * of the specified types from the spec files (rather than something simple like {@code 'integer'} 021 * or {@code 'string'}), that {@code PPR} will not even use the Json {@code "type"} property. 022 * 023 * <BR /><BR />Instead, the {@code "$ref"} property will contain a "Reference as a String" (which 024 * will later require linkinig) that gives the name of the class / type of which the {@code PPR} 025 * is a reference. 026 */ 027@Torello.JavaDoc.Annotations.StaticFunctional 028@Torello.JavaDoc.Annotations.JDHeaderBackgroundImg(EmbedTagFileID="CONSTRUCTOR_JDHBI") 029public class Helper$TypeProps 030{ 031 private Helper$TypeProps() { } 032 033 private static final Ret2<TypeProp, TypeProp> EMPTY_RET2 = new Ret2<>(null, null); 034 035 static Ret2<TypeProp, TypeProp> get(final JsonObject jo) 036 { 037 // getString(JsonObject jo, String propertyName, boolean isOptional, boolean throwOnNull) 038 final String typePropStr = ReadJSON.getString(jo, "type", true, true); 039 040 041 // If there is no "type" Json-Property, then there is a zero 0% chance that there is going 042 // to be an "items" Json-Property. As such, if 'typePropStr' is null, return 2 nulls 043 // immediately. 044 045 if (typePropStr == null) return EMPTY_RET2; 046 047 // Conver the "type" String into an insance of the TypeProp enum.... 048 final TypeProp typeProp = TypeProp.valueOf(typePropStr.toUpperCase()); 049 050 051 // Similar to before, but ... Here, if there did happen to be a "type" Json Property, 052 // unless that "type" equaled the String "array", then there (again) is a zero 0% chance 053 // that there is going to be an "items" Json-Property. If it was something other than 054 // "array", return the first TypeProp enum instance immediately, and null for the items 055 // TypeProp instance. 056 057 if (typeProp != TypeProp.ARRAY) return new Ret2<>(typeProp, null); 058 059 060 // Here, if this line of code is reached, then the "items" Json Property is not goingt to 061 // be optional. This ReadJSON invocation will throw an exception if the "items" property 062 // isn't available inside the input JsonObject / 'jo' instance. 063 // 064 // getJsonObject(JsonObject, String propertyName, boolean isOptional, boolean throwOnNull) 065 066 final JsonObject arrItemsProp = ReadJSON.getJsonObject(jo, "items", false, true); 067 068 069 // Lastly, now that we have the "items" Json Property, which is actually another / inner 070 // JsonObject, we need to extract the contents of this JsonObject. This inner JO, which is 071 // being called "arrItemsProp" may have exactly one of two different Json Properties 072 // itself. They are: 073 // 074 // 1) "type": "some-type" 075 // 2) "$ref": "some-TypeNode-Name" 076 // 077 // If the caller of this method is a constructor for a PPR, then this "items" Json-Object 078 // could just as easily be a "$ref" array, as it could be a "type" array. If the caller of 079 // this method is a TypeNode, it would only be possible for this "items" Json-Object to be 080 // a 'jo' that contains a "type" property, itself. TypeNode TCE's may not be declared as 081 // array's of references. Only PPR's may have array's of references. 082 // 083 // In such cases, if the "items" 'jo' isn't an object that has a "type" Json-Property, then 084 // by definition it must have a "$ref" Json-Property instead. This is where an 'Entity' is 085 // being declared as an array of some other declared type. If this were Java instead of 086 // JSON, it would be like declaring an array of some Java-Class, rather than a primitive 087 // array such as 'int[]' or 'boolean[]' 088 // 089 // If the Entity is an array of "$ref", then we need to just return null in place of the 090 // 2nd TypeProp Parameter. This is going to be done intentionally. What this actually 091 // means is that if an "Entity" - which is the Root Object Inheritance Class for all AST 092 // Nodes - is declared as an "array", but the "component class" (Java calls the class about 093 // which an array is declared as the "component" class) is an actual object rather than a 094 // primitive, then that component class is going to be extracted and computed by another 095 // constructor, elswhere in this package's source code. 096 // 097 // This is because there is only, single, kind of AST Node that is permitted to declare 098 // array's of references - PPR Nodes. If a TCE is declared as an "array", it must be a 099 // "simple array" - using one of types that are listed in the "TypeProp" enum. 100 // 101 // *** NOTE: The TypeProp 'enum' is **NEARLY** but not identical to Java-Primitives. 102 // 103 // 1) First, Java Class 'java.lang.String' is one of the types listed in TypeProp - which 104 // is not a Java-Primitive, but it is treated like a "Simple Type" - not a 105 // Reference-Type in this package. In the JsonAST Package "Reference Types" are types 106 // which point to ANOTHER DECLARED TYPE FROM THIS VERY JSON-AST TREE! 107 // 108 // For Example: In the "JavaScript API", inside the "RunTime Domain", there is a type 109 // called "RunTime.RemoteObject" - **THAT** would be a "$ref" type. 110 // A PPR whose "type" was "RunTime.RemoteObject[]" would be a reference array 111 // While a PPR whose Type was "String[]" would be treated like a simple array 112 // 113 // 2) Second, class "Number" does not directly map to a Java Primitive. It is unknown 114 // whether a browser which is connected over the Web-Sockets will switch back and forth 115 // between "integer" and "float" types. However, if the specifications JSON File 116 // declares a PPR to be a "number" rather than an "integer", such a declaration is 117 // treated as if the browser may return either an integer or a real number. 118 // 119 // As such, the Java Boxed-Type "Number" is used, which allows for both class 120 // 'java.lang.Integer' and also 'java.lang.Double'. The Java-HTML 'ReadJSON' package' 121 // ReadJSON class is good about figuring out which of the two to return. 122 // 123 // 124 // getString(JsonObject jo, String propertyName, boolean isOptional, boolean throwOnNull) 125 // PAY CLOSE ATTENTION: 'isOption' ==> TRUE (won't throw if this Json-Property is missing) 126 127 final String arrType = ReadJSON.getString(arrItemsProp, "type", true, true); 128 129 130 // If It was missing, just leave it off. The PPR Construtor will look for a "$ref" 131 // Property instead. It will even throw there if there also happens to not be a "$ref" 132 // property inside the "items" Json Object either! 133 134 if (arrType == null) return new Ret2<>(typeProp, null); 135 136 // It wasn't null, so there was a "type" property inside the "items" Json Object. 137 final TypeProp arrTypeProp = TypeProp.valueOf(arrType.toUpperCase()); 138 139 return new Ret2<>(typeProp, arrTypeProp); 140 } 141 142}