package mil.nga.giat.geowave.core.geotime.store.query;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
public class TemporalConstraints
{
private LinkedList<TemporalRange> constraints = new LinkedList<TemporalRange>();
private String name;
public static final TemporalRange FULL_RANGE = new TemporalRange(
TemporalRange.START_TIME,
TemporalRange.END_TIME);
public TemporalConstraints() {
}
public String getName() {
return name;
}
public void empty() {
constraints.clear();
}
public TemporalConstraints(
String name ) {
this.name = name;
}
public TemporalConstraints(
List<TemporalRange> ranges,
String name ) {
this.constraints.addAll(ranges);
this.name = name;
}
public TemporalConstraints(
TemporalRange range,
String name ) {
this.constraints.add(range);
this.name = name;
}
public void replaceWithIntersections(
final TemporalConstraints constraints ) {
this.constraints = TemporalConstraints.findIntersections(
this,
constraints).constraints;
}
public void replaceWithMerged(
final TemporalConstraints constraints ) {
this.constraints = TemporalConstraints.merge(
this,
constraints).constraints;
}
public void add(
final TemporalRange range ) {
int pos = 0;
TemporalRange nextNeighbor = null;
for (final TemporalRange aRange : constraints) {
nextNeighbor = aRange;
if (nextNeighbor.getStartTime().after(
range.getStartTime())) {
break;
}
else if (nextNeighbor.getEndTime().after(
range.getStartTime()) || nextNeighbor.getEndTime().equals(
range.getStartTime())) {
if (range.getEndTime().before(
nextNeighbor.getEndTime())) {
// subsummed
return;
}
else {
// replaced with larger range
constraints.set(
pos,
new TemporalRange(
nextNeighbor.getStartTime(),
range.getEndTime()));
return;
}
}
pos++;
}
if ((nextNeighbor != null) && nextNeighbor.getStartTime().before(
range.getEndTime())) {
constraints.add(
pos,
new TemporalRange(
range.getStartTime(),
TemporalConstraints.max(
nextNeighbor.getEndTime(),
range.getEndTime())));
}
else {
constraints.add(
pos,
range);
}
}
public static final Date max(
final Date one,
final Date two ) {
return one.before(two) ? two : one;
}
public static final Date min(
final Date one,
final Date two ) {
return one.before(two) ? one : two;
}
public Date getMinOr(
final Date min,
int exclusivityIncrement ) {
return (constraints.isEmpty()) ? min : exclusivityIncrement == 0 ? constraints.getFirst().getStartTime()
: new Date(
constraints.getFirst().getStartTime().getTime() + exclusivityIncrement);
}
public Date getMaxOr(
final Date max,
int exclusivityIncrement ) {
return (constraints.isEmpty()) ? max : exclusivityIncrement == 0 ? constraints.getLast().getEndTime()
: new Date(
constraints.getLast().getEndTime().getTime() + exclusivityIncrement);
}
public boolean isEmpty() {
return constraints.isEmpty();
}
public TemporalRange getEndRange() {
return (constraints.isEmpty()) ? FULL_RANGE : constraints.getLast();
}
public TemporalRange getStartRange() {
return (constraints.isEmpty()) ? FULL_RANGE : constraints.getFirst();
}
public List<TemporalRange> getRanges() {
return constraints == null ? Collections.<TemporalRange> emptyList() : constraints;
}
public static final TemporalConstraints findIntersections(
final TemporalConstraints sideL,
final TemporalConstraints sideR ) {
if (sideL.constraints.isEmpty()) {
return sideR;
}
if (sideR.constraints.isEmpty()) {
return sideL;
}
final TemporalConstraints newSet = new TemporalConstraints(
sideL.name);
for (final TemporalRange lRange : sideL.constraints) {
for (final TemporalRange rRange : sideR.constraints) {
if (lRange.getEndTime().before(
rRange.getStartTime()) || rRange.getEndTime().before(
lRange.getStartTime())) {
continue;
}
newSet.add(new TemporalRange(
max(
lRange.getStartTime(),
rRange.getStartTime()),
min(
lRange.getEndTime(),
rRange.getEndTime())));
}
}
return newSet;
}
public static final TemporalConstraints merge(
final TemporalConstraints left,
final TemporalConstraints right ) {
if (left.isEmpty()) {
return right;
}
if (right.isEmpty()) {
return left;
}
final TemporalConstraints newSetOfRanges = new TemporalConstraints(
left.name);
newSetOfRanges.constraints.addAll(left.constraints);
for (final TemporalRange range : right.constraints) {
newSetOfRanges.add(range);
}
return newSetOfRanges;
}
public byte[] toBinary() {
final ByteBuffer buffer = ByteBuffer.allocate(4 + (constraints.size() * TemporalRange.getBufferSize()));
buffer.putInt(constraints.size());
for (final TemporalRange range : constraints) {
buffer.put(range.toBinary());
}
return buffer.array();
}
public void fromBinary(
final byte[] data ) {
final ByteBuffer buffer = ByteBuffer.wrap(data);
final int s = buffer.getInt();
final byte[] rangeBuf = new byte[TemporalRange.getBufferSize()];
for (int i = 0; i < s; i++) {
buffer.get(rangeBuf);
final TemporalRange range = new TemporalRange();
range.fromBinary(rangeBuf);
add(range);
}
}
@Override
public String toString() {
return "TemporalConstraints [constraints=" + constraints + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (prime * result) + ((constraints == null) ? 0 : constraints.hashCode());
return result;
}
@Override
public boolean equals(
final Object obj ) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final TemporalConstraints other = (TemporalConstraints) obj;
if (constraints == null) {
if (other.constraints != null) {
return false;
}
}
else if (!constraints.equals(other.constraints)) {
return false;
}
return true;
}
}