001/*
002 * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025package Torello.Java.ReadOnly;
026
027import java.io.Serializable;
028
029import java.util.*;
030
031import java.util.function.BiConsumer;
032import java.util.function.BiFunction;
033import java.util.function.Consumer;
034import java.util.function.Predicate;
035import java.util.function.Function;
036
037import Torello.Java.ReadOnly.ROTreeMapBuilder;
038import Torello.Java.Additional.Tuple2;
039
040/**
041 * Immutable Wrapper for <CODE>java&#46;util&#46;TreeMap</CODE>, found in the "Java Collections
042 * Framework".
043 * 
044 * <EMBED CLASS=globalDefs DATA-JDK=TreeMap>
045 * <EMBED CLASS='external-html' DATA-FILE-ID=DATA_CLASS>
046 * 
047 * @param <K> the type of keys maintained by this map
048 * @param <V> the type of mapped values
049 */
050@Torello.JavaDoc.JDHeaderBackgroundImg(EmbedTagFileID="JDHBI_MAIN")
051@SuppressWarnings("unchecked")
052public class ReadOnlyTreeMap<K, V>
053    // extends AbstractReadOnlyMap<K, V>
054    implements ReadOnlyNavigableMap<K, V>, java.io.Serializable
055{
056    // ********************************************************************************************
057    // ********************************************************************************************
058    // Protected & Private Fields, Methods, Statics
059    // ********************************************************************************************
060    // ********************************************************************************************
061
062
063    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */
064    protected static final long serialVersionUID = 1;
065
066    // Minor Optimization where new TreeMap's that have no contents always re-use this static
067    // instance.  Since this instance is completely empty, the Raw-Types things is irrelevant.
068
069    @SuppressWarnings("rawtypes")
070    private static final TreeMap EMPTY_TREE_MAP = new TreeMap();
071
072    // Singleton & Empty ReadOnlyTreeMap, Uses the "Supplier Constructor"
073    @SuppressWarnings("rawtypes")
074    private static final ReadOnlyTreeMap EMPTY_READONLY_TREE_MAP =
075        new ReadOnlyTreeMap(EMPTY_TREE_MAP);
076
077    // The actual TreeMap used by this instance.
078    private final TreeMap<K, V> treeMap;
079
080    // TRUE     => This was built using the class ROTreeMapBuilder
081    // FALSE    => This was built using the clone() of a standard java.util.TreeMap constructor
082
083    private final boolean fromBuilderOrTreeMap;
084
085    // Mimics the C++ Keyword/Concept of "Friend Class".   Is "Friends With" ROTreeMapBuilder
086    static class AccessBadge { private AccessBadge() { } }
087    private static final AccessBadge friendClassBadge = new AccessBadge();
088
089
090    // ********************************************************************************************
091    // ********************************************************************************************
092    // Builder, Acess-Badge Constructor - and Static "Empty" getter (which is used by the builder)
093    // ********************************************************************************************
094    // ********************************************************************************************
095
096
097    /**
098     * Returns an empty, <B STYLE='color: red;'>singleton</B>, instance of {@code ReadOnlyTreeMap}.
099     * @param <X> Returned {@link ReadOnlyMap}'s Key-Type.
100     * @param <Y> Returned {@link ReadOnlyMap}'s Value-Type.  
101     * 
102     * @return An empty map.  Since this map is both empty &amp; read-only, a raw-type singleton 
103     * will suffice for all operations offered by this clas.
104     */
105    public static <X, Y> ReadOnlyTreeMap<X, Y> emptyROTM()
106    { return (ReadOnlyTreeMap<X, Y>) EMPTY_READONLY_TREE_MAP; }
107
108    // To all the readers out there following along: The "AccessBadge" thing is just a slightly
109    // wimpier substitute for the C++ keyword / concept 'friend' or "Friend Class".  It means this
110    // constructor is (for all intents and purposes) a private-constructor, except for the class
111    // ROTreeMapBuilder
112    //
113    // This is the Constructor used by the Builder.  It has a "Zero-Size" Optimization
114
115    ReadOnlyTreeMap(ROTreeMapBuilder<K, V> rotmb, ROTreeMapBuilder.AccessBadge badge)
116    {
117        Objects.requireNonNull(badge, "Access Badge is null.  Requires Friend-Class Badge");
118
119        this.fromBuilderOrTreeMap = true;
120        this.treeMap = rotmb;
121    }
122
123
124    // ********************************************************************************************
125    // ********************************************************************************************
126    // Modified-Original Constructors
127    // ********************************************************************************************
128    // ********************************************************************************************
129
130
131    /**
132     * Copies the contents of parameter {@code 'map'}, and saves saves it, thereby guaranteeing
133     * {@code 'this'} instance is Read-Only and fully-shielded from outside modification.
134     * 
135     * @param map The {@code Map} to be copied into {@code 'this'} instance internal and private
136     * {@code 'treeMap'} field.
137     */
138    public ReadOnlyTreeMap(Map<K, V> map)
139    {
140        this.fromBuilderOrTreeMap = false;
141
142        this.treeMap = (map.size() == 0)
143            ? ((TreeMap<K, V>) EMPTY_TREE_MAP)
144            : new TreeMap<K, V>(map);
145    }
146
147    /**
148     * If only a small amount of processing needs to be done on the contents of some Java
149     * Map, and using an entire Builder-Class seems disproportionately complex - <I>this
150     * constructor can convert any Java {@code Map} into a {@code ReadOnlyTreeMap}, using
151     * a simple {@code 'mapTranslator'}</I>.
152     * 
153     * @param <X> The Key-Type of the User-Provided {@code Map}.
154     * @param <Y> The Value-Type of the User-Provided {@code Map}.
155     * 
156     * @param refHolder This must a non-null instance of {@link Tuple2}.  The provided
157     * {@code Consumer} is just that, a {@code 'Consumer'} rather than a {@code 'Function'}, since
158     * the results of each translation must be assigned to the values inside this tuple in order
159     * for them to be inserted into this {@code ReadOnlyTreeMap}.
160     * 
161     * @param map Any Java {@code Map}.
162     * 
163     * @param mapTranslator A function for mapping the iterated elements of Map-Types {@code 'X'}
164     * and {@code 'Y'}, into the actual {@code TreeMap's} Key-Type {@code 'K'}, and Value-Type
165     * {@code 'V'}.  The results of this translation must be placed into the fields inside
166     * {@code 'refHolder'}.
167     * 
168     * <BR /><BR />If this parameter is passed null, this method will throw a
169     * {@code NullPointerException}.
170     * 
171     * @param filter An optional filter that can be used to prevent &amp; prohibit any chosen
172     * elements from input {@code 'map'} from being inserted into {@code 'this'}
173     * {@code ReadOnlyTreeMap}.
174     * 
175     * <BR /><BR />This parameter may be passed null, and if it is, it will be silently ignored, 
176     * and all entries present inside {@code 'map'} will be processed and inserted into
177     * {@code 'this'}
178     * 
179     * @param comparator <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
180     * 
181     * @throws NullPointerException if either parameter {@code 'i'} or parameter 
182     * {@code 'mapTranslator'} is passed null.
183     */
184    public <X, Y> ReadOnlyTreeMap(
185            Tuple2<K, V>                refHolder,
186            Map<X, Y>                   map,
187            Consumer<Map.Entry<X, Y>>   mapTranslator,
188            Predicate<Map.Entry<X, Y>>  filter,
189            Comparator<? super K>       comparator
190        )
191    {
192        Objects.requireNonNull(refHolder, ROHelpers.NULL_MSG + "'refHolder'");
193        Objects.requireNonNull(mapTranslator, ROHelpers.NULL_MSG + "'mapTranslator'");
194
195        fromBuilderOrTreeMap = false;
196
197        TreeMap<K, V> treeMap = (comparator != null)
198            ? new TreeMap<>(comparator)
199            : new TreeMap<>();
200
201        if (filter == null)
202
203            for (Map.Entry<X, Y> entry : map.entrySet())
204            {
205                mapTranslator.accept(entry);
206                treeMap.put(refHolder.a, refHolder.b);
207            }
208
209        else for (Map.Entry<X, Y> entry : map.entrySet())
210        {
211            if (! filter.test(entry)) continue;
212            mapTranslator.accept(entry);
213            treeMap.put(refHolder.a, refHolder.b);
214        }
215
216        // Empty Optimization (throw away, completely, the reference, use static-constant)
217        this.treeMap = (treeMap.size() == 0) ? ((TreeMap<K, V>) EMPTY_TREE_MAP) : treeMap;
218    }
219
220
221    // ********************************************************************************************
222    // ********************************************************************************************
223    // New Constructors, January 2024
224    // ********************************************************************************************
225    // ********************************************************************************************
226
227
228    /**
229     * Constructs an instance of {@code ReadOnlyTreeMap} that contains the keys present in
230     * parameter {@code 'keys'}, and values generated by {@code 'valueMapper'} - using each of the
231     * {@code 'keys'} as input.
232     * 
233     * <EMBED CLASS='external-html' DATA-FILE-ID=LOOK_AT_IT>
234     * 
235     * @param keys          Any Java {@code Iterable} instance.
236     * @param valueMapper   A user provided function to compute a map value, based on a map key.
237     * @param filter        <EMBED CLASS='external-html' DATA-FILE-ID=MAP_ITERABLE_FILTER>
238     * @param comparator    <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
239     *  
240     * @throws NullPointerException if either {@code 'keys'} or {@code 'valueMapper'} are passed
241     * null.
242     */
243    public ReadOnlyTreeMap(
244            Iterable<? extends K>               keys,
245            Function<? super K, ? extends V>    valueMapper,
246            Predicate<? super K>                filter,
247            Comparator<? super K>               comparator
248        )
249    {
250        Objects.requireNonNull(keys, ROHelpers.NULL_MSG + "'keys'");
251        Objects.requireNonNull(valueMapper, ROHelpers.NULL_MSG + "'valueMapper'");
252
253        fromBuilderOrTreeMap = false;
254
255        TreeMap<K, V> treeMap = (comparator != null)
256            ? new TreeMap<>(comparator)
257            : new TreeMap<>();
258
259        if (filter == null)
260            for (K key : keys)
261                treeMap.put(key, valueMapper.apply(key));
262
263        else
264            for (K key : keys)
265                if (filter.test(key))
266                    treeMap.put(key, valueMapper.apply(key));
267
268        // Empty Optimization (throw away, completely, the reference, use static-constant)
269        this.treeMap = (treeMap.size() == 0) ? ((TreeMap<K, V>) EMPTY_TREE_MAP) : treeMap;
270    }
271
272    /**
273     * Constructs an instance of {@code ReadOnlyTreeMap} that has been populated by the Key-Value
274     * Pairs left in {@code 'refHolder'} by each invocation of the {@code Runnable} parameter
275     * {@code 'computeNextEntry'}.  Key-Value Pairs are inserted until an invocation of the 
276     * {@code Runnable} leaves null in {@code refHolder.a} and {@code refHolder.b}
277     * 
278     * <EMBED CLASS='external-html' DATA-FILE-ID=LOOK_AT_IT>
279     * 
280     * @param refHolder         <EMBED CLASS='external-html' DATA-FILE-ID=REF_HOLDER>
281     * @param computeNextEntry  <EMBED CLASS='external-html' DATA-FILE-ID=COMPUTE_NEXT_RUN>
282     * @param comparator        <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
283     *  
284     * @throws NullPointerException if either {@code 'refHolder'} or {@code 'computeNextEntry'} are
285     * passed null.
286     */
287    public ReadOnlyTreeMap(
288            Tuple2<K, V>            refHolder,
289            Runnable                computeNextEntry,
290            Comparator<? super K>   comparator
291        )
292    {
293        Objects.requireNonNull(refHolder, ROHelpers.NULL_MSG + "'refHolder'");
294        Objects.requireNonNull(computeNextEntry, ROHelpers.NULL_MSG + "'computeNextEntry'");
295
296        fromBuilderOrTreeMap = false;
297
298        TreeMap<K, V> treeMap = (comparator != null)
299            ? new TreeMap<>(comparator)
300            : new TreeMap<>();
301
302        do
303        {
304            computeNextEntry.run();
305            if ((refHolder.a == null) && (refHolder.b == null)) break;
306            treeMap.put(refHolder.a, refHolder.b);
307        }
308        while (true);
309
310        // Empty Optimization (throw away, completely, the reference, use static-constant)
311        this.treeMap = (treeMap.size() == 0) ? ((TreeMap<K, V>) EMPTY_TREE_MAP) : treeMap;
312    }
313
314    /**
315     * Populates an instance of {@code ReadOnlyTreeMap} by iterating the input {@code 'source'}
316     * iterable, and passing each value returned by that {@code Iterator} to the
317     * {@code 'computeNextEntry'} Java {@code Consumer}.
318     * 
319     * <BR /><BR />It is the programmer's responsibility to properly place each Key-Value Pair 
320     * that is intending to be inserted into the final {@code Map} instance into the
321     * {@code 'refHolder'} instance.  After each invocation of {@code 'computeNextEntry'}, this 
322     * constructor's logic will retrieve the values within {@code 'refHolder.a'} and
323     * {@code 'refHolder.b'} and insert them into this instance internal {@code TreeMap}.
324     * 
325     * <EMBED CLASS='external-html' DATA-FILE-ID=LOOK_AT_IT>
326     * 
327     * @param <X>               The type of the elements inside {@code 'source'}
328     * @param source            Any Java {@code Iterable} instance.
329     * @param refHolder         <EMBED CLASS='external-html' DATA-FILE-ID=REF_HOLDER>
330     * @param computeNextEntry  <EMBED CLASS='external-html' DATA-FILE-ID=COMPUTE_NEXT_CONS>
331     * @param filter            <EMBED CLASS='external-html' DATA-FILE-ID=MAP_ITERABLE_FILTER>
332     * @param comparator        <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
333     * 
334     * @throws NullPointerException if either {@code 'refHolder'}, {@code 'computeNextEntry'} or
335     * {@code 'source'} are passed null.
336     */
337    public <X> ReadOnlyTreeMap(
338            Iterable<X>             source,
339            Tuple2<K, V>            refHolder,
340            Consumer<? super X>     computeNextEntry,
341            Predicate<? super X>    filter,
342            Comparator<? super K>   comparator
343        )
344    {
345        Objects.requireNonNull(refHolder, ROHelpers.NULL_MSG + "'refHolder'");
346        Objects.requireNonNull(computeNextEntry, ROHelpers.NULL_MSG + "'computeNextEntry'");
347
348        fromBuilderOrTreeMap = false;
349
350        TreeMap<K, V> treeMap = (comparator != null)
351            ? new TreeMap<>(comparator)
352            : new TreeMap<>();
353
354        X x; // temp var
355        Iterator<X> iter = source.iterator();
356
357        if (filter == null)
358
359            while (iter.hasNext())
360            {
361                computeNextEntry.accept(iter.next());
362                treeMap.put(refHolder.a, refHolder.b);
363            }
364
365        else
366
367            while (iter.hasNext())
368                if (filter.test(x = iter.next()))
369                {
370                    computeNextEntry.accept(x);
371                    treeMap.put(refHolder.a, refHolder.b);
372                }
373
374        // Empty Optimization (throw away, completely, the reference, use static-constant)
375        this.treeMap = (treeMap.size() == 0) ? ((TreeMap<K, V>) EMPTY_TREE_MAP) : treeMap;
376    }
377
378
379    // ********************************************************************************************
380    // ********************************************************************************************
381    // Array Constructors, March 2024
382    // ********************************************************************************************
383    // ********************************************************************************************
384
385
386    /**
387     * Retrieves elements from the VarArgs Generic-Array parameter {@code 'elements'}, and
388     * subsequently invokes the {@code 'computeNextEntry'} processor to populate this
389     * {@code ReadOnlyTreeMap}.
390     * 
391     * @param <X>                  The type of array parameter {@code 'elements'}
392     * @param refHolder            <EMBED CLASS='external-html' DATA-FILE-ID=REF_HOLDER>
393     * @param computeNextEntry     <EMBED CLASS='external-html' DATA-FILE-ID=ARR_COMPUTE_NEXT_CONS>
394     * @param filter               <EMBED CLASS='external-html' DATA-FILE-ID=MAP_ARRAY_FILTER>
395     * @param comparator           <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
396     * @param elements             Any Generic VarArgs-Array
397     * @throws ClassCastException  <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CCEX>
398     * 
399     * @throws NullPointerException if either {@code 'refHolder'} or {@code 'computeNextEntry'}
400     * are passed null
401     */
402    public <X> ReadOnlyTreeMap(
403            Tuple2<K, V>            refHolder,
404            Consumer<? super X>     computeNextEntry,
405            Predicate<? super X>    filter,
406            Comparator<? super K>   comparator,
407            X...                    elements
408        )
409    {
410        Objects.requireNonNull(refHolder, ROHelpers.NULL_MSG + "'refHolder'");
411        Objects.requireNonNull(computeNextEntry, ROHelpers.NULL_MSG + "'computeNextEntry'");
412
413        this.fromBuilderOrTreeMap = false;
414
415        TreeMap<K, V> treeMap = (comparator != null) ? new TreeMap<>(comparator) : new TreeMap<>();
416
417        if (filter == null) for (X e : elements)
418        {
419            computeNextEntry.accept(e);
420            treeMap.put(refHolder.a, refHolder.b);
421        }
422
423        else for (X x : elements) if (filter.test(x))
424        {
425            computeNextEntry.accept(x);
426            treeMap.put(refHolder.a, refHolder.b);
427        }
428
429        // Empty Optimization (throw away, completely, the reference, use static-constant)
430        this.treeMap = (treeMap.size() == 0) ? ((TreeMap<K, V>) EMPTY_TREE_MAP) : treeMap;
431    }
432
433    /**
434     * Retrieves elements from the Java Primitive-Array parameter {@code 'primitiveArray'}, and
435     * subsequently invokes the {@code 'computeNextEntry'} processor to populate this
436     * {@code ReadOnlyTreeMap}.
437     * 
438     * @param filter               <EMBED CLASS='external-html' DATA-FILE-ID=PRED_FILT_PRIM>
439     * @param computeNextEntry     <EMBED CLASS='external-html' DATA-FILE-ID=ARR_COMPUTE_NEXT_CONS>
440     * @param refHolder            <EMBED CLASS='external-html' DATA-FILE-ID=REF_HOLDER>
441     * @param comparator           <EMBED CLASS='external-html' DATA-FILE-ID=COMPARATOR>
442     * @param primitiveArray       Any Java Primitive-Array
443     * @throws ClassCastException  <EMBED CLASS='external-html' DATA-FILE-ID=PRIM_ARR_CCEX>
444     * 
445     * @throws NullPointerException if either {@code 'refHolder'} or {@code 'computeNextEntry'}
446     * are passed null
447     * 
448     */
449    public <X> ReadOnlyTreeMap(
450            Predicate<?>            filter,
451            Consumer<?>             computeNextEntry,
452            Tuple2<K, V>            refHolder,
453            Comparator<? super K>   comparator,
454            Object                  primitiveArray
455        )
456    {
457        Objects.requireNonNull(refHolder, ROHelpers.NULL_MSG + "'refHolder'");
458        Objects.requireNonNull(computeNextEntry, ROHelpers.NULL_MSG + "'computeNextEntry'");
459
460        this.fromBuilderOrTreeMap = false;
461
462        TreeMap<K, V> treeMap = ROHelpers.buildROMap(
463            primitiveArray,
464            (int arrayLen) -> (comparator != null) ? new TreeMap<>(comparator) : new TreeMap<>(),
465            filter,
466            refHolder,
467            computeNextEntry
468        );
469
470        // Empty Optimization (throw away, completely, the reference, use static-constant)
471        this.treeMap = (treeMap.size() == 0) ? ((TreeMap<K, V>) EMPTY_TREE_MAP) : treeMap;
472    }
473
474
475    // ********************************************************************************************
476    // ********************************************************************************************
477    // Convert to java.util Types
478    // ********************************************************************************************
479    // ********************************************************************************************
480
481
482    /**
483     * Clone's {@code 'this'} instance internal {@code TreeMap<K, V>} field, and returns it. 
484     * <EMBED CLASS='external-html' DATA-TYPE=TreeMap DATA-FILE-ID=CLONE_TO>
485     * 
486     * @return An independent, mutable copy of {@code 'this'} instance internal
487     * {@code TreeMap<K, V>} data-structure.
488     */
489    public TreeMap<K, V> cloneToTreeMap()
490    {
491        if (! fromBuilderOrTreeMap) return (TreeMap<K, V>) this.treeMap.clone();
492
493        TreeMap<K, V> ret = new TreeMap<K, V>();
494
495        for (Map.Entry<K, V> e :
496            ((ROTreeMapBuilder<K, V>) this.treeMap)._entrySet(friendClassBadge))
497
498            ret.put(e.getKey(), e.getValue());
499
500        return ret; 
501    }
502
503    /**
504     * Invokes {@code java.util.Collections.unmodifiableMap} on the internal {@code TreeMap}.
505     * <EMBED CLASS='external-html' DATA-RET_TYPE=Map DATA-FILE-ID=WRAP_TO_IMMUTABLE>
506     * 
507     * @return A {@code Map} which adheres to the JDK interface {@code java.util.Map}, but throws
508     * an {@code UnsupportedOperationException} if a user attempts to invoke a Mutator-Method on
509     * the returned instance.
510     */
511    public Map<K, V> wrapToImmutableMap()
512    { return Collections.unmodifiableMap(this.treeMap); }
513
514
515    // ********************************************************************************************
516    // ********************************************************************************************
517    // Original JDK Methods, java.util.TreeMap
518    // ********************************************************************************************
519    // ********************************************************************************************
520    
521
522    /**
523     * Returns the number of key-value mappings in this map.
524     * @return the number of key-value mappings in this map
525     */
526    public int size()
527    { return this.treeMap.size(); }
528
529    /**
530     * Returns {@code TRUE} if this map contains a mapping for the specified key.
531     *
532     * @param key key whose presence in this map is to be tested
533     * @return {@code TRUE} if this map contains a mapping for the specified key
534     * 
535     * @throws ClassCastException if the specified key cannot be compared with the keys currently
536     * in the map
537     * 
538     * @throws NullPointerException if the specified key is null and this map uses natural
539     * ordering, or its comparator does not permit null keys
540     */
541    public boolean containsKey(Object key)
542    { return this.treeMap.containsKey(key); }
543
544    /**
545     * Returns {@code TRUE} if this map maps one or more keys to the specified value.  More
546     * formally, returns {@code TRUE} if and only if this map contains at least one mapping to a
547     * value {@code v} such that {@code (value==null ? v==null : value.equals(v))}.
548     *
549     * @param value value whose presence in this map is to be tested
550     * @return {@code TRUE} if a mapping to {@code value} exists; {@code FALSE} otherwise
551     */
552    public boolean containsValue(Object value)
553    { return this.treeMap.containsValue(value); }
554
555    /**
556     * Returns the value to which the specified key is mapped, or {@code null} if this map contains
557     * no mapping for the key.
558     *
559     * <BR /><BR />More formally, if this map contains a mapping from a key {@code k} to a value
560     * {@code v} such that {@code key} compares equal to {@code k} according to the map's ordering,
561     * then this method returns {@code v}; otherwise it returns {@code null}.  (There can be at
562     * most one such mapping.)
563     *
564     * <BR /><BR />A return value of {@code null} does not <em>necessarily</em> indicate that the
565     * map contains no mapping for the key; it's also possible that the map explicitly maps the key
566     * to {@code null}.  The {@link #containsKey containsKey} operation may be used to distinguish
567     * these two cases.
568     *
569     * @throws ClassCastException if the specified key cannot be compared with the keys currently
570     * in the map
571     * 
572     * @throws NullPointerException if the specified key is null and this map uses natural
573     * ordering, or its comparator does not permit null keys
574     */
575    public V get(Object key)
576    { return this.treeMap.get(key); }
577
578    public Comparator<? super K> comparator()
579    { return this.treeMap.comparator(); }
580
581    /** @throws NoSuchElementException {@inheritDoc} */
582    public K firstKey()
583    { return this.treeMap.firstKey(); }
584
585    /** @throws NoSuchElementException {@inheritDoc} */
586    public K lastKey()
587    { return this.treeMap.lastKey(); }
588
589    public ReadOnlyMap.Entry<K,V> firstEntry()
590    { return new EntryImpl<>(this.treeMap.firstEntry()); }
591
592    public ReadOnlyMap.Entry<K,V> lastEntry()
593    { return new EntryImpl<>(this.treeMap.lastEntry()); }
594
595    /**
596     * @throws ClassCastException {@inheritDoc}
597     * 
598     * @throws NullPointerException if the specified key is null and this map uses natural
599     * ordering, or its comparator does not permit null keys
600     */
601    public ReadOnlyMap.Entry<K,V> lowerEntry(K key)
602    { return new EntryImpl<>(this.treeMap.lowerEntry(key)); }
603
604    /**
605     * @throws ClassCastException {@inheritDoc}
606     * 
607     * @throws NullPointerException if the specified key is null and this map uses natural
608     * ordering, or its comparator does not permit null keys
609     */
610    public K lowerKey(K key)
611    { return this.treeMap.lowerKey(key); }
612
613    /**
614     * @throws ClassCastException {@inheritDoc}
615     * 
616     * @throws NullPointerException if the specified key is null and this map uses natural
617     * ordering, or its comparator does not permit null keys
618     */
619    public ReadOnlyMap.Entry<K,V> floorEntry(K key)
620    { return new EntryImpl<>(this.treeMap.floorEntry(key)); }
621
622    /**
623     * @throws ClassCastException {@inheritDoc}
624     * 
625     * @throws NullPointerException if the specified key is null and this map uses natural
626     * ordering, or its comparator does not permit null keys
627     */
628    public K floorKey(K key)
629    { return this.treeMap.floorKey(key); }
630
631    /**
632     * @throws ClassCastException {@inheritDoc}
633     * 
634     * @throws NullPointerException if the specified key is null and this map uses natural
635     * ordering, or its comparator does not permit null keys
636     */
637    public ReadOnlyMap.Entry<K,V> ceilingEntry(K key)
638    { return new EntryImpl<>(this.treeMap.ceilingEntry(key)); }
639
640    /**
641     * @throws ClassCastException {@inheritDoc}
642     * 
643     * @throws NullPointerException if the specified key is null and this map uses natural
644     * ordering, or its comparator does not permit null keys
645     */
646    public K ceilingKey(K key)
647    { return this.treeMap.ceilingKey(key); }
648
649    /**
650     * @throws ClassCastException {@inheritDoc}
651     * 
652     * @throws NullPointerException if the specified key is null and this map uses natural
653     * ordering, or its comparator does not permit null keys
654     */
655    public ReadOnlyMap.Entry<K,V> higherEntry(K key)
656    { return new EntryImpl<>(this.treeMap.higherEntry(key)); }
657
658    /**
659     * @throws ClassCastException {@inheritDoc}
660     * 
661     * @throws NullPointerException if the specified key is null and this map uses natural
662     * ordering, or its comparator does not permit null keys
663     */
664    public K higherKey(K key)
665    { return this.treeMap.higherKey(key); }
666
667    /** Returns a {@link ReadOnlySet} view of the keys contained in this map. */
668    public ReadOnlySet<K> keySet()
669    {
670        return InterfaceBuilder.toReadOnlySet(
671            fromBuilderOrTreeMap
672                ? ((ROTreeMapBuilder<K, V>) this.treeMap)._keySet(friendClassBadge)
673                : this.treeMap.keySet()
674        );
675    }
676
677    public ReadOnlyNavigableSet<K> navigableKeySet()
678    {
679        return InterfaceBuilder.toReadOnlyNavigableSet(
680            fromBuilderOrTreeMap
681                ? ((ROTreeMapBuilder<K, V>) this.treeMap)._navigableKeySet(friendClassBadge)
682                : this.treeMap.navigableKeySet()
683        );
684    }
685
686    public ReadOnlyNavigableSet<K> descendingKeySet()
687    {
688        return InterfaceBuilder.toReadOnlyNavigableSet(
689            fromBuilderOrTreeMap
690                ? ((ROTreeMapBuilder<K, V>) this.treeMap)._descendingKeySet(friendClassBadge)
691                : this.treeMap.descendingKeySet()
692        );
693    }
694
695    /** Returns a {@link ReadOnlyCollection} view of the values contained in this map. */
696    public ReadOnlyCollection<V> values()
697    {
698        return InterfaceBuilder.toReadOnlyCollection(
699            fromBuilderOrTreeMap
700                ? ((ROTreeMapBuilder<K, V>) this.treeMap)._values(friendClassBadge)
701                : this.treeMap.values()
702        );
703    }
704
705    /**
706     * Returns a {@link ReadOnlySet} view of the mappings contained in this map.
707     * 
708     * @return At the moment, a {@link ReadOnlyTreeSet} is arbitrarily used for the type of the
709     * returned instance
710     */
711    public ReadOnlySet<ReadOnlyMap.Entry<K, V>> entrySet()
712    {
713        return ROHelpers.toReadOnlyEntrySet(
714            fromBuilderOrTreeMap
715                ? ((ROTreeMapBuilder<K, V>) this.treeMap)._entrySet(friendClassBadge)
716                : this.treeMap.entrySet()
717        );
718    }
719
720    public ReadOnlyNavigableMap<K, V> descendingMap()
721    {
722        return InterfaceBuilder.toReadOnlyNavigableMap(
723            fromBuilderOrTreeMap
724                ? ((ROTreeMapBuilder<K, V>) this.treeMap)._descendingMap(friendClassBadge)
725                : this.treeMap.descendingMap()
726        );
727    }
728
729    /**
730     * @throws ClassCastException {@inheritDoc}
731     * 
732     * @throws NullPointerException if {@code fromKey} or {@code toKey} is null and this map uses
733     * natural ordering, or its comparator does not permit null keys
734     * 
735     * @throws IllegalArgumentException {@inheritDoc}
736     */
737    public ReadOnlyNavigableMap<K,V> subMap(
738            K fromKey, boolean fromInclusive,
739            K toKey,   boolean toInclusive
740        )
741    {
742        return InterfaceBuilder.toReadOnlyNavigableMap(
743            fromBuilderOrTreeMap
744                ? ((ROTreeMapBuilder<K, V>) this.treeMap)._subMap
745                    (fromKey, fromInclusive, toKey, toInclusive, friendClassBadge)
746                : this.treeMap.subMap(fromKey, fromInclusive, toKey, toInclusive)
747        );
748    }
749
750    /**
751     * @throws ClassCastExceptionv{@inheritDoc}
752     * 
753     * @throws NullPointerException if {@code toKey} is nullvand this map uses natural ordering, or
754     * its comparator does not permit null keys
755     * 
756     * @throws IllegalArgumentException {@inheritDoc}
757     */
758    public ReadOnlyNavigableMap<K,V> headMap(K toKey, boolean inclusive)
759    {
760        return InterfaceBuilder.toReadOnlyNavigableMap(
761            fromBuilderOrTreeMap
762                ? ((ROTreeMapBuilder<K, V>) this.treeMap)._headMap
763                    (toKey, inclusive, friendClassBadge)
764                : this.treeMap.headMap(toKey, inclusive)
765        );
766    }
767
768    /**
769     * @throws ClassCastException {@inheritDoc}
770     * 
771     * @throws NullPointerException if {@code fromKey} is null and this map uses natural ordering,
772     * or its comparator does not permit null keys
773     * 
774     * @throws IllegalArgumentException {@inheritDoc}
775     */
776    public ReadOnlyNavigableMap<K,V> tailMap(K fromKey, boolean inclusive)
777    {
778        return InterfaceBuilder.toReadOnlyNavigableMap(
779            fromBuilderOrTreeMap
780                ? ((ROTreeMapBuilder<K, V>) this.treeMap)._tailMap
781                    (fromKey, inclusive, friendClassBadge)
782                : this.treeMap.tailMap(fromKey, inclusive)
783        );
784    }
785
786    /**
787     * @throws ClassCastException {@inheritDoc}
788     * 
789     * @throws NullPointerException if {@code fromKey} or {@code toKey} is null and this map uses
790     * natural ordering, or its comparator does not permit null keys
791     * 
792     * @throws IllegalArgumentException {@inheritDoc}
793     */
794    public ReadOnlySortedMap<K,V> subMap(K fromKey, K toKey)
795    {
796        return InterfaceBuilder.toReadOnlySortedMap(
797            fromBuilderOrTreeMap
798                ? ((ROTreeMapBuilder<K, V>) this.treeMap)._subMap
799                    (fromKey, toKey, friendClassBadge)
800                : this.treeMap.subMap(fromKey, toKey)
801        );
802    }
803
804    /**
805     * @throws ClassCastException {@inheritDoc}
806     * 
807     * @throws NullPointerException if {@code toKey} is null and this map uses natural ordering, or
808     * its comparator does not permit null keys
809     * 
810     * @throws IllegalArgumentException {@inheritDoc}
811     */
812    public ReadOnlySortedMap<K,V> headMap(K toKey)
813    {
814        return InterfaceBuilder.toReadOnlySortedMap(
815            fromBuilderOrTreeMap
816                ? ((ROTreeMapBuilder<K, V>) this.treeMap)._headMap(toKey, friendClassBadge)
817                : this.treeMap.headMap(toKey)
818        );
819    }
820
821    /**
822     * @throws ClassCastException {@inheritDoc}
823     * 
824     * @throws NullPointerException if {@code fromKey} is null and this map uses natural ordering,
825     * or its comparator does not permit null keys
826     * 
827     * @throws IllegalArgumentException {@inheritDoc}
828     */
829    public ReadOnlySortedMap<K,V> tailMap(K fromKey)
830    {
831        return InterfaceBuilder.toReadOnlySortedMap(
832            fromBuilderOrTreeMap
833                ? ((ROTreeMapBuilder<K, V>) this.treeMap)._tailMap(fromKey, friendClassBadge)
834                : this.treeMap.tailMap(fromKey)
835        );
836    }
837
838    @Override
839    public void forEach(BiConsumer<? super K, ? super V> action)
840    { this.treeMap.forEach(action); }
841
842
843    // ********************************************************************************************
844    // ********************************************************************************************
845    // Misc Stuff that is defined in a super-class - for java.util, but not for Java.ReadOnly
846    // ********************************************************************************************
847    // ********************************************************************************************
848
849
850    public boolean isEmpty()
851    { return this.treeMap.isEmpty(); }
852
853
854    // ********************************************************************************************
855    // ********************************************************************************************
856    // java.lang.Object
857    // ********************************************************************************************
858    // ********************************************************************************************
859
860
861    /**
862     * Returns a {@code String} representation of this map. The {@code String} representation
863     * consists of a list of key-value mappings in the order returned by the map's entrySet view's
864     * iterator, enclosed in braces ({@code "{}"}). Adjacent mappings are separated by the
865     * characters {@code ", "} (comma and space).  Each key-value mapping is rendered as the key
866     * followed by an equals sign ({@code "="}) followed by the associated value.  Keys and values
867     * are converted to {@code String's} as by {@code String.valueOf(Object)}.
868     * 
869     * @return a {@code String} representation of this {@code TreeMap} 
870     */
871    public String toString()
872    {
873        return ROHelpers.toString(
874            this.treeMap, // if the map contains itself, it is needed for printing purposes
875            fromBuilderOrTreeMap
876                ? ((ROTreeMapBuilder<K, V>) this.treeMap)._entrySet(friendClassBadge)
877                : this.treeMap.entrySet()
878        );
879    }
880
881    /**
882     * Compares the specified Object with this Map for equality, as per the definition in the 
883     * class {@code java.util.TreeMap}.
884     *
885     * @param  o object to be compared for equality with this {@code ReadOnlyTreeMap}.
886     * @return {@code TRUE} if the specified Object is equal to this map
887     */
888    public boolean equals(Object o)
889    { return ROHelpers.roMapEq(this, o); }
890
891    /**
892     * Returns the hash code value for this Map as per the definition in the class
893     * {@code java.util.TreeMap}.
894     */
895    public int hashCode() 
896    { return this.treeMap.hashCode(); }
897
898}