001/*
002 * ============================================================================
003 * Copyright © 2002-2019 by Thomas Thrien.
004 * All Rights Reserved.
005 * ============================================================================
006 * Licensed to the public under the agreements of the GNU Lesser General Public
007 * License, version 3.0 (the "License"). You may obtain a copy of the License at
008 *
009 *      http://www.gnu.org/licenses/lgpl.html
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014 * License for the specific language governing permissions and limitations
015 * under the License.
016 */
017
018package org.tquadrat.foundation.util;
019
020import static org.apiguardian.api.API.Status.STABLE;
021
022import java.io.Serializable;
023
024import org.apiguardian.api.API;
025import org.tquadrat.foundation.annotation.ClassVersion;
026import org.tquadrat.foundation.lang.Pair;
027import org.tquadrat.foundation.util.internal.RangeMapImpl;
028
029/**
030 *  <p>{@code A range map is used to map a value to a given numerical range.}
031 *  The lower border of the lowest range is always
032 *  {@link Double#MAX_VALUE -Double.MAX_VALUE}.
033 *
034 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
035 *  @version $Id: RangeMap.java 1017 2022-02-10 19:39:09Z tquadrat $
036 *  @since 0.0.7
037 *
038 *  @param <T>  The type of the mapped value.
039 *
040 *  @see RangeFunctions
041 *
042 *  @UMLGraph.link
043 */
044@ClassVersion( sourceVersion = "$Id: RangeMap.java 1017 2022-02-10 19:39:09Z tquadrat $" )
045@API( status = STABLE, since = "0.0.7" )
046public sealed interface RangeMap<T> extends Serializable
047    permits RangeMapImpl
048{
049        /*---------*\
050    ====** Methods **==========================================================
051        \*---------*/
052    /**
053     *  <p>{@summary Adds a range.} If there is already a range with the given
054     *  {@code key}, it will <i>not</i> replaced by the new one!</p>
055     *  <p>The method will return a reference to the map itself; this allows
056     *  to chain it with other
057     *  {@code #addRange(double, Object)}
058     *  method calls.</p>
059     *
060     *  @return A reference to this range map instance.
061     *
062     *  @param  key The upper border of the range.
063     *  @param  value   The mapped value.
064     */
065    public RangeMap<T> addRange( final double key, final T value );
066
067    /**
068     *  Clears the range map.
069     */
070    public void clear();
071
072    /**
073     *  Returns a copy of this range map.
074     *
075     *  @param  modifiable  {@code true} if the copy can be modified,
076     *      {@code false} otherwise.
077     *  @return The copy.
078     */
079    public RangeMap<T> copy( final boolean modifiable );
080
081    /**
082     *  Returns a modifiable copy of this range map.
083     *
084     *  @return The copy.
085     */
086    public default RangeMap<T> copy() { return copy( true ); }
087
088    /**
089     *  Returns the entries in their order.
090     *
091     *  @return The entries; for an empty range map, an empty array will be
092     *      returned.
093     */
094    public Pair<Double,T>[] entries();
095
096    /**
097     *  Returns the value for the range the given key is in.
098     *
099     *  @param  key The key.
100     *  @return The value that is mapped to the range.
101     *  @throws IllegalStateException   No entry was added to the range map; it
102     *      is empty.
103     */
104    public T get( final double key ) throws IllegalStateException;
105
106    /**
107     *  <p>{@summary Returns {@code true} if the range map is empty.}</p>
108     *  <p>Usually, a range map is empty only after a call to
109     *  {@link #clear()}
110     *  or when the last entry was removed by a call to
111     *  {@link #removeRange(double)},
112     *  but special implementations of this interface can handle this
113     *  differently.</p>
114     *
115     *  @return {@code true} if the range map is empty, {@code false}
116     *      if there were already some entries added to it.
117     */
118    public boolean isEmpty();
119
120    /**
121     *  The factory method for a new instance of {@code RangeMap}.
122     *
123     *  @param  <V> The value type for the range map.
124     *  @param  defaultValue    The default value; this is the that is returned
125     *      if the key is above all range limits.
126     *  @param  includes    {@code true} if the limit belongs to the
127     *      range, {@code false} otherwise.
128     *  @return The new range map instance.
129     */
130    public static <V> RangeMap<V> of( final V defaultValue, final boolean includes )
131    {
132        final RangeMap<V> retValue = new RangeMapImpl<>( includes );
133        retValue.setDefault( defaultValue );
134
135        //---* Done *----------------------------------------------------------
136        return retValue;
137    }   //  of()
138
139    /**
140     *  <p>{@summary Removes a range.} Nothing happens if there is no range for
141     *  the given key value.</p>
142     *  <p>After this operation, the range map can be empty.</p>
143     *  <p>The method will return a reference to the map itself; this allows
144     *  to chain it with
145     *  {@link #addRange(double, Object)} method calls.</p>
146     *
147     *  @param  key The key for the range to remove.
148     *  @return A reference to this range map instance.
149     */
150    public RangeMap<T> removeRange( double key );
151
152    /**
153     *  <p>{@summary Replaces an already existing range.} If there is no range
154     *  for the given key value, the method will just add a new range.</p>
155     *  <p>The method will return a reference to the map itself; this allows to
156     *  chain it with
157     *  {@link #addRange(double, Object)} method calls.</p>
158     *
159     *  @param  key The upper border of the range.
160     *  @param  value   The mapped value.
161     *  @return A reference to this range map instance.
162     */
163    public default RangeMap<T> replaceRange( final double key, final T value )
164    {
165        removeRange( key );
166        addRange( key, value );
167
168        //---* Done *----------------------------------------------------------
169        return this;
170    }   //  replaceRange()
171
172    /**
173     *  <p>{@summary Sets the default value and overwrites that one that was
174     *  set on creation of the range map.}</p>
175     *  <p>The default value is that one that is returned if the key is above
176     *  all range limits.</p>
177     *  <p>The method will return a reference to the map itself; this allows
178     *  to chain it with
179     *  {@link #addRange(double, Object)} method calls.</p>
180     *
181     *  @param  value   The mapped value.
182     *  @return A reference to this range map instance.
183     *
184     *  @see #of(Object,boolean)
185     */
186    public RangeMap<T> setDefault( final T value );
187}
188//  interface RangeMap
189
190/*
191 *  End of File
192 */