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