/* * RHQ Management Platform * Copyright (C) 2005-2011 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 as published by * the Free Software Foundation version 2 of the License. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.rhq.coregui.client.util.measurement; import com.google.gwt.i18n.client.NumberFormat; import org.rhq.core.domain.measurement.MeasurementUnits; import org.rhq.core.domain.measurement.composite.MeasurementNumericValueAndUnits; import org.rhq.core.domain.measurement.util.MeasurementConversionException; import org.rhq.coregui.client.util.MeasurementConverterClient; /** * Parses measurement strings given in the typical form of "[sign] magnitude [units]" such as: * * -1.0 * +1.0s * 200MB * * This is purposefully written without java.text and java.util.regex classes so GWT 2.0 * can use this class. * * @author Greg Hinkle * @author John Mazzitelli */ public class MeasurementParser { public static MeasurementNumericValueAndUnits parse(String input, MeasurementUnits targetUnits) throws MeasurementConversionException { if (input == null) { return new MeasurementNumericValueAndUnits(Double.valueOf(0.0), targetUnits); } input = input.trim(); if (input.length() == 0) { return new MeasurementNumericValueAndUnits(Double.valueOf(0.0), targetUnits); } int i = 0; // skip over the sign, we'll deal with that later if (input.startsWith("+") || input.startsWith("-")) { i = 1; } // find the end of the magnitude (i.e. the number itself) // note we allow for decimals - and we allow for either "." or "," as the decimal point for i18n purposes for (; i < input.length(); i++) { char ch = input.charAt(i); if (!(Character.isDigit(ch) || ch == '.' || ch == ',')) { break; } } String magnitude = input.substring(0, i); String units = ""; if (i <= input.length()) { // gobble everything after the magnitude and consider it the units units = input.substring(i); units = units.trim(); } MeasurementUnits fromUnits; if (units.equals("")) { /* * no units is valid, and we assume the passed targetUnits; however, we will * still need to check that the number is well-formed, so continue processing. */ fromUnits = targetUnits; } else { fromUnits = MeasurementUnits.getUsingDisplayUnits(units, targetUnits.getFamily()); if ((fromUnits == null) || (!fromUnits.isComparableTo(targetUnits))) { throw new MeasurementConversionException("The units in '" + input + "' were not valid, " + "expected '" + targetUnits.getFamily() + "' units, received '" + units + "' units"); } } try { if (magnitude.startsWith("+")) { magnitude = magnitude.substring(1); } Number convertedMagnitude = NumberFormat.getDecimalFormat().parse(magnitude); Double scaledMagnitude; // apply relative scale if applicable, otherwise perform standard scaling if (MeasurementUnits.Family.RELATIVE == targetUnits.getFamily()) { scaledMagnitude = MeasurementUnits.scaleDown(convertedMagnitude.doubleValue(), targetUnits); } else { MeasurementNumericValueAndUnits valueAndUnits = new MeasurementNumericValueAndUnits(convertedMagnitude .doubleValue(), fromUnits); scaledMagnitude = MeasurementConverterClient.scale(valueAndUnits, targetUnits); } return new MeasurementNumericValueAndUnits(scaledMagnitude, targetUnits); } catch (Exception e) { throw new MeasurementConversionException("The magnitude in '" + input + "' did not parse correctly " + "as a valid, localized, stringified number "); } } }