001: /* ====================================================================
002: * The LateralNZ Software License, Version 1.0
003: *
004: * Copyright (c) 2003 LateralNZ. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by
021: * LateralNZ (http://www.lateralnz.org/) and other third parties."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. The names "LateralNZ" must not be used to endorse or promote
026: * products derived from this software without prior written
027: * permission. For written permission, please
028: * contact oss@lateralnz.org.
029: *
030: * 5. Products derived from this software may not be called "Panther",
031: * or "Lateral" or "LateralNZ", nor may "PANTHER" or "LATERAL" or
032: * "LATERALNZ" appear in their name, without prior written
033: * permission of LateralNZ.
034: *
035: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: *
049: * This software consists of voluntary contributions made by many
050: * individuals on behalf of LateralNZ. For more
051: * information on Lateral, please see http://www.lateralnz.com/ or
052: * http://www.lateralnz.org
053: *
054: */
055: package org.lateralnz.common.util;
056:
057: import java.util.HashMap;
058: import java.util.Locale;
059: import java.text.ParseException;
060: import java.text.DecimalFormat;
061:
062: /**
063: * command number formatting utilities
064: *
065: * @author J R Briggs
066: */
067: public final class NumericUtils implements Constants {
068: private static final String CLASSNAME = NumericUtils.class
069: .getName();
070: private static final String DIGITS = "0123456789.";
071:
072: private static HashMap numberFormatters = new HashMap();
073:
074: private NumericUtils() {
075: }
076:
077: /**
078: * loads and caches a numberformat
079: */
080: private static final DecimalFormat getFormat(String className,
081: Locale locale) {
082: DecimalFormat format;
083: String key = className + UNDERSCORE + UNDERSCORE
084: + (locale != null ? locale.toString() : EMPTY);
085: if (!numberFormatters.containsKey(key)) {
086: if (locale != null) {
087: format = (DecimalFormat) DecimalFormat
088: .getInstance(locale);
089: } else {
090: format = (DecimalFormat) DecimalFormat.getInstance();
091: }
092:
093: synchronized (numberFormatters) {
094: if (!numberFormatters.containsKey(key)) {
095: numberFormatters.put(key, format);
096: }
097: }
098: } else {
099: format = (DecimalFormat) numberFormatters.get(key);
100: }
101:
102: return format;
103: }
104:
105: /**
106: *
107: */
108: public static final String format(String callerClassName, long l,
109: String pattern) {
110: return format(callerClassName, l, null, pattern);
111: }
112:
113: public static final String format(String callerClassName, float f,
114: String pattern) {
115: return format(callerClassName, f, null, pattern);
116: }
117:
118: public static final String format(String callerClassName, double d,
119: String pattern) {
120: return format(callerClassName, d, null, pattern);
121: }
122:
123: public static final String format(String callerClassName, long l,
124: Locale locale, String pattern) {
125: DecimalFormat format = getFormat(callerClassName, locale);
126: synchronized (format) {
127: format.applyPattern(pattern);
128: return format.format(l);
129: }
130: }
131:
132: public static final String format(String callerClassName, float f,
133: Locale locale, String pattern) {
134: DecimalFormat format = getFormat(callerClassName, locale);
135: synchronized (format) {
136: format.applyPattern(pattern);
137: return format.format(f);
138: }
139: }
140:
141: /**
142: */
143: public static final String format(String callerClassName, double d,
144: Locale locale, String pattern) {
145: DecimalFormat format = getFormat(callerClassName, locale);
146: synchronized (format) {
147: format.applyPattern(pattern);
148: return format.format(d);
149: }
150: }
151:
152: public static final boolean isNumber(String s) {
153: if (StringUtils.isEmpty(s)) {
154: return false;
155: } else {
156: for (int i = 0; i < s.length(); i++) {
157: char c = s.charAt(i);
158: if (DIGITS.indexOf(c) < 0) {
159: return false;
160: }
161: }
162: return true;
163: }
164: }
165:
166: /**
167: */
168: public static final double parseDouble(String callerClassName,
169: String s, String pattern) throws ParseException {
170: return parseDouble(callerClassName, s, null, pattern);
171: }
172:
173: /**
174: * turns a string representation of a date into a date object using a cached format
175: * @param callerClassName the class of the object calling this method (used for caching)
176: * @param s the string date to convert
177: * @param locale the locale to use in conversion
178: * @param pattern the date format to use
179: */
180: public static final double parseDouble(String callerClassName,
181: String s, Locale locale, String pattern)
182: throws ParseException {
183: if (StringUtils.isEmpty(s)) {
184: return 0.0d;
185: }
186:
187: DecimalFormat format = getFormat(callerClassName, locale);
188: synchronized (format) {
189: format.applyPattern(pattern);
190: Number n = format.parse(s);
191: return n.doubleValue();
192: }
193: }
194:
195: public static final byte[] toByteArray(int n) {
196: return toByteArray(n, true);
197: }
198:
199: public static final byte[] toByteArray(int n, boolean calcLength) {
200: int len;
201: if (calcLength) {
202: len = (int) (Math
203: .ceil(Math.ceil(Math.log(n) / Math.log(2)) / 8));
204: } else {
205: len = 4;
206: }
207: byte[] b = new byte[len];
208: int shift = 8 * (len - 1);
209: for (int i = 0; i < len; i++) {
210: b[i] = (byte) (n >>> shift);
211: shift -= 8;
212: }
213: return b;
214: }
215:
216: public static final int toInt(byte[] b) {
217: return toInt(b, 0, b.length);
218: }
219:
220: public static final int toInt(byte[] b, int offset, int len) {
221: int n = 0;
222: int shift = 8 * (len - 1);
223: for (int i = offset; i < offset + len; i++) {
224: n |= (int) (b[i] & 0xff) << shift;
225: shift -= 8;
226: }
227: return n;
228: }
229:
230: public static final String toString(byte[] b) {
231: StringBuffer sb = new StringBuffer();
232: int len = b.length - 1;
233: for (int i = 0; i <= len; i++) {
234: sb.append(Integer.toHexString(b[i] & 0xff));
235: if (i < len) {
236: sb.append(SPACE);
237: }
238: }
239: return sb.toString();
240: }
241:
242: }
|