Ignore:
Timestamp:
2016-01-03T18:13:45+01:00 (8 years ago)
Author:
bastiK
Message:

refactor some code from StyleCache into separate classes (see #9891)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/mappaint/StyleCache.java

    r9278 r9284  
    22package org.openstreetmap.josm.gui.mappaint;
    33
    4 import java.util.ArrayList;
    5 import java.util.Arrays;
    6 import java.util.Collection;
    7 import java.util.Iterator;
    8 import java.util.List;
    9 import java.util.Objects;
    10 
    114import org.openstreetmap.josm.data.osm.Storage;
    12 import org.openstreetmap.josm.gui.mappaint.styleelement.StyleElement;
    13 import org.openstreetmap.josm.tools.Pair;
    145
    156/**
    167 * Caches styles for a single primitive.
    17  * Splits the range of possible scale values (0 < scale < +Infinity) into multiple
    18  * subranges, for each scale range it keeps a list of styles.
    19  * Immutable class, equals & hashCode is required (the same for StyleList, StyleElement
    20  and its subclasses).
    218 */
    22 public final class StyleCache {
    23     /* list of boundaries for the scale ranges */
    24     private final List<Double> bd;
    25     /* styles for each scale range */
    26     private final List<StyleList> data;
     9public final class StyleCache extends DividedScale<StyleElementList> {
    2710
    2811    // TODO: clean up the intern pool from time to time (after purge or layer removal)
     
    3114    public static final StyleCache EMPTY_STYLECACHE = (new StyleCache()).intern();
    3215
    33     private StyleCache() {
    34         bd = new ArrayList<>();
    35         bd.add(0.0);
    36         bd.add(Double.POSITIVE_INFINITY);
    37         data = new ArrayList<>();
    38         data.add(null);
     16    private StyleCache(StyleCache sc) {
     17        super(sc);
    3918    }
    4019
    41     private StyleCache(StyleCache s) {
    42         bd = new ArrayList<>(s.bd);
    43         data = new ArrayList<>(s.data);
     20    private StyleCache() {
     21        super();
    4422    }
    4523
    4624    /**
    47      * List of Styles, immutable
     25     * Add data object which is valid for the given range.
     26     *
     27     * This is only possible, if there is no data for the given range yet.
     28     *
     29     * @param o data object
     30     * @param r the valid range
     31     * @return a new, updated, <code>DividedScale</code> object
    4832     */
    49     public static class StyleList implements Iterable<StyleElement> {
    50         private final List<StyleElement> lst;
    51 
    52         /**
    53          * Constructs a new {@code StyleList}.
    54          */
    55         public StyleList() {
    56             lst = new ArrayList<>();
    57         }
    58 
    59         public StyleList(StyleElement... init) {
    60             lst = new ArrayList<>(Arrays.asList(init));
    61         }
    62 
    63         public StyleList(Collection<StyleElement> sl) {
    64             lst = new ArrayList<>(sl);
    65         }
    66 
    67         public StyleList(StyleList sl, StyleElement s) {
    68             lst = new ArrayList<>(sl.lst);
    69             lst.add(s);
    70         }
    71 
    72         @Override
    73         public Iterator<StyleElement> iterator() {
    74             return lst.iterator();
    75         }
    76 
    77         public boolean isEmpty() {
    78             return lst.isEmpty();
    79         }
    80 
    81         public int size() {
    82             return lst.size();
    83         }
    84 
    85         @Override
    86         public String toString() {
    87             return lst.toString();
    88         }
    89 
    90         @Override
    91         public boolean equals(Object obj) {
    92             if (obj == null || getClass() != obj.getClass())
    93                 return false;
    94             final StyleList other = (StyleList) obj;
    95             return Objects.equals(lst, other.lst);
    96         }
    97 
    98         @Override
    99         public int hashCode() {
    100             return lst.hashCode();
    101         }
    102     }
    103 
    104     /**
    105      * looks up styles for a certain scale value
    106      * @param scale scale
    107      * @return style list
    108      */
    109     public StyleList get(double scale) {
    110         if (scale <= 0)
    111             throw new IllegalArgumentException("scale must be <= 0 but is "+scale);
    112         for (int i = 0; i < data.size(); ++i) {
    113             if (bd.get(i) < scale && scale <= bd.get(i+1)) {
    114                 return data.get(i);
    115             }
    116         }
    117         throw new AssertionError();
    118     }
    119 
    120     /**
    121      * looks up styles for a certain scale value and additionally returns
    122      * the scale range for the returned styles
    123      * @param scale scale
    124      * @return pair containing syle list and range
    125      */
    126     public Pair<StyleList, Range> getWithRange(double scale) {
    127         if (scale <= 0)
    128             throw new IllegalArgumentException("scale must be <= 0 but is "+scale);
    129         for (int i = 0; i < data.size(); ++i) {
    130             if (bd.get(i) < scale && scale <= bd.get(i+1)) {
    131                 return new Pair<>(data.get(i), new Range(bd.get(i), bd.get(i+1)));
    132             }
    133         }
    134         throw new AssertionError();
    135     }
    136 
    137     public StyleCache put(StyleList sl, Range r) {
    138         return put(sl, r.getLower(), r.getUpper());
    139     }
    140 
    141     /**
    142      * add a new styles to the cache. this is only possible, if
    143      * for this scale range, there is nothing in the cache yet.
    144      * @param sl style list
    145      * @param lower lower bound
    146      * @param upper upper bound
    147      * @return interned style cache
    148      */
    149     public StyleCache put(StyleList sl, double lower, double upper) {
     33    @Override
     34    public StyleCache put(StyleElementList o, Range r) {
    15035        StyleCache s = new StyleCache(this);
    151         s.putImpl(sl, lower, upper);
     36        s.putImpl(o, r.getLower(), r.getUpper());
    15237        s.consistencyTest();
    153         return s.intern();
    154     }
    155 
    156     // this exception type is for debugging #8997 and can later be replaced
    157     // by AssertionError
    158     public static class RangeViolatedError extends Error {
    159         public RangeViolatedError() {
    160         }
    161 
    162         public RangeViolatedError(String message) {
    163             super(message);
    164         }
    165     }
    166 
    167     /**
    168      * ASCII-art explanation:
    169      *
    170      *              data[i]
    171      *  --|-------|---------|--
    172      * bd[i-1]  bd[i]    bd[i+1]
    173      *
    174      *         (--------]
    175      *       lower     upper
    176      * @param sl style list
    177      * @param lower lower bound
    178      * @param upper upper bound
    179      */
    180     private void putImpl(StyleList sl, double lower, double upper) {
    181         int i = 0;
    182         while (bd.get(i) < lower) {
    183             ++i;
    184         }
    185         if (bd.get(i) == lower) {
    186             if (upper > bd.get(i+1))
    187                 throw new RangeViolatedError("the new range must be within a single subrange (1)");
    188             if (data.get(i) != null)
    189                 throw new RangeViolatedError("the new range must be within a subrange that has no data");
    190 
    191             if (bd.get(i+1) == upper) {
    192                 //  --|-------|--------|--
    193                 //   i-1      i       i+1
    194                 //            (--------]
    195                 data.set(i, sl);
    196             } else {
    197                 //  --|-------|--------|--
    198                 //   i-1      i       i+1
    199                 //            (-----]
    200                 bd.add(i+1, upper);
    201                 data.add(i, sl);
    202             }
    203             return;
    204         } else {
    205             if (bd.get(i) < upper)
    206                 throw new RangeViolatedError("the new range must be within a single subrange (2)");
    207             if (data.get(i-1) != null)
    208                 throw new AssertionError();
    209 
    210             //  --|-------|--------|--
    211             //   i-1      i       i+1
    212             //       (--]   or
    213             //       (----]
    214             bd.add(i, lower);
    215             data.add(i, sl);
    216 
    217             //  --|--|----|--------|--
    218             //   i-1 i   i+1      i+2
    219             //       (--]
    220             if (bd.get(i+1) > upper) {
    221                 bd.add(i+1, upper);
    222                 data.add(i+1, null);
    223             }
    224             return;
    225         }
    226     }
    227 
    228     public void consistencyTest() {
    229         if (bd.size() < 2) throw new AssertionError(bd);
    230         if (data.isEmpty()) throw new AssertionError(data);
    231         if (bd.size() != data.size() + 1) throw new AssertionError();
    232         if (bd.get(0) != 0) throw new AssertionError();
    233         if (bd.get(bd.size() - 1) != Double.POSITIVE_INFINITY) throw new AssertionError();
    234         for (int i = 0; i < data.size() - 1; ++i) {
    235             if (bd.get(i) >= bd.get(i + 1)) throw new AssertionError();
    236         }
     38        s.intern();
     39        return s;
    23740    }
    23841
     
    24245     * @return style cache
    24346     */
    244     public StyleCache intern() {
     47    private StyleCache intern() {
    24548        return internPool.putUnique(this);
    24649    }
    247 
    248     @Override
    249     public boolean equals(Object obj) {
    250         if (obj == null || getClass() != obj.getClass())
    251             return false;
    252         final StyleCache other = (StyleCache) obj;
    253         return bd.equals(other.bd) && data.equals(other.data);
    254     }
    255 
    256     @Override
    257     public int hashCode() {
    258         int hash = 7;
    259         hash = 23 * hash + bd.hashCode();
    260         hash = 23 * hash + data.hashCode();
    261         return hash;
    262     }
    263 
    264     @Override
    265     public String toString() {
    266         return "SC{" + bd + ' ' + data + '}';
    267     }
    26850}
Note: See TracChangeset for help on using the changeset viewer.