/components/server/src/ome/tools/hibernate/SqlArray.java
Java | 354 lines | 294 code | 44 blank | 16 comment | 20 complexity | 9720c737385a29793088a98f80581cc9 MD5 | raw file
- package ome.tools.hibernate;
- import java.sql.Array;
- import java.sql.Connection;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.sql.Timestamp;
- import java.sql.Types;
- import java.util.Calendar;
- import java.util.Date;
- import java.util.GregorianCalendar;
- import java.util.List;
- import java.util.Map;
- /**
- * Hibernate type to store a java array using SQL ARRAY.
- *
- * @author Sylvain
- *
- * References : http://forum.hibernate.org/viewtopic.php?t=946973
- * http://archives.postgresql.org/pgsql-jdbc/2003-02/msg00141.php
- */
- public class SqlArray<T> implements Array {
- public final static ListAsSQLArrayUserType.ArrayFactory FACTORY =
- new ListAsSQLArrayUserType.ArrayFactory() {
- public Array BOOLEAN(Connection conn, List<Boolean> value) {
- return new BOOLEAN(value);
- }
- public Array DATE(Connection conn, List<Date> value) {
- return new DATE(value);
- }
- public Array DOUBLE(Connection conn, List<Double> value) {
- return new DOUBLE(value);
- }
- public Array FLOAT(Connection conn, List<Float> value) {
- return new FLOAT(value);
- }
- public Array INTEGER(Connection conn, List<Integer> value) {
- return new INTEGER(value);
- }
- public Array STRING(Connection conn, List<String> value) throws SQLException {
- return new STRING(value);
- }
- public Array STRING2(Connection conn, List<String[]> value) throws SQLException {
- return new STRING2(value);
- }
- };
- private List<T> data;
- private int baseType;
- private String baseTypeName = null;
- protected SqlArray(List<T> data, int baseType) {
- this.data = data;
- this.baseType = baseType;
- }
- protected SqlArray(List<T> data, int baseType, String baseTypeName) {
- this(data, baseType);
- this.baseTypeName = baseTypeName;
- }
- public static class BOOLEAN extends SqlArray<Boolean> {
- public BOOLEAN(List<Boolean> data) {
- super(data, Types.BIT);
- }
- }
- public static class INTEGER extends SqlArray<Integer> {
- public INTEGER(List<Integer> data) {
- super(data, Types.INTEGER);
- }
- }
- public static class FLOAT extends SqlArray<Float> {
- public FLOAT(List<Float> data) {
- super(data, Types.FLOAT);
- }
- }
- public static class DOUBLE extends SqlArray<Double> {
- public DOUBLE(List<Double> data) {
- super(data, Types.DOUBLE);
- }
- }
- public static class STRING extends SqlArray<String> {
- public STRING(List<String> data) {
- super(data, Types.VARCHAR, "text");
- }
- }
- public static class STRING2 extends SqlArray<String[]> {
- public STRING2(List<String[]> data) {
- super(data, Types.VARCHAR, "text");
- }
- }
- public static class DATE extends SqlArray<Date> {
- public DATE(List<Date> data) {
- super(data, Types.TIMESTAMP);
- }
- }
- public String getBaseTypeName() {
- if (baseTypeName != null) {
- return baseTypeName;
- } else {
- throw new RuntimeException("No baseTypeName");
- // return SessionsManager.getSettings().getDialect().getTypeName(
- // baseType );
- }
- }
- public int getBaseType() {
- return baseType;
- }
- public Object getArray() {
- return data.toArray();
- }
- public Object getArray(long index, int count) {
- int lastIndex = count - (int) index;
- if (lastIndex > data.size())
- lastIndex = data.size();
- return data.subList((int) (index - 1), lastIndex).toArray();
- }
- @SuppressWarnings("unused")
- public Object getArray(Map<String, Class<?>> arg0) {
- throw new UnsupportedOperationException();
- }
- @SuppressWarnings("unused")
- public Object getArray(long arg0, int arg1, Map<String, Class<?>> arg2) {
- throw new UnsupportedOperationException();
- }
- public ResultSet getResultSet() {
- throw new UnsupportedOperationException();
- }
- @SuppressWarnings("unused")
- public ResultSet getResultSet(Map<String, Class<?>> arg0) {
- throw new UnsupportedOperationException();
- }
- @SuppressWarnings("unused")
- public ResultSet getResultSet(long index, int count) {
- throw new UnsupportedOperationException();
- }
- @SuppressWarnings("unused")
- public ResultSet getResultSet(long arg0, int arg1,
- Map<String, Class<?>> arg2) {
- throw new UnsupportedOperationException();
- }
- // @Override Not allowed in Java 5
- public void free() {
- // do nothing. Required by Java 6
- }
- @Override
- public String toString() {
- StringBuilder result = new StringBuilder();
- result.append('{');
- boolean first = true;
- for (T t : data) {
- if (first)
- first = false;
- else
- result.append(',');
- if (t == null) {
- result.append("null");
- continue;
- }
- switch (baseType) {
- case Types.BIT:
- case Types.BOOLEAN:
- result.append(((Boolean) t).booleanValue() ? "true" : "false");
- break;
- case Types.INTEGER:
- case Types.FLOAT:
- case Types.DOUBLE:
- case Types.REAL:
- case Types.NUMERIC:
- case Types.DECIMAL:
- result.append(t);
- break;
- case Types.VARCHAR:
- if (t instanceof String[]) {
- String[] arr = (String[])t;
- result.append('{');
- for (int i = 0; i < arr.length; i++) {
- if (i>0) {
- result.append(",");
- }
- appendString(result, arr[i]);
- }
- result.append('}');
- } else {
- String s = (String) t;
- appendString(result, s);
- }
- break;
- case Types.TIMESTAMP:
- Date d = (Date) t;
- result.append('\'');
- appendDate(result, d);
- result.append(d);
- result.append('\'');
- break;
- default:
- throw new UnsupportedOperationException("Unsupported type "
- + baseType + " / " + getBaseTypeName());
- }
- }
- result.append('}');
- return result.toString();
- }
- /**
- * Refactored out by Josh for text[][] support
- */
- private void appendString(StringBuilder result, String s) {
- // Escape the string
- result.append('\"');
- for (int p = 0; p < s.length(); ++p) {
- char ch = s.charAt(p);
- if (ch == '\0')
- throw new IllegalArgumentException(
- "Zero bytes may not occur in string parameters.");
- if (ch == '\\' || ch == '"')
- result.append('\\');
- result.append(ch);
- }
- result.append('\"');
- }
- private static GregorianCalendar calendar = null;
- protected void appendDate(StringBuilder sb, Date date) {
- if (calendar == null)
- calendar = new GregorianCalendar();
- calendar.setTime(date);
- // Append Date
- {
- int l_year = calendar.get(Calendar.YEAR);
- // always use at least four digits for the year so very
- // early years, like 2, don't get misinterpreted
- //
- int l_yearlen = String.valueOf(l_year).length();
- for (int i = 4; i > l_yearlen; i--)
- sb.append("0");
- sb.append(l_year);
- sb.append('-');
- int l_month = calendar.get(Calendar.MONTH) + 1;
- if (l_month < 10)
- sb.append('0');
- sb.append(l_month);
- sb.append('-');
- int l_day = calendar.get(Calendar.DAY_OF_MONTH);
- if (l_day < 10)
- sb.append('0');
- sb.append(l_day);
- }
- sb.append(' ');
- // Append Time
- {
- int hours = calendar.get(Calendar.HOUR_OF_DAY);
- if (hours < 10)
- sb.append('0');
- sb.append(hours);
- sb.append(':');
- int minutes = calendar.get(Calendar.MINUTE);
- if (minutes < 10)
- sb.append('0');
- sb.append(minutes);
- sb.append(':');
- int seconds = calendar.get(Calendar.SECOND);
- if (seconds < 10)
- sb.append('0');
- sb.append(seconds);
- if (date instanceof Timestamp) {
- // Add nanoseconds.
- // This won't work for postgresql versions < 7.2 which only want
- // a two digit fractional second.
- Timestamp t = (Timestamp) date;
- char[] decimalStr = { '0', '0', '0', '0', '0', '0', '0', '0',
- '0' };
- char[] nanoStr = Integer.toString(t.getNanos()).toCharArray();
- System.arraycopy(nanoStr, 0, decimalStr, decimalStr.length
- - nanoStr.length, nanoStr.length);
- sb.append('.');
- sb.append(decimalStr, 0, 6);
- }
- }
- // Append Time Zone offset
- {
- // int offset = -(date.getTimezoneOffset());
- int offset = (calendar.get(Calendar.ZONE_OFFSET) + calendar
- .get(Calendar.DST_OFFSET))
- / (60 * 1000);
- int absoff = Math.abs(offset);
- int hours = absoff / 60;
- int mins = absoff - hours * 60;
- sb.append((offset >= 0) ? "+" : "-");
- if (hours < 10)
- sb.append('0');
- sb.append(hours);
- if (mins < 10)
- sb.append('0');
- sb.append(mins);
- }
- // Append Era
- if (calendar.get(Calendar.ERA) == GregorianCalendar.BC)
- sb.append(" BC");
- }
- }