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