001package Torello.Browser.JsonAST; 002 003import static Torello.Java.C.BRED; 004import static Torello.Java.C.BCYAN; 005import static Torello.Java.C.RESET; 006 007import Torello.Java.StorageWriter; 008import Torello.Java.ReadOnly.ReadOnlyList; 009import Torello.Java.ReadOnly.ReadOnlyArrayList; 010 011/** 012 * After parsing both API Spec-Files, each and every Json Property namem {@code "ref$"} needs to 013 * have it's {@code String} converted into a genuine {@link TCE} instance; this process is 014 * called <B>'Linking'</B> and it is identical to the linkng that the Java Compiler {@code javac} 015 * performs when converting variables & fields inside source files into class files. 016 * 017 * <EMBED CLASS='external-html' DATA-FILE-ID=LINKER> 018 */ 019@Torello.JavaDoc.Annotations.StaticFunctional 020@Torello.JavaDoc.Annotations.JDHeaderBackgroundImg(EmbedTagFileID="LINKER_JDHBI") 021public class Linker 022{ 023 private Linker() { } 024 025 static void run( 026 final StorageWriter sw, 027 final API browser, 028 final API js 029 ) 030 { 031 sw.println(BCYAN + "Run Linker on all Entities" + RESET); 032 Helper$FindDomain.initialize(browser, js); 033 034 // Primarily these two invocations are really quite crucial. 035 // These two lines set the fields "reference" and "referenceArray" for all PPR instances. 036 037 linkAllAPI(js); 038 linkAllAPI(browser); 039 040 sw.println(BRED + "DONE" + RESET + '\n'); 041 042 043 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 044 // Setting a PPR's "Computed Type as String" (and "as Byte") 045 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 046 // 047 // Of a "high importance" is remembering that the "Computed Type as String", and also the 048 // internal field "Computed Type as Byte" simply *MAY NOT BE SET* inside of class 'PPR' 049 // *UNTIL* the fields 'PPR.reference' and 'PPR.referenceArray' have been set. 050 // 051 // There are cases where the "Computed Type" will be something simple such as 052 // 'java.lang.String', However, there are also cases where the "Computed Type" of a PPR 053 // (Method-[P]arameter, Method-[R]eturns, or Type-[P]roperty) will be a reference to a type 054 // defined by CDP itself. 055 // 056 // The PPR's "Computed Type", when it is "STRING", could easily be converted to 057 // 'java.lang.String' when the PPR is constructed (and, therefore, done inside the 058 // constructor). Howver, the "Computed Type" is only *SOMETIMES* a simple or standard Java 059 // type like 'String' or 'int'. There are also situations where a PPR's computed type is 060 // some kind of actual Java POJO / Class. (Maybe the "Computed Type" is 061 // 'Network.AssociatedCookie', did you ever think of that one? Or maybe the PPR is: 062 // 'DOM.DetachedElementInfo') 063 // 064 // In those cases, thee "Computed Type as a String" cannot be done until *BOTH* its fields 065 // 'PPR.reference' and 'PPR.referenceArray' have been set. 066 // 067 // Note that the three lines directly above *THIS COMMENT* are doing exactly that! 068 // They are setting the PPR.reference & PPR.referenceArray fields! 069 // 070 // THUSLY... AND MOST IMPORTANTLY ... THESE THREE LINES (BELOW) *MUST* COME *AFTER* THE 071 // PREVIOUS THREE LINES. 072 // 073 // This concept has been encoded / hardcoded into an error-check & throw thingy that I added 074 // into the methods PPR.setCTAS(), PPR.setReference(), and PPR.setReferenceArray(). 075 076 sw.println(BCYAN + "Generate CTAS for All PPR's" + RESET); 077 PPR_CTAS.iterateSetCTAS(js); 078 PPR_CTAS.iterateSetCTAS(browser); 079 080 081 // NOTE: class TypeNode also has a "CTAS" ad a "CTAB" field. However, with Type's, there 082 // is a zero percent chance for a "type" to collapse into another CDP "type" 083 // 084 // That means that the CTAS / CTAB can be computed inside of the constructor... 085 // 086 // This is because they don't need to be "linked" in a way where the value needs to be 087 // computed after all of the constructors have completed building the POJO's... 088 // 089 // That meanns the CTAS / CTAB fields can actually be declared 'final' inside the class 090 // definitions themselves. 091 // 092 // That means "linking TypeNode's" doesn't actually happen. Only PPR's need to go through 093 // this literal hell. 094 095 sw.println(BRED + "DONE" + RESET); 096 } 097 098 private static void linkAllAPI(final API api) 099 { for (final Domain d : api.domains) linkDomain(d); } 100 101 private static void linkDomain(final Domain DOMAIN) 102 { 103 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 104 // The 'Domain.depAsStrs' ('dependencies' array). Unused, but accounted for 105 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 106 // 107 // Domain's MIGHT / POSSIBLY have a 'dependencies' String Array. 108 // If they do, convert the dependency as a STRING to a REFERENCE. 109 // 110 // NOTE: this 'dependencies' is not used anywhere in the code of my Code-Generator 111 // The only reason I'm "linking" this Domain.dependencies field is because it exists, 112 // and perhaps one day me or somebody else will find a use for it. For now, this is 113 // extracted out of the Domain's JSON Definition, but it is totally ignored and 114 // unused! 115 // 116 // Afterwards, there is some simple error checking. It just ascertains whether or not the 117 // linker code above, actually succeded in linking all of the `Domain.depAsStrs` Strings 118 // from 'java.lang.String' into instances of 'JsonAST.Domain' 119 // 120 // MOST IMPORTANT NOTE OF ALL: 121 // This little loop and this little check are completely superfluous. These fields 122 // are not used anywhere by the AST (this package - Torello.Browser.JsonAST), nor are 123 // they used by the Code Generator classes (Torello.Browser.CodeGenerator) 124 // 125 // Inside of the '.json' files which define this API, each Domain has a short little 126 // list of "other domains" upon which "this domain" depends. It is essentially 127 // identical to a class in 'java.util' - for instance 'java.util.ArrayList' doing an 128 // import of somethign from 'java.util.regex' (or something like that) 129 // 130 // The only issue is, because Google Chrome and the Browser treat each "Domain" as a 131 // "separate Package" and because I place all domains from a single API into the same 132 // exact Java Package - I neither know nor care what is in the field 133 // 'Domain.dependencies' 134 // 135 // Link it from a String to reference. Get it over with. Fix it and forget it. 136 // Perhaps one day this will be used, but that day is not today. 137 138 final ReadOnlyList<Domain> dependencies = new ReadOnlyArrayList<Domain>( 139 DOMAIN.depAsStrs, 140 (String s) -> Helper$FindDomain.find(s), 141 DOMAIN.depAsStrs.size() 142 ); 143 144 for (int i=0; i < dependencies.size(); i++) 145 if (dependencies.get(i) == null) 146 throw new Error("Unknown Domain Dependency: " + DOMAIN.depAsStrs.get(i)); 147 148 DOMAIN.setDependencies(dependencies); 149 150 151 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 152 // Now Iterate all of the TCE's in this Domain, and run the linker on each of them 153 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 154 155 for (final TypeNode type : DOMAIN.types) 156 if (type.properties != null) 157 for (final PPR field : type.properties) 158 linkAllPPR(field); 159 160 for (final EventNode type : DOMAIN.events) 161 if (type.parameters != null) 162 for (final PPR field : type.parameters) 163 linkAllPPR(field); 164 165 for (final CommandNode command : DOMAIN.commands) 166 { 167 if (command.parameters != null) 168 for (final PPR param : command.parameters) linkAllPPR(param); 169 170 if (command.returns != null) 171 for (final PPR retVal : command.returns) linkAllPPR(retVal); 172 173 if (command.redirect != null) linkCommandNodeRedirect(command); 174 } 175 } 176 177 178 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 179 // CommandNode "redirect" (**COMPLETELY UNUSED** in my code - but maintained / accounted for) 180 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 181 // 182 // IF YOU THINK THE "Domain.dependencies" field is completely ignored, unused and serves no 183 // purpose in my code. 184 // 185 // You should try laying around and wondering whether or not the "redirectDomain" has any 186 // bearing on the Code Generator... Guess what? The answer is "NO!" 187 // 188 // It is really *REALLY* easy to link this "Domain as a String" into a "Domain as a Reference" 189 // or "pointer". So I go ahead and do that here. Do I use it? ... No way! 190 191 private static void linkCommandNodeRedirect(final CommandNode cn) 192 { 193 // Resolve 'redirect' from a java.lang.String, into a 'Domain' reference. 194 final Domain redirectDomain = Helper$FindDomain.find(cn.redirect); 195 196 // Error Checking 197 if (redirectDomain == null) throw new ASTError( 198 "Unknown redirect domain: [" + cn.redirect + "]\n" + 199 "For TCE:\n" + cn.toString() + '\n' + 200 "at:\n" + 201 cn.exceptionLocationSummary() 202 ); 203 204 cn.setRedirectDomain(redirectDomain); 205 } 206 207 208 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 209 // link PPR 210 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 211 // 212 // THIS CODE IS, HOWEVER, IS THE PRIMARY PURPOSE OF THIS FILE - (see above, although this 213 // "setCTAS" is also really important) 214 215 private static void linkAllPPR(final PPR ppr) 216 { 217 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 218 // HERE IT IS: PPR.setReference(...) 219 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 220 221 if (ppr.ref != null) 222 ppr.setReference(Helper$FindTypeNode.find(ppr, ppr.ref)); 223 224 225 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 226 // HERE IT IS TOO: PPR.setReferenceArray(...) 227 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 228 229 if (ppr.refArray != null) 230 ppr.setReferenceArray(Helper$FindTypeNode.find(ppr, ppr.refArray)); 231 } 232} 233