1 22 23 package org.xquark.schema.datatypes; 24 25 import java.math.BigDecimal ; 26 27 import org.xquark.schema.SchemaException; 28 import org.xquark.schema.validation.ValidationContextProvider; 29 30 31 class DecimalType extends ComparableType { 32 private static final String RCSRevision = "$Revision: 1.3 $"; 33 private static final String RCSName = "$Name: $"; 34 35 private static final BigDecimal MAX_LONG = new BigDecimal (Long.MAX_VALUE); 36 private static final BigDecimal MIN_LONG = new BigDecimal (Long.MIN_VALUE); 37 38 private int totalDigits = -1; 39 private int fractionDigits = -1; 40 private ComparableConstraints longConstraints = null; 41 42 DecimalType() { 43 super("decimal", PrimitiveType.DECIMAL); 44 } 45 46 public Object toValidType(Object data) { 47 if ((data instanceof Long ) || (data instanceof BigDecimal )) { 48 return data; 49 } else if (data instanceof Number ) { 50 return new Long (((Number )data).longValue()); 51 } else { 52 return (Long )data; 53 } 54 } 55 56 57 public Object clone() throws CloneNotSupportedException { 58 DecimalType result = (DecimalType) super.clone(); 59 initLongConstraints(); 60 return result; 61 } 62 63 protected void setTotalDigits(String value, boolean fixed) throws SchemaException { 64 int val; 65 try { 66 val = Integer.parseInt(value.trim()); 67 } catch (NumberFormatException nfe) { 68 throw new SchemaException("unknown-error-code.2"); 70 } 71 if (val <= 0) { 72 throw new SchemaException("unknown-error-code.2"); 74 } 75 if ((totalDigits != -1 && val > totalDigits) || (super.isFixed(PrimitiveType.TOTALDIGITS_FACET) && val != totalDigits)) { 76 throw new SchemaException("totalDigits-valid-restriction"); 78 } 79 if (fractionDigits != -1 && fractionDigits > val) { 80 throw new SchemaException("fractionDigits-totalDigits"); 82 } 83 totalDigits = val; 84 super.setFixed(PrimitiveType.TOTALDIGITS_FACET, fixed); 85 } 86 87 protected void setFractionDigits(String value, boolean fixed) throws SchemaException { 88 int val; 89 try { 90 val = Integer.parseInt(value.trim()); 91 } catch (NumberFormatException nfe) { 92 throw new SchemaException("unknown-error-code.2"); 94 } 95 96 if (val < 0) { 97 throw new SchemaException("unknown-error-code.2"); 99 } 100 101 if ((fractionDigits != -1 && val > fractionDigits) 102 || (super.isFixed(PrimitiveType.FRACTIONDIGITS_FACET) && val != fractionDigits)) { 103 throw new SchemaException("fractionDigits-valid-restriction.1"); 105 } 106 if (totalDigits != -1 && val > totalDigits) { 107 throw new SchemaException("fractionDigits-totalDigits"); 109 } 110 fractionDigits = val; 111 super.setFixed(PrimitiveType.FRACTIONDIGITS_FACET, fixed); 112 113 initLongConstraints(); 114 } 115 116 private void initLongConstraints() { 117 if (fractionDigits == 0) { 118 BigDecimal min = (BigDecimal )super.getMinValue(); 119 BigDecimal max = (BigDecimal )super.getMaxValue(); 120 if (min != null && min.compareTo(MIN_LONG) >= 0 && max != null && max.compareTo(MAX_LONG) <= 0) { 121 longConstraints = new ComparableConstraints(); 122 longConstraints.setMinValue(new Long (min.longValue()), super.isMinInclusive()); 123 longConstraints.setMaxValue(new Long (max.longValue()), super.isMaxInclusive()); 124 } 125 } 126 } 127 128 protected void setMinExclusive(String value, boolean fixed) throws SchemaException { 129 longConstraints = null; 130 super.setMinExclusive(value, fixed); 131 initLongConstraints(); 132 } 133 134 protected void setMinInclusive(String value, boolean fixed) throws SchemaException { 135 longConstraints = null; 136 super.setMinInclusive(value, fixed); 137 initLongConstraints(); 138 } 139 140 protected void setMaxExclusive(String value, boolean fixed) throws SchemaException { 141 longConstraints = null; 142 super.setMaxExclusive(value, fixed); 143 initLongConstraints(); 144 } 145 146 protected void setMaxInclusive(String value, boolean fixed) throws SchemaException { 147 longConstraints = null; 148 super.setMaxInclusive(value, fixed); 149 initLongConstraints(); 150 } 151 152 protected Comparable toComparable(String value) throws SchemaException { 153 Long longValue = toLong(value); 154 if (longValue != null) return longValue; 155 else return toBigDecimal(value); 156 } 157 158 private Long toLong(String value) throws SchemaException { 159 if (longConstraints == null) return null; 160 Long result = null; 161 try { 162 result = new Long (value); 163 } catch (NumberFormatException ex) { 164 result = null; 165 } 166 return result; 167 } 168 169 private BigDecimal toBigDecimal(String value) throws SchemaException { 170 BigDecimal result = null; 174 try { 175 result = new BigDecimal (value); 176 } catch (NumberFormatException ex) { 177 super.invalidValue(value); 178 } 179 return result; 180 } 181 182 protected Comparable checkComparable(Comparable comp) throws SchemaException { 183 if (longConstraints != null && comp instanceof Long ) { 184 longConstraints.checkConstraints(comp); 185 } else { 186 super.checkComparable(comp); 187 } 188 return comp; 189 } 190 191 protected void checkDecimal(Number dec) throws SchemaException { 192 int sc = 0; 193 if (dec instanceof BigDecimal ) { 194 BigDecimal bigDec = (BigDecimal ) dec; 195 sc = bigDec.scale(); 196 if (fractionDigits != -1 && sc > fractionDigits) 197 super.invalidFacet("cvc-fractionDigits-valid", new Integer (fractionDigits), bigDec.toString()); 198 } 199 if (totalDigits != -1) { 200 double maxVal = Math.pow(10, totalDigits-sc); 201 if (Math.abs(dec.doubleValue()) >= maxVal) 202 super.invalidFacet("cvc-totalDigits-valid", new Integer (totalDigits), dec.toString()); 203 } 204 } 205 206 public void checkFacets(Object valueSpace) throws SchemaException { 207 super.checkFacets(valueSpace); 208 checkDecimal((Number )valueSpace); 209 } 210 211 public int getTotalDigits() { 212 return totalDigits; 213 } 214 215 public int getFractionDigits() { 216 return fractionDigits; 217 } 218 219 public String toXMLString(Object obj, ValidationContextProvider context) { 220 if (obj == null) return null; 221 if (obj instanceof Long ) return obj.toString(); 222 else { 223 String result = null; 224 BigDecimal data = (BigDecimal )obj; 225 result = data.toString(); 226 if (fractionDigits == 0) { 227 int index = result.indexOf('.'); 228 if (index != -1) return result.substring(0, index); 229 else return result; 230 } else { 231 int index = result.indexOf('.'); 232 int last = result.length() - 1; 233 if (index == -1) { 234 return result+".0"; 235 } else if (index == last) { 236 return result+"0"; 237 } else { 238 while (last > index+1 && result.charAt(last) == '0') last--; 239 return result.substring(0, last+1); 240 } 241 } 242 } 243 } 244 245 } 246 | Popular Tags |