/* * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2004-2008], Hyperic, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License 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 for more * details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ package org.hyperic.util.units; import java.math.BigDecimal; import java.text.NumberFormat; import java.text.ParsePosition; import java.util.Arrays; import java.util.Locale; import org.hyperic.util.ArrayUtil; class UnitsUtil implements UnitsConstants { static final BigDecimal FACT_NONE = new BigDecimal(Integer.toString(1)); static final BigDecimal FACT_BIT = new BigDecimal(0.125); // Binary scaling factors static final BigDecimal FACT_KILO_BIN = new BigDecimal(Integer.toString(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(Integer.toString(1)); static final BigDecimal FACT_MICROS = new BigDecimal(Integer.toString(1000)); static final BigDecimal FACT_MILLIS = new BigDecimal(Integer.toString(1000000)); static final BigDecimal FACT_JIFFYS = new BigDecimal(Integer.toString(10000000)); static final BigDecimal FACT_SECS = FACT_MILLIS.multiply(new BigDecimal(Integer.toString(1000))); static final BigDecimal FACT_MINS = FACT_SECS.multiply(new BigDecimal(Integer.toString(60))); static final BigDecimal FACT_HOURS = FACT_MINS.multiply(new BigDecimal(Integer.toString(60))); static final BigDecimal FACT_DAYS = FACT_HOURS.multiply(new BigDecimal(Integer.toString(24))); static final BigDecimal FACT_WEEKS = FACT_DAYS.multiply(new BigDecimal(Integer.toString(7))); static final BigDecimal FACT_YEARS = FACT_DAYS.multiply(new BigDecimal(Integer.toString(365))); static void checkValidUnits(int unit){ if(unit < UNIT_NONE || unit >= UNIT_MAX) throw new IllegalArgumentException("Invalid units specified"); } static void checkValidScale(int scale){ if(!(scale >= SCALE_NONE && scale <= SCALE_BIT)) throw new IllegalArgumentException("Invalid scale specified"); } static void checkValidScaleForUnits(int unit, int scale){ if(scale == SCALE_NONE || (unit == UNIT_BITS && scale == SCALE_BIT) || ((unit == UNIT_BYTES || unit == UNIT_BITS || unit == UNIT_BYTES2BITS) && scale >= SCALE_KILO && scale <= SCALE_PETA) || ((unit == UNIT_DURATION || unit == UNIT_DATE || unit == UNIT_APPROX_DUR) && scale >= SCALE_YEAR && scale <= SCALE_NANO) || (unit == UNIT_PERCENTAGE && scale != SCALE_NONE) || (unit == UNIT_NONE && scale != SCALE_NONE)) { return; } 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(); } }