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