/*
* Licensed under the Apache License, Version 2.0 (the "License");
*
* You may not use this file except in compliance with the License.
*
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributions from 2013-2017 where performed either by US government
* employees, or under US Veterans Health Administration contracts.
*
* US Veterans Health Administration contributions by government employees
* are work of the U.S. Government and are not subject to copyright
* protection in the United States. Portions contributed by government
* employees are USGovWork (17USC ยง105). Not subject to copyright.
*
* Contribution by contractors to the US Veterans Health Administration
* during this period are contractually contributed under the
* Apache License, Version 2.0.
*
* See: https://www.usa.gov/government-works
*
* Contributions prior to 2013:
*
* Copyright (C) International Health Terminology Standards Development Organisation.
* Licensed under the Apache License, Version 2.0.
*
*/
package sh.isaac.api.util;
//~--- JDK imports ------------------------------------------------------------
import java.math.BigDecimal;
import java.util.Optional;
//~--- non-JDK imports --------------------------------------------------------
import sh.isaac.api.component.sememe.version.dynamicSememe.DynamicSememeData;
import sh.isaac.api.component.sememe.version.dynamicSememe.dataTypes.DynamicSememeDouble;
import sh.isaac.api.component.sememe.version.dynamicSememe.dataTypes.DynamicSememeFloat;
import sh.isaac.api.component.sememe.version.dynamicSememe.dataTypes.DynamicSememeInteger;
import sh.isaac.api.component.sememe.version.dynamicSememe.dataTypes.DynamicSememeLong;
//~--- classes ----------------------------------------------------------------
/**
* Various number related utilities.
*
* @author darmbrust
*/
public class NumericUtils {
/**
* Compare.
*
* @param x the x
* @param y the y
* @return the int
*/
public static int compare(final Number x, final Number y) {
if (isSpecial(x) || isSpecial(y)) {
return Double.compare(x.doubleValue(), y.doubleValue());
} else {
return toBigDecimal(x).compareTo(toBigDecimal(y));
}
}
/**
* Parses the unknown.
*
* @param value the value
* @return the number
* @throws NumberFormatException the number format exception
*/
public static Number parseUnknown(String value)
throws NumberFormatException {
if (value == null) {
throw new NumberFormatException("No value");
}
final String temp = value.trim();
try {
return Integer.parseInt(temp);
} catch (final Exception e) {
// noop
}
try {
return Long.parseLong(temp);
} catch (final Exception e) {
// noop
}
try {
return Float.parseFloat(temp);
} catch (final Exception e) {
// noop
}
return Double.parseDouble(temp);
}
/**
* Read number.
*
* @param value the value
* @return the number
* @throws NumberFormatException the number format exception
*/
public static Number readNumber(DynamicSememeData value)
throws NumberFormatException {
if (value instanceof DynamicSememeDouble) {
return ((DynamicSememeDouble) value).getDataDouble();
} else if (value instanceof DynamicSememeFloat) {
return ((DynamicSememeFloat) value).getDataFloat();
} else if (value instanceof DynamicSememeInteger) {
return ((DynamicSememeInteger) value).getDataInteger();
} else if (value instanceof DynamicSememeLong) {
return ((DynamicSememeLong) value).getDataLong();
} else {
throw new NumberFormatException("The value passed in to the validator is not a number");
}
}
/**
* To big decimal.
*
* @param number the number
* @return the big decimal
* @throws NumberFormatException the number format exception
*/
public static BigDecimal toBigDecimal(final Number number)
throws NumberFormatException {
if ((number instanceof Integer) || (number instanceof Long)) {
return new BigDecimal(number.longValue());
} else if ((number instanceof Float) || (number instanceof Double)) {
return new BigDecimal(number.doubleValue());
} else {
throw new NumberFormatException("Unexpected data type passed in to toBigDecimal (" + number.getClass() + ")");
}
}
//~--- get methods ---------------------------------------------------------
/**
* Gets the int.
*
* @param string the string
* @return the int
*/
public static Optional<Integer> getInt(String string) {
try {
return Optional.of(Integer.parseInt(string.trim()));
} catch (final Exception e) {
return Optional.empty();
}
}
/**
* Checks if int.
*
* @param string the string
* @return true, if int
*/
public static boolean isInt(String string) {
return (getInt(string).isPresent());
}
/**
* Gets the long.
*
* @param string the string
* @return the long
*/
public static Optional<Long> getLong(String string) {
try {
return Optional.of(Long.parseLong(string.trim()));
} catch (final Exception e) {
return Optional.empty();
}
}
/**
* Checks if long.
*
* @param string the string
* @return true, if long
*/
public static boolean isLong(String string) {
return getLong(string).isPresent();
}
/**
* Same as isInt / getInt - however - only returns a value if the parsed integer is negative.
*
* @param string the string
* @return the nid
*/
public static Optional<Integer> getNID(String string) {
final Optional<Integer> possibleInt = getInt(string);
return (possibleInt.isPresent() && (possibleInt.get() < 0)) ? possibleInt
: Optional.empty();
}
/**
* Checks if nid.
*
* @param string the string
* @return true, if nid
*/
public static boolean isNID(String string) {
return (getNID(string).isPresent());
}
/**
* Checks if special.
*
* @param x the x
* @return true, if special
*/
private static boolean isSpecial(final Number x) {
final boolean specialDouble = (x instanceof Double) &&
(Double.isNaN((Double) x) || Double.isInfinite((Double) x));
final boolean specialFloat = (x instanceof Float) && (Float.isNaN((Float) x) || Float.isInfinite((Float) x));
return specialDouble || specialFloat;
}
}