001: /*
002: * $Id: DoubleType.java,v 1.1 2005/05/02 22:29:40 ahimanikya Exp $
003: * =======================================================================
004: * Copyright (c) 2005 Axion Development Team. 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
011: * copyright notice, this list of conditions and the following
012: * disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The names "Tigris", "Axion", nor the names of its contributors may
020: * not be used to endorse or promote products derived from this
021: * software without specific prior written permission.
022: *
023: * 4. Products derived from this software may not be called "Axion", nor
024: * may "Tigris" or "Axion" appear in their names without specific prior
025: * written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
030: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
032: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
033: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
034: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
035: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
036: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
037: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
038: * =======================================================================
039: */
040:
041: package org.axiondb.types;
042:
043: import java.io.DataInput;
044: import java.io.DataOutput;
045: import java.io.IOException;
046: import java.math.BigDecimal;
047: import java.util.Comparator;
048:
049: import org.axiondb.AxionException;
050: import org.axiondb.DataType;
051:
052: /**
053: * A {@link DataType}representing a double value.
054: *
055: * @version $Revision: 1.1 $ $Date: 2005/05/02 22:29:40 $
056: * @author Jonathan Giron
057: */
058: public class DoubleType extends BaseNumberDataType {
059:
060: public DoubleType() {
061: }
062:
063: public int getJdbcType() {
064: return java.sql.Types.DOUBLE;
065: }
066:
067: public String getPreferredValueClassName() {
068: return "java.lang.Double";
069: }
070:
071: public int getPrecision() {
072: return String.valueOf(Double.MAX_VALUE).length();
073: }
074:
075: public int getPrecisionRadix() {
076: return 10;
077: }
078:
079: public int getScale() {
080: // NOTE: Per ANSI SQL-2003 standard approximate data types like double do not have
081: // a scale value - only a precision value.
082: return 0;
083: }
084:
085: public int getColumnDisplaySize() {
086: return String.valueOf(Double.MAX_VALUE).length();
087: }
088:
089: /**
090: * Returns <code>"double"</code>
091: *
092: * @return <code>"double"</code>
093: */
094: public String toString() {
095: return "double";
096: }
097:
098: /**
099: * Returns a <tt>Double</tt> converted from the given <i>value </i>, or throws
100: * {@link IllegalArgumentException}if the given <i>value </i> isn't
101: * {@link #accepts acceptable}.
102: */
103: public Object convert(Object value) throws AxionException {
104: BigDecimal bdValue = null;
105: if (value instanceof Double) {
106: double doubleValue = ((Number) value).doubleValue();
107: if (Double.isInfinite(doubleValue)
108: || Double.isNaN(doubleValue)) {
109: throw new AxionException(22003);
110: }
111: return value;
112: } else if (value instanceof BigDecimal) {
113: bdValue = (BigDecimal) value;
114: } else if (value instanceof Number) {
115: return new Double(((Number) value).doubleValue());
116: } else if (value instanceof String) {
117: try {
118: bdValue = new BigDecimal(value.toString().trim());
119: } catch (NumberFormatException e) {
120: throw new AxionException(22018);
121: }
122: } else {
123: return super .convert(value);
124: }
125:
126: assertValueInRange(bdValue);
127: return new Double(bdValue.doubleValue());
128: }
129:
130: /**
131: * @see #write
132: */
133: public Object read(DataInput in) throws IOException {
134: double value = in.readDouble();
135: if (Double.MIN_VALUE == value) {
136: if (!in.readBoolean()) {
137: return null;
138: }
139: }
140: return new Double(value);
141: }
142:
143: /** <code>true</code> */
144: public boolean supportsSuccessor() {
145: return true;
146: }
147:
148: public Object successor(Object value)
149: throws IllegalArgumentException {
150: Double obj = (Double) value;
151: double v = obj.doubleValue();
152: if (Double.MAX_VALUE == v) {
153: return value;
154: }
155:
156: long ieee754Bits = Double.doubleToLongBits(v);
157: long sign = (ieee754Bits & SIGN_MASK);
158: boolean isNegative = (SIGN_NEGATIVE == sign);
159:
160: long accumExpMantissa = (ieee754Bits & EXP_MANTISSA_MASK);
161: if (isNegative) {
162: if (0x0L != accumExpMantissa) {
163: accumExpMantissa -= 1L;
164: } else {
165: sign = 0x0L;
166: accumExpMantissa = 0x0L;
167: }
168: } else {
169: if (0x0L != accumExpMantissa) {
170: accumExpMantissa += 1L;
171: } else {
172: accumExpMantissa = 1L;
173: }
174: }
175: return new Double(Double.longBitsToDouble(sign
176: | accumExpMantissa));
177: }
178:
179: public void write(Object value, DataOutput out) throws IOException {
180: if (null == value) {
181: out.writeDouble(Double.MIN_VALUE);
182: out.writeBoolean(false);
183: } else {
184: try {
185: double val = ((Double) (convert(value))).doubleValue();
186: out.writeDouble(val);
187: if (Double.MIN_VALUE == val) {
188: out.writeBoolean(true);
189: }
190: } catch (AxionException e) {
191: throw new IOException(e.getMessage());
192: }
193:
194: }
195: }
196:
197: public DataType makeNewInstance() {
198: return new DoubleType();
199: }
200:
201: public int compare(Object a, Object b) {
202: double pa = ((Number) a).doubleValue();
203: double pb = ((Number) b).doubleValue();
204: return (pa < pb) ? -1 : ((pa == pb) ? 0 : 1);
205: }
206:
207: protected Comparator getComparator() {
208: return this ;
209: }
210:
211: private void assertValueInRange(BigDecimal bdValue)
212: throws AxionException {
213: long expMantissa = Double.doubleToLongBits(bdValue
214: .doubleValue())
215: & EXP_MANTISSA_MASK;
216: if (expMantissa > EXP_MANTISSA_MAX) {
217: throw new AxionException(22003);
218: }
219: }
220:
221: private static final long serialVersionUID = -831981915887585231L;
222:
223: private static final long EXP_MANTISSA_MASK = 0x7FFFFFFFFFFFFFFFL;
224: private static final long EXP_MANTISSA_MAX = 0x7FEFFFFFFFFFFFFFL;
225: private static final long SIGN_MASK = 0x8000000000000000L;
226: private static final long SIGN_NEGATIVE = SIGN_MASK;
227: }
|