001package Torello.Java.Additional;
002
003import java.util.*;
004import java.util.stream.*;
005import java.util.function.Function;
006
007/**
008 * <CODE>VarListBuilderWithApplyAndSort&lt;T, U&gt; - Documentation.</CODE><BR /><BR />
009 * <EMBED CLASS="external-html" DATA-FILE-ID="VLBWAASTU">
010 */
011@SuppressWarnings("unchecked")
012public class VarListBuilderWithApplyAndSort<T, U>
013{
014    /**
015     * This {@code VarList} instance has a {@code 'retrieve()'} method that will return a
016     * {@code Vector} whose {@code Vector}-contents are of parametrized-type {@code 'U'}.
017     * The {@code Vector} returned will have already been sorted upon return.
018     */
019    public final VarList<Vector<U>, T>          VECTOR;
020
021    /**
022     * This {@code VarList} instance has a {@code 'retrieve()'} method that will return an
023     * {@code ArrayList} whose {@code ArrayList}-contents are of parametrized-type {@code 'U'}.
024     * The {@code ArrayList} returned will have already been sorted upon return.
025     */
026    public final VarList<ArrayList<U>, T>       ARRAYLIST;
027
028    /**
029     * This {@code VarList} instance has a {@code 'retrieve()'} method that will return an
030     * {@code Iterator} whose {@code Iterator}-contents are of parametrized-type {@code 'U'}.
031     * The {@code Iterator} returned will have already been sorted upon return.
032     */
033    public final VarList<Iterator<U>, T>        ITERATOR;
034
035    /**
036     * This {@code VarList} instance has a {@code 'retrieve()'} method that will return an
037     * {@code array} whose {@code array}-contents are of parametrized-type {@code 'U'}.
038     * The {@code array} returned will have already been sorted upon return.
039     */
040    public final VarList<U[], T>                ARRAY;
041
042    /**
043     * This {@code VarList} instance has a {@code 'retrieve()'} method that will return a
044     * {@code Stream} whose {@code Stream}-contents are of parametrized-type {@code 'U'}.
045     * The {@code Stream} returned will have already been sorted upon return.
046     */
047    public final VarList<Stream<U>, T>          STREAM;
048
049    /**
050     * Instances of {@code Stream.Builder} cannot be sorted.  Only a built {@code Stream}
051     * may be sorted.  Therefore this parameter shall always be null.
052     */
053    public final VarList<Stream.Builder<U>, T>  STREAM_BUILDER = null;
054
055    /**
056     * This {@code VarList} instance has a {@code 'retrieve()'} method that will return a
057     * {@code LinkedList} whose {@code LinkedList}-contents are of parametrized-type {@code 'U'}.
058     * The {@code LinkedList} returned will have already been sorted upon return.
059     */
060    public final VarList<LinkedList<U>, T>      LINKEDLIST;
061
062    /**
063     * This {@code VarList} instance has a {@code 'retrieve()'} method that will return a
064     * {@code TreeSet} whose {@code TreeSet}-contents are of parametrized-type {@code 'U'}.
065     * The {@code TreeSet} returned will have already been sorted upon return.
066     */
067    public final VarList<TreeSet<U>, T>         TREESET;
068
069    /**
070     * This {@code VarList} instance has a {@code 'retrieve()'} method that will return a
071     * {@code Stack} whose {@code Stack}-contents are of parametrized-type {@code 'U'}.
072     * The {@code Stack} returned will have already been sorted upon return.
073     */
074    public final VarList<Stack<U>, T>           STACK;
075
076
077    /**
078     * Builds all 8 of the {@code VarList's} provided by this builder class.
079     *
080     * @param transformer This {@code transform} is used to convert the contents of the returned
081     * list-type.  As noticed by its type, {@code 'Function<T, U>'}, the final type of the returned
082     * {@code VarList} will of type {@code 'U'}, although while building this {@code 'VarList'},
083     * the elements that shall be inserted will be of type {@code 'T'}.
084     * <BR /><BR />It is the job of the transformer parameter to convert the elements from type
085     * {@code 'T'} to type {@code 'U'}
086     *
087     * @param comparator This is used to sort the returned list.  Notice that this
088     * {@code 'comparator'} shall sort list-elements of type {@code 'U'}.  The list that is
089     * ultimately returned by these {@code VarList's} will be of type {@code 'U'} (because of the
090     * transform).
091     *
092     * <BR /><BR /><B><SPAN STYLE="color: red;">NOTICE</SPAN></B> The {@code 'comparator'} is of
093     * parametrized-type {@code 'U'}.  This is because the sort shall occur <B>AFTER</B> the
094     * transform.
095     *
096     * @param outputClass The final list that is built will be of type {@code class U}.  Because
097     * Java generics use "Type Erasure," this class must be obtained here.  It is  used for array
098     * generation or array-construction.
099     */
100    public VarListBuilderWithApplyAndSort
101        (Function<T, U> transformer, Comparator<U> comparator, Class<U> outputClass)
102    { 
103        VECTOR          = new VECTOR_CLASS          (null, transformer, comparator, false);
104        ARRAYLIST       = new ARRAYLIST_CLASS       (null, transformer, comparator, false);
105        ITERATOR        = new ITERATOR_CLASS        (null, transformer, comparator);
106        ARRAY           = new ARRAY_CLASS           (null, transformer, comparator, outputClass);
107        STREAM          = new STREAM_CLASS          (null, transformer, comparator);
108        // STREAM_BUILDER;     // Cannot sort a builder, always 'null'
109        LINKEDLIST      = new LINKEDLIST_CLASS      (null, transformer, comparator, false);
110        TREESET         = new TREESET_CLASS         (null, transformer, comparator, false);
111        STACK           = new STACK_CLASS           (null, transformer, comparator, false);
112    }
113
114    private class VECTOR_CLASS implements VarList<Vector<U>, T>
115    {
116        private       Vector<U>             v;
117        private final Function<T, U>        transformer;
118        private final Comparator<U>         comparator;
119        private final boolean               append;
120
121        public final VarList<Vector<U>, T>  create()                { return append ? this : new VECTOR_CLASS(new Vector<>(), transformer, comparator, false); }
122        public final VarList<Vector<U>, T>  appendTo(Vector<U> v)   { return new VECTOR_CLASS(v, transformer, comparator, true); }
123        public void                         insert(T t)             { v.add(transformer.apply(t)); }
124        public final Vector<U>              retrieve()              { v.sort(comparator); return v; }
125
126        public VECTOR_CLASS(Vector<U> v, Function<T, U> transformer, Comparator<U> comparator, boolean append)
127        { this.v=v; this.transformer=transformer; this.comparator=comparator; this.append=append; }
128    }
129
130    private class ARRAYLIST_CLASS implements VarList<ArrayList<U>, T>
131    {
132        private       ArrayList<U>          al;
133        private final Function<T, U>        transformer;
134        private final Comparator<U>         comparator;
135        private final boolean               append;
136
137        public VarList<ArrayList<U>, T>     create()                    { return append ? this : new ARRAYLIST_CLASS(new ArrayList<>(), transformer, comparator, false); }
138        public VarList<ArrayList<U>, T>     appendTo(ArrayList<U> al)   { return new ARRAYLIST_CLASS(al, transformer, comparator, true); }
139        public void                         insert(T t)                 { al.add(transformer.apply(t)); }
140        public ArrayList<U>                 retrieve()                  { al.sort(comparator); return al; }
141
142        public ARRAYLIST_CLASS(ArrayList<U> al, Function<T, U> transformer, Comparator<U> comparator, boolean append)
143        { this.al=al; this.transformer=transformer; this.comparator=comparator; this.append=append; }
144    }
145
146    private class ITERATOR_CLASS implements VarList<Iterator<U>, T>
147    {
148        private       Vector<U>             v;
149        private final Function<T, U>        transformer;
150        private final Comparator<U>         comparator;
151
152        public VarList<Iterator<U>, T>      create()            { return new ITERATOR_CLASS(new Vector<>(), transformer, comparator); }
153        public VarList<Iterator<U>, T>  appendTo(Iterator<U> s) { VarList.throwUOE("Iterator"); return null; }
154        public void                         insert(T t)         { v.add(transformer.apply(t)); }
155        public Iterator<U>                  retrieve()          { v.sort(comparator); return v.iterator(); }
156
157        public ITERATOR_CLASS(Vector<U> v, Function<T, U> transformer, Comparator<U> comparator)
158        { this.v=v; this.transformer=transformer; this.comparator=comparator; }
159    }
160
161    private class ARRAY_CLASS implements VarList<U[], T>
162    {
163        private       Stream.Builder<U>     sb;
164        private final Function<T, U>        transformer;
165        private final Comparator<U>         comparator;
166        private final Class<U>              outputClass;
167
168        // Class<U> clazz = null;
169        public VarList<U[], T>              create()        { return new ARRAY_CLASS(Stream.builder(), transformer, comparator, outputClass); }
170        public VarList<U[], T>              appendTo(U[] a) { VarList.throwUOE("array"); return null; }
171        public void                         insert(T t)     { sb.accept(transformer.apply(t)); }
172        public U[]                          retrieve()
173        {
174            // This idea is straight out of hell.  It does work.  The "IntFunction<U[]>" is how java.util.stream.Stream deals with generic array creation.
175            // The part about java.lang.reflect.Array is copied from "Techie Delight".  It is how to implement Generic Array Creation.
176            java.util.function.IntFunction<U[]> arrayGenerator = (int length) -> (U[]) java.lang.reflect.Array.newInstance(outputClass, length);
177            return sb.build().sorted(comparator).toArray(arrayGenerator);
178        }
179
180        public ARRAY_CLASS(Stream.Builder<U> sb, Function<T, U> transformer, Comparator<U> comparator, Class<U> outputClass)
181        { this.sb=sb; this.transformer=transformer; this.comparator=comparator; this.outputClass=outputClass; }
182    }
183
184    private class STREAM_CLASS implements VarList<Stream<U>, T>
185    {
186        private       Stream.Builder<U>     sb;
187        private final Function<T, U>        transformer;
188        private final Comparator<U>         comparator;
189
190        public VarList<Stream<U>, T>        create()                { return new STREAM_CLASS(Stream.builder(), transformer, comparator); }
191        public VarList<Stream<U>, T>        appendTo(Stream<U> s)   { VarList.throwUOE("Stream"); return null; }
192        public void                         insert(T t)             { sb.accept(transformer.apply(t)); }
193        public Stream<U>                    retrieve()              { return sb.build().sorted(comparator); }
194
195        public STREAM_CLASS(Stream.Builder<U> sb, Function<T, U> transformer, Comparator<U> comparator)
196        { this.sb=sb; this.transformer=transformer; this.comparator=comparator; }
197    }
198
199    private class LINKEDLIST_CLASS implements VarList<LinkedList<U>, T>
200    {
201        private       LinkedList<U>         ll;
202        private final Function<T, U>        transformer;
203        private final Comparator<U>         comparator;
204        private final boolean               append;
205
206        public VarList<LinkedList<U>, T>    create()                    { return append ? this : new LINKEDLIST_CLASS(new LinkedList<>(), transformer, comparator, false); }
207        public VarList<LinkedList<U>, T>    appendTo(LinkedList<U> ll)  { return new LINKEDLIST_CLASS(ll, transformer, comparator, true); }   
208        public void                         insert(T t)                 { ll.add(transformer.apply(t)); }
209        public LinkedList<U>                retrieve()                  { ll.sort(comparator); return ll; }
210
211        public LINKEDLIST_CLASS(LinkedList<U> ll, Function<T, U> transformer, Comparator<U> comparator, boolean append)
212        { this.ll=ll; this.transformer=transformer; this.comparator=comparator; this.append=append; }
213    }
214
215    private class TREESET_CLASS implements VarList<TreeSet<U>, T>
216    {
217        private       TreeSet<U>            ts;
218        private final Function<T, U>        transformer;
219        private final Comparator<U>         comparator;
220        private final boolean               append;
221
222        public VarList<TreeSet<U>, T>       create()                { return append ? this : new TREESET_CLASS(new TreeSet<>(), transformer, comparator, false); }
223        public VarList<TreeSet<U>, T>       appendTo(TreeSet<U> ts) { return new TREESET_CLASS(ts, transformer, comparator, true); }
224        public void                         insert(T t)             { ts.add(transformer.apply(t)); }
225        public TreeSet<U>                   retrieve()              { return ts; }
226
227        public TREESET_CLASS(TreeSet<U> ts, Function<T, U> transformer, Comparator<U> comparator, boolean append)
228        { this.ts=ts; this.transformer=transformer; this.comparator=comparator; this.append=append; }
229    }
230
231    private class STACK_CLASS implements VarList<Stack<U>, T>
232    {
233        private       Stack<U>              s;
234        private final Function<T, U>        transformer;
235        private final Comparator<U>         comparator;
236        private final boolean               append;
237
238        public VarList<Stack<U>, T>         create()                { return append ? this : new STACK_CLASS(new Stack<>(), transformer, comparator, false); }
239        public VarList<Stack<U>, T>         appendTo(Stack<U> s)    { return new STACK_CLASS(s, transformer, comparator, true); }
240        public void                         insert(T t)             { s.push(transformer.apply(t)); }
241        public Stack<U>                     retrieve()              { s.sort(comparator); return s; }
242
243        public STACK_CLASS(Stack<U> s, Function<T, U> transformer, Comparator<U> comparator, boolean append)
244        { this.s=s; this.transformer=transformer; this.comparator=comparator; this.append=append; }
245    }
246}