Java tutorial
/** * Copyright 2017 TerraMeta Software, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.cloudgraph.rdb.service; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.math.BigInteger; import java.sql.Blob; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.plasma.sdo.DataFlavor; import org.plasma.sdo.DataType; import org.plasma.sdo.PlasmaProperty; import org.plasma.sdo.helper.DataConverter; import commonj.sdo.Property; import commonj.sdo.Type; public class RDBDataConverter { private static Log log = LogFactory.getFactory().getInstance(RDBDataConverter.class); static public volatile RDBDataConverter INSTANCE = initializeInstance(); private Map<Integer, String> sqlTypeMap = new HashMap<Integer, String>(); private RDBDataConverter() { // Get all field in java.sql.Types Field[] fields = java.sql.Types.class.getFields(); for (int i = 0; i < fields.length; i++) { try { String name = fields[i].getName(); Integer value = (Integer) fields[i].get(null); sqlTypeMap.put(value, name); } catch (IllegalAccessException e) { } } } private static synchronized RDBDataConverter initializeInstance() { if (INSTANCE == null) INSTANCE = new RDBDataConverter(); return INSTANCE; } public Object fromJDBCDataType(ResultSet rs, int columnIndex, int sourceType, PlasmaProperty targetProperty) throws SQLException { Object result = convertFrom(rs, columnIndex, sourceType, targetProperty); return result; } public int toJDBCDataType(PlasmaProperty sourceProperty, Object value) throws SQLException { int result = convertToSqlType(sourceProperty, value); ; return result; } public Object toJDBCDataValue(PlasmaProperty sourceProperty, Object value) throws SQLException { Object result = convertToSqlValue(sourceProperty, value); return result; } public DataFlavor toJDBCDataFlavor(PlasmaProperty sourceProperty) { if (!sourceProperty.getType().isDataType()) throw new IllegalArgumentException("expected data type property, not " + sourceProperty.toString()); PlasmaProperty dataProperty = sourceProperty; return dataProperty.getDataFlavor(); } private Object convertToSqlValue(Property property, Object value) throws SQLException { if (!property.getType().isDataType()) throw new IllegalArgumentException("expected data type property, not " + property.toString()); DataType dataType = DataType.valueOf(property.getType().getName()); Object result; switch (dataType) { case String: case URI: case Month: case MonthDay: case Day: case Time: case Year: case YearMonth: case YearMonthDay: case Duration: result = DataConverter.INSTANCE.toString(property.getType(), value); break; case Date: // Plasma SDO allows more precision than just month/day/year // in an SDO date datatype, and using java.sql.Date will // truncate // here so use java.sql.Timestamp. Date date = DataConverter.INSTANCE.toDate(property.getType(), value); result = new java.sql.Timestamp(date.getTime()); break; case DateTime: date = DataConverter.INSTANCE.toDate(property.getType(), value); result = new java.sql.Timestamp(date.getTime()); break; case Decimal: result = DataConverter.INSTANCE.toDecimal(property.getType(), value); break; case Bytes: result = DataConverter.INSTANCE.toBytes(property.getType(), value); break; case Byte: result = DataConverter.INSTANCE.toByte(property.getType(), value); break; case Boolean: result = DataConverter.INSTANCE.toBoolean(property.getType(), value); break; case Character: result = DataConverter.INSTANCE.toString(property.getType(), value); break; case Double: result = DataConverter.INSTANCE.toDouble(property.getType(), value); break; case Float: result = DataConverter.INSTANCE.toDouble(property.getType(), value); break; case Int: result = DataConverter.INSTANCE.toInt(property.getType(), value); break; case Integer: result = DataConverter.INSTANCE.toInteger(property.getType(), value); break; case Long: result = DataConverter.INSTANCE.toLong(property.getType(), value); break; case Short: result = DataConverter.INSTANCE.toShort(property.getType(), value); break; case Strings: result = DataConverter.INSTANCE.toString(property.getType(), value); break; case Object: default: result = DataConverter.INSTANCE.toString(property.getType(), value); break; } return result; } private int convertToSqlType(Property property, Object value) { int result; if (!property.getType().isDataType()) throw new IllegalArgumentException("expected data type property, not " + property.toString()); DataType dataType = DataType.valueOf(property.getType().getName()); switch (dataType) { case String: case URI: case Month: case MonthDay: case Day: case Time: case Year: case YearMonth: case YearMonthDay: case Duration: case Strings: result = java.sql.Types.VARCHAR; break; case Date: // Plasma SDO allows more precision than just month/day/year // in an SDO date datatype, and using java.sql.Date will // truncate // here so use java.sql.Timestamp. result = java.sql.Types.TIMESTAMP; break; case DateTime: result = java.sql.Types.TIMESTAMP; // FIXME: so what SDO datatype maps to a SQL timestamp?? break; case Decimal: result = java.sql.Types.DECIMAL; break; case Bytes: // FIXME: how do we know whether a Blob here result = java.sql.Types.VARBINARY; break; case Byte: result = java.sql.Types.VARBINARY; break; case Boolean: result = java.sql.Types.BOOLEAN; break; case Character: result = java.sql.Types.CHAR; break; case Double: result = java.sql.Types.DOUBLE; break; case Float: result = java.sql.Types.FLOAT; break; case Int: result = java.sql.Types.INTEGER; break; case Integer: result = java.sql.Types.BIGINT; break; case Long: result = java.sql.Types.INTEGER; // FIXME: no JDBC long?? break; case Short: result = java.sql.Types.SMALLINT; break; case Object: default: result = java.sql.Types.VARCHAR; break; } return result; } private Object convertFrom(ResultSet rs, int columnIndex, int sourceType, Property property) throws SQLException { Object result = null; if (!property.getType().isDataType()) throw new IllegalArgumentException("expected data type property, not " + property.toString()); DataType targetDataType = DataType.valueOf(property.getType().getName()); switch (targetDataType) { case String: case URI: case Month: case MonthDay: case Day: case Time: case Year: case YearMonth: case YearMonthDay: case Duration: result = rs.getString(columnIndex); break; case Date: java.sql.Timestamp ts = rs.getTimestamp(columnIndex); if (ts != null) result = new java.util.Date(ts.getTime()); break; case DateTime: ts = rs.getTimestamp(columnIndex); if (ts != null) { // format DateTime String for SDO java.util.Date date = new java.util.Date(ts.getTime()); result = DataConverter.INSTANCE.getDateTimeFormat().format(date); } break; case Decimal: result = rs.getBigDecimal(columnIndex); break; case Bytes: if (sourceType != Types.BLOB) { result = rs.getBytes(columnIndex); } else if (sourceType == Types.BLOB) { Blob blob = rs.getBlob(columnIndex); if (blob != null) { long blobLen = blob.length(); // for debugging // Note: blob.getBytes(columnIndex, blob.length()); is // somehow truncating the array // by something like 14 bytes (?!!) even though // blob.length() returns the expected length // using getBinaryStream which is preferred anyway InputStream is = blob.getBinaryStream(); try { byte[] bytes = IOUtils.toByteArray(is); long len = bytes.length; // for debugging result = bytes; } catch (IOException e) { throw new RDBServiceException(e); } finally { try { is.close(); } catch (IOException e) { log.error(e.getMessage(), e); } } } } break; case Byte: result = rs.getByte(columnIndex); break; case Boolean: result = rs.getBoolean(columnIndex); break; case Character: result = rs.getInt(columnIndex); break; case Double: result = rs.getDouble(columnIndex); break; case Float: result = rs.getFloat(columnIndex); break; case Int: result = rs.getInt(columnIndex); break; case Integer: result = new BigInteger(rs.getString(columnIndex)); break; case Long: result = rs.getLong(columnIndex); break; case Short: result = rs.getShort(columnIndex); break; case Strings: String value = rs.getString(columnIndex); if (value != null) { String[] values = value.split("\\s"); List<String> list = new ArrayList<String>(values.length); for (int i = 0; i < values.length; i++) list.add(values[i]); // what no Java 5 sugar for this ?? result = list; } break; case Object: default: result = rs.getObject(columnIndex); break; } return result; } public String toJDBCString(Type sourceType, PlasmaProperty sourceProperty, Object value) { String result = null; DataFlavor flavor = sourceProperty.getDataFlavor(); switch (flavor) { case integral: case real: result = value.toString(); break; case string: result = "'" + value.toString() + "'"; break; default: result = value.toString(); } return result; } public String getJdbcTypeName(int jdbcType) { return sqlTypeMap.get(jdbcType); } }