001/* 002 * $Id$ 003 * 004 * Copyright 2009 Sun Microsystems, Inc., 4150 Network Circle, 005 * Santa Clara, California 95054, U.S.A. All rights reserved. 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 020 * 021 */ 022package org.jdesktop.swingx.table; 023 024import java.math.BigDecimal; 025import java.text.Format; 026import java.text.NumberFormat; 027import java.text.ParseException; 028 029import javax.swing.text.NumberFormatter; 030 031/** 032 * Experiment to work around Issue #1183-swingx: NumberEditorExt throws exception 033 * on getCellValue. Remaining issue: no visual error feedback if the expected 034 * number type exceeds its range. 035 * 036 * @author Jeanette Winzenburg 037 * 038 * @deprecated (pre-1.6.2) moved to text package 039 */ 040@Deprecated 041class StrictNumberFormatter extends NumberFormatter { 042 043 044 private BigDecimal maxAsBig; 045 private BigDecimal minAsBig; 046 047 /** 048 * @param format 049 */ 050 public StrictNumberFormatter(NumberFormat format) { 051 super(format); 052 } 053 054 /** 055 * {@inheritDoc} <p> 056 * 057 * Overridden to automatically set the minimum/maximum to the boundaries of 058 * the Number type if it corresponds to a raw type, or null if not. 059 */ 060 @Override 061 public void setValueClass(Class<?> valueClass) { 062 super.setValueClass(valueClass); 063 updateMinMax(); 064 } 065 066 067 /** 068 * 069 */ 070 @SuppressWarnings("unchecked") 071 private void updateMinMax() { 072 Comparable min = null; 073 Comparable max = null; 074 if (getValueClass() == Integer.class) { 075 max = Integer.MAX_VALUE; 076 min = Integer.MIN_VALUE; 077 } else if (getValueClass() == Long.class) { 078 max = Long.MAX_VALUE; 079 min = Long.MIN_VALUE; 080 } else if (getValueClass() == Short.class) { 081 max = Short.MAX_VALUE; 082 min = Short.MIN_VALUE; 083 } else if (getValueClass() == Byte.class) { 084 max = Byte.MAX_VALUE; 085 min = Byte.MIN_VALUE; 086 } else if (getValueClass() == Float.class) { 087 max = Float.MAX_VALUE; 088 min = Float.MIN_VALUE; 089 } else if (getValueClass() == Double.class) { 090 // don*t understand what's happening here, naive compare with bigDecimal 091 // fails - so don't do anything for now 092 // JW: revisit! 093 } 094 setMaximum(max); 095 setMinimum(min); 096 } 097 098 099 @SuppressWarnings("unchecked") 100 @Override 101 public void setMaximum(Comparable max) { 102 super.setMaximum(max); 103 this.maxAsBig = max != null ? new BigDecimal(max.toString()) : null; 104 } 105 106 @SuppressWarnings("unchecked") 107 @Override 108 public void setMinimum(Comparable minimum) { 109 super.setMinimum(minimum); 110 this.minAsBig = minimum != null ? new BigDecimal(minimum.toString()) : null; 111 } 112 113 114 /** 115 * Returns the <code>Object</code> representation of the 116 * <code>String</code> <code>text</code>, may be null. 117 * 118 * @param text <code>String</code> to convert 119 * @return <code>Object</code> representation of text 120 * @throws ParseException if there is an error in the conversion 121 */ 122 @Override 123 public Object stringToValue(String text) throws ParseException { 124 Object value = getParsedValue(text, getFormat()); 125 try { 126 if (!isValueInRange(value, true)) { 127 throw new ParseException("Value not within min/max range", 0); 128 } 129 } catch (ClassCastException cce) { 130 throw new ParseException("Class cast exception comparing values: " 131 + cce, 0); 132 } 133 return convertValueToValueClass(value, getValueClass()); 134 } 135 136 /** 137 * Converts the passed in value to the passed in class. This only 138 * works if <code>valueClass</code> is one of <code>Integer</code>, 139 * <code>Long</code>, <code>Float</code>, <code>Double</code>, 140 * <code>Byte</code> or <code>Short</code> and <code>value</code> 141 * is an instanceof <code>Number</code>. 142 */ 143 private Object convertValueToValueClass(Object value, Class<?> valueClass) { 144 if (valueClass != null && (value instanceof Number)) { 145 if (valueClass == Integer.class) { 146 return new Integer(((Number)value).intValue()); 147 } 148 else if (valueClass == Long.class) { 149 return new Long(((Number)value).longValue()); 150 } 151 else if (valueClass == Float.class) { 152 return new Float(((Number)value).floatValue()); 153 } 154 else if (valueClass == Double.class) { 155 return new Double(((Number)value).doubleValue()); 156 } 157 else if (valueClass == Byte.class) { 158 return new Byte(((Number)value).byteValue()); 159 } 160 else if (valueClass == Short.class) { 161 return new Short(((Number)value).shortValue()); 162 } 163 } 164 return value; 165 } 166 167 /** 168 * Invokes <code>parseObject</code> on <code>f</code>, returning 169 * its value. 170 */ 171 private Object getParsedValue(String text, Format f) throws ParseException { 172 if (f == null) { 173 return text; 174 } 175 return f.parseObject(text); 176 } 177 178 179 /** 180 * Returns true if <code>value</code> is between the min/max. 181 * 182 * @param wantsCCE If false, and a ClassCastException is thrown in 183 * comparing the values, the exception is consumed and 184 * false is returned. 185 */ 186 private boolean isValueInRange(Object orgValue, boolean wantsCCE) { 187 if (orgValue == null) return true; 188 if ((getMinimum() == null) && getMaximum() == null) return true; 189 190 BigDecimal value = new BigDecimal(orgValue.toString()); 191 Comparable<BigDecimal> min = getMinimumAsBig(); 192 193 try { 194 if (min != null && min.compareTo(value) > 0) { 195 return false; 196 } 197 } catch (ClassCastException cce) { 198 if (wantsCCE) { 199 throw cce; 200 } 201 return false; 202 } 203 204 Comparable<BigDecimal> max = getMaximumAsBig(); 205 try { 206 if (max != null && max.compareTo(value) < 0) { 207 return false; 208 } 209 } catch (ClassCastException cce) { 210 if (wantsCCE) { 211 throw cce; 212 } 213 return false; 214 } 215 return true; 216 } 217 218 219 private Comparable<BigDecimal> getMinimumAsBig() { 220 return minAsBig; 221 } 222 223 private Comparable<BigDecimal> getMaximumAsBig() { 224 return maxAsBig; 225 } 226 227 228}