001: /*
002: * Copyright 2006-2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.opensource.org/licenses/ecl1.php
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.kuali.core.web.format;
017:
018: import java.math.BigDecimal;
019: import java.text.DecimalFormat;
020: import java.text.ParseException;
021: import java.util.regex.Pattern;
022:
023: import org.apache.log4j.Logger;
024: import org.kuali.RiceKeyConstants;
025:
026: /**
027: * This class is used to format BigDecimal objects.
028: */
029: public class BigDecimalFormatter extends Formatter {
030: private static Logger LOG = Logger
031: .getLogger(BigDecimalFormatter.class);
032: private static final Pattern DECIMAL_PATTERN = Pattern
033: .compile("\\-?[0-9,]*\\.?[0-9]*");
034:
035: /**
036: * Unformats its argument and returns a KualiDecimal instance initialized with the resulting string value
037: *
038: * @see org.kuali.core.web.format.Formatter#convertToObject(java.lang.String)
039: */
040: protected Object convertToObject(String target) {
041: BigDecimal value = null;
042:
043: LOG.debug("convertToObject '" + target + "'");
044:
045: if (target != null) {
046:
047: // preemptively detect non-numeric-related symbols, since NumberFormat.parse seems to be silently deleting them
048: // (i.e. 9aaaaaaaaaaaaaaa is silently converted into 9)
049: if (!DECIMAL_PATTERN.matcher(target).matches()) {
050: throw new FormatException("parsing",
051: RiceKeyConstants.ERROR_NUMERIC, target);
052: }
053:
054: // actually reformat the numeric value
055: DecimalFormat formatter = new DecimalFormat();
056: formatter.setParseBigDecimal(true);
057: try {
058: Number parsedNumber = formatter.parse(target);
059: value = new BigDecimal(parsedNumber.toString());
060: } catch (NumberFormatException e) {
061: throw new FormatException("parsing",
062: RiceKeyConstants.ERROR_BIG_DECIMAL, target, e);
063: } catch (ParseException e) {
064: throw new FormatException("parsing",
065: RiceKeyConstants.ERROR_BIG_DECIMAL, target, e);
066: }
067: }
068:
069: return value;
070: }
071:
072: /**
073: * Returns a string representation of its argument formatted as a decimal value.
074: *
075: * @see org.kuali.core.web.format.Formatter#format(java.lang.Object)
076: */
077: public Object format(Object obj) {
078: LOG.debug("format '" + obj + "'");
079: if (obj == null)
080: return null;
081:
082: DecimalFormat formatter = new DecimalFormat();
083: String string = null;
084:
085: try {
086: BigDecimal number = (BigDecimal) obj;
087:
088: if (number != null && number.scale() > 0) {
089: //remember to force a scale (with whatever rounding) in your java object to enforce this
090: formatter.setMinimumFractionDigits(number.scale());
091: } else {//arbitrary scale
092: //according to the api this line shouldn't be needed for BigDecimal and it should be
093: //able to do arbitrary precision, however it didn't work in my tests it appears there
094: //is an open java bug that relates to this sun bug (sun BUG:5060859) and that's why
095: //we may need this workaround for now
096: formatter.setMaximumFractionDigits(340);
097: }
098: string = formatter.format(number);
099: } catch (IllegalArgumentException e) {
100: throw new FormatException("formatting",
101: RiceKeyConstants.ERROR_BIG_DECIMAL, obj.toString(),
102: e);
103: } catch (ClassCastException e) {
104: throw new FormatException("formatting",
105: RiceKeyConstants.ERROR_BIG_DECIMAL, obj.toString(),
106: e);
107: }
108:
109: return string;
110: }
111: }
|