/tags/release-0.1-rc2/hive/external/serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/ObjectInspectorConverters.java

# · Java · 313 lines · 209 code · 42 blank · 62 comment · 20 complexity · 14a024c414d42874623962b2579ea71d MD5 · raw file

  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. package org.apache.hadoop.hive.serde2.objectinspector;
  19. import java.util.ArrayList;
  20. import java.util.List;
  21. import java.util.Map;
  22. import org.apache.hadoop.hive.serde2.objectinspector.primitive.JavaStringObjectInspector;
  23. import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorConverter;
  24. import org.apache.hadoop.hive.serde2.objectinspector.primitive.SettableBooleanObjectInspector;
  25. import org.apache.hadoop.hive.serde2.objectinspector.primitive.SettableByteObjectInspector;
  26. import org.apache.hadoop.hive.serde2.objectinspector.primitive.SettableDoubleObjectInspector;
  27. import org.apache.hadoop.hive.serde2.objectinspector.primitive.SettableFloatObjectInspector;
  28. import org.apache.hadoop.hive.serde2.objectinspector.primitive.SettableIntObjectInspector;
  29. import org.apache.hadoop.hive.serde2.objectinspector.primitive.SettableLongObjectInspector;
  30. import org.apache.hadoop.hive.serde2.objectinspector.primitive.SettableShortObjectInspector;
  31. import org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableStringObjectInspector;
  32. /**
  33. * ObjectInspectorConverters.
  34. *
  35. */
  36. public final class ObjectInspectorConverters {
  37. /**
  38. * A converter which will convert objects with one ObjectInspector to another.
  39. */
  40. public static interface Converter {
  41. Object convert(Object input);
  42. }
  43. /**
  44. * IdentityConverter.
  45. *
  46. */
  47. public static class IdentityConverter implements Converter {
  48. public Object convert(Object input) {
  49. return input;
  50. }
  51. }
  52. /**
  53. * Returns a converter that converts objects from one OI to another OI. The
  54. * returned (converted) object belongs to this converter, so that it can be
  55. * reused across different calls.
  56. */
  57. public static Converter getConverter(ObjectInspector inputOI,
  58. ObjectInspector outputOI) {
  59. // If the inputOI is the same as the outputOI, just return an
  60. // IdentityConverter.
  61. if (inputOI == outputOI) {
  62. return new IdentityConverter();
  63. }
  64. switch (outputOI.getCategory()) {
  65. case PRIMITIVE:
  66. switch (((PrimitiveObjectInspector) outputOI).getPrimitiveCategory()) {
  67. case BOOLEAN:
  68. return new PrimitiveObjectInspectorConverter.BooleanConverter(
  69. (PrimitiveObjectInspector) inputOI,
  70. (SettableBooleanObjectInspector) outputOI);
  71. case BYTE:
  72. return new PrimitiveObjectInspectorConverter.ByteConverter(
  73. (PrimitiveObjectInspector) inputOI,
  74. (SettableByteObjectInspector) outputOI);
  75. case SHORT:
  76. return new PrimitiveObjectInspectorConverter.ShortConverter(
  77. (PrimitiveObjectInspector) inputOI,
  78. (SettableShortObjectInspector) outputOI);
  79. case INT:
  80. return new PrimitiveObjectInspectorConverter.IntConverter(
  81. (PrimitiveObjectInspector) inputOI,
  82. (SettableIntObjectInspector) outputOI);
  83. case LONG:
  84. return new PrimitiveObjectInspectorConverter.LongConverter(
  85. (PrimitiveObjectInspector) inputOI,
  86. (SettableLongObjectInspector) outputOI);
  87. case FLOAT:
  88. return new PrimitiveObjectInspectorConverter.FloatConverter(
  89. (PrimitiveObjectInspector) inputOI,
  90. (SettableFloatObjectInspector) outputOI);
  91. case DOUBLE:
  92. return new PrimitiveObjectInspectorConverter.DoubleConverter(
  93. (PrimitiveObjectInspector) inputOI,
  94. (SettableDoubleObjectInspector) outputOI);
  95. case STRING:
  96. if (outputOI instanceof WritableStringObjectInspector) {
  97. return new PrimitiveObjectInspectorConverter.TextConverter(
  98. (PrimitiveObjectInspector) inputOI);
  99. } else if (outputOI instanceof JavaStringObjectInspector) {
  100. return new PrimitiveObjectInspectorConverter.StringConverter(
  101. (PrimitiveObjectInspector) inputOI);
  102. }
  103. default:
  104. throw new RuntimeException("Hive internal error: conversion of "
  105. + inputOI.getTypeName() + " to " + outputOI.getTypeName()
  106. + " not supported yet.");
  107. }
  108. case STRUCT:
  109. return new StructConverter((StructObjectInspector) inputOI,
  110. (SettableStructObjectInspector) outputOI);
  111. case LIST:
  112. return new ListConverter((ListObjectInspector) inputOI,
  113. (SettableListObjectInspector) outputOI);
  114. case MAP:
  115. return new MapConverter((MapObjectInspector) inputOI,
  116. (SettableMapObjectInspector) outputOI);
  117. default:
  118. throw new RuntimeException("Hive internal error: conversion of "
  119. + inputOI.getTypeName() + " to " + outputOI.getTypeName()
  120. + " not supported yet.");
  121. }
  122. }
  123. /**
  124. * A converter class for List.
  125. */
  126. public static class ListConverter implements Converter {
  127. ListObjectInspector inputOI;
  128. SettableListObjectInspector outputOI;
  129. ObjectInspector inputElementOI;
  130. ObjectInspector outputElementOI;
  131. ArrayList<Converter> elementConverters;
  132. Object output;
  133. public ListConverter(ListObjectInspector inputOI,
  134. SettableListObjectInspector outputOI) {
  135. this.inputOI = inputOI;
  136. this.outputOI = outputOI;
  137. inputElementOI = inputOI.getListElementObjectInspector();
  138. outputElementOI = outputOI.getListElementObjectInspector();
  139. output = outputOI.create(0);
  140. elementConverters = new ArrayList<Converter>();
  141. }
  142. @Override
  143. public Object convert(Object input) {
  144. if (input == null) {
  145. return null;
  146. }
  147. // Create enough elementConverters
  148. // NOTE: we have to have a separate elementConverter for each element,
  149. // because the elementConverters can reuse the internal object.
  150. // So it's not safe to use the same elementConverter to convert multiple
  151. // elements.
  152. int size = inputOI.getListLength(input);
  153. while (elementConverters.size() < size) {
  154. elementConverters.add(getConverter(inputElementOI, outputElementOI));
  155. }
  156. // Convert the elements
  157. outputOI.resize(output, size);
  158. for (int index = 0; index < size; index++) {
  159. Object inputElement = inputOI.getListElement(input, index);
  160. Object outputElement = elementConverters.get(index).convert(
  161. inputElement);
  162. outputOI.set(output, index, outputElement);
  163. }
  164. return output;
  165. }
  166. }
  167. /**
  168. * A converter class for Struct.
  169. */
  170. public static class StructConverter implements Converter {
  171. StructObjectInspector inputOI;
  172. SettableStructObjectInspector outputOI;
  173. List<? extends StructField> inputFields;
  174. List<? extends StructField> outputFields;
  175. ArrayList<Converter> fieldConverters;
  176. Object output;
  177. public StructConverter(StructObjectInspector inputOI,
  178. SettableStructObjectInspector outputOI) {
  179. this.inputOI = inputOI;
  180. this.outputOI = outputOI;
  181. inputFields = inputOI.getAllStructFieldRefs();
  182. outputFields = outputOI.getAllStructFieldRefs();
  183. assert (inputFields.size() == outputFields.size());
  184. fieldConverters = new ArrayList<Converter>(inputFields.size());
  185. for (int f = 0; f < inputFields.size(); f++) {
  186. fieldConverters.add(getConverter(inputFields.get(f)
  187. .getFieldObjectInspector(), outputFields.get(f)
  188. .getFieldObjectInspector()));
  189. }
  190. output = outputOI.create();
  191. }
  192. @Override
  193. public Object convert(Object input) {
  194. if (input == null) {
  195. return null;
  196. }
  197. // Convert the fields
  198. for (int f = 0; f < inputFields.size(); f++) {
  199. Object inputFieldValue = inputOI.getStructFieldData(input, inputFields
  200. .get(f));
  201. Object outputFieldValue = fieldConverters.get(f).convert(
  202. inputFieldValue);
  203. outputOI.setStructFieldData(output, outputFields.get(f),
  204. outputFieldValue);
  205. }
  206. return output;
  207. }
  208. }
  209. /**
  210. * A converter class for Map.
  211. */
  212. public static class MapConverter implements Converter {
  213. MapObjectInspector inputOI;
  214. SettableMapObjectInspector outputOI;
  215. ObjectInspector inputKeyOI;
  216. ObjectInspector outputKeyOI;
  217. ObjectInspector inputValueOI;
  218. ObjectInspector outputValueOI;
  219. ArrayList<Converter> keyConverters;
  220. ArrayList<Converter> valueConverters;
  221. Object output;
  222. public MapConverter(MapObjectInspector inputOI,
  223. SettableMapObjectInspector outputOI) {
  224. this.inputOI = inputOI;
  225. this.outputOI = outputOI;
  226. inputKeyOI = inputOI.getMapKeyObjectInspector();
  227. outputKeyOI = outputOI.getMapKeyObjectInspector();
  228. inputValueOI = inputOI.getMapValueObjectInspector();
  229. outputValueOI = outputOI.getMapValueObjectInspector();
  230. keyConverters = new ArrayList<Converter>();
  231. valueConverters = new ArrayList<Converter>();
  232. output = outputOI.create();
  233. }
  234. @Override
  235. public Object convert(Object input) {
  236. if (input == null) {
  237. return null;
  238. }
  239. // Create enough keyConverters/valueConverters
  240. // NOTE: we have to have a separate key/valueConverter for each key/value,
  241. // because the key/valueConverters can reuse the internal object.
  242. // So it's not safe to use the same key/valueConverter to convert multiple
  243. // key/values.
  244. // NOTE: This code tries to get all key-value pairs out of the map.
  245. // It's not very efficient. The more efficient way should be to let MapOI
  246. // return an Iterator. This is currently not supported by MapOI yet.
  247. Map<?, ?> map = inputOI.getMap(input);
  248. int size = map.size();
  249. while (keyConverters.size() < size) {
  250. keyConverters.add(getConverter(inputKeyOI, outputKeyOI));
  251. valueConverters.add(getConverter(inputValueOI, outputValueOI));
  252. }
  253. // CLear the output
  254. outputOI.clear(output);
  255. // Convert the key/value pairs
  256. int entryID = 0;
  257. for (Map.Entry<?, ?> entry : map.entrySet()) {
  258. Object inputKey = entry.getKey();
  259. Object inputValue = entry.getValue();
  260. Object outputKey = keyConverters.get(entryID).convert(inputKey);
  261. Object outputValue = valueConverters.get(entryID).convert(inputValue);
  262. entryID++;
  263. outputOI.put(output, outputKey, outputValue);
  264. }
  265. return output;
  266. }
  267. }
  268. private ObjectInspectorConverters() {
  269. // prevent instantiation
  270. }
  271. }