/*
* -----------------------------------------------------------------------
* Copyright © 2013-2016 Meno Hochschild, <http://www.menodata.de/>
* -----------------------------------------------------------------------
* This file (IntervalComparator.java) is part of project Time4J.
*
* Time4J is free software: You can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* Time4J is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Time4J. If not, see <http://www.gnu.org/licenses/>.
* -----------------------------------------------------------------------
*/
package net.time4j.range;
import net.time4j.engine.TimeLine;
import java.util.Comparator;
/**
* <p>Standardimplementierung zum Sortieren von Intervallen zuerst nach
* Start und dann nach Länge. </p>
*
* @author Meno Hochschild
*/
final class IntervalComparator<T>
implements Comparator<ChronoInterval<T>> {
//~ Instanzvariablen --------------------------------------------------
private final boolean calendrical;
private final TimeLine<T> axis;
//~ Konstruktoren -----------------------------------------------------
IntervalComparator(
boolean calendrical,
TimeLine<T> axis
) {
super();
this.calendrical = calendrical;
this.axis = axis;
}
//~ Methoden ----------------------------------------------------------
@Override
public int compare(
ChronoInterval<T> o1,
ChronoInterval<T> o2
) {
Boundary<T> bs1 = o1.getStart();
Boundary<T> bs2 = o2.getStart();
if (bs1.isInfinite()) {
if (bs2.isInfinite()) {
return this.compareEnd(o1, o2);
} else {
return -1;
}
} else if (bs2.isInfinite()) {
return 1;
}
T start1 = bs1.getTemporal();
T start2 = bs2.getTemporal();
if (bs1.isOpen()) {
start1 = this.axis.stepForward(start1);
}
if (bs2.isOpen()) {
start2 = this.axis.stepForward(start2);
}
// open max condition (rare edge case)
if (start1 == null) {
if (start2 == null) {
return 0;
} else {
return 1;
}
} else if (start2 == null) {
return -1;
}
int delta = this.axis.compare(start1, start2);
if (delta == 0) {
delta = this.compareEnd(o1, o2);
}
return delta;
}
private int compareEnd(
ChronoInterval<T> o1,
ChronoInterval<T> o2
) {
Boundary<T> be1 = o1.getEnd();
Boundary<T> be2 = o2.getEnd();
if (be1.isInfinite()) {
if (be2.isInfinite()) {
return 0;
} else {
return 1;
}
} else if (be2.isInfinite()) {
return -1;
}
T end1 = be1.getTemporal();
T end2 = be2.getTemporal();
if (this.calendrical) {
if (be1.isOpen()) {
end1 = this.axis.stepBackwards(end1);
}
if (be2.isOpen()) {
end2 = this.axis.stepBackwards(end2);
}
// closed min condition (rare edge case)
if (end1 == null) {
if (end2 == null) {
return 0;
} else {
return -1;
}
} else if (end2 == null) {
return 1;
}
} else {
if (be1.isClosed()) {
end1 = this.axis.stepForward(end1);
}
if (be2.isClosed()) {
end2 = this.axis.stepForward(end2);
}
// closed max condition (rare edge case)
if (end1 == null) {
if (end2 == null) {
return 0;
} else {
return 1;
}
} else if (end2 == null) {
return -1;
}
}
// default case
return this.axis.compare(end1, end2);
}
}