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.Additional.Ret2; 022 023 024// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 025// JDUInternal 026// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 027 028import Torello.JDUInternal.Annotations.ReflAnnotations.ReflAnnotationData; 029 030import Torello.JDUInternal.Parse.HTML.Signature.D1_CallableSignature; 031 032 033// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 034// The new Source-Code Parser: com.sun.source.* 035// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 036 037import com.sun.source.tree.MethodTree; 038 039 040/** 041 *<B CLASS=JDDescLabel>Reflection Class:</B> 042 * 043 * <BR />Holds all information extracted from <CODE>'.java'</CODE> Source-Files about Method's 044 * identified in that file. 045 * 046 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_GET_INST> 047 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_METHOD> 048 */ 049@JDHeaderBackgroundImg(EmbedTagFileID={"REFLECTION_EXTENSION"}) 050public class Method 051 extends Callable 052 implements java.io.Serializable, Comparable<Method>, Cloneable 053{ 054 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ 055 public static final long serialVersionUID = 1; 056 057 /** 058 * The return type of the {@code method}, as a {@code String}. If this is a method with a 059 * {@code 'void'} return-type, this shall be "void". 060 */ 061 public final String returnType; 062 063 /** 064 * The return type of the {@code method}, as a {@code String}. 065 * <BR /><BR /> 066 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_JOW_TITLE> 067 */ 068 public final String returnTypeJOW; 069 070 071 // ******************************************************************************************** 072 // ******************************************************************************************** 073 // Reference-Hook: com.sun.source.tree 074 // ******************************************************************************************** 075 // ******************************************************************************************** 076 077 078 /** 079 * <EMBED CLASS='external-html' DATA-FILE-ID=SSTB_HOOK_FIELD> 080 * 081 * If a user decides to make use of the native Oracle {@code MethodTree} instance that was 082 * used to build this {@code Method} instance, it may be retrieved from this {@code transient} 083 * field. 084 */ 085 public final transient MethodTree methodTree; 086 087 088 // ******************************************************************************************** 089 // ******************************************************************************************** 090 // Constructor - com.sun.source.tree 091 // ******************************************************************************************** 092 // ******************************************************************************************** 093 094 095 // Public, but internally-used-only Constructor for "Method" 096 public Method( 097 final MethodTree mt, 098 final ReflAnnotationData rad, 099 final TreeUtils util 100 ) 101 { 102 super(mt, mt.getName().toString(), Entity.METHOD, rad, util); 103 104 this.returnType = mt.getReturnType().toString(); 105 this.returnTypeJOW = StrSource.typeToJavaIdentifier(this.returnType); 106 this.methodTree = mt; 107 } 108 109 110 // ******************************************************************************************** 111 // ******************************************************************************************** 112 // Constructor: Used Internally by SignatureParse / SummaryHTMLFile 113 // ******************************************************************************************** 114 // ******************************************************************************************** 115 116 117 // Ensures that the Version with longer type-information strings is used. 118 // Java Doc often uses longer type strings than is available from the source-code parse 119 // Remember, JavaParser Symbol-Solver doesn't work well, and the Sun/Oracle Parser doesn't have 120 // a linker at all. 121 // 122 // Called from JDUInternal.ParseHTML.SignatureParse: 123 // This is used when the JavaDocHTMLFile is asking that a method be retrieved based on 124 // input from **BOTH** the HTML-File **AND** the Source-File 125 126 public Method(final D1_CallableSignature cSig, final Method mFromSourceParser) 127 { 128 // Does the same thing as the loop statement below, but for the "parameterTypes" 129 super(cSig, mFromSourceParser); 130 131 // Java Doc always produces "java.lang.String", while JP just gives "String" 132 // 133 // REMEMBER: JP is lazy when it comes to "Package Information" for types. 134 // Java-Doc includes it often - BUT NOT ALWAYS. (See above comment) 135 // 136 // Remember, though, the rest of the JavaParser fields are filled out, Java Doc 137 // leaves out all the other information that JP retrieves. 138 139 this.returnType = 140 (cSig.returnType.length() > mFromSourceParser.returnType.length()) 141 ? cSig.returnType 142 : mFromSourceParser.returnType; 143 144 // This should never matter. They must be identical. 145 this.returnTypeJOW = mFromSourceParser.returnTypeJOW; 146 147 // Save the reference hook 148 this.methodTree = mFromSourceParser.methodTree; 149 } 150 151 // Used for "Synthetic Methods ONLY!" Literally, this line is the only way this particular 152 // Constructor could ever be called: 153 // 154 // From JDUInternal.ParseHTML.SignatureParse: 155 // if (StrCmpr.equalsXOR(cSig.name, "valueOf", "values")) return new Method(cSig); 156 157 public Method(final D1_CallableSignature cSig) 158 { 159 // Does the same thing as the loop statement below, but for the "parameterTypes" 160 super(cSig, Entity.METHOD); 161 162 this.returnType = cSig.returnType; 163 this.returnTypeJOW = cSig.returnTypeJOW; 164 this.methodTree = null; 165 } 166 167 168 // ******************************************************************************************** 169 // ******************************************************************************************** 170 // toString() 171 // ******************************************************************************************** 172 // ******************************************************************************************** 173 174 175 /** 176 * Generates a string of this method, with most information included. 177 * 178 * <BR /><BR /><B CLASS=JDDescLabel>Reduced Information:</B> 179 * 180 * <BR />This {@code 'toString'} will not return every piece of information contained by this 181 * class. For example, both the method body, and any possible JavaDoc Comments are not 182 * included. For a more enhanced {@code toString()} method version, invoke the 183 * {@link #toString(int) toString(PrintFlags)} method which accepts {@link PF Print-Flags}. 184 * 185 * @return A printable {@code String} of this method. 186 * @see PF 187 * @see #toString(int) 188 */ 189 public String toString() 190 { 191 return 192 "Name: [" + name + "]\n" + 193 "Signature: [" + StrPrint.abbrevEndRDSF(signature, MAX_STR_LEN, true) + "]\n" + 194 "Modifiers: [" + StrCSV.toCSV(modifiers, true, true, null) + "]\n" + 195 printedParameterNamesTS() + 196 printedParameterTypesTS() + 197 "Return Type: [" + returnType + "]\n" + 198 printedExceptionsTS() + 199 200 // This will **NEVER** be null - unless 'this' instance was built from an HTML File, 201 // rather than a source-code file. Instances like that are only used temporarily, and 202 // are garbage collected instantly. Do this check anyway (just in case). 203 204 "Location: " + ((this.location == null) 205 ? "null" 206 : ('[' + this.location.quickSummary() + ']')); 207 } 208 209 /** 210 * <EMBED CLASS='external-html' DATA-FILE-ID=TO_STR_PF> 211 * @param flags These are defined in the {@link PF Print-Flags} class 212 * @return A printable {@code String} of this {@code Method}. 213 * @see #toString() 214 * @see PF 215 */ 216 public String toString(int flags) 217 { 218 boolean color = (flags & UNIX_COLORS) > 0; 219 Ret2<Boolean, Boolean> jow = jowFlags(flags); 220 221 return 222 printedName("Method", 20, color) + 223 printedSignature(20, color) + 224 printedModifiers(20) + 225 printedParamNames() + 226 printedParamTypes(jow) + 227 printedReturnType(jow, color) + 228 printedExceptions() + 229 printedLocation(20, color, (flags & BRIEF_LOCATION) > 0) + 230 231 // The previous method does not add a '\n' end to the end of the returned string 232 // These are both optional, they add a '\n' AT THE BEGINNING if one of them is included 233 234 printedComments(20, color, (flags & JAVADOC_COMMENTS) > 0) + 235 printedCallableBody(flags); 236 } 237 238 private String printedReturnType(Ret2<Boolean, Boolean> jow, boolean color) 239 { 240 String rt = null, rtJOW = null; 241 242 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 243 // Worry about the colors first 244 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 245 246 if (jow.a || jow.b) 247 rtJOW = color ? (BGREEN + returnTypeJOW + RESET) : returnTypeJOW; 248 249 if (! jow.b) 250 rt = color ? (BGREEN + returnType + RESET) : returnType; 251 252 253 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 254 // Now print the string 255 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 256 257 if (jow.b /*onlyJOW*/) return "Return Simple-Type: [" + rtJOW + "]\n"; 258 259 else if (jow.a /*addJOW*/) return 260 "Return Type: [" + rt + "]\n" + 261 "Return Simple-Type: [" + rtJOW + "]\n"; 262 263 else return "Return Type: [" + rt + "]\n"; 264 } 265 266 267 // ******************************************************************************************** 268 // ******************************************************************************************** 269 // CompareTo & Equals 270 // ******************************************************************************************** 271 // ******************************************************************************************** 272 273 274 /** 275 * Java's {@code interface Comparable<T>} requirements. This does a very simple comparison 276 * using the two method's {@link #name} field. If the name comparison will not 277 * suffice in making a decision, then the number of parameters, and parameter-types are used 278 * to making the sort-decision. 279 * 280 * @param m Any other {@code Method} to be compared to {@code 'this' Method} 281 * 282 * @return An integer that fulfills Java's {@code Comparable<Method>} interface 283 * requirements. 284 */ 285 public int compareTo(Method m) 286 { 287 // Identical References 288 if (this == m) return 0; 289 290 // Sorting by ignoring case is best - usually for the looks of a list 291 // NOTE: Returning '0' is bad, because a TreeSet will remove duplicate-elements. This 292 // means two different meethods with the same name would not "fit" into a treeset. 293 294 int ret = this.name.compareToIgnoreCase(m.name); 295 if (ret != 0) return ret; 296 297 // Try to identify a different without ignoring case. 298 ret = this.name.compareTo(m.name); 299 if (ret != 0) return ret; 300 301 ret = this.numParameters() - m.numParameters(); 302 if (ret != 0) return ret; 303 304 for (int i=0; i < this.parameterTypesJOW.size(); i++) 305 { 306 ret = this.parameterTypesJOW.get(i).compareTo(m.parameterTypesJOW.get(i)); 307 if (ret != 0) return ret; 308 } 309 310 return 0; 311 } 312 313 /** 314 * This <I>should be called an "atypical version" of </I>the usual {@code equals(Object other)} 315 * method. This version of equals merely compares the name and parameters-list of the method. 316 * The presumption here is that the definition of a 'method' only has 317 * meaning - <I>at all</I> - inside the context of a {@code class, interface, } or 318 * {@code enumerated-type} where that method is defined. Since inside any {@code '.java'} 319 * source-code file, there may only be one method with a given name and parameter-list, this 320 * shall return {@code TRUE} whenever the method being compared has the same name and parameter 321 * types as {@code 'this'} does. 322 * 323 * @param other This may be any other {@code method}. It is <I><B>strongly suggested</B></I> 324 * that this be a {@code method} defined in the same {@code '.java'} source-code file as 325 * {@code 'this' method}. 326 * 327 * @return This method returns {@code TRUE} when {@code 'this'} instance of {@code Method} has 328 * <B>both</B> the same {@code public final Sting name} <B>and</B> the same parameter-list as 329 * {@code 'other'}. 330 */ 331 public boolean equals(Method other) 332 { 333 // The method's must have the same name! 334 if (! this.name.equals(other.name)) return false; 335 336 // If the number of parameters in the 'other' instance of Method differ from the number 337 // of parameters in 'this' Method, then return FALSE immediately. It cannot be a match. 338 339 if (this.numParameters() != other.numParameters()) return false; 340 341 // If both of these have zero parameters, and their names have matched, return true 342 // immediately 343 344 if (this.numParameters() == 0) return true; 345 346 // If any of the parameter-names are different, break immediately and return false; 347 for (int i=0; i < this.parameterNames.size(); i++) 348 if (! this.parameterNames.get(i).equals(other.parameterNames.get(i))) return false; 349 350 // If the parameter-types listed by the javadoc '.html' file differ from the parameter 351 // types listed in the original '.java' source-code file, then break immediately. 352 // 353 // NOTE: The "package-information" for the FULL CLASS OR INTERFACE NAME is not always 354 // available. 355 356 for (int i=0; i < this.parameterTypesJOW.size(); i++) 357 if (! this.parameterTypesJOW.get(i).equals(other.parameterTypesJOW.get(i))) 358 return false; 359 360 // ALL TEST PASSED 361 return true; 362 } 363}