001package Torello.JavaDoc;
002
003
004// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
005// Standard-Java Imports
006// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
007
008import java.io.IOException;
009import java.util.List;
010import java.util.function.Consumer;
011
012
013// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
014// Java-HTML Imports
015// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
016
017import Torello.Java.*;
018
019import static Torello.JavaDoc.PF.*;
020
021import Torello.Java.ReadOnly.ReadOnlyList;
022import Torello.Java.ReadOnly.ReadOnlyArrayList;
023
024
025// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
026// The new Source-Code Parser: com.sun.source.*
027// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
028
029import com.sun.source.tree.VariableTree;
030import com.sun.source.tree.ExpressionTree;
031import com.sun.source.tree.NewClassTree;
032
033
034/**
035 * <B STYLE='color:darkred;'>Reflection Class:</B>
036 * 
037 * Holds all information extracted from <CODE>'&#46;java' enum</CODE> Source-Files about 
038 * Enumerated-Constants's identified in that {@code 'enum'} file.
039 * 
040 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_GET_INST>
041 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_ENUM_CONST>
042 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_DIAGRAM>
043 */
044@JDHeaderBackgroundImg(EmbedTagFileID={"REFLECTION_EXTENSION"})
045public class EnumConstant
046    extends Declaration
047    implements java.io.Serializable, Comparable<EnumConstant>, Cloneable
048{
049    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */
050    public static final long serialVersionUID = 1;
051
052    @Override
053    String codeHiLiteString() { return this.signature; }
054
055
056    // ********************************************************************************************
057    // ********************************************************************************************
058    // Public Fields: Param-Expressions
059    // ********************************************************************************************
060    // ********************************************************************************************
061
062
063    /**
064     * The parameters passed to the constructor that constructed the enumerated-constant instance.
065     * 
066     * <BR /><BR />Many {@code enum's} do not usually use constructors for their constants - using
067     * a constructor is an extra-feature that allows other, informational data to be ascribed to
068     * the constant.  If no constructor was used, then there (obviously) couldn't have been any
069     * expressions passed to a constructor for the constant.  In such cases, this field will be
070     * null.
071     */
072    public final ReadOnlyList<String> paramExpressions;
073
074
075    // ********************************************************************************************
076    // ********************************************************************************************
077    // Reference-Hook: com.sun.source.tree
078    // ********************************************************************************************
079    // ********************************************************************************************
080
081
082    /**
083     * <EMBED CLASS='external-html' DATA-FILE-ID=SSTB_HOOK_FIELD>
084     * 
085     * If a user decides to make use of the native Sun/Oracle {@code VariableTree} instance that
086     * was used to build this {@code EnumConstant} instance, it may be retrieved from this
087     * {@code transient} field.
088     * 
089     * <BR /><BR /><B>NOTE:</B> The package {@code com.sun.source.tree} "reuses" or "overloads" the
090     * {@code VariableTree} object such that it may represent either a Field, or an Enumerated
091     * Constant.
092     */
093    public final transient VariableTree variableTree;
094
095
096    // ********************************************************************************************
097    // ********************************************************************************************
098    // Constructor - com.sun.source.tree 
099    // ********************************************************************************************
100    // ********************************************************************************************
101
102
103    /**
104     * <EMBED CLASS="defs" DATA-KIND=EnumConstant DATA-ENTITY=VariableTree>
105     * <EMBED CLASS='external-html' DATA-FILE-ID=RC_DESCRIPTION>
106     * @param vt <EMBED CLASS='external-html' DATA-FILE-ID=RC_PARAM_TREE>
107     * @param util <EMBED CLASS='external-html' DATA-FILE-ID=RC_PARAM_UTIL>
108     */
109    public EnumConstant(VariableTree vt, TreeUtils util)
110    {
111        super(
112            util,                       // TreeUtils instance (contains all the parser and stuff)
113            vt,                         // 'Tree' instance
114            null,                       // ModifiersTree: Annotations on the Field & key-words
115                                        //
116                                        // TO-DO: ********  RESEARCH THIS, MAYBE FIX THIS ********
117                                        // HERE - THE PRESUMPTION IS THAT AN ANNOTATION MAY NOT BE
118                                        // PLACED ON AN ENUM-CONSTANT - AND THEREFORE, NEITHER THE
119                                        // MODIFIERS NOR THE ANNOTATIONS ARE RELEVANT!!
120                                        // *******************************************************
121            vt.getName().toString(),    // Name of the Field
122            // vt.toString().trim(),    // Signature
123            Entity.ENUM_CONSTANT,       // Entity
124            null                        // Pass 'null' to the 'body' tree-node
125        );
126
127        // List<? extends ExpressionTree> args = ...
128        @SuppressWarnings("unchecked")
129        List<ExpressionTree> args =
130            (List<ExpressionTree>) ((NewClassTree) vt.getInitializer()).getArguments();
131
132        if ((args == null) || (args.size() == 0))
133            this.paramExpressions = EMPTY_READONLY_LIST;
134
135        else this.paramExpressions = new ReadOnlyArrayList<String>
136            (args, (ExpressionTree et) -> et.toString().trim(), args.size());
137
138        // Reference Hooks: This was built using the com.sun.source.tree.VariableTree class, so
139        // there  simply isn't a com.github.javaparser.ast.body.EnumConstantDeclaration (so it is
140        // set to null)
141
142        this.variableTree = vt;
143    }
144
145
146    // ********************************************************************************************
147    // ********************************************************************************************
148    // toString()
149    // ********************************************************************************************
150    // ********************************************************************************************
151
152
153    /**
154     * Generates a {@code String} of this {@code Enum Constant}, with all information included.
155     * 
156     * @return A printable {@code String} of this {@code EnumConstant}.
157     * 
158     * @see StrCSV#toCSV(String[], boolean, boolean, Integer)
159     * @see #toString(int)
160     */
161    public String toString()
162    {
163        return
164            "Name:        [" + name + "]\n" +
165            "Declaration: [" + StrPrint.abbrevEndRDSF(signature, MAX_STR_LEN, true) + "]\n" +
166
167            // This will **NEVER** be null - unless 'this' instance was built from an HTML File,
168            // rather than a source-code file.  Instances like that are only used temporarily, and
169            // are garbage collected instantly.  Do this check anyway (just in case).
170
171            "Location:    " + ((this.location == null)
172                ? "null" 
173                : ('[' + this.location.quickSummary() + ']'));
174    }
175
176    /**
177     * Generates a {@code String} of this {@code EnumConst}, with all information included. This
178     * will also included any content requested by the {@code 'flags'} parameter.  For this class
179     * ({@code EnumConstant}), the only additional information printed by this {@code 'toString'} 
180     * method is the Java-Doc Comment {@code String}.
181     * 
182     * <BR /><BR />This {@code String} may also have UNIX color codes added.
183     * 
184     * @param flags These are the {@code toString(...)} flags from class {@code PF}
185     * ("Print Flags"). View available flags listed in class {@link PF}.
186     * 
187     * @return A printable {@code String} of this {@code AnnotationElem}.
188     * 
189     * @see PF
190     * @see StrCSV#toCSV(String[], boolean, boolean, Integer)
191     * @see #toString()
192     */
193    public String toString(int flags)
194    {
195        boolean color = (flags & UNIX_COLORS) > 0;
196
197        return
198            printedName("Enum-Const", 17, color) + 
199            printedDeclaration(17, color) +
200            printedParamExpressions(17) +
201            printedLocation(17, color, (flags & BRIEF_LOCATION) > 0) +
202
203            // The previous method does not add a '\n' end to the end of the returned string
204            // This is optional, it adds a '\n' AT THE BEGINNING if it is included
205
206            printedComments(17, color, (flags & JAVADOC_COMMENTS) > 0);
207    }
208
209    private String printedParamExpressions(int LEN)
210    {
211        if ((paramExpressions == null) || (paramExpressions.size() == 0))
212            return "";
213
214        return StringParse.rightSpacePad("Initializer:", LEN) +
215            "[" + StrCSV.toCSV(paramExpressions, false, false, null) + "]\n";
216    }
217
218
219    // ********************************************************************************************
220    // ********************************************************************************************
221    // CompareTo & Equals 
222    // ********************************************************************************************
223    // ********************************************************************************************
224
225
226    /**
227     * Java's {@code interface Comparable<T>} requirements.  This does a very simple comparison
228     * using the two constants' {@code 'name'} field.
229     * 
230     * @param ec Any other {@code EnumConstant} to be compared to {@code 'this' EnumConstant}
231     * 
232     * @return An integer that fulfills Java's
233     * {@code interface Comparable<EnumConstant> public boolean compareTo(EnumConstant ec)}
234     * method requirements.
235     */
236    public int compareTo(EnumConstant ec)
237    { return (this == ec) ? 0 : this.name.compareTo(ec.name); }
238
239    /**
240     * This <I>should be called an "atypical version" of </I> the usual {@code equals(Object
241     * other)} method.  This version of equals merely compares the name of the constant defined.
242     * The presumption here is that the definition of an 'constant' only has meaning - <I>at
243     * all</I> - inside the context of an {@code enum} where that constant has been defined.  Since
244     * inside any {@code '.java'} {@code enum}, there may only be one element with a given name,
245     * this method shall return {@code TRUE} whenever the constant being compared also has the same
246     * name.
247     * 
248     * @param other This may be any other {@code EnumConstant}.  It is <I><B>strongly
249     * suggested</B></I> that {@code 'other'} be a {@code constant} defined in the same
250     * {@code '.java'} source-code file as {@code 'this'} constant.
251     * 
252     * @return This method returns {@code TRUE} when {@code 'this'} instance of
253     * {@code EnumConstant} has the same {@code 'name'} as the name of input-parameter
254     * {@code 'other'}
255     */
256    public boolean equals(EnumConstant other)
257    { return this.name.equals(other.name); }
258}