001package Torello.JavaDoc; 002 003 004// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 005// Standard-Java Imports 006// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 007 008import java.io.IOException; 009import java.util.Optional; 010 011 012// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 013// Java-HTML Imports 014// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 015 016import Torello.Java.*; 017 018import static Torello.Java.C.*; 019import static Torello.JavaDoc.PF.*; 020 021import Torello.Java.ReadOnly.ReadOnlyList; 022import Torello.Java.ReadOnly.ROArrayListBuilder; 023 024 025// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 026// JDUInternal 027// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 028 029import Torello.JDUInternal.Annotations.EntityAnnotations.EntityAnnotationData; 030 031 032// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 033// The new Source-Code Parser: com.sun.source.* 034// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 035 036import com.sun.source.tree.Tree; 037import com.sun.source.tree.VariableTree; 038import com.sun.source.tree.ExpressionTree; 039 040 041/** 042 * <B CLASS=JDDescLabel>Reflection Class:</B> 043 * 044 * <BR />Holds all information extracted from <CODE>'.java'</CODE> Source-Files about Field's 045 * identified in that file. 046 * 047 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_GET_INST> 048 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_FIELD> 049 */ 050@JDHeaderBackgroundImg(EmbedTagFileID={"REFLECTION_EXTENSION"}) 051public class Field extends Declaration 052 implements java.io.Serializable, Comparable<Field>, Cloneable 053{ 054 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ 055 protected static final long serialVersionUID = 1; 056 057 @Override 058 String codeHiLiteString() { return this.signature; } 059 060 061 // ******************************************************************************************** 062 // ******************************************************************************************** 063 // Public Fields: The Type, and the Initializer 064 // ******************************************************************************************** 065 // ******************************************************************************************** 066 067 068 /** The definition of this field, as a {@code String}. */ 069 public final String definition; 070 071 /** The type / class of this field, as a {@code String}. */ 072 public final String type; 073 074 /** 075 * The type / class of this field, as a {@code String}. 076 * <BR /><BR /> 077 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_JOW_TITLE> 078 */ 079 public final String typeJOW; 080 081 082 // ******************************************************************************************** 083 // ******************************************************************************************** 084 // Reference-Hook: com.sun.source.tree 085 // ******************************************************************************************** 086 // ******************************************************************************************** 087 088 089 /** 090 * <EMBED CLASS='external-html' DATA-FILE-ID=SSTB_HOOK_FIELD> 091 * 092 * If a user decides to make use of the native Oracle {@code VariableTree}-Instance that 093 * was used to build this {@code Field}-Instance, the {@code VariableTree} may be retrieved 094 * from this {@code transient} field. 095 */ 096 public final transient VariableTree variableTree; 097 098 099 // ******************************************************************************************** 100 // ******************************************************************************************** 101 // Constructor - com.sun.source.tree 102 // ******************************************************************************************** 103 // ******************************************************************************************** 104 105 106 // Public, but internally-used-only Constructor for "Field" 107 public Field( 108 final VariableTree vt, 109 final EntityAnnotationData ead, 110 final TreeUtils util 111 ) 112 { 113 super( 114 ead, // Stuff for building EntityAnnotationMirrors 115 util, // TreeUtils instance (contains all the parser and stuff) 116 vt, // 'Tree' instance 117 vt.getModifiers(), // ModifiersTree: Annotations on the Field & key-words 118 vt.getName().toString(), // Name of the Field 119 Entity.FIELD, // Entity 120 vt.getInitializer() // NEW: Pass the initializer to the 'body' tree-node 121 ); 122 123 this.type = vt.getType().toString(); 124 this.typeJOW = StrSource.typeToJavaIdentifier(this.type); 125 126 ExpressionTree initializer = vt.getInitializer(); 127 128 this.definition = (initializer == null) ? null : util.substring(initializer).trim(); 129 130 // Reference Hook: This was built using the com.sun.source.tree.VariableTree class 131 this.variableTree = vt; 132 } 133 134 135 // ******************************************************************************************** 136 // ******************************************************************************************** 137 // Constructor: Used Internally by SignatureParse 138 // ******************************************************************************************** 139 // ******************************************************************************************** 140 141 142 // Ensures that the Version with longer type-information strings is used. 143 // Java Doc often uses longer type strings than is available from the source-code parse 144 // Remember, JavaParser Symbol-Solver doesn't work well, and the Sun/Oracle Parser doesn't have 145 // a linker at all. 146 // 147 // Intended for JDU Internal-Use-Only 148 149 public Field(final Field fFromSourceParser, final Field fFromHTMLParser) 150 { 151 // Calls the super 'clone' constructor for Declaration 152 // Java Parser has much more information for everything, except the "Type" 153 // JP elects to leave off the "Package Information" for types - while Java Doc includes 154 // it (**unless** it can provide an <A HREF=...> for the type, then it leaves it off too!) 155 156 super(fFromSourceParser); 157 158 // Continuing with: "JP has this info", while Java Doc just leaves this blank. 159 this.definition = fFromSourceParser.definition; 160 161 // Java Doc always produces "java.lang.String", while JP just gives "String" 162 /// 163 // REMEMBER: JP is lazy when it comes to "Package Information" for types. 164 // Java-Doc includes it often - BUT NOT ALWAYS. (See above comment) 165 // 166 // Remember, though, the rest of the JavaParser fields are filled out, Java Doc 167 // leaves out all the other information that JP retrieves. 168 169 this.type = 170 (fFromHTMLParser.type.length() > fFromSourceParser.type.length()) 171 ? fFromHTMLParser.type 172 : fFromSourceParser.type; 173 174 // This should never matter. They must be identical. 175 this.typeJOW = fFromSourceParser.typeJOW; 176 this.variableTree = fFromSourceParser.variableTree; 177 } 178 179 180 // ************************************************************************************* 181 // ************************************************************************************* 182 // toString() 183 // ************************************************************************************* 184 // ************************************************************************************* 185 186 187 /** 188 * Generates a {@code String} of this field, with all information included. 189 * @return A printable {@code String} of this field. 190 * @see #toString(int) 191 */ 192 public String toString() 193 { 194 String defStr = (definition == null) 195 ? "null" 196 : StrPrint.abbrevEndRDSF(definition, MAX_STR_LEN, true); 197 198 return 199 "Name: [" + name + "]\n" + 200 "Declaration: [" + StrPrint.abbrevEndRDSF(signature, MAX_STR_LEN, true) + "]\n" + 201 "Type: [" + type + "]\n" + 202 "Definition: [" + defStr + "]\n" + 203 "Modifiers: [" + StrCSV.toCSV(modifiers, true, true, null) + "]\n" + 204 205 // This will **NEVER** be null - unless 'this' instance was built from an HTML File, 206 // rather than a source-code file. Instances like that are only used temporarily, and 207 // are garbage collected instantly. Do this check anyway (just in case). 208 209 "Location: " + ((this.location == null) 210 ? "null" 211 : ('[' + this.location.quickSummary() + ']')); 212 } 213 214 /** 215 * <EMBED CLASS='external-html' DATA-FILE-ID=TO_STR_PF> 216 * 217 * <BR /><BR />There is additional information printed by this {@code 'toString'} method 218 * (versus the zero-argument, standard, Java {@code 'toString'}). This method will print any 219 * available Java-Doc Comment's that were placed on this {@code Field}. 220 * 221 * <BR /><BR />This {@code 'toString'} also allows for adding UNIX-Terminal color codes. 222 * 223 * @param flags These are defined in the {@link PF Print-Flags} class 224 * @return A printable {@code String} of this {@code Field}. 225 * @see PF 226 * @see #toString() 227 */ 228 public String toString(int flags) 229 { 230 boolean color = (flags & UNIX_COLORS) > 0; 231 232 return 233 printedName("Field", 15, color) + 234 printedDeclaration(15, color) + 235 printedType(jowFlags(flags)) + 236 printedDefinition(color) + 237 printedModifiers(15) + 238 printedLocation(15, color, (flags & BRIEF_LOCATION) > 0) + 239 240 // The previous method does not add a '\n' end to the end of the returned string 241 // This is optional, it adds a '\n' AT THE BEGINNING if it is included 242 243 printedComments(15, color, (flags & JAVADOC_COMMENTS) > 0); 244 } 245 246 private String printedType(Torello.Java.Additional.Ret2<Boolean, Boolean> jow) 247 { 248 if (jow.a /*add-JOW*/) 249 return 250 "Type: [" + type + "]\n" + 251 "Type-JOW: [" + typeJOW + "]\n"; 252 else if (jow.b /*only-JOW*/) 253 return "Type-JOW: [" + typeJOW + "]\n"; 254 else 255 return "Type: [" + type + "]\n"; 256 } 257 258 private String printedDefinition(boolean color) 259 { 260 return (definition == null) 261 ? "Definition: [null]\n" 262 : "Definition: [" + 263 (color ? BGREEN : "") + 264 StrPrint.abbrevEndRDSF(definition, MAX_STR_LEN, true) + 265 (color ? RESET : "") + "]\n"; 266 } 267 268 269 // ************************************************************************************* 270 // ************************************************************************************* 271 // CompareTo & Equals Stuff 272 // ************************************************************************************* 273 // ************************************************************************************* 274 275 276 /** 277 * Java's {@code interface Comparable<T>} requirements. This does a very simple comparison 278 * using the two field's {@link #name} field. 279 * 280 * @param f Any other {@code Field} to be compared to {@code 'this' Field} 281 * 282 * @return An integer that fulfills Java's {@code Comparable<Field>} interface 283 * requirements. 284 */ 285 public int compareTo(Field f) 286 { return (this == f) ? 0 : this.name.compareTo(f.name); } 287 288 /** 289 * This <I>should be called an "atypical version" of </I> the usual {@code equals(Object 290 * other)} method. This version of equals merely compares the name of the field defined. The 291 * presumption here is that the definition of a 'field' only has meaning - <I>at all</I> - 292 * inside the context of a {@code class, interface, } or {@code enumerated-type} where that 293 * field is defined. Since inside any {@code '.java'} source-code file, there may only be one 294 * field with a given name, this method shall return {@code TRUE} whenever the field being 295 * compared also has the same name. 296 * 297 * @param other This may be any other field. It is <I><B>strongly suggested</B></I> that 298 * {@code 'other'} be a field defined in the same {@code '.java'} source-code file as 299 * {@code 'this'} field. 300 * 301 * @return This method returns {@code TRUE} when {@code 'this'} instance of {@code Field} has 302 * the same {@code 'name'} as the name-field of input-parameter {@code 'other'} 303 */ 304 public boolean equals(Field other) 305 { return this.name.equals(other.name); } 306 307 308 // ******************************************************************************************** 309 // ******************************************************************************************** 310 // A.I. Token-Stream Generator-Method 311 // ******************************************************************************************** 312 // ******************************************************************************************** 313 314 315 public ReadOnlyList<ReadOnlyList<String>> getTokenStreams() 316 { 317 final ROArrayListBuilder<ReadOnlyList<String>> tokens = new ROArrayListBuilder<>(); 318 final ROArrayListBuilder<String> b = new ROArrayListBuilder<>(); 319 320 tokens.add(ReadOnlyList.of("SECTION", "entity", "field")); 321 tokens.add(ReadOnlyList.of("SECTION", "name", this.name)); 322 tokens.add(ReadOnlyList.of("SECTION", "signature", this.signature)); 323 tokens.add(ReadOnlyList.of("SECTION", "type", this.typeJOW)); 324 325 if ((this.modifiers != null) && (modifiers.size() > 0)) 326 { 327 b.clear(); 328 b.add("SECTION"); 329 b.add("modifiers"); 330 for (String m : this.modifiers) b.add(m); 331 tokens.add(b.build()); 332 } 333 334 if ((this.annotations != null) && (annotations.size() > 0)) 335 { 336 b.clear(); 337 b.add("SECTION"); 338 b.add("annotations"); 339 for (String a : this.annotations) b.add(a); 340 tokens.add(b.build()); 341 } 342 343 if ((this.definition != null) && (!this.definition.isEmpty())) 344 tokens.add(ReadOnlyList.of("SECTION", "definition", this.definition)); 345 346 return tokens.build(); 347 } 348}