001package Torello.Browser.JsonAST; 002 003import Torello.JavaDoc.Annotations.JDHeaderBackgroundImg; 004 005import Torello.Java.ReadOnly.ReadOnlyList; 006import Torello.Java.ReadOnly.ReadOnlySet; 007 008import Torello.Java.Additional.Ret2; 009import Torello.Java.Additional.Ret4; 010 011import Torello.Java.StrCSV; 012 013import javax.json.JsonObject; 014import javax.json.JsonArray; 015 016/** 017 * Root ancestor for all CDP JSON entities parsed from the protocol specs 018 * (<CODE>browser_protocol.json</CODE> and <CODE>js_protocol.json</CODE>). 019 * 020 * <EMBED CLASS='external-html' DATA-FILE-ID=AST_TREES> 021 * <EMBED CLASS="external-html" DATA-FILE-ID=Entity> 022 * 023 * @see TCE 024 * @see PPR 025 * @see PropName 026 * @see TypeProp 027 */ 028@JDHeaderBackgroundImg(EmbedTagFileID="AST_NODES_JDHBI") 029public abstract class Entity implements java.io.Serializable, Comparable<Entity> 030{ 031 // ******************************************************************************************** 032 // ******************************************************************************************** 033 // STATIC FINAL FIELDS 034 // ******************************************************************************************** 035 // ******************************************************************************************** 036 037 038 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ 039 protected static final long serialVersionUID = 1; 040 041 042 // ******************************************************************************************** 043 // ******************************************************************************************** 044 // Constant & Final Instance-Fields (Set by the Constructor) 045 // ******************************************************************************************** 046 // ******************************************************************************************** 047 048 049 /** 050 * Monotonic ID for this CDP entity used by {@code equals} and {@code hashCode}. 051 * <EMBED CLASS='external-html' DATA-FILE-ID=Entity.id> 052 */ 053 public final int id = IDManager.nextID(); 054 055 /** 056 * CDP domain that owns this entity (for example, {@code 'Network'} or {@code 'DOM'}). 057 * <EMBED CLASS='external-html' DATA-FILE-ID=Entity.ownerDomain> 058 */ 059 public final Domain ownerDomain; 060 061 /** 062 * Canonical CDP name for this entity. 063 * <EMBED CLASS='external-html' DATA-FILE-ID=Entity.name> 064 */ 065 public final String name; 066 067 /** 068 * Human-readable description of the CDP entity as specified in the protocol, by Google. 069 * <EMBED CLASS='external-html' DATA-FILE-ID=Entity.description> 070 */ 071 public final String description; 072 073 /** 074 * There are only two concrete subclasses of {@code Entity}: {@link PPR} and {@TCE}. 075 * <EMBED CLASS='external-html' DATA-FILE-ID=Entity.whichEntity> 076 */ 077 public final WhichEntity whichEntity; 078 079 /** 080 * List of all {@code JsonObject} property keys for this CDP item, as parsed from the 081 * {@code JsonObjet} from which this {@code Entity} instance was extracted. 082 * <EMBED CLASS='external-html' DATA-FILE-ID=Entity.propNames> 083 */ 084 public final ReadOnlyList<PropName> propNames; 085 086 /** 087 * The {@link JsonObject} {@code "type"} Property for this item as a strict enum. 088 * <EMBED CLASS='external-html' DATA-FILE-ID=Entity.typeProp> 089 */ 090 public final TypeProp typeProp; 091 092 /** 093 * Additional type, used when the {@link #typeProp} equals {@link TypeProp#ARRAY}. 094 * <EMBED CLASS='external-html' DATA-FILE-ID=Entity.arrItemsTypeProp> 095 */ 096 public final TypeProp arrItemsTypeProp; 097 098 /** 099 * True if this CDP item is optional. 100 * <EMBED CLASS='external-html' DATA-FILE-ID=Entity.optional> 101 */ 102 public final boolean optional; 103 104 /** 105 * True if this CDP item is marked experimental. 106 * <EMBED CLASS='external-html' DATA-FILE-ID=Entity.experimental> 107 */ 108 public final boolean experimental; 109 110 /** 111 * True if this CDP item is marked deprecated. 112 * <EMBED CLASS='external-html' DATA-FILE-ID=Entity.deprecated> 113 */ 114 public final boolean deprecated; 115 116 /** 117 * Allowed enumeration {@code String} values for this CDP item. 118 * <EMBED CLASS='external-html' DATA-FILE-ID=Entity.enumVals> 119 */ 120 public final ReadOnlyList<String> enumVals; 121 122 /** 123 * Comma-separated rendering of {@link #enumVals}, used to facilitate printing summaries. 124 * <EMBED CLASS='external-html' DATA-FILE-ID=Entity.enumValsStr> 125 */ 126 public final String enumValsStr; 127 128 /** 129 * Every {@code Entity} instance is parsed from a {@link JsonArray}; this is the array index. 130 * <EMBED CLASS='external-html' DATA-FILE-ID=Entity.index> 131 */ 132 public final int index; 133 134 135 // ******************************************************************************************** 136 // ******************************************************************************************** 137 // Constructor 138 // ******************************************************************************************** 139 // ******************************************************************************************** 140 141 142 Entity( 143 final Domain ownerDomain, 144 final WhichEntity which, 145 final JsonObject jo, 146 final int index, 147 final ReadOnlySet<String> extraAllowedJsonPropNames 148 ) 149 { 150 this.ownerDomain = ownerDomain; 151 this.whichEntity = which; 152 this.index = index; 153 154 155 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 156 // The complete list of Json-Properties contained by this object (at the top level) 157 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 158 // 159 // This is used inside the "exception location summry". This must be done first.. 160 this.name = Helper$Name.getName(this, jo); 161 162 163 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 164 // JsonException - Expected Keys 165 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 166 // 167 // Make sure we have looked at all the elements in the JsonObject 168 // If there are any we missed, throw an exception. 169 170 Helper$CheckKeys.entityCheck(this, jo, extraAllowedJsonPropNames); 171 172 173 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 174 // The complete list of Json-Properties contained by this object (at the top level) 175 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 176 177 this.propNames = Helper$Misc.getPropNames(jo); 178 179 180 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 181 // typeProp & arrItemsTypeProp 182 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 183 184 Ret2<TypeProp, TypeProp> ret2 = Helper$TypeProps.get(jo); 185 186 this.typeProp = ret2.a; 187 this.arrItemsTypeProp = ret2.b; 188 189 190 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 191 // this.description & FLAGS 192 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 193 194 final Ret4<String, Boolean, Boolean, Boolean> ret4 = Helper$Misc.getDescAndFlags(jo); 195 196 this.description = ret4.a; 197 this.optional = ret4.b; 198 this.experimental = ret4.c; 199 this.deprecated = ret4.d; 200 201 202 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 203 // An 'enum' property in the JsonObject / Entity 204 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 205 206 this.enumVals = Helper$Enum.getEnumPropertyOrNull(this, jo); 207 208 this.enumValsStr = (enumVals == null) 209 ? null 210 : StrCSV.toCSV(enumVals, (String s) -> ("\"" + s + "\""), true, null); 211 } 212 213 /** Helper method, used to print this node's vital information. */ 214 public final String exceptionLocationSummary() 215 { 216 return 217 "Node-Name: [" + this.name + "]\n" + 218 "Owner-Domain: [" + this.ownerDomain.name + "]\n" + 219 "WhichEntity: [" + this.whichEntity + "]\n" + 220 "Class-Name: [" + this.getClass().getSimpleName() + "]\n" + 221 "JsonArray Index: [" + this.index + "]\n"; 222 } 223 224 225 // The Type-Parameter "T" is a lesser-known trick to get around a (somewhat glaring) JDK / 226 // 'javac' bug. Initializing final variables mandates that all Code-Execution Paths assign 227 // some value to a final variable! This is required either inside of a constructor, and also 228 // for local final variables too! However, if one Code Execution Path ends with a method that 229 // is clearly guaranteed to throw an exception - as below - then 'javac' will flag an error 230 // saying that "variable [XXX] might not have been initialized." 231 // 232 // Place the word "throw" in front of the call to this method, and it will prevent that 233 // complaint. 234 235 final <T extends Throwable> T verifyThrow(final String message) 236 { 237 throw new ASTError 238 (message + '\n' + this.toString() + '\n' + this.exceptionLocationSummary()); 239 } 240 241 242 // ******************************************************************************************** 243 // ******************************************************************************************** 244 // Comparable, Object 245 // ******************************************************************************************** 246 // ******************************************************************************************** 247 248 249 /** Uses several pieces of information for generating a comparison value. */ 250 public final int compareTo(final Entity other) 251 { 252 if (this == other) return 0; 253 if (other == null) return 1; 254 255 if (this.ownerDomain.ownerAPI != other.ownerDomain.ownerAPI) 256 return this.ownerDomain.ownerAPI.name.compareTo 257 (other.ownerDomain.ownerAPI.name); 258 259 if (this.ownerDomain != other.ownerDomain) 260 return this.ownerDomain.name.compareTo(other.ownerDomain.name); 261 262 if (this.whichEntity != other.whichEntity) 263 return this.whichEntity.compareTo(other.whichEntity); 264 265 int c = this.name.compareTo(other.name); 266 267 return (c != 0) 268 ? c 269 : Integer.compare(this.hashCode(), other.hashCode()); 270 } 271 272 /** Returns the {@link #id} as a hash value. */ 273 public final int hashCode() 274 { return id; } 275 276 /** Checks that this {@link #id} is equal to {@code other.id}. */ 277 public final boolean equals(final Object other) 278 { 279 if (other == null) return false; 280 if (!(other instanceof Entity)) return false; 281 return this.id == ((Entity) other).id; 282 } 283}