• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.timezone.location.storage.s2;
18 
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Collections;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Objects;
25 import java.util.Spliterator;
26 import java.util.function.Consumer;
27 
28 /**
29  * Wraps a collection of {@link S2LevelRange} objects, sorted by {@link
30  * S2LevelRange#getStartCellId()} that must all be at the same level and must not overlap. Gaps
31  * are permitted.
32  *
33  * @param <T> the exact subtype of {@link S2LevelRange}
34  */
35 public final class SortedS2Ranges<T extends S2LevelRange> implements Iterable<T> {
36 
37     private final int mS2Level;
38 
39     private final List<T> mRanges;
40 
SortedS2Ranges(int s2Level, List<T> ranges)41     private SortedS2Ranges(int s2Level, List<T> ranges) {
42         mS2Level = s2Level;
43         mRanges = Collections.unmodifiableList(new ArrayList<>(ranges));
44     }
45 
46     /**
47      * Creates a {@link SortedS2Ranges} from a pre-sorted set of ranges with the same S2 level.
48      *
49      * @thorws IllegalArgumentException if the ranges are at different levels, ranges are not
50      *     sorted, or ranges overlap
51      */
createFromSorted( int s2Level, T... ranges)52     public static <T extends S2LevelRange> SortedS2Ranges<T> createFromSorted(
53             int s2Level, T... ranges) {
54         return createFromSorted(s2Level, Arrays.asList(ranges));
55     }
56 
57     /**
58      * Creates a {@link SortedS2Ranges} from a pre-sorted set of ranges with the same S2 level.
59      *
60      * @thorws IllegalArgumentException if the ranges are at different levels, ranges are not
61      *     sorted, or ranges overlap
62      */
createFromSorted( int s2Level, List<T> ranges)63     public static <T extends S2LevelRange> SortedS2Ranges<T> createFromSorted(
64             int s2Level, List<T> ranges) {
65         // Validate - look for overlapping ranges or ranges of the wrong level.
66         S2LevelRange previousRange = null;
67         for (S2LevelRange currentRange : ranges) {
68             int currentRangeLevel = currentRange.getS2Level();
69             // Validate all the levels are the same.
70             if (s2Level != currentRangeLevel) {
71                 throw new IllegalArgumentException(
72                         "currentRange=" + currentRange + " is not at level " + s2Level);
73             }
74 
75             if (previousRange != null) {
76                 if (previousRange.overlaps(currentRange)) {
77                     throw new IllegalArgumentException("previous range " + previousRange
78                             + " overlaps next range " + currentRange);
79                 }
80                 if (!previousRange.startsBefore(currentRange)) {
81                     throw new IllegalArgumentException("previous range " + previousRange
82                             + " must start before next range " + currentRange);
83                 }
84             }
85 
86             previousRange = currentRange;
87         }
88         return new SortedS2Ranges<>(s2Level, ranges);
89     }
90 
91     /** Returns the S2 level of the ranges. */
getS2Level()92     public int getS2Level() {
93         return mS2Level;
94     }
95 
96     /** Returns an unmodifiable list of all of the ranges. */
getRanges()97     public List<T> getRanges() {
98         return mRanges;
99     }
100 
101     @Override
iterator()102     public Iterator<T> iterator() {
103         return mRanges.iterator();
104     }
105 
106     @Override
forEach(Consumer<? super T> action)107     public void forEach(Consumer<? super T> action) {
108         mRanges.forEach(action);
109     }
110 
111     @Override
spliterator()112     public Spliterator<T> spliterator() {
113         return mRanges.spliterator();
114     }
115 
116     @Override
equals(Object o)117     public boolean equals(Object o) {
118         if (this == o) {
119             return true;
120         }
121         if (o == null || getClass() != o.getClass()) {
122             return false;
123         }
124         SortedS2Ranges<?> that = (SortedS2Ranges<?>) o;
125         return mS2Level == that.mS2Level
126                 && mRanges.equals(that.mRanges);
127     }
128 
129     @Override
hashCode()130     public int hashCode() {
131         return Objects.hash(mS2Level, mRanges);
132     }
133 
134     @Override
toString()135     public String toString() {
136         return "SortedS2Ranges{"
137                 + "mS2Level=" + mS2Level
138                 + ", mRanges=" + mRanges
139                 + '}';
140     }
141 }
142