1 package org.varienaja.util;
2
3 import java.util.Iterator;
4 import java.util.Set;
5 import java.util.TreeSet;
6
7
8
9
10
11
12
13
14 class Range implements Comparable<Range> {
15
16 private long _start, _end;
17
18 public Range(long start, long end) {
19 setStart(start);
20 setEnd(end);
21 }
22
23 public long getEnd() {
24 return _end;
25 }
26
27 public void setEnd(long end) {
28 if (end>=_start) _end = end;
29 }
30
31 public long getStart() {
32 return _start;
33 }
34
35 public void setStart(long start) {
36 _start = start;
37 }
38
39 public boolean contains(long l) {
40 return (_start<=l) && (l<=_end);
41 }
42
43 public boolean equals(Object o) {
44 if (o instanceof Range) {
45 Range test = (Range) o;
46 return (test.getEnd()==getEnd()) && (test.getStart()==getStart());
47 } else {
48 return false;
49 }
50 }
51
52 public int hashCode() {
53 Long l = _start * _end;
54 return l.intValue();
55 }
56
57 public int compareTo(Range test) {
58 if (test.getStart()>getEnd()) {
59 return -1;
60 } else {
61 if (test.getEnd()<getStart()) {
62 return 1;
63 } else {
64 return 0;
65 }
66 }
67 }
68
69 public long itemCount() {
70 return 1+_end-_start;
71 }
72
73 public String toString() {
74 return "["+_start+"..."+_end+"]";
75 }
76
77 }
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94 public class DenseSet {
95 protected Set<Range> _ranges;
96
97 public DenseSet() {
98 _ranges = new TreeSet<Range>();
99 }
100
101
102
103
104 public int size() {
105 int result = 0;
106 for (Range range:_ranges) {
107 result += range.itemCount();
108 }
109 return result;
110 }
111
112
113
114
115
116
117 public boolean add(long l) {
118 Range candidate = findRangeContaining(l);
119 if (candidate==null) {
120
121 Range candidateSmaller = findRangeContaining(l-1);
122 Range candidateLarger = findRangeContaining(l+1);
123 if (candidateSmaller==null) {
124 if (candidateLarger==null) {
125 _ranges.add(new Range(l,l));
126 } else {
127 candidateLarger.setStart(l);
128 }
129 } else {
130 if (candidateLarger==null) {
131 candidateSmaller.setEnd(l);
132 } else {
133
134 _ranges.remove(candidateLarger);
135 candidateSmaller.setEnd(candidateLarger.getEnd());
136 }
137 }
138 return true;
139 } else {
140 return false;
141 }
142 }
143
144
145
146
147
148
149
150 public boolean remove(long l) {
151 Range range = findRangeContaining(l);
152 if (range!=null) {
153 if (range.getStart()==l) {
154
155 if (range.getEnd()>l) {
156 range.setStart(l+1);
157 } else {
158 _ranges.remove(range);
159 }
160 } else {
161
162 if (range.getEnd()==l) {
163 if (range.getStart()<l) {
164 range.setEnd(l-1);
165 } else {
166 _ranges.remove(range);
167 }
168 } else {
169
170 Range newOne = new Range(l+1,range.getEnd());
171 range.setEnd(l-1);
172 _ranges.add(newOne);
173 }
174 }
175 return true;
176 } else {
177 return false;
178 }
179 }
180
181
182
183
184
185 public void clear() {
186 _ranges.clear();
187 }
188
189
190
191
192
193
194 private Range findRangeContaining(long l) {
195
196 for (Range range:_ranges) {
197 if (range.contains(l)) return range;
198 }
199 return null;
200 }
201
202 public String toString() {
203 StringBuilder sb = new StringBuilder();
204 sb.append("Size: ");
205 sb.append(size());
206 sb.append(" Elements: ");
207 sb.append(_ranges.size());
208 sb.append(" ");
209 Iterator<Range> it = _ranges.iterator();
210 while (it.hasNext()) {
211 sb.append(it.next().toString());
212 if (it.hasNext()) sb.append(", ");
213 }
214 return sb.toString();
215 }
216
217
218
219
220
221
222 public String prettyPrint() {
223 StringBuilder sb = new StringBuilder();
224 Iterator<Range> it = _ranges.iterator();
225 while(it.hasNext()) {
226 Range range = it.next();
227 long start = range.getStart();
228 long end = range.getEnd();
229 sb.append(start);
230 if(start!=end) {
231 sb.append("-");
232 sb.append(range.getEnd());
233 }
234 if(it.hasNext()) {
235 sb.append(",");
236 }
237 }
238 return sb.toString();
239 }
240
241
242
243
244
245
246 public long get(long index) {
247 for (Range range:_ranges) {
248 index -= range.itemCount();
249 if (index<0) {
250 return range.getStart() + index + range.itemCount();
251 }
252 }
253 return -1;
254 }
255
256
257
258
259
260
261 public boolean contains(long l) {
262 return findRangeContaining(l)!=null;
263 }
264
265 public boolean equals(Object o) {
266 boolean result = false;
267 if (o instanceof DenseSet) {
268 DenseSet other = (DenseSet) o;
269 if (this.size()==other.size()) {
270 result = true;
271 Iterator<Range> it1 = _ranges.iterator();
272 Iterator<Range> it2 = other._ranges.iterator();
273 while(it1.hasNext()) {
274 Range r1 = it1.next();
275 if(it2.hasNext()) {
276 Range r2 = it2.next();
277 if(!r1.equals(r2)) {
278 break;
279 }
280 } else {
281 break;
282 }
283 }
284 }
285 }
286 return result;
287 }
288
289 public int hashCode() {
290 int result = 0;
291 for(Range range: _ranges) {
292 result = (3 * result) + range.hashCode();
293 }
294 return result;
295 }
296 }