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