/src/main/java/com/t11e/discovery/datatool/ResultSetConvertor.java

http://github.com/t11e/discovery_datatool · Java · 221 lines · 207 code · 10 blank · 4 comment · 27 complexity · 14c4c828f6fbe3946a8f9515b7e3206d MD5 · raw file

  1. package com.t11e.discovery.datatool;
  2. import java.sql.ResultSet;
  3. import java.sql.ResultSetMetaData;
  4. import java.sql.SQLException;
  5. import java.util.ArrayList;
  6. import java.util.Collections;
  7. import java.util.HashMap;
  8. import java.util.HashSet;
  9. import java.util.LinkedHashMap;
  10. import java.util.List;
  11. import java.util.Map;
  12. import java.util.Set;
  13. import org.apache.commons.lang.StringUtils;
  14. import com.t11e.discovery.datatool.column.BooleanColumnProcessor;
  15. import com.t11e.discovery.datatool.column.DateColumnProcessor;
  16. import com.t11e.discovery.datatool.column.IItemPropertiesFromColumnProcessor;
  17. import com.t11e.discovery.datatool.column.ItemPropertiesFromColumnProcessor;
  18. import com.t11e.discovery.datatool.column.ItemPropertiesFromUnscopedJsonColumnProcessor;
  19. import com.t11e.discovery.datatool.column.JsonColumnProcessor;
  20. import com.t11e.discovery.datatool.column.LowerCaseStringColumnProcessor;
  21. import com.t11e.discovery.datatool.column.StringColumnProcessor;
  22. import com.t11e.discovery.datatool.column.TimeColumnProcessor;
  23. import com.t11e.discovery.datatool.column.TimestampColumnProcessor;
  24. import com.t11e.discovery.datatool.column.UpperCaseStringColumnProcessor;
  25. public class ResultSetConvertor
  26. {
  27. private static final IItemPropertiesFromColumnProcessor JSON = new ItemPropertiesFromColumnProcessor(
  28. JsonColumnProcessor.INSTANCE);
  29. private static final IItemPropertiesFromColumnProcessor[] LOWER_STRING = new IItemPropertiesFromColumnProcessor[]{
  30. new ItemPropertiesFromColumnProcessor(LowerCaseStringColumnProcessor.INSTANCE)};
  31. private static final IItemPropertiesFromColumnProcessor[] UPPER_STRING = new IItemPropertiesFromColumnProcessor[]{
  32. new ItemPropertiesFromColumnProcessor(UpperCaseStringColumnProcessor.INSTANCE)};
  33. private static final IItemPropertiesFromColumnProcessor[] STRING = new IItemPropertiesFromColumnProcessor[]{
  34. new ItemPropertiesFromColumnProcessor(StringColumnProcessor.INSTANCE)};
  35. private static final IItemPropertiesFromColumnProcessor[] DATE = new IItemPropertiesFromColumnProcessor[]{
  36. new ItemPropertiesFromColumnProcessor(DateColumnProcessor.INSTANCE)};
  37. private static final IItemPropertiesFromColumnProcessor[] TIME = new IItemPropertiesFromColumnProcessor[]{
  38. new ItemPropertiesFromColumnProcessor(TimeColumnProcessor.INSTANCE)};
  39. private static final IItemPropertiesFromColumnProcessor[] TIMESTAMP = new IItemPropertiesFromColumnProcessor[]{
  40. new ItemPropertiesFromColumnProcessor(TimestampColumnProcessor.INSTANCE)};
  41. private final PropertyCase propertyCase;
  42. private final Set<String> scopedJsonColumns;
  43. private final Set<String> unscopedJsonColumns;
  44. private final Set<String> changeValueCaseColumns;
  45. private IItemPropertiesFromColumnProcessor[][] columnProcessors;
  46. private String[] columnNames;
  47. private Map<String, String> lowercaseKeyToActualKey = Collections.emptyMap();
  48. public ResultSetConvertor(final PropertyCase propertyCase, final Set<String> scopedJsonColumns,
  49. final Set<String> unscopedJsonColumns,
  50. final Set<String> potentialChangeValueCaseColumns)
  51. {
  52. this.propertyCase = propertyCase;
  53. if (PropertyCase.LEGACY != propertyCase && PropertyCase.PRESERVE != propertyCase && potentialChangeValueCaseColumns != null)
  54. {
  55. changeValueCaseColumns = new HashSet<String>(potentialChangeValueCaseColumns.size());
  56. for (final String columnLabel : potentialChangeValueCaseColumns)
  57. {
  58. changeValueCaseColumns.add(propertyCase.convert(columnLabel));
  59. }
  60. }
  61. else
  62. {
  63. changeValueCaseColumns = Collections.emptySet();
  64. }
  65. this.scopedJsonColumns = scopedJsonColumns != null ? scopedJsonColumns : Collections.<String> emptySet();
  66. this.unscopedJsonColumns = unscopedJsonColumns != null ? unscopedJsonColumns : Collections.<String> emptySet();
  67. }
  68. public Map<String, Object> getRowAsMap(final ResultSet rs)
  69. throws SQLException
  70. {
  71. lazyInitialize(rs);
  72. final Map<String, Object> properties = new LinkedHashMap<String, Object>();
  73. for (int idx = 0; idx < columnProcessors.length; ++idx)
  74. {
  75. final int column = idx + 1;
  76. final IItemPropertiesFromColumnProcessor[] processors = columnProcessors[idx];
  77. if (processors != null)
  78. {
  79. final String name = columnNames[idx];
  80. for (final IItemPropertiesFromColumnProcessor processor : processors)
  81. {
  82. processor.processColumn(properties, rs, column, name);
  83. }
  84. }
  85. }
  86. return properties;
  87. }
  88. /**
  89. * Given a potential column alias, return the actual column alias if a match is found ignoring case in the available column aliases.
  90. * Can only be called after getRowAsMap().
  91. */
  92. public String getKey(final String potentialKey)
  93. {
  94. return lowercaseKeyToActualKey.get(StringUtils.lowerCase(potentialKey));
  95. }
  96. private void lazyInitialize(final ResultSet rs)
  97. throws SQLException
  98. {
  99. if (columnProcessors == null)
  100. {
  101. final ResultSetMetaData metaData = rs.getMetaData();
  102. final IItemPropertiesFromColumnProcessor[][] processors = new IItemPropertiesFromColumnProcessor[metaData.getColumnCount()][];
  103. final String[] names = new String[processors.length];
  104. lowercaseKeyToActualKey = new HashMap<String, String>();
  105. for (int idx = 0; idx < processors.length; idx++)
  106. {
  107. final int column = idx + 1;
  108. final String columnName = metaData.getColumnLabel(column);
  109. final String convertedName = propertyCase.convert(columnName);
  110. names[idx] = convertedName;
  111. processors[idx] = getColumnProcessor(metaData, column, convertedName);
  112. lowercaseKeyToActualKey.put(StringUtils.lowerCase(convertedName), convertedName);
  113. }
  114. columnProcessors = processors;
  115. columnNames = names;
  116. }
  117. }
  118. private IItemPropertiesFromColumnProcessor[] getColumnProcessor(
  119. final ResultSetMetaData md,
  120. final int column,
  121. final String columnLabel)
  122. throws SQLException
  123. {
  124. IItemPropertiesFromColumnProcessor[] output;
  125. switch (md.getColumnType(column))
  126. {
  127. case java.sql.Types.BIT:
  128. case java.sql.Types.BOOLEAN:
  129. output = new ItemPropertiesFromColumnProcessor[]{new ItemPropertiesFromColumnProcessor(BooleanColumnProcessor.INSTANCE)};
  130. break;
  131. case java.sql.Types.TINYINT:
  132. case java.sql.Types.SMALLINT:
  133. case java.sql.Types.INTEGER:
  134. case java.sql.Types.BIGINT:
  135. case java.sql.Types.FLOAT:
  136. case java.sql.Types.REAL:
  137. case java.sql.Types.DOUBLE:
  138. case java.sql.Types.NUMERIC:
  139. case java.sql.Types.DECIMAL:
  140. output = STRING;
  141. break;
  142. case java.sql.Types.CHAR:
  143. case java.sql.Types.VARCHAR:
  144. case java.sql.Types.LONGVARCHAR:
  145. case java.sql.Types.CLOB:
  146. {
  147. final String columnLabelLower = StringUtils.lowerCase(columnLabel);
  148. if (columnLabel != null &&
  149. (scopedJsonColumns.contains(columnLabelLower)
  150. || unscopedJsonColumns.contains(columnLabelLower)))
  151. {
  152. final List<IItemPropertiesFromColumnProcessor> jsonProcessors = new ArrayList<IItemPropertiesFromColumnProcessor>(2);
  153. if (scopedJsonColumns.contains(columnLabelLower))
  154. {
  155. jsonProcessors.add(JSON);
  156. }
  157. if (unscopedJsonColumns.contains(columnLabelLower))
  158. {
  159. jsonProcessors.add(new ItemPropertiesFromUnscopedJsonColumnProcessor(JsonColumnProcessor.INSTANCE, propertyCase));
  160. }
  161. output = jsonProcessors.toArray(new IItemPropertiesFromColumnProcessor[jsonProcessors.size()]);
  162. }
  163. else if (columnLabel != null && changeValueCaseColumns.contains(columnLabel))
  164. {
  165. switch (propertyCase)
  166. {
  167. case LOWER:
  168. output = LOWER_STRING;
  169. break;
  170. case UPPER:
  171. output = UPPER_STRING;
  172. break;
  173. default:
  174. output = STRING;
  175. break;
  176. }
  177. }
  178. else
  179. {
  180. output = STRING;
  181. }
  182. break;
  183. }
  184. case java.sql.Types.DATE:
  185. output = DATE;
  186. break;
  187. case java.sql.Types.TIME:
  188. output = TIME;
  189. break;
  190. case java.sql.Types.TIMESTAMP:
  191. output = TIMESTAMP;
  192. break;
  193. case java.sql.Types.BINARY:
  194. case java.sql.Types.VARBINARY:
  195. case java.sql.Types.LONGVARBINARY:
  196. case java.sql.Types.NULL:
  197. case java.sql.Types.OTHER:
  198. case java.sql.Types.JAVA_OBJECT:
  199. case java.sql.Types.DISTINCT:
  200. case java.sql.Types.STRUCT:
  201. case java.sql.Types.ARRAY:
  202. case java.sql.Types.BLOB:
  203. case java.sql.Types.REF:
  204. case java.sql.Types.DATALINK:
  205. default:
  206. output = null;
  207. break;
  208. }
  209. return output;
  210. }
  211. }