001: /*
002: * $Id: VarBinaryType.java,v 1.9 2005/11/03 01:26:57 ahimanikya Exp $
003: * =======================================================================
004: * Copyright (c) 2002-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.io.Serializable;
047: import java.sql.Blob;
048: import java.sql.Clob;
049: import java.sql.Types;
050: import java.util.Comparator;
051:
052: import org.axiondb.AxionException;
053: import org.axiondb.DataType;
054:
055: /**
056: * A {@link DataType}representing a {@link BinaryArray}value.
057: *
058: * @version $Revision: 1.9 $ $Date: 2005/11/03 01:26:57 $
059: * @author Rahul Dwivedi
060: * @author Rodney Waldhoff
061: * @author Ahimanikya Satapathy
062: */
063: public class VarBinaryType extends BaseDataType implements
064: Serializable, Comparator, DataType.NonFixedPrecision {
065:
066: public VarBinaryType() {
067: this (1);
068: }
069:
070: /** Creates a new instance of VarBinaryType */
071: public VarBinaryType(int length) {
072: setLength(length);
073: }
074:
075: public void setLength(int length) {
076: this ._length = length;
077:
078: }
079:
080: public int getColumnDisplaySize() {
081: return Integer.MAX_VALUE;
082: }
083:
084: public int getPrecision() {
085: return _length;
086: }
087:
088: /**
089: * Return <code>true</code> if a field of my type can be assigned the given non-
090: * <code>null</code> <i>value </i>, <code>false</code> otherwise.
091: *
092: * @param value non- <code>null</code> value
093: */
094: public boolean accepts(Object value) {
095: return true;
096: }
097:
098: public boolean supportsSuccessor() {
099: return true;
100: }
101:
102: public Object successor(Object value)
103: throws IllegalArgumentException {
104: byte[] val = (byte[]) value;
105: if (val.length == 0) {
106: return new byte[] { Byte.MIN_VALUE };
107: }
108: byte last = val[val.length - 1];
109: if (last == Byte.MAX_VALUE) {
110: byte[] newval = new byte[val.length + 1];
111: System.arraycopy(val, 0, newval, 0, val.length);
112: newval[val.length] = Byte.MIN_VALUE;
113: return newval;
114: }
115: byte[] newval = new byte[val.length];
116: System.arraycopy(val, 0, newval, 0, val.length - 1);
117: newval[val.length - 1] = (byte) (last + 1);
118: return newval;
119: }
120:
121: /**
122: * Converts an {@link #accepts acceptable}value to one of the appropriate type.
123: */
124: public Object convert(Object value) throws AxionException {
125: if (value instanceof byte[]) {
126: if (((byte[]) value).length <= _length) {
127: return (byte[]) value;
128: }
129: throw new AxionException(22001);
130: } else if (null == value) {
131: return null;
132: } else if (value instanceof Blob) {
133: try {
134: return convert(((Blob) value).getBytes(1,
135: (int) ((Blob) value).length()));
136: } catch (Exception e) {
137: throw new AxionException(e);
138: }
139: } else if (value instanceof Clob) {
140: try {
141: return convert(((Clob) value).getSubString(1,
142: (int) ((Clob) value).length()));
143: } catch (Exception e) {
144: throw new AxionException(e);
145: }
146: } else {
147: return String.valueOf(value).getBytes();
148: }
149: }
150:
151: public byte[] toByteArray(Object value) throws AxionException {
152: return (byte[]) convert(value);
153: }
154:
155: /**
156: * Returns {@link java.sql.Types#VARBINARY}.
157: */
158: public int getJdbcType() {
159: return Types.VARBINARY;
160: }
161:
162: public DataType makeNewInstance() {
163: return new VarBinaryType();
164: }
165:
166: /**
167: * Instantiate an object of my type from the given {@link DataInput}. The next
168: * sequence of bytes to be read from the <code>DataInput</code> will have been
169: * written by {@link #write}.
170: *
171: * @param in DataInput from which to read data
172: * @throws IOException if error occurs during read
173: */
174: public Object read(DataInput in) throws IOException {
175: int length = in.readInt();
176: if (-1 == length) {
177: return null;
178: } else if (length > _length) {
179: throw new IOException(
180: "Record length exceeds length for this binary type instance.");
181: }
182:
183: byte[] data = new byte[length];
184: in.readFully(data);
185: return data;
186: }
187:
188: /**
189: * Write an object of my type to the given {@link DataOutput}.
190: *
191: * @param value the value to write, which must be {@link #accepts acceptable}to this
192: * <code>DataType</code>
193: * @param out DataOutput to receive data
194: * @throws IOException if error occurs while writing value, or if <code>value</code> is invalid
195: * for this type
196: */
197: public void write(Object value, DataOutput out) throws IOException {
198: try {
199: byte[] val = (byte[]) convert(value);
200: if (null == val) {
201: out.writeInt(-1);
202: } else {
203: out.writeInt(val.length);
204: out.write(val);
205: }
206: } catch (AxionException e) {
207: throw new IOException(e.getMessage());
208: }
209: }
210:
211: public String toString(Object value) {
212: if (value instanceof byte[]) {
213: return new String((byte[]) value);
214: }
215: return null == value ? null : value.toString();
216: }
217:
218: public Comparator getComparator() {
219: return this ;
220: }
221:
222: public int compare(Object a, Object b) throws ClassCastException {
223: return compare((byte[]) a, (byte[]) b);
224: }
225:
226: public void setPrecision(int newSize) {
227: _length = newSize;
228: }
229:
230: private int compare(byte[] left, byte[] right) {
231: for (int i = 0; i < left.length; i++) {
232: if (i >= right.length) {
233: return 1;
234: } else if (left[i] < right[i]) {
235: return -1;
236: } else if (left[i] > right[i]) {
237: return 1;
238: }
239: }
240: return left.length < right.length ? -1 : 0;
241: }
242:
243: private int _length = 0;
244: private static final long serialVersionUID = -7647413688800437403L;
245: }
|