001package Torello.Java.Additional;
002
003import java.util.*;
004import java.util.stream.*;
005import java.util.function.Function;
006
007import Torello.Java.FileNode;
008import Torello.Java.FileNode.RetTypeChoice;
009
010/**
011 * Implementation of the <CODE>FileNode</CODE> class <CODE>'RetTypeChoice'</CODE>.
012 * 
013 * <EMBED CLASS="external-html" DATA-FILE-ID=VLB_NOTE>
014 * <EMBED CLASS="external-html" DATA-FILE-ID=VLB_APPLY_SORT>
015 * 
016 * @param <ORIGINAL> This is the original 'type' of the container's contents, <I>before those
017 * contents are transformed</I>.  In the case of {@link FileNode} and {@link RetTypeChoice}, this
018 * shall always be type {@code FileNode}.
019 * 
020 * <BR /><BR /><B STYLE='color: red;'>IMPORTANT:</B> The {@code Sort} is performed
021 * <B><I>after</I></B> the {@code Apply} transformation.
022 * 
023 * @param <TRANSFORMED> This is the 'type' of the contents of the container that is ultimately
024 * returned to the user by this {@code 'VarList'} selection-choice.  Note that the salient point
025 * is <I>the original container's content's type is transformed, and that the returned container's
026 * content's type will not be the same as the input-type, after the transformation</I>
027 * 
028 * <BR /><BR />In the case of {@link FileNode} and {@link RetTypeChoice}, the usage of this builder
029 * class is, sort-of, "a cute way of saying" {@link FileNode#toString()} and / or
030 * {@link FileNode#getFullPathName()}) - <I>depending upon whether the user is requesting one of 
031 * the <B>{@code 'FILENAME'}</B> variants, or one of the <B>{@code 'FULLPATH'}</B> variants</I>
032 * 
033 * <BR /><BR /><B>NOTE:</B>In the above two mentioned cases, type {@code <TRANSFORMED>} type will
034 * be {@code java.lang.String}.  (While the {@code <ORIGINAL>} type is {@code 'FileNode'}).
035 */
036@SuppressWarnings("unchecked")
037public class VarListBuilderWithApplyAndSort<ORIGINAL, TRANSFORMED>
038{
039    /**
040     * This {@code VarList} instance has a {@code 'retrieve()'} method that will return a
041     * {@code Vector} whose {@code Vector}-contents are of parametrized-type {@code 'TRANs'}.
042     * The {@code Vector} returned will have already been sorted upon return.
043     */
044    public final VarList<Vector<TRANSFORMED>, ORIGINAL> VECTOR;
045
046    /**
047     * This {@code VarList} instance has a {@code 'retrieve()'} method that will return an
048     * {@code ArrayList} whose {@code ArrayList}-contents are of parametrized-type
049     * {@code 'TRANSFORMED'}.  The {@code ArrayList} returned will have already been sorted upon
050     * return.
051     */
052    public final VarList<ArrayList<TRANSFORMED>, ORIGINAL> ARRAYLIST;
053
054    /**
055     * This {@code VarList} instance has a {@code 'retrieve()'} method that will return an
056     * {@code Iterator} whose {@code Iterator}-contents are of parametrized-type
057     * {@code 'TRANSFORMED'}.  The {@code Iterator} returned will have already been sorted upon
058     * return.
059     */
060    public final VarList<Iterator<TRANSFORMED>, ORIGINAL> ITERATOR;
061
062    /**
063     * This {@code VarList} instance has a {@code 'retrieve()'} method that will return an
064     * {@code array} whose {@code array}-contents are of parametrized-type {@code 'TRANSFORMED'}.
065     * The {@code array} returned will have already been sorted upon return.
066     */
067    public final VarList<TRANSFORMED[], ORIGINAL> ARRAY;
068
069    /**
070     * This {@code VarList} instance has a {@code 'retrieve()'} method that will return a
071     * {@code Stream} whose {@code Stream}-contents are of parametrized-type {@code 'TRANSFORMED'}.
072     * The {@code Stream} returned will have already been sorted upon return.
073     */
074    public final VarList<Stream<TRANSFORMED>, ORIGINAL> STREAM;
075
076    /**
077     * Instances of {@code Stream.Builder} cannot be sorted.  Only a built {@code Stream}
078     * may be sorted.  Therefore this parameter shall always be null.
079     */
080    public final VarList<Stream.Builder<TRANSFORMED>, ORIGINAL> STREAM_BUILDER = null;
081
082    /**
083     * This {@code VarList} instance has a {@code 'retrieve()'} method that will return a
084     * {@code LinkedList} whose {@code LinkedList}-contents are of parametrized-type
085     * {@code 'TRANSFORMED'}.  The {@code LinkedList} returned will have already been sorted upon
086     * return.
087     */
088    public final VarList<LinkedList<TRANSFORMED>, ORIGINAL> LINKEDLIST;
089
090    /**
091     * This {@code VarList} instance has a {@code 'retrieve()'} method that will return a
092     * {@code TreeSet} whose {@code TreeSet}-contents are of parametrized-type
093     * {@code 'TRANSFORMED'}.  The {@code TreeSet} returned will have already been sorted upon
094     * return.
095     */
096    public final VarList<TreeSet<TRANSFORMED>, ORIGINAL> TREESET;
097
098    /**
099     * This {@code VarList} instance has a {@code 'retrieve()'} method that will return a
100     * {@code Stack} whose {@code Stack}-contents are of parametrized-type {@code 'TRANSFORMED'}.
101     * The {@code Stack} returned will have already been sorted upon return.
102     */
103    public final VarList<Stack<TRANSFORMED>, ORIGINAL> STACK;
104
105
106    /**
107     * Builds all 8 of the {@code VarList's} provided by this builder class.
108     *
109     * @param transformer This {@code transform} is used to convert the contents of the returned
110     * list-type.  As noticed by its type, {@code 'Function<ORIGINAL, TRANSFORMED>'}, the final
111     * type of the returned {@code VarList} will of type {@code 'TRANSFORMED'}, although while
112     * building this {@code 'VarList'}, the elements that shall be inserted will be of type
113     * {@code 'ORIGINAL'}.
114     *
115     * <BR /><BR />It is the job of the transformer parameter to convert the elements from type
116     * {@code 'ORIGINAL'} to type {@code 'TRANSFORMED'}
117     *
118     * @param comparator This is used to sort the returned list.  Notice that this
119     * {@code 'comparator'} shall sort list-elements of type {@code 'TRANSFORMED'}.  The list that
120     * is ultimately returned by these {@code VarList's} will be of type {@code 'TRANSFORMED'}.
121     *
122     * <BR /><BR /><B><SPAN STYLE="color: red;">NOTICE</SPAN></B> The {@code 'comparator'} is of
123     * parametrized-type {@code 'TRANSFORMED'}.  This is because the sort shall occur <B>AFTER</B> the
124     * transform.
125     *
126     * @param outputClass The final list that is built will be of type {@code class U}.  Because
127     * Java generics use "Type Erasure," this class must be obtained here.  It is  used for array
128     * generation or array-construction.
129     */
130    public VarListBuilderWithApplyAndSort(
131            Function<ORIGINAL, TRANSFORMED> transformer, Comparator<TRANSFORMED> comparator,
132            Class<TRANSFORMED> outputClass
133        )
134    { 
135        VECTOR          = new VECTOR_CLASS          (null, transformer, comparator, false);
136        ARRAYLIST       = new ARRAYLIST_CLASS       (null, transformer, comparator, false);
137        ITERATOR        = new ITERATOR_CLASS        (null, transformer, comparator);
138        ARRAY           = new ARRAY_CLASS           (null, transformer, comparator, outputClass);
139        STREAM          = new STREAM_CLASS          (null, transformer, comparator);
140        // STREAM_BUILDER;     // Cannot sort a builder, always 'null'
141        LINKEDLIST      = new LINKEDLIST_CLASS      (null, transformer, comparator, false);
142        TREESET         = new TREESET_CLASS         (null, transformer, comparator, false);
143        STACK           = new STACK_CLASS           (null, transformer, comparator, false);
144    }
145
146    private class VECTOR_CLASS implements VarList<Vector<TRANSFORMED>, ORIGINAL>
147    {
148        private       Vector<TRANSFORMED>               v;
149        private final Function<ORIGINAL, TRANSFORMED>   transformer;
150        private final Comparator<TRANSFORMED>           comparator;
151        private final boolean                           append;
152
153        public final VarList<Vector<TRANSFORMED>, ORIGINAL> create()
154        { return append ? this : new VECTOR_CLASS(new Vector<>(), transformer, comparator, false); }
155
156        public final VarList<Vector<TRANSFORMED>, ORIGINAL> appendTo(Vector<TRANSFORMED> v)
157        { return new VECTOR_CLASS(v, transformer, comparator, true); }
158
159        public void insert(ORIGINAL original) { v.add(transformer.apply(original)); }
160
161        public final Vector<TRANSFORMED> retrieve() { v.sort(comparator); return v; }
162
163        public VECTOR_CLASS(
164                Vector<TRANSFORMED> v, Function<ORIGINAL, TRANSFORMED> transformer,
165                Comparator<TRANSFORMED> comparator, boolean append
166            )
167        { this.v=v; this.transformer=transformer; this.comparator=comparator; this.append=append; }
168    }
169
170    private class ARRAYLIST_CLASS implements VarList<ArrayList<TRANSFORMED>, ORIGINAL>
171    {
172        private       ArrayList<TRANSFORMED>            al;
173        private final Function<ORIGINAL, TRANSFORMED>   transformer;
174        private final Comparator<TRANSFORMED>           comparator;
175        private final boolean                           append;
176
177        public VarList<ArrayList<TRANSFORMED>, ORIGINAL> create()
178        { return append ? this : new ARRAYLIST_CLASS(new ArrayList<>(), transformer, comparator, false); }
179
180        public VarList<ArrayList<TRANSFORMED>, ORIGINAL> appendTo(ArrayList<TRANSFORMED> al)
181        { return new ARRAYLIST_CLASS(al, transformer, comparator, true); }
182
183        public void insert(ORIGINAL original) { al.add(transformer.apply(original)); }
184
185        public ArrayList<TRANSFORMED> retrieve() { al.sort(comparator); return al; }
186
187        public ARRAYLIST_CLASS(
188                ArrayList<TRANSFORMED> al, Function<ORIGINAL, TRANSFORMED> transformer,
189                Comparator<TRANSFORMED> comparator, boolean append
190            )
191        { this.al=al; this.transformer=transformer; this.comparator=comparator; this.append=append; }
192    }
193
194    private class ITERATOR_CLASS implements VarList<Iterator<TRANSFORMED>, ORIGINAL>
195    {
196        private       Vector<TRANSFORMED>               v;
197        private final Function<ORIGINAL, TRANSFORMED>   transformer;
198        private final Comparator<TRANSFORMED>           comparator;
199
200        public VarList<Iterator<TRANSFORMED>, ORIGINAL> create()
201        { return new ITERATOR_CLASS(new Vector<>(), transformer, comparator); }
202
203        public VarList<Iterator<TRANSFORMED>, ORIGINAL> appendTo(Iterator<TRANSFORMED> s)
204        { VarList.throwUOE("Iterator"); return null; }
205
206        public void insert(ORIGINAL original) { v.add(transformer.apply(original)); }
207
208        public Iterator<TRANSFORMED> retrieve() { v.sort(comparator); return v.iterator(); }
209
210        public ITERATOR_CLASS(
211                Vector<TRANSFORMED> v, Function<ORIGINAL, TRANSFORMED> transformer,
212                Comparator<TRANSFORMED> comparator
213            )
214        { this.v=v; this.transformer=transformer; this.comparator=comparator; }
215    }
216
217    private class ARRAY_CLASS implements VarList<TRANSFORMED[], ORIGINAL>
218    {
219        private       Stream.Builder<TRANSFORMED>       sb;
220        private final Function<ORIGINAL, TRANSFORMED>   transformer;
221        private final Comparator<TRANSFORMED>           comparator;
222        private final Class<TRANSFORMED>                outputClass;
223
224        public VarList<TRANSFORMED[], ORIGINAL> create()
225        { return new ARRAY_CLASS(Stream.builder(), transformer, comparator, outputClass); }
226
227        public VarList<TRANSFORMED[], ORIGINAL> appendTo(TRANSFORMED[] a)
228        { VarList.throwUOE("array"); return null; }
229
230        public void insert(ORIGINAL original) { sb.accept(transformer.apply(original)); }
231
232        public TRANSFORMED[] retrieve()
233        {
234            // This idea is straight out of hell.  It does work.  The "IntFunction<TRANSFORMED[]>"
235            // is how java.util.stream.Stream deals with generic array creation.
236            //
237            // The part about java.lang.reflect.Array is copied from "Techie Delight".  It is how
238            // to implement Generic Array Creation.
239
240            java.util.function.IntFunction<TRANSFORMED[]> arrayGenerator = (int length) ->
241                (TRANSFORMED[]) java.lang.reflect.Array.newInstance(outputClass, length);
242
243            return sb.build().sorted(comparator).toArray(arrayGenerator);
244        }
245
246        public ARRAY_CLASS(
247                Stream.Builder<TRANSFORMED> sb, Function<ORIGINAL, TRANSFORMED> transformer,
248                Comparator<TRANSFORMED> comparator, Class<TRANSFORMED> outputClass
249            )
250        {
251            this.sb=sb;
252            this.transformer=transformer;
253            this.comparator=comparator;
254            this.outputClass=outputClass;
255        }
256    }
257
258    private class STREAM_CLASS implements VarList<Stream<TRANSFORMED>, ORIGINAL>
259    {
260        private       Stream.Builder<TRANSFORMED>       sb;
261        private final Function<ORIGINAL, TRANSFORMED>   transformer;
262        private final Comparator<TRANSFORMED>           comparator;
263
264        public VarList<Stream<TRANSFORMED>, ORIGINAL> create()
265        { return new STREAM_CLASS(Stream.builder(), transformer, comparator); }
266
267        public VarList<Stream<TRANSFORMED>, ORIGINAL> appendTo(Stream<TRANSFORMED> s)
268        { VarList.throwUOE("Stream"); return null; }
269
270        public void insert(ORIGINAL original) { sb.accept(transformer.apply(original)); }
271
272        public Stream<TRANSFORMED> retrieve() { return sb.build().sorted(comparator); }
273
274        STREAM_CLASS(
275                Stream.Builder<TRANSFORMED> sb, Function<ORIGINAL, TRANSFORMED> transformer,
276                Comparator<TRANSFORMED> comparator
277            )
278        { this.sb=sb; this.transformer=transformer; this.comparator=comparator; }
279    }
280
281    private class LINKEDLIST_CLASS implements VarList<LinkedList<TRANSFORMED>, ORIGINAL>
282    {
283        private       LinkedList<TRANSFORMED>           ll;
284        private final Function<ORIGINAL, TRANSFORMED>   transformer;
285        private final Comparator<TRANSFORMED>           comparator;
286        private final boolean                           append;
287
288        public VarList<LinkedList<TRANSFORMED>, ORIGINAL> create()
289        {
290            return append
291                ? this
292                : new LINKEDLIST_CLASS(new LinkedList<>(), transformer, comparator, false);
293        }
294
295        public VarList<LinkedList<TRANSFORMED>, ORIGINAL> appendTo(LinkedList<TRANSFORMED> ll)
296        { return new LINKEDLIST_CLASS(ll, transformer, comparator, true); }
297
298        public void insert(ORIGINAL original) { ll.add(transformer.apply(original)); }
299
300        public LinkedList<TRANSFORMED> retrieve() { ll.sort(comparator); return ll; }
301
302        public LINKEDLIST_CLASS(
303                LinkedList<TRANSFORMED> ll, Function<ORIGINAL, TRANSFORMED> transformer,
304                Comparator<TRANSFORMED> comparator, boolean append
305            )
306        { this.ll=ll; this.transformer=transformer; this.comparator=comparator; this.append=append; }
307    }
308
309    private class TREESET_CLASS implements VarList<TreeSet<TRANSFORMED>, ORIGINAL>
310    {
311        private       TreeSet<TRANSFORMED>              ts;
312        private final Function<ORIGINAL, TRANSFORMED>   transformer;
313        private final Comparator<TRANSFORMED>           comparator;
314        private final boolean                           append;
315
316        public VarList<TreeSet<TRANSFORMED>, ORIGINAL> create()
317        { return append ? this : new TREESET_CLASS(new TreeSet<>(), transformer, comparator, false); }
318
319        public VarList<TreeSet<TRANSFORMED>, ORIGINAL> appendTo(TreeSet<TRANSFORMED> ts)
320        { return new TREESET_CLASS(ts, transformer, comparator, true); }
321
322        public void insert(ORIGINAL original) { ts.add(transformer.apply(original)); }
323
324        public TreeSet<TRANSFORMED> retrieve() { return ts; }
325
326        public TREESET_CLASS(
327                TreeSet<TRANSFORMED> ts, Function<ORIGINAL, TRANSFORMED> transformer,
328                Comparator<TRANSFORMED> comparator, boolean append
329            )
330        { this.ts=ts; this.transformer=transformer; this.comparator=comparator; this.append=append; }
331    }
332
333    private class STACK_CLASS implements VarList<Stack<TRANSFORMED>, ORIGINAL>
334    {
335        private       Stack<TRANSFORMED>                s;
336        private final Function<ORIGINAL, TRANSFORMED>   transformer;
337        private final Comparator<TRANSFORMED>           comparator;
338        private final boolean                           append;
339
340        public VarList<Stack<TRANSFORMED>, ORIGINAL> create()
341        { return append ? this : new STACK_CLASS(new Stack<>(), transformer, comparator, false); }
342
343        public VarList<Stack<TRANSFORMED>, ORIGINAL> appendTo(Stack<TRANSFORMED> s)
344        { return new STACK_CLASS(s, transformer, comparator, true); }
345
346        public void insert(ORIGINAL original) { s.push(transformer.apply(original)); }
347
348        public Stack<TRANSFORMED> retrieve() { s.sort(comparator); return s; }
349
350        public STACK_CLASS(
351                Stack<TRANSFORMED> s, Function<ORIGINAL, TRANSFORMED> transformer,
352                Comparator<TRANSFORMED> comparator, boolean append
353            )
354        { this.s=s; this.transformer=transformer; this.comparator=comparator; this.append=append; }
355    }
356}