/*
* XXL: The eXtensible and fleXible Library for data processing
*
* Copyright (C) 2000-2013 Prof. Dr. Bernhard Seeger Head of the Database Research Group Department
* of Mathematics and Computer Science University of Marburg Germany
*
* This library is free software; you can redistribute it and/or modify it under the terms of the
* GNU Lesser General Public License as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library;
* If not, see <http://www.gnu.org/licenses/>.
*
* http://code.google.com/p/xxl/
*/
package xxl.core.io.converters;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import xxl.core.indexStructures.builder.BPlusTree.ManagedType;
import xxl.core.io.converters.BooleanConverter;
import xxl.core.io.converters.ByteConverter;
import xxl.core.io.converters.DateConverter;
import xxl.core.io.converters.DoubleConverter;
import xxl.core.io.converters.FloatConverter;
import xxl.core.io.converters.IntegerConverter;
import xxl.core.io.converters.LongConverter;
import xxl.core.io.converters.MeasuredConverter;
import xxl.core.io.converters.ShortConverter;
import xxl.core.io.converters.TimeConverter;
import xxl.core.io.converters.TimestampConverter;
import xxl.core.relational.JavaType;
/**
* This class provides a converter which is able to read and write objects of <i>primitive</i> java
* type, see {@link JavaType} with the built-in measured converters.
*
* <b>Information:</b> The MeasuredTupleConverter auto matches Java types and relational types, e.g.
* VARCHAR and LONGNVARCHAR to java.lang.String using {@link xxl.core.util.ConvertUtils#toJavaType
* Convert.toJavaTyp()} and vice versa using {@link xxl.core.util.ConvertUtils#toRelationalType
* Convert.toRelationalType()}. Please note that every type is matched currently but not every
* relational type can be written or read at this point. If you use e.g. CLOB (JDBC) type the
* MeasuredTupleConverter will throw an <code>UnsupportedOperationException</code>. <br/>
* <br/>
* <b>Note:</b> If you want to use <i>String</i> objects, please consider to use Tuples (
* {@link MeasuredTupleConverter}) instead of primitive types. That's because String does not have a
* fixed size which is required.
*
* @see xxl.core.relational.JavaType Java Types
* @see ManagedType Use different data types for an index structure
* @see MeasuredTupleConverter Converter for tuples
*
*
* @author Marcus Pinnecke (pinnecke@mathematik.uni-marburg.de)
*/
public final class MeasuredPrimitiveConverter extends MeasuredConverter<Object> {
/**
*
*/
private static final long serialVersionUID = -462920155889816381L;
private JavaType mJavaType;
/**
* Creates a new converter for objects of type Tuple. A tuple includes a lot of different typed
* objects. Since a tuple does not know his own object types a description of the data type of the
* contained objects will be needed here. <br/>
* <b>Note:</b> Please check that meta data and tuples match in their object size (dimension) <br/>
*
* @param type A type description of the contained objects within your tuples. You can use objects
* which implements {@link java.sql.ResultSetMetaData ResultSetMetaData}
*
* @throws NullPointerException if tupleMetaData is null
*/
public MeasuredPrimitiveConverter(JavaType type) {
if (type == null)
throw new NullPointerException(
"MeasuredTupleConverter JavaType (type) is null");
mJavaType = type;
}
@Override
public int getMaxObjectSize() {
int typeSize = 0;
switch (mJavaType) {
case BOOLEAN:
typeSize = BooleanConverter.SIZE;
break;
case BYTE:
typeSize = ByteConverter.SIZE;
break;
case DATE:
typeSize = DateConverter.SIZE;
break;
case DOUBLE:
typeSize = DoubleConverter.SIZE;
break;
case FLOAT:
typeSize = FloatConverter.SIZE;
break;
case INT:
typeSize = IntegerConverter.SIZE;
break;
case LONG:
typeSize = LongConverter.SIZE;
break;
case SHORT:
typeSize = ShortConverter.SIZE;
break;
// case STRING:
// typeSize = FixedSizeStringConverter.calculateSize(mTupleMetaData
// .getContentLength(columnIndex + 1));
// break;
case TIME:
typeSize = TimeConverter.SIZE;
break;
case TIMESTAMP:
typeSize = TimestampConverter.SIZE;
break;
default:
throw new UnsupportedOperationException("Not implemented yet for \""
+ mJavaType + "\"");
}
return typeSize;
}
/**
* Restores a tuple from an input. This read based on the meta data information given in
* constructor. <br/>
* <b>Note:</b> Please check that meta data and tuples match in their object size (dimension) <br/>
*
* @param dataInput the input from which the tuple should be loaded<br/>
* <br/>
* @param _ ignore this argument, it's unused
* @return The restored tuple with the schema you defined in the constructor
* @throws IOException if it fails to read from <code>dataInput</code> RuntimeException if tuple
* dimension and meta data dimension does not match SQLException if a SQLException occurs
* within your <code>ResultSetMetaData</code>
*/
@Override
public Object read(DataInput dataInput, Object _) throws IOException {
Object retval = null;
try {
switch (mJavaType) {
case BOOLEAN:
retval = BooleanConverter.DEFAULT_INSTANCE.read(dataInput);
break;
case BYTE:
retval = ByteConverter.DEFAULT_INSTANCE.read(dataInput);
break;
case DATE:
retval = DateConverter.DEFAULT_INSTANCE.read(dataInput);
break;
case DOUBLE:
retval = DoubleConverter.DEFAULT_INSTANCE.read(dataInput);
break;
case FLOAT:
retval = FloatConverter.DEFAULT_INSTANCE.read(dataInput);
break;
case INT:
retval = IntegerConverter.DEFAULT_INSTANCE.read(dataInput);
break;
case LONG:
retval = LongConverter.DEFAULT_INSTANCE.read(dataInput);
break;
case SHORT:
retval = ShortConverter.DEFAULT_INSTANCE.read(dataInput);
break;
// case STRING:
// retval = StringConverter.DEFAULT_INSTANCE.read(dataInput);
// checkStringJustFitsMaxCharacterLength((String) retval,
// columnIndex + 1);
// break;
case TIME:
retval = TimeConverter.DEFAULT_INSTANCE.read(dataInput);
break;
case TIMESTAMP:
retval = TimestampConverter.DEFAULT_INSTANCE.read(dataInput);
break;
default:
throw new UnsupportedOperationException("Not implemented yet for \""
+ mJavaType.toString() + "\"");
}
} catch (IOException e) {
e.printStackTrace();
}
return retval;
}
/**
* Stores a tuple sequentially into <code>dataOutput</code>. This writing operations needs info
* about each column type which you set in constructor of MeasuredTupleConverter.<br/>
* <b>Note:</b> Please check that meta data and tuples match in their object size (dimension) <br/>
*
* @throws NullPointerException if singleTuple is null <b>IOException</b> if it fails to write
* into <code>dataOutput</code> <b>RuntimeException</b> if tuple dimension and meta data
* dimension does not match <b>SQLException</b> if a SQLException occurs within your
* <code>ResultSetMetaData</code>
*/
@Override
public void write(DataOutput dataOutput, Object object) throws IOException {
if (object == null)
throw new NullPointerException(
"MeasuredTupleConverter::write object (Object) is null");
try {
switch (mJavaType) {
case BOOLEAN:
BooleanConverter.DEFAULT_INSTANCE.write(dataOutput, (Boolean) object);
break;
case BYTE:
ByteConverter.DEFAULT_INSTANCE.write(dataOutput, (Byte) object);
break;
case DATE:
DateConverter.DEFAULT_INSTANCE.write(dataOutput,
(object instanceof Long)
? new Date((Long) object)
: (Date) object);
break;
case DOUBLE:
DoubleConverter.DEFAULT_INSTANCE.write(dataOutput, (Double) object);
break;
case FLOAT:
FloatConverter.DEFAULT_INSTANCE.write(dataOutput, (Float) object);
break;
case INT:
IntegerConverter.DEFAULT_INSTANCE.write(dataOutput, (Integer) object);
break;
case LONG:
LongConverter.DEFAULT_INSTANCE.write(dataOutput, (Long) object);
break;
case SHORT:
ShortConverter.DEFAULT_INSTANCE.write(dataOutput, (Short) object);
break;
// Support String
// case STRING:
// String content = tuple.getString(columnIndex + 1);
// checkStringJustFitsMaxCharacterLength(content, columnIndex + 1);
// StringConverter.DEFAULT_INSTANCE.write(dataOutput, content);
// break;
case TIME:
TimeConverter.DEFAULT_INSTANCE.write(dataOutput,
(object instanceof Long)
? new Time((Long) object)
: (Time) object);
break;
case TIMESTAMP:
TimestampConverter.DEFAULT_INSTANCE.write(dataOutput,
(object instanceof Long)
? new Timestamp((Long) object)
: (Timestamp) object);
break;
default:
throw new UnsupportedOperationException("Not implemented yet for \""
+ mJavaType + "\"");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}