PageRenderTime 50ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/components/server/src/ome/tools/hibernate/SqlArray.java

https://github.com/ximenesuk/openmicroscopy
Java | 354 lines | 294 code | 44 blank | 16 comment | 20 complexity | 9720c737385a29793088a98f80581cc9 MD5 | raw file
  1. package ome.tools.hibernate;
  2. import java.sql.Array;
  3. import java.sql.Connection;
  4. import java.sql.ResultSet;
  5. import java.sql.SQLException;
  6. import java.sql.Timestamp;
  7. import java.sql.Types;
  8. import java.util.Calendar;
  9. import java.util.Date;
  10. import java.util.GregorianCalendar;
  11. import java.util.List;
  12. import java.util.Map;
  13. /**
  14. * Hibernate type to store a java array using SQL ARRAY.
  15. *
  16. * @author Sylvain
  17. *
  18. * References : http://forum.hibernate.org/viewtopic.php?t=946973
  19. * http://archives.postgresql.org/pgsql-jdbc/2003-02/msg00141.php
  20. */
  21. public class SqlArray<T> implements Array {
  22. public final static ListAsSQLArrayUserType.ArrayFactory FACTORY =
  23. new ListAsSQLArrayUserType.ArrayFactory() {
  24. public Array BOOLEAN(Connection conn, List<Boolean> value) {
  25. return new BOOLEAN(value);
  26. }
  27. public Array DATE(Connection conn, List<Date> value) {
  28. return new DATE(value);
  29. }
  30. public Array DOUBLE(Connection conn, List<Double> value) {
  31. return new DOUBLE(value);
  32. }
  33. public Array FLOAT(Connection conn, List<Float> value) {
  34. return new FLOAT(value);
  35. }
  36. public Array INTEGER(Connection conn, List<Integer> value) {
  37. return new INTEGER(value);
  38. }
  39. public Array STRING(Connection conn, List<String> value) throws SQLException {
  40. return new STRING(value);
  41. }
  42. public Array STRING2(Connection conn, List<String[]> value) throws SQLException {
  43. return new STRING2(value);
  44. }
  45. };
  46. private List<T> data;
  47. private int baseType;
  48. private String baseTypeName = null;
  49. protected SqlArray(List<T> data, int baseType) {
  50. this.data = data;
  51. this.baseType = baseType;
  52. }
  53. protected SqlArray(List<T> data, int baseType, String baseTypeName) {
  54. this(data, baseType);
  55. this.baseTypeName = baseTypeName;
  56. }
  57. public static class BOOLEAN extends SqlArray<Boolean> {
  58. public BOOLEAN(List<Boolean> data) {
  59. super(data, Types.BIT);
  60. }
  61. }
  62. public static class INTEGER extends SqlArray<Integer> {
  63. public INTEGER(List<Integer> data) {
  64. super(data, Types.INTEGER);
  65. }
  66. }
  67. public static class FLOAT extends SqlArray<Float> {
  68. public FLOAT(List<Float> data) {
  69. super(data, Types.FLOAT);
  70. }
  71. }
  72. public static class DOUBLE extends SqlArray<Double> {
  73. public DOUBLE(List<Double> data) {
  74. super(data, Types.DOUBLE);
  75. }
  76. }
  77. public static class STRING extends SqlArray<String> {
  78. public STRING(List<String> data) {
  79. super(data, Types.VARCHAR, "text");
  80. }
  81. }
  82. public static class STRING2 extends SqlArray<String[]> {
  83. public STRING2(List<String[]> data) {
  84. super(data, Types.VARCHAR, "text");
  85. }
  86. }
  87. public static class DATE extends SqlArray<Date> {
  88. public DATE(List<Date> data) {
  89. super(data, Types.TIMESTAMP);
  90. }
  91. }
  92. public String getBaseTypeName() {
  93. if (baseTypeName != null) {
  94. return baseTypeName;
  95. } else {
  96. throw new RuntimeException("No baseTypeName");
  97. // return SessionsManager.getSettings().getDialect().getTypeName(
  98. // baseType );
  99. }
  100. }
  101. public int getBaseType() {
  102. return baseType;
  103. }
  104. public Object getArray() {
  105. return data.toArray();
  106. }
  107. public Object getArray(long index, int count) {
  108. int lastIndex = count - (int) index;
  109. if (lastIndex > data.size())
  110. lastIndex = data.size();
  111. return data.subList((int) (index - 1), lastIndex).toArray();
  112. }
  113. @SuppressWarnings("unused")
  114. public Object getArray(Map<String, Class<?>> arg0) {
  115. throw new UnsupportedOperationException();
  116. }
  117. @SuppressWarnings("unused")
  118. public Object getArray(long arg0, int arg1, Map<String, Class<?>> arg2) {
  119. throw new UnsupportedOperationException();
  120. }
  121. public ResultSet getResultSet() {
  122. throw new UnsupportedOperationException();
  123. }
  124. @SuppressWarnings("unused")
  125. public ResultSet getResultSet(Map<String, Class<?>> arg0) {
  126. throw new UnsupportedOperationException();
  127. }
  128. @SuppressWarnings("unused")
  129. public ResultSet getResultSet(long index, int count) {
  130. throw new UnsupportedOperationException();
  131. }
  132. @SuppressWarnings("unused")
  133. public ResultSet getResultSet(long arg0, int arg1,
  134. Map<String, Class<?>> arg2) {
  135. throw new UnsupportedOperationException();
  136. }
  137. // @Override Not allowed in Java 5
  138. public void free() {
  139. // do nothing. Required by Java 6
  140. }
  141. @Override
  142. public String toString() {
  143. StringBuilder result = new StringBuilder();
  144. result.append('{');
  145. boolean first = true;
  146. for (T t : data) {
  147. if (first)
  148. first = false;
  149. else
  150. result.append(',');
  151. if (t == null) {
  152. result.append("null");
  153. continue;
  154. }
  155. switch (baseType) {
  156. case Types.BIT:
  157. case Types.BOOLEAN:
  158. result.append(((Boolean) t).booleanValue() ? "true" : "false");
  159. break;
  160. case Types.INTEGER:
  161. case Types.FLOAT:
  162. case Types.DOUBLE:
  163. case Types.REAL:
  164. case Types.NUMERIC:
  165. case Types.DECIMAL:
  166. result.append(t);
  167. break;
  168. case Types.VARCHAR:
  169. if (t instanceof String[]) {
  170. String[] arr = (String[])t;
  171. result.append('{');
  172. for (int i = 0; i < arr.length; i++) {
  173. if (i>0) {
  174. result.append(",");
  175. }
  176. appendString(result, arr[i]);
  177. }
  178. result.append('}');
  179. } else {
  180. String s = (String) t;
  181. appendString(result, s);
  182. }
  183. break;
  184. case Types.TIMESTAMP:
  185. Date d = (Date) t;
  186. result.append('\'');
  187. appendDate(result, d);
  188. result.append(d);
  189. result.append('\'');
  190. break;
  191. default:
  192. throw new UnsupportedOperationException("Unsupported type "
  193. + baseType + " / " + getBaseTypeName());
  194. }
  195. }
  196. result.append('}');
  197. return result.toString();
  198. }
  199. /**
  200. * Refactored out by Josh for text[][] support
  201. */
  202. private void appendString(StringBuilder result, String s) {
  203. // Escape the string
  204. result.append('\"');
  205. for (int p = 0; p < s.length(); ++p) {
  206. char ch = s.charAt(p);
  207. if (ch == '\0')
  208. throw new IllegalArgumentException(
  209. "Zero bytes may not occur in string parameters.");
  210. if (ch == '\\' || ch == '"')
  211. result.append('\\');
  212. result.append(ch);
  213. }
  214. result.append('\"');
  215. }
  216. private static GregorianCalendar calendar = null;
  217. protected void appendDate(StringBuilder sb, Date date) {
  218. if (calendar == null)
  219. calendar = new GregorianCalendar();
  220. calendar.setTime(date);
  221. // Append Date
  222. {
  223. int l_year = calendar.get(Calendar.YEAR);
  224. // always use at least four digits for the year so very
  225. // early years, like 2, don't get misinterpreted
  226. //
  227. int l_yearlen = String.valueOf(l_year).length();
  228. for (int i = 4; i > l_yearlen; i--)
  229. sb.append("0");
  230. sb.append(l_year);
  231. sb.append('-');
  232. int l_month = calendar.get(Calendar.MONTH) + 1;
  233. if (l_month < 10)
  234. sb.append('0');
  235. sb.append(l_month);
  236. sb.append('-');
  237. int l_day = calendar.get(Calendar.DAY_OF_MONTH);
  238. if (l_day < 10)
  239. sb.append('0');
  240. sb.append(l_day);
  241. }
  242. sb.append(' ');
  243. // Append Time
  244. {
  245. int hours = calendar.get(Calendar.HOUR_OF_DAY);
  246. if (hours < 10)
  247. sb.append('0');
  248. sb.append(hours);
  249. sb.append(':');
  250. int minutes = calendar.get(Calendar.MINUTE);
  251. if (minutes < 10)
  252. sb.append('0');
  253. sb.append(minutes);
  254. sb.append(':');
  255. int seconds = calendar.get(Calendar.SECOND);
  256. if (seconds < 10)
  257. sb.append('0');
  258. sb.append(seconds);
  259. if (date instanceof Timestamp) {
  260. // Add nanoseconds.
  261. // This won't work for postgresql versions < 7.2 which only want
  262. // a two digit fractional second.
  263. Timestamp t = (Timestamp) date;
  264. char[] decimalStr = { '0', '0', '0', '0', '0', '0', '0', '0',
  265. '0' };
  266. char[] nanoStr = Integer.toString(t.getNanos()).toCharArray();
  267. System.arraycopy(nanoStr, 0, decimalStr, decimalStr.length
  268. - nanoStr.length, nanoStr.length);
  269. sb.append('.');
  270. sb.append(decimalStr, 0, 6);
  271. }
  272. }
  273. // Append Time Zone offset
  274. {
  275. // int offset = -(date.getTimezoneOffset());
  276. int offset = (calendar.get(Calendar.ZONE_OFFSET) + calendar
  277. .get(Calendar.DST_OFFSET))
  278. / (60 * 1000);
  279. int absoff = Math.abs(offset);
  280. int hours = absoff / 60;
  281. int mins = absoff - hours * 60;
  282. sb.append((offset >= 0) ? "+" : "-");
  283. if (hours < 10)
  284. sb.append('0');
  285. sb.append(hours);
  286. if (mins < 10)
  287. sb.append('0');
  288. sb.append(mins);
  289. }
  290. // Append Era
  291. if (calendar.get(Calendar.ERA) == GregorianCalendar.BC)
  292. sb.append(" BC");
  293. }
  294. }