/*
* Copyright 2013-2016 Skynav, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY SKYNAV, INC. AND ITS CONTRIBUTORS “AS IS” AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL SKYNAV, INC. OR ITS CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.skynav.ttx.util;
public class TimeCoordinate implements Comparable<TimeCoordinate> {
public enum Type {
Unspecified,
Invalid,
Unresolved,
Indefinite,
Definite;
}
public static final TimeCoordinate UNSPECIFIED = new TimeCoordinate(Type.Unspecified);
public static final TimeCoordinate INVALID = new TimeCoordinate(Type.Invalid);
public static final TimeCoordinate UNRESOLVED = new TimeCoordinate(Type.Unresolved);
public static final TimeCoordinate INDEFINITE = new TimeCoordinate(Type.Indefinite);
public static final TimeCoordinate ZERO = new TimeCoordinate(0);
private Type type = Type.Unresolved;
private double value;
public TimeCoordinate() {
this(Type.Unresolved);
}
public TimeCoordinate(Type type) {
this(type, 0);
}
public TimeCoordinate(double value) {
this(Type.Definite, value);
}
public TimeCoordinate(Type type, double value) {
assert (type == Type.Definite) || (value == 0);
this.type = type;
this.value = value;
}
public boolean isUnspecified() { return type == Type.Unspecified; }
public boolean isSpecified() { return !isUnspecified(); }
public boolean isInvalid() { return type == Type.Invalid; }
public boolean isUnresolved() { return type == Type.Unresolved; }
public boolean isIndefinite() { return type == Type.Indefinite; }
public boolean isDefinite() { return type == Type.Definite; }
public boolean isZero() { return isDefinite() && (value == 0); }
public Type getType() { return type; }
public double getValue() { return value; }
public int hashCode() {
int hc = 23;
hc = hc * 31 + getType().ordinal();
hc = hc * 31 + Double.valueOf(getValue()).hashCode();
return hc;
}
public boolean equals(Object o) {
if (o instanceof TimeCoordinate) {
TimeCoordinate c = (TimeCoordinate) o;
return (c.getType() == getType()) && (c.getValue() == getValue());
} else
return false;
}
public String toString() {
return isDefinite() ? Double.toString(getValue()) : getType().name();
}
public int compareTo(TimeCoordinate c) {
if (less(this, c))
return -1;
else if (greater(this, c))
return 1;
else if (equals(c))
return 0;
else
return -1;
}
public static TimeCoordinate fromValue(double value) {
if (value == 0)
return ZERO;
else
return new TimeCoordinate(value);
}
public static TimeCoordinate parse(String value) {
if (value == null)
return TimeCoordinate.UNSPECIFIED;
else if (value.equals("indefinite"))
return TimeCoordinate.INDEFINITE;
else if (value.equals("unresolved"))
return TimeCoordinate.UNRESOLVED;
else {
try {
return fromValue(Double.parseDouble(value));
} catch (NumberFormatException e) {
return TimeCoordinate.INVALID;
}
}
}
public static TimeCoordinate min(TimeCoordinate c1, TimeCoordinate c2) {
assert !c1.isInvalid();
assert !c2.isInvalid();
if (c1.isZero())
return c1;
else if (c2.isZero())
return c2;
else if (c1.isDefinite()) {
if (c2.isDefinite())
return (c1.getValue() < c2.getValue()) ? c1 : c2;
else
return c1;
} else if (c1.isIndefinite()) {
if (c2.isDefinite())
return c2;
else
return c1;
} else
return c2;
}
public static TimeCoordinate max(TimeCoordinate c1, TimeCoordinate c2) {
assert !c1.isInvalid();
assert !c2.isInvalid();
if (c1.isUnresolved())
return c1;
else if (c2.isUnresolved())
return c2;
else if (c1.isDefinite()) {
if (c2.isDefinite())
return (c1.getValue() > c2.getValue()) ? c1 : c2;
else
return c2;
} else
return c1;
}
public static boolean less(TimeCoordinate c1, TimeCoordinate c2) {
return !c1.equals(c2) && min(c1,c2).equals(c1);
}
public static boolean greater(TimeCoordinate c1, TimeCoordinate c2) {
return !c1.equals(c2) && max(c1,c2).equals(c1);
}
public TimeCoordinate neg() {
if (isZero())
return this;
else if (isDefinite())
return fromValue(-1 * getValue());
else
return this;
}
public static TimeCoordinate add(TimeCoordinate d1, TimeCoordinate d2) {
assert !d1.isInvalid();
assert !d2.isInvalid();
if (d1.isUnresolved())
return d1;
else if (d2.isUnresolved())
return d2;
else if (d1.isDefinite()) {
if (d2.isDefinite())
return fromValue(d1.getValue() + d2.getValue());
else
return d2;
} else
return d1;
}
public static TimeCoordinate sub(TimeCoordinate d1, TimeCoordinate d2) {
return add(d1, d2.neg());
}
public static TimeCoordinate mul(TimeCoordinate d1, TimeCoordinate d2) {
assert !d1.isInvalid();
assert !d2.isInvalid();
if (d1.isZero())
return d1;
else if (d2.isZero())
return d2;
else if (d1.isUnresolved())
return d1;
else if (d2.isUnresolved())
return d2;
else if (d1.isDefinite()) {
if (d2.isDefinite())
return fromValue(d1.getValue() * d2.getValue());
else
return d2;
} else
return d1;
}
}