/*
* RHQ Management Platform
* Copyright (C) 2005-2008 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation, and/or the GNU Lesser
* General Public License, version 2.1, also as published by the Free
* Software Foundation.
*
* This program 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 General Public License and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with this program;
* if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.rhq.core.clientapi.util.units;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.Locale;
import org.rhq.core.clientapi.util.ArrayUtil;
import static org.rhq.core.clientapi.util.units.ScaleConstants.SCALE_NONE;
import static org.rhq.core.clientapi.util.units.UnitsConstants.UNIT_BITS;
import static org.rhq.core.clientapi.util.units.UnitsConstants.UNIT_BYTES;
import static org.rhq.core.clientapi.util.units.UnitsConstants.UNIT_DATE;
import static org.rhq.core.clientapi.util.units.UnitsConstants.UNIT_DURATION;
import static org.rhq.core.clientapi.util.units.UnitsConstants.UNIT_NONE;
import static org.rhq.core.clientapi.util.units.UnitsConstants.UNIT_PERCENTAGE;
import static org.rhq.core.clientapi.util.units.UnitsConstants.UNIT_TEMPERATURE;
class UnitsUtil {
static final BigDecimal FACT_NONE = new BigDecimal(1);
// Binary scaling factors
static final BigDecimal FACT_KILO_BIN = new BigDecimal(1 << 10);
static final BigDecimal FACT_MEGA_BIN = FACT_KILO_BIN.multiply(FACT_KILO_BIN);
static final BigDecimal FACT_GIGA_BIN = FACT_MEGA_BIN.multiply(FACT_KILO_BIN);
static final BigDecimal FACT_TERA_BIN = FACT_GIGA_BIN.multiply(FACT_KILO_BIN);
static final BigDecimal FACT_PETA_BIN = FACT_TERA_BIN.multiply(FACT_KILO_BIN);
// The following factors are how to convert a number in FACT_* to
// nanoseconds.
static final BigDecimal FACT_NANOS = new BigDecimal(1);
static final BigDecimal FACT_MICROS = new BigDecimal(1000);
static final BigDecimal FACT_MILLIS = new BigDecimal(1000000);
static final BigDecimal FACT_JIFFYS = new BigDecimal(10000000);
static final BigDecimal FACT_SECS = FACT_MILLIS.multiply(new BigDecimal(1000));
static final BigDecimal FACT_MINS = FACT_SECS.multiply(new BigDecimal(60));
static final BigDecimal FACT_HOURS = FACT_MINS.multiply(new BigDecimal(60));
static final BigDecimal FACT_DAYS = FACT_HOURS.multiply(new BigDecimal(24));
static final BigDecimal FACT_WEEKS = FACT_DAYS.multiply(new BigDecimal(7));
static final BigDecimal FACT_YEARS = FACT_DAYS.multiply(new BigDecimal(365));
static void checkValidScaleForUnits(UnitsConstants unit, ScaleConstants scale) {
EnumSet<ScaleConstants> weightSet = ScaleConstants.getBinaryScaleSet();
EnumSet<ScaleConstants> timeSet = ScaleConstants.getTimeSet();
EnumSet<ScaleConstants> temperatureSet = ScaleConstants.getTemperatureSet();
// if(!(scale == SCALE_NONE ||
// ((unit == UNIT_BYTES || unit == UNIT_BITS) &&
// scale >= SCALE_KILO && scale <= SCALE_PETA)
// ||
// ((unit == UNIT_DURATION || unit == UNIT_DATE) &&
// scale >= SCALE_YEAR && scale <= SCALE_NANO)
// ||
// (unit == UNIT_PERCENTAGE && scale != SCALE_NONE) ||
// (unit == UNIT_NONE && scale != SCALE_NONE)))
if (!((scale == SCALE_NONE) || (((unit == UNIT_BYTES) || (unit == UNIT_BITS)) && weightSet.contains(scale))
|| (((unit == UNIT_DURATION) || (unit == UNIT_DATE)) && timeSet.contains(scale))
|| (((unit == UNIT_TEMPERATURE)) && temperatureSet.contains(scale))
|| ((unit == UNIT_PERCENTAGE) && (scale != SCALE_NONE)) || ((unit == UNIT_NONE) && (scale != SCALE_NONE)))) {
throw new IllegalArgumentException("Scale is not valid for the " + "specified units");
}
}
/**
* Find the index of the first character which is not a number.
*
* @return The index of the first character which is not a number. If the entire value is a number, then -1 is
* returned
*/
static int findNonNumberIdx(String val, NumberFormat fmt) {
ParsePosition pos = new ParsePosition(0);
fmt.parse(val, pos);
if (pos.getIndex() == val.length()) {
return -1;
}
return pos.getIndex();
}
/**
* Get a NumberFormat which shows enough significant figures, such that each value passed in is distinguishable from
* the next. (if they are not the same value)
*/
public static NumberFormat getNumberFormat(double[] inValues, Locale locale) {
NumberFormat res;
String[] sValues;
double[] values;
int numDigits;
res = NumberFormat.getInstance(locale);
values = new double[inValues.length];
System.arraycopy(inValues, 0, values, 0, inValues.length);
Arrays.sort(values);
values = ArrayUtil.uniq(values);
if (values.length < 2) {
res.setMinimumFractionDigits(1);
res.setMaximumFractionDigits(1);
return res;
}
/**
* Find a NumberFormat, such that the numbers can all be formatted
* uniquely. We have to do this iteratively, checking all the
* values, since the NumberFormat rounding can cause multiple
* unique values to the same one. This kinda sux, since it's
* slow, but not much we can do here.
*/
numDigits = 0;
sValues = new String[values.length];
while (numDigits < 9) {
res.setMinimumFractionDigits(numDigits);
res.setMaximumFractionDigits(numDigits);
for (int i = 0; i < sValues.length; i++) {
sValues[i] = res.format(values[i]);
}
Arrays.sort(sValues);
if (ArrayUtil.isUniq(sValues) == false) {
numDigits++;
} else {
break;
}
}
return res;
}
public static int getUniqueDigits(double[] inValues, Locale locale) {
return getNumberFormat(inValues, locale).getMaximumFractionDigits();
}
}