/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2007-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library 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;
* version 2.1 of the License.
*
* This library 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.
*
* This package contains documentation from OpenGIS specifications.
* OpenGIS consortium's work is fully acknowledged here.
*/
package org.geotools.metadata.iso.identification;
import org.opengis.metadata.identification.RepresentativeFraction;
import org.geotools.resources.i18n.ErrorKeys;
import org.geotools.resources.i18n.Errors;
/**
* A scale where {@linkplain #getDenominator denominator} = {@code 1 / scale}.
* This implementation is set up as a {@linkplain Number number} - because it is.
*
* @source $URL$
* @version $Id$
* @author Jody Garnett
*
* @since 2.4
*/
public class RepresentativeFractionImpl extends Number implements RepresentativeFraction {
/**
* Serial number for compatibility with different versions.
*/
private static final long serialVersionUID = 7228422109144637537L;
/**
* The number below the line in a vulgar fraction.
*/
private long denominator;
/**
* Default empty constructor.
*/
public RepresentativeFractionImpl() {
}
/**
* Creates a new representative fraction from the specified denominator.
*
* @param denominator The denominator.
*/
public RepresentativeFractionImpl(final long denominator) {
this.denominator = denominator;
}
/**
* Creates a representative fraction from a scale as a {@code double} value.
* The {@linkplain #getDenominator denominator} will be set to {@code 1/scale}.
*
* @param scale The scale as a number between 0 and 1.
* @return The representative fraction created from the given scale.
* @throws IllegalArgumentException if the condition {@code abs(scale) <= 1} is not meet.
*/
public static RepresentativeFraction fromScale(final double scale)
throws IllegalArgumentException
{
if (Math.abs(scale) <= 1 || scale == Double.POSITIVE_INFINITY) {
// Note: we accept positive infinity, but not negative infinity because
// we can't represent a negative zero using 'long' primitive type.
return new RepresentativeFractionImpl(Math.round(1.0 / scale)); // flip!
} else {
throw new IllegalArgumentException(Errors.format(ErrorKeys.ILLEGAL_ARGUMENT_$2, "scale", scale));
}
}
/**
* @deprecated This is equivalent to {@link #doubleValue}.
*/
@Deprecated
public double toScale(){
return doubleValue();
}
/**
* Returns the scale in a form usable for computation.
*
* @return <code>1.0 / {@linkplain #getDenominator() denominator}</code>
*/
public double doubleValue() {
return 1.0 / (double) denominator;
}
/**
* Returns the scale as a {@code float} type.
*/
public float floatValue() {
return 1.0f / (float) denominator;
}
/**
* Returns the scale as an integer. This method returns 0, 1 or throws an exception
* as specified in {@link #intValue}.
*
* @throws ArithmeticException if the {@linkplain #getDenominator denominator} is 0.
*/
public long longValue() throws ArithmeticException {
return intValue();
}
/**
* Returns the scale as an integer. If the denominator is 0, then this method throws an
* {@link ArithmeticException} since infinities can not be represented by an integer.
* Otherwise if the denominator is 1, then this method returns 1. Otherwise returns 0
* 0 since the scale is a fraction between 0 and 1, and such value can not be represented
* as an integer.
*
* @throws ArithmeticException if the {@linkplain #getDenominator denominator} is 0.
*/
public int intValue() throws ArithmeticException {
if (denominator == 1) {
return 1;
} else if (denominator != 0) {
return 0;
} else {
throw new ArithmeticException();
}
}
/**
* Returns the number below the line in a vulgar fraction.
*/
public long getDenominator() {
return denominator;
}
/**
* Sets the denominator value.
*
* @param denominator The new denominator value.
*/
public void setDenominator(final long denominator) {
this.denominator = denominator;
}
/**
* Compares this object with the specified value for equality.
*
* @param object The object to compare with.
* @return {@code true} if both objects are equal.
*/
@Override
public boolean equals(final Object object) {
/*
* Note: 'equals(Object)' and 'hashCode()' implementations are defined in the interface,
* in order to ensure that the following requirements hold:
*
* - a.equals(b) == b.equals(a) (reflexivity)
* - a.equals(b) implies (a.hashCode() == b.hashCode())
*/
if (object instanceof RepresentativeFraction) {
final RepresentativeFraction that = (RepresentativeFraction) object;
return denominator == that.getDenominator();
}
return false;
}
/**
* Returns a hash value for this representative fraction.
*/
@Override
public int hashCode() {
return (int) denominator;
}
}