package com.github.pfichtner.jrunalyser.base.data;
import java.io.Serializable;
import javax.annotation.Nonnegative;
import com.github.pfichtner.jrunalyser.base.data.stat.Functions;
import com.google.common.collect.Interner;
import com.google.common.collect.Interners;
import com.google.common.collect.Ordering;
import com.google.common.primitives.Doubles;
public class DefaultDistance implements Distance, Serializable {
private static final long serialVersionUID = -6510597074912185860L;
private static final Ordering<Distance> orderByDistanceUnit = Ordering
.natural().onResultOf(Functions.Distances.distanceUnit);
private static final Interner<DefaultDistance> interner = Interners
.newWeakInterner();
private final DistanceUnit distanceUnit;
private final double value;
private DefaultDistance(@Nonnegative double value, DistanceUnit distanceUnit) {
this.distanceUnit = distanceUnit;
this.value = value;
}
public static DefaultDistance of(double value, DistanceUnit distanceUnit) {
return interner.intern(new DefaultDistance(value, distanceUnit));
}
@Override
public DistanceUnit getDistanceUnit() {
return this.distanceUnit;
}
@Override
public double getValue(DistanceUnit distanceUnit) {
return convertTo(distanceUnit).value;
}
@Override
public DefaultDistance convertTo(DistanceUnit targetUnit) {
return targetUnit == this.distanceUnit ? this : DefaultDistance.of(
targetUnit.convert(this.value, this.distanceUnit), targetUnit);
}
private DistanceUnit findSmallerUnit(final Distance other) {
return orderByDistanceUnit.min(this, other).getDistanceUnit();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime
* result
+ ((this.distanceUnit == null) ? 0 : this.distanceUnit
.hashCode());
long temp;
temp = Double.doubleToLongBits(this.value);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DefaultDistance other = (DefaultDistance) obj;
if (this.distanceUnit != other.distanceUnit)
return false;
if (Double.doubleToLongBits(this.value) != Double
.doubleToLongBits(other.value))
return false;
return true;
}
@Override
public int compareTo(Distance other) {
final DistanceUnit smaller = findSmallerUnit(other);
return Doubles.compare(getValue(smaller), other.getValue(smaller));
}
@Override
public Distance add(Distance other) {
return DefaultDistance.of(this.value + getOtherVal(other),
this.distanceUnit);
}
@Override
public Distance subtract(Distance other) {
return DefaultDistance.of(this.value - getOtherVal(other),
this.distanceUnit);
}
@Override
public Distance divide(double divider) {
return DefaultDistance.of(this.value / divider, this.distanceUnit);
}
@Override
public Distance multiply(double multiplier) {
return DefaultDistance.of(this.value * multiplier, this.distanceUnit);
}
private double getOtherVal(Distance other) {
return other.getValue(this.distanceUnit);
}
@Override
public String toString() {
return "DefaultDistance [distanceUnit=" + this.distanceUnit
+ ", value=" + this.value + "]";
}
}