-
Notifications
You must be signed in to change notification settings - Fork 14
/
Interval.java
739 lines (690 loc) · 27.7 KB
/
Interval.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
package com.lodborg.intervaltree;
import java.util.Comparator;
/**
* A representation of a generic interval. The interval can be open or closed (the start
* and end points may be inclusive or exclusive), as well as bounded and unbounded (it can
* extend to positive or negative infinity).
*
* The class doesn't assume that the intervals are numeric, instead it is generalized to
* represent a contiguous subset of elements, where contiguity is defined with respect to
* an arbitrary total order function. These elements can be for example {@link java.util.Date}s
* or basically any type, the elements of which can be compared to one another. Since the
* class requires its generic variable to implement the {@link Comparable} interface, all
* comparisons in the internals of the {@code Interval} class are done via the interface method.
*
* When subclassing the {@code Interval} class, note that the start and end points of the
* interval <strong>can</strong> be {@code null}. A {@code null} start point represents
* the negative infinity and a {@code null} end point represents positive infinity. This
* fact needs to be kept in mind in particular when overwriting methods with default
* implementations in the {@code Interval} class, such as {@link #contains(Comparable)},
* {@link #isLeftOf(Comparable)}, and in particular {@link #equals(Object)} and
* {@link #hashCode()}.
*
* @param <T> The type that represents a single point from the domain of definition of the
* interval.
*/
public abstract class Interval<T extends Comparable<? super T>> {
private T start, end;
private boolean isStartInclusive, isEndInclusive;
/**
* An enum representing all possible types of bounded intervals.
*/
public enum Bounded {
/**
* An interval, in which both start and end point are exclusive.
*/
OPEN,
/**
* An interval, in which both start and end point are inclusive.
*/
CLOSED,
/**
* An interval, in which the start is exclusive and the end is inclusive.
*/
CLOSED_RIGHT,
/**
* An interval, in which the start is inclusive and the end is exclusive.
*/
CLOSED_LEFT
}
public enum Unbounded {
/**
* An interval extending to positive infinity and having an exclusive start
* point as a lower bound. For example, (5, +inf)
*/
OPEN_LEFT,
/**
* An interval extending to positive infinity and having an inclusive start
* point as a lower bound. For example, [5, +inf)
*/
CLOSED_LEFT,
/**
* An interval extending to negative infinity and having an exclusive end
* point as an upper bound. For example, (-inf, 5)
*/
OPEN_RIGHT,
/**
* An interval extending to negative infinity and having an inclusive end
* point as an upper bound. For example, (-inf, 5]
*/
CLOSED_RIGHT
}
/**
* Instantiates a new interval representing all points in the domain of definition,
* i.e. this will instantiate the interval (-inf, +inf).
*/
public Interval(){
isStartInclusive = true;
isEndInclusive = true;
}
/**
* Instantiates a new bounded interval.
*
* @param start The start point of the interval
* @param end The end point of the interval.
* @param type Description of whether the interval is open/closed at one or both
* of its ends. See {@link Bounded the documentation of the Bounded enum}
* for more information on the different possibilities.
*/
public Interval(T start, T end, Bounded type){
this.start = start;
this.end = end;
if (type == null)
type = Bounded.CLOSED;
switch (type){
case OPEN:
break;
case CLOSED:
isStartInclusive = true;
isEndInclusive = true;
break;
case CLOSED_RIGHT:
isEndInclusive = true;
break;
default:
isStartInclusive = true;
break;
}
}
/**
* Instantiates a new unbounded interval - an interval that extends to positive or
* negative infinity. The interval will be bounded by either the start point
* or the end point and unbounded in the other point.
*
* @param value The bounding value for either the start or the end point.
* @param type Describes, if the interval extends to positive or negative infinity,
* as well as if it is open or closed at the bounding point. See {@link Unbounded
* the Unbounded enum} for description of the different possibilities.
*/
public Interval(T value, Unbounded type){
if (type == null)
type = Unbounded.CLOSED_RIGHT;
switch (type){
case OPEN_LEFT:
start = value;
isStartInclusive = false;
isEndInclusive = true;
break;
case CLOSED_LEFT:
start = value;
isStartInclusive = true;
isEndInclusive = true;
break;
case OPEN_RIGHT:
end = value;
isStartInclusive = true;
isEndInclusive = false;
break;
default:
end = value;
isStartInclusive = true;
isEndInclusive = true;
break;
}
}
/**
* Checks if the current interval contains no points.
*
* <p>In particular, if the end point is less than the start point, then the interval is
* considered to be empty. There are, however other instances, in which an interval is empty.
* For example, in the class {@link IntegerInterval}, an open interval, whose start and end
* points differ by one, for example the interval (4, 5), is empty, because it contains no integers
* in it. The same interval, however, will <strong>not</strong> be considered empty in the
* {@link DoubleInterval} class, because there are Double numbers within this interval.
* </p>
*
* @return {@code true}, if the current interval is empty or {@code false} otherwise.
*/
public boolean isEmpty() {
if (start == null || end == null)
return false;
int compare = start.compareTo(end);
if (compare>0)
return true;
if (compare == 0 && (!isEndInclusive || !isStartInclusive))
return true;
return false;
}
/**
* Used to create new instances of a specific {@code Interval} subclass.
* <p>
* The {@code Interval} class aims to avoid reflexion. On several occasions, however, the class
* needs to create new instances of the {@code Interval} class. To be able to guarantee that they
* will have the desired runtime type, the {@link #create()} method of a specific reference object
* is called.
* </p>
* <p>
* Generally, the only thing you need to do in your implementation of this abstract method is
* to call the default constructor of your subclass and return the new interval.
* </p>
* @return A new instance of the particular {@code Interval} class.
*/
protected abstract Interval<T> create();
/**
* Returns the center of the current interval. If the center of the interval exists, but can't
* be determined, return any point inside the interval. This method will be used only to
* instantiate the midpoint of a new {@link TreeNode} inside a {@link IntervalTree}, which is why
* it is not necessary to return exactly the center of the interval, but it will help the
* {@link IntervalTree} perform slightly better.
*
* @return The center point of the current interval, if it exists or {@code null} otherwise. If the
* center exists but can't be determined correctly, return any point inside the interval.
*/
public abstract T getMidpoint();
/**
* Creates a new instance of the particular {@code Interval} subclass.
*
* @param start The start point of the interval
* @param isStartInclusive {@code true}, if the start is inclusive or false otherwise
* @param end The end point of the interval
* @param isEndInclusive {@code true}, if the end is inclusive or false otherwise
* @return The newly created interval.
*/
protected Interval<T> create(T start, boolean isStartInclusive, T end, boolean isEndInclusive){
Interval<T> interval = create();
interval.start = start;
interval.isStartInclusive = isStartInclusive;
interval.end = end;
interval.isEndInclusive = isEndInclusive;
return interval;
}
/** Returns the start point of the interval. */
public T getStart(){
return start;
}
/** Returns the end point of the interval. */
public T getEnd(){
return end;
}
/** Returns {@code true}, if the start point is a part of the interval, or false otherwise. */
public boolean isStartInclusive(){
return isStartInclusive;
}
/** Returns {@code true}, if the end point is a part of the interval, or false otherwise. */
public boolean isEndInclusive(){
return isEndInclusive;
}
/**
* Determines if the current interval is a single point.
*
* @return {@code true}, if the current interval represents a single point.
*/
public boolean isPoint(){
if (start == null || end == null) {
return false;
}
return start.compareTo(end) == 0 && isStartInclusive && isEndInclusive;
}
/**
* Determines if the current interval contains a query point.
*
* @param query The point.
* @return {@code true}, if the current interval contains the {@code query} point or false otherwise.
*/
public boolean contains(T query){
if (isEmpty() || query == null) {
return false;
}
int startCompare = start == null ? 1 : query.compareTo(start);
int endCompare = end == null ? -1 : query.compareTo(end);
if (startCompare > 0 && endCompare < 0) {
return true;
}
return (startCompare == 0 && isStartInclusive) || (endCompare == 0 && isEndInclusive);
}
/**
* Returns an interval, representing the intersection of two intervals. More formally, for every
* point {@code x} in the returned interval, {@code x} will belong in both the current interval
* and the {@code other} interval.
*
* @param other The other interval
* @return The intersection of the current interval wih the {@code other} interval.
*/
public Interval<T> getIntersection(Interval<T> other){
if (other == null || isEmpty() || other.isEmpty())
return null;
// Make sure that the one with the smaller starting point gets intersected with the other.
// If necessary, swap the intervals
if ((other.start == null && start != null) || (start != null && start.compareTo(other.start)>0))
return other.getIntersection(this);
if (end != null && other.start != null && (end.compareTo(other.start) < 0 || (end.compareTo(other.start) == 0 && (!isEndInclusive || !other.isStartInclusive))))
return null;
T newStart, newEnd;
boolean isNewStartInclusive, isNewEndInclusive;
// If other.start is null, this means my start is also null, because we made sure
// that the caller object hast the smaller start point => the new start is null
if (other.start == null){
newStart = null;
isNewStartInclusive = true;
} else {
newStart = other.start;
if (start != null && other.start.compareTo(start) == 0)
isNewStartInclusive = other.isStartInclusive && isStartInclusive;
else
isNewStartInclusive = other.isStartInclusive;
}
if (end == null){
newEnd = other.end;
isNewEndInclusive = other.isEndInclusive;
} else if (other.end == null){
newEnd = end;
isNewEndInclusive = isEndInclusive;
} else {
int compare = end.compareTo(other.end);
if (compare == 0){
newEnd = end;
isNewEndInclusive = isEndInclusive && other.isEndInclusive;
} else if (compare < 0){
newEnd = end;
isNewEndInclusive = isEndInclusive;
} else {
newEnd = other.end;
isNewEndInclusive = other.isEndInclusive;
}
}
Interval<T> intersection = create(newStart, isNewStartInclusive, newEnd, isNewEndInclusive);
return intersection.isEmpty() ? null : intersection;
}
/**
* Checks if the current interval contains the entirety of another interval. More formally,
* this method returns {@code true}, if for every point {@code x} from the interval {@code another}
* this point {@code x} also belongs to the current interval.
*
* @param another Another interval.
* @return {@code true}, if the interval {@code another} is contained in the current interval in
* its entirety, or {@code false} otherwise.
*/
public boolean contains(Interval<T> another){
if (another == null || isEmpty() || another.isEmpty()){
return false;
}
Interval<T> intersection = getIntersection(another);
return intersection != null && intersection.equals(another);
}
/**
* Checks if the current interval intersects another interval. More formally, this method
* returns {@code true} if there is at least one point the current interval, that also
* belongs to the {@code query} interval.
*
* @param query The interval being checked for intersection with the current interval.
* @return {@code true}, if the two intervals intersect or {@code false} otherwise.
*/
public boolean intersects(Interval<T> query){
if (query == null)
return false;
Interval<T> intersection = getIntersection(query);
return intersection != null;
}
/**
* This method checks, if this current interval is entirely to the right of a point. More formally,
* the method will return {@code true}, if for every point {@code x} from the current interval the inequality
* {@code x} > {@code point} holds. If the parameter {@code inclusive} is set to {@code false}, this
* method will return {@code true} also if the start point of the interval is equal to the reference
* {@code point}.
*
* @param point The reference point
* @param inclusive {@code false} if the reference {@code point} is allowed to be the start point
* of the current interval.
* @return {@code true}, if the current interval is entirely to the right of the {@code other}
* interval, or {@code false} instead.
*/
public boolean isRightOf(T point, boolean inclusive){
if (point == null || start == null)
return false;
int compare = point.compareTo(start);
if (compare != 0)
return compare < 0;
return !isStartInclusive() || !inclusive;
}
/**
* This method checks, if this current interval is entirely to the right of a point. More formally,
* the method will return true, if for every point {@code x} from the current interval the inequality
* {@code x} > {@code point} holds. This formal definition implies in particular that if the start point
* of the current interval is equal to the reference {@code point} and the end point is open, the method
* will return {@code true}.
*
* @param point The reference point
* @return {@code true}, if the current interval is entirely to the right of the {@code other}
* interval, or {@code false} instead.
*/
public boolean isRightOf(T point){
return isRightOf(point, true);
}
/**
* This method checks, if this current interval is entirely to the right of another interval
* with no common points. More formally, the method will return true, if for every point {@code x}
* from the current interval and for every point {@code y} from the {@code other} interval the
* inequality {@code x} > {@code y} holds. This formal definition implies in particular that if the start point
* of the current interval is equal to the end point of the {@code other} interval, the method
* will return {@code false} only if both points are inclusive and {@code true} in all other cases.
*
* @param other The reference interval
* @return {@code true}, if the current interval is entirely to the right of the {@code other}
* interval, or {@code false} instead.
*/
public boolean isRightOf(Interval<T> other){
if (other == null || other.isEmpty())
return false;
return isRightOf(other.end, other.isEndInclusive());
}
/**
* This method checks, if this current interval is entirely to the left of a point. More formally,
* the method will return {@code true}, if for every point {@code x} from the current interval the inequality
* {@code x} < {@code point} holds. If the parameter {@code inclusive} is set to {@code false}, this
* method will return {@code true} also if the end point of the interval is equal to the reference
* {@code point}.
*
* @param point The reference point
* @param inclusive {@code false} if the reference {@code point} is allowed to be the end point
* of the current interval.
* @return {@code true}, if the current interval is entirely to the left of the {@code other}
* interval, or {@code false} instead.
*/
public boolean isLeftOf(T point, boolean inclusive){
if (point == null || end == null)
return false;
int compare = point.compareTo(end);
if (compare != 0)
return compare > 0;
return !isEndInclusive() || !inclusive;
}
/**
* This method checks, if this current interval is entirely to the left of a point. More formally,
* the method will return true, if for every point {@code x} from the current interval the inequality
* {@code x} < {@code point} holds. This formal definition implies in particular that if the end point
* of the current interval is equal to the reference {@code point} and the end point is open, the method
* will return {@code true}.
*
* @param point The reference point
* @return {@code true}, if the current interval is entirely to the left of the {@code other}
* interval, or {@code false} instead.
*/
public boolean isLeftOf(T point){
return isLeftOf(point, true);
}
/**
* This method checks, if this current interval is entirely to the left of another interval
* with no common points. More formally, the method will return true, if for every point {@code x}
* from the current interval and for every point {@code y} from the {@code other} interval the
* inequality {@code x} < {@code y} holds. This formal definition implies in particular that if the end point
* of the current interval is equal to the start point of the {@code other} interval, the method
* will return {@code false} only if both points are inclusive and {@code true} in all other cases.
*
* @param other The reference interval
* @return {@code true}, if the current interval is entirely to the left of the {@code other}
* interval, or {@code false} instead.
*/
public boolean isLeftOf(Interval<T> other){
if (other == null || other.isEmpty())
return false;
return isLeftOf(other.start, other.isStartInclusive());
}
/**
* A {@link Comparator} that only considers the start points of the intervals. It can not and must
* not be used as a standalone {@link Comparator}. It only serves to create a more readable and
* modular code.
*/
private int compareStarts(Interval<T> other){
if (start == null && other.start == null)
return 0;
if (start == null)
return -1;
if (other.start == null)
return 1;
int compare = start.compareTo(other.start);
if (compare != 0)
return compare;
if (isStartInclusive ^ other.isStartInclusive)
return isStartInclusive ? -1 : 1;
return 0;
}
/**
* A {@link Comparator} that only considers the end points of the intervals. It can not and must
* not be used as a standalone {@link Comparator}. It only serves to create a more readable and
* modular code.
*/
private int compareEnds(Interval<T> other){
if (end == null && other.end == null)
return 0;
if (end == null)
return 1;
if (other.end == null)
return -1;
int compare = end.compareTo(other.end);
if (compare != 0)
return compare;
if (isEndInclusive ^ other.isEndInclusive)
return isEndInclusive ? 1 : -1;
return 0;
}
/**
* A comparator that can be used as a parameter for sorting functions. The start comparator sorts the intervals
* in <em>ascending</em> order by placing the intervals with a smaller start point before intervals with greater
* start points. This corresponds to a line sweep from left to right.
* <p>
* Intervals with start point null (negative infinity) are considered smaller than all other intervals.
* If two intervals have the same start point, the closed start point is considered smaller than the open one.
* For example, [0, 2) is considered smaller than (0, 2).
* </p>
* <p>
* To ensure that this comparator can also be used in sets it considers the end points of the intervals, if the
* start points are the same. Otherwise the set will not be able to handle two different intervals, sharing
* the same starting point, and omit one of the intervals.
* </p>
* <p>
* Since this is a static method of a generic class, it involves unchecked calls to class methods. It is left to
* ths user to ensure that she compares intervals from the same class, otherwise an exception might be thrown.
* </p>
*/
public static Comparator<Interval> sweepLeftToRight = new Comparator<Interval>() {
@Override
public int compare(Interval a, Interval b) {
int compare = a.compareStarts(b);
if (compare != 0)
return compare;
compare = a.compareEnds(b);
if (compare != 0)
return compare;
return a.compareSpecialization(b);
}
};
/**
* A comparator that can be used as a parameter for sorting functions. The end comparator sorts the intervals
* in <em>descending</em> order by placing the intervals with a greater end point before intervals with smaller
* end points. This corresponds to a line sweep from right to left.
* <p>
* Intervals with end point null (positive infinity) are placed before all other intervals. If two intervals
* have the same end point, the closed end point is placed before the open one. For example, [0, 10) is placed
* after (0, 10].
* </p>
* <p>
* To ensure that this comparator can also be used in sets it considers the start points of the intervals, if the
* end points are the same. Otherwise the set will not be able to handle two different intervals, sharing
* the same end point, and omit one of the intervals.
* </p>
* <p>
* Since this is a static method of a generic class, it involves unchecked calls to class methods. It is left to
* ths user to ensure that she compares intervals from the same class, otherwise an exception might be thrown.
* </p>
*/
public static Comparator<Interval> sweepRightToLeft = new Comparator<Interval>() {
@Override
public int compare(Interval a, Interval b) {
int compare = b.compareEnds(a);
if (compare != 0)
return compare;
compare = b.compareStarts(a);
if (compare != 0)
return compare;
return a.compareSpecialization(b);
}
};
/**
* A method that should be overwritten by subclasses of {@code Interval}, if they have properties
* that characterize the objects of the class and are used to identify them. It is used to create
* a total order between distinct objects, that would otherwise be considered equal, if only
* the start and end points were considered. If you don't have any such special properties, you
* may leave the default implementation of this method.
* <p>
* This method functions as a traditional {@link Comparator}, bit can not and should not be used
* on its own, nor should it be implemented as a full standalone comparator. Instead, it is always
* used in conjunction with one of the two base {@link Comparator}s in the {@code Interval} class -
* {@link #sweepLeftToRight} and {@link #sweepRightToLeft}. This method will only be executed if
* the main comparator returns 0, i.e. if it considers the intervals to be equal. At that moment,
* the start and end points would already have been compared to one another, which is why this method
* should <strong>disregard the start and end points</strong> completely and only consider the
* special properties defined in the particular subclass.
* </p>
* <p>
* It is vital to overwrite this method, if you have any properties in your subclass, that identify
* the interval, such as for example user IDs, student IDs or room numbers. The two base comparators
* are used within the underlying {@link java.util.TreeSet}s, which may discard two distinct interval
* objects, that have the same start and end points.
*</p>
* @param other The object that is being compared to this interval
* @return <ul>
* <li>-1, if this object is less than the {@code other},</li>
* <li>0, if the two objects are equal,</li>
* <li>1, if this object is greater than the {@code other}.</li>
* </ul>
*/
protected int compareSpecialization(Interval<T> other){
return 0;
}
@Override
public int hashCode() {
int prime = 31;
int result = start == null ? 0 : start.hashCode();
result = prime * result +(end == null ? 0 : end.hashCode());
result = prime * result + (isStartInclusive ? 1 : 0);
result = prime * result + (isEndInclusive ? 1 : 0);
return result;
}
@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof Interval))
return false;
Interval<T> other = (Interval<T>) obj;
if (start == null ^ other.start == null)
return false;
if (end == null ^ other.end == null)
return false;
if (isEndInclusive ^ other.isEndInclusive)
return false;
if (isStartInclusive ^ other.isStartInclusive)
return false;
if (start != null && !start.equals(other.start))
return false;
if (end != null && !end.equals(other.end))
return false;
return true;
}
public Builder builder(){
return new Builder(this);
}
/**
* Used to create new intervals in an intuitive fashion by using the builder pattern.
* Since the implementation of the {@code Interval} class strives to avoid reflexion,
* despite being generic class, the {@code Builder} inner class is not static. Instead
* it is always tied to a particular object, so that it can build new objects from this
* specific runtime type.
*/
public class Builder {
private Interval<T> interval;
/**
* {@code private} constructor, used only in the internals of the {@link Interval}
* class. You can create new instances of the class by using either an existing
* object:
* <pre>existingInterval.builder()</pre>
* or by instantiating an "everything" interval with the default constructor and
* calling its {@link Interval#builder() builder} method:
* <pre>new IntegerInterval().builder()</pre>
*
* @param ref A reference object used only to determine the runtime type of the
* new object. The reference interval doesn't influence the start and
* end points of the new interval in any way.
*/
private Builder(Interval<T> ref){
interval = ref.create();
}
/**
* Sets the start point of the currently building interval to the given value.
* The interval will be open to the left. If this method is called more than
* once or in conjunction with the {@link #greaterEqual(Comparable)} method, only
* the last call in the subsequence will take effect.
*
* @param start The value for the start point of the new interval.
*/
public Builder greater(T start){
interval.start = start;
interval.isStartInclusive = false;
return this;
}
/**
* Sets the start point of the currently building interval to the given value.
* The interval will be closed to the left. If this method is called more than
* once or in conjunction with the {@link #greater(Comparable)} method, only
* the last call in the subsequence will take effect.
*
* @param start The value for the start point of the new interval.
*/
public Builder greaterEqual(T start){
interval.start = start;
interval.isStartInclusive = true;
return this;
}
/**
* Sets the end point of the currently building interval to the given value.
* The interval will be open to the right. If this method is called more than
* once or in conjunction with the {@link #lessEqual(Comparable)} method, only
* the last call in the subsequence will take effect.
*
* @param end The value for the end point of the new interval.
*/
public Builder less(T end){
interval.end = end;
interval.isEndInclusive = false;
return this;
}
/**
* Sets the end point of the currently building interval to the given value.
* The interval will be closed to the right. If this method is called more than
* once or in conjunction with the {@link #lessEqual(Comparable)} method, only
* the last call in the subsequence will take effect.
*
* @param end The value for the end point of the new interval.
*/
public Builder lessEqual(T end){
interval.end = end;
interval.isEndInclusive = true;
return this;
}
/**
* Builds the new interval
* @return The newly created interval.
*/
public Interval<T> build(){
return interval;
}
}
}