PageRenderTime 31ms CodeModel.GetById 9ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 0ms

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

#
Java | 295 lines | 203 code | 32 blank | 60 comment | 28 complexity | dd532b5c8863f18cc604528c1c94f7bd 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
 19package org.apache.hadoop.hive.serde2.objectinspector;
 20
 21import java.lang.reflect.Field;
 22import java.lang.reflect.GenericArrayType;
 23import java.lang.reflect.ParameterizedType;
 24import java.lang.reflect.Type;
 25import java.util.ArrayList;
 26import java.util.Arrays;
 27import java.util.HashMap;
 28import java.util.List;
 29import java.util.Map;
 30
 31import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
 32import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils;
 33import org.apache.hadoop.io.Text;
 34
 35/**
 36 * ObjectInspectorFactory is the primary way to create new ObjectInspector
 37 * instances.
 38 * 
 39 * SerDe classes should call the static functions in this library to create an
 40 * ObjectInspector to return to the caller of SerDe2.getObjectInspector().
 41 * 
 42 * The reason of having caches here is that ObjectInspector is because
 43 * ObjectInspectors do not have an internal state - so ObjectInspectors with the
 44 * same construction parameters should result in exactly the same
 45 * ObjectInspector.
 46 */
 47public final class ObjectInspectorFactory {
 48
 49  /**
 50   * ObjectInspectorOptions describes what ObjectInspector to use. JAVA is to
 51   * use pure JAVA reflection. THRIFT is to use JAVA reflection and filter out
 52   * __isset fields, PROTOCOL_BUFFERS filters out has*.
 53   * New ObjectInspectorOptions can be added here when available.
 54   *
 55   * We choose to use a single HashMap objectInspectorCache to cache all
 56   * situations for efficiency and code simplicity. And we don't expect a case
 57   * that a user need to create 2 or more different types of ObjectInspectors
 58   * for the same Java type.
 59   */
 60  public enum ObjectInspectorOptions {
 61    JAVA, THRIFT, PROTOCOL_BUFFERS
 62  };
 63
 64  private static HashMap<Type, ObjectInspector> objectInspectorCache = new HashMap<Type, ObjectInspector>();
 65
 66  public static ObjectInspector getReflectionObjectInspector(Type t,
 67      ObjectInspectorOptions options) {
 68    ObjectInspector oi = objectInspectorCache.get(t);
 69    if (oi == null) {
 70      oi = getReflectionObjectInspectorNoCache(t, options);
 71      objectInspectorCache.put(t, oi);
 72    }
 73    verifyObjectInspector(options, oi, ObjectInspectorOptions.JAVA, new Class[]{ThriftStructObjectInspector.class,
 74      ProtocolBuffersStructObjectInspector.class});
 75    verifyObjectInspector(options, oi, ObjectInspectorOptions.THRIFT, new Class[]{ReflectionStructObjectInspector.class,
 76        ProtocolBuffersStructObjectInspector.class});
 77    verifyObjectInspector(options, oi, ObjectInspectorOptions.PROTOCOL_BUFFERS, new Class[]{ThriftStructObjectInspector.class,
 78        ReflectionStructObjectInspector.class});
 79
 80    return oi;
 81  }
 82
 83  /**
 84   * Verify that we don't have an unexpected type of object inspector.
 85   * @param option The option to verify
 86   * @param oi The ObjectInspector to verify
 87   * @param checkOption We're only interested in this option type
 88   * @param classes ObjectInspector should not be of these types
 89   */
 90  private static void verifyObjectInspector(ObjectInspectorOptions option, ObjectInspector oi,
 91      ObjectInspectorOptions checkOption, Class[] classes) {
 92
 93    if (option.equals(checkOption)) {
 94      for (Class checkClass : classes) {
 95        if (oi.getClass().equals(checkClass)) {
 96          throw new RuntimeException(
 97            "Cannot call getObjectInspectorByReflection with more then one of " +
 98            Arrays.toString(ObjectInspectorOptions.values()) + "!");
 99        }
100      }
101    }
102  }
103
104  private static ObjectInspector getReflectionObjectInspectorNoCache(Type t,
105      ObjectInspectorOptions options) {
106    if (t instanceof GenericArrayType) {
107      GenericArrayType at = (GenericArrayType) t;
108      return getStandardListObjectInspector(getReflectionObjectInspector(at
109          .getGenericComponentType(), options));
110    }
111
112    if (t instanceof ParameterizedType) {
113      ParameterizedType pt = (ParameterizedType) t;
114      // List?
115      if (List.class.isAssignableFrom((Class<?>) pt.getRawType())) {
116        return getStandardListObjectInspector(getReflectionObjectInspector(pt
117            .getActualTypeArguments()[0], options));
118      }
119      // Map?
120      if (Map.class.isAssignableFrom((Class<?>) pt.getRawType())) {
121        return getStandardMapObjectInspector(getReflectionObjectInspector(pt
122            .getActualTypeArguments()[0], options),
123            getReflectionObjectInspector(pt.getActualTypeArguments()[1],
124            options));
125      }
126      // Otherwise convert t to RawType so we will fall into the following if
127      // block.
128      t = pt.getRawType();
129    }
130
131    // Must be a class.
132    if (!(t instanceof Class)) {
133      throw new RuntimeException(ObjectInspectorFactory.class.getName()
134          + " internal error:" + t);
135    }
136    Class<?> c = (Class<?>) t;
137
138    // Java Primitive Type?
139    if (PrimitiveObjectInspectorUtils.isPrimitiveJavaType(c)) {
140      return PrimitiveObjectInspectorFactory
141          .getPrimitiveJavaObjectInspector(PrimitiveObjectInspectorUtils
142          .getTypeEntryFromPrimitiveJavaType(c).primitiveCategory);
143    }
144
145    // Java Primitive Class?
146    if (PrimitiveObjectInspectorUtils.isPrimitiveJavaClass(c)) {
147      return PrimitiveObjectInspectorFactory
148          .getPrimitiveJavaObjectInspector(PrimitiveObjectInspectorUtils
149          .getTypeEntryFromPrimitiveJavaClass(c).primitiveCategory);
150    }
151
152    // Primitive Writable class?
153    if (PrimitiveObjectInspectorUtils.isPrimitiveWritableClass(c)) {
154      return PrimitiveObjectInspectorFactory
155          .getPrimitiveWritableObjectInspector(PrimitiveObjectInspectorUtils
156          .getTypeEntryFromPrimitiveWritableClass(c).primitiveCategory);
157    }
158
159    // Must be struct because List and Map need to be ParameterizedType
160    assert (!List.class.isAssignableFrom(c));
161    assert (!Map.class.isAssignableFrom(c));
162
163    // Create StructObjectInspector
164    ReflectionStructObjectInspector oi;
165    switch (options) {
166    case JAVA:
167      oi = new ReflectionStructObjectInspector();
168      break;
169    case THRIFT:
170      oi = new ThriftStructObjectInspector();
171      break;
172    case PROTOCOL_BUFFERS:
173      oi = new ProtocolBuffersStructObjectInspector();
174      break;
175    default:
176      throw new RuntimeException(ObjectInspectorFactory.class.getName()
177          + ": internal error.");
178    }
179    // put it into the cache BEFORE it is initialized to make sure we can catch
180    // recursive types.
181    objectInspectorCache.put(t, oi);
182    Field[] fields = ObjectInspectorUtils.getDeclaredNonStaticFields(c);
183    ArrayList<ObjectInspector> structFieldObjectInspectors = new ArrayList<ObjectInspector>(
184        fields.length);
185    for (int i = 0; i < fields.length; i++) {
186      if (!oi.shouldIgnoreField(fields[i].getName())) {
187        structFieldObjectInspectors.add(getReflectionObjectInspector(fields[i]
188            .getGenericType(), options));
189      }
190    }
191    oi.init(c, structFieldObjectInspectors);
192    return oi;
193  }
194
195  static HashMap<ObjectInspector, StandardListObjectInspector> cachedStandardListObjectInspector = new HashMap<ObjectInspector, StandardListObjectInspector>();
196
197  public static StandardListObjectInspector getStandardListObjectInspector(
198      ObjectInspector listElementObjectInspector) {
199    StandardListObjectInspector result = cachedStandardListObjectInspector
200        .get(listElementObjectInspector);
201    if (result == null) {
202      result = new StandardListObjectInspector(listElementObjectInspector);
203      cachedStandardListObjectInspector.put(listElementObjectInspector, result);
204    }
205    return result;
206  }
207
208  static HashMap<List<ObjectInspector>, StandardMapObjectInspector> cachedStandardMapObjectInspector = new HashMap<List<ObjectInspector>, StandardMapObjectInspector>();
209
210  public static StandardMapObjectInspector getStandardMapObjectInspector(
211      ObjectInspector mapKeyObjectInspector,
212      ObjectInspector mapValueObjectInspector) {
213    ArrayList<ObjectInspector> signature = new ArrayList<ObjectInspector>(2);
214    signature.add(mapKeyObjectInspector);
215    signature.add(mapValueObjectInspector);
216    StandardMapObjectInspector result = cachedStandardMapObjectInspector
217        .get(signature);
218    if (result == null) {
219      result = new StandardMapObjectInspector(mapKeyObjectInspector,
220          mapValueObjectInspector);
221      cachedStandardMapObjectInspector.put(signature, result);
222    }
223    return result;
224  }
225
226  static HashMap<List<ObjectInspector>, StandardUnionObjectInspector>
227    cachedStandardUnionObjectInspector =
228      new HashMap<List<ObjectInspector>, StandardUnionObjectInspector>();
229
230  public static StandardUnionObjectInspector getStandardUnionObjectInspector(
231      List<ObjectInspector> unionObjectInspectors) {
232    StandardUnionObjectInspector result = cachedStandardUnionObjectInspector
233        .get(unionObjectInspectors);
234    if (result == null) {
235      result = new StandardUnionObjectInspector(unionObjectInspectors);
236      cachedStandardUnionObjectInspector.put(unionObjectInspectors, result);
237    }
238    return result;
239  }
240
241  static HashMap<ArrayList<List<?>>, StandardStructObjectInspector> cachedStandardStructObjectInspector = new HashMap<ArrayList<List<?>>, StandardStructObjectInspector>();
242
243  public static StandardStructObjectInspector getStandardStructObjectInspector(
244      List<String> structFieldNames,
245      List<ObjectInspector> structFieldObjectInspectors) {
246    ArrayList<List<?>> signature = new ArrayList<List<?>>();
247    signature.add(structFieldNames);
248    signature.add(structFieldObjectInspectors);
249    StandardStructObjectInspector result = cachedStandardStructObjectInspector
250        .get(signature);
251    if (result == null) {
252      result = new StandardStructObjectInspector(structFieldNames,
253          structFieldObjectInspectors);
254      cachedStandardStructObjectInspector.put(signature, result);
255    }
256    return result;
257  }
258
259  static HashMap<List<StructObjectInspector>, UnionStructObjectInspector> cachedUnionStructObjectInspector = new HashMap<List<StructObjectInspector>, UnionStructObjectInspector>();
260
261  public static UnionStructObjectInspector getUnionStructObjectInspector(
262      List<StructObjectInspector> structObjectInspectors) {
263    UnionStructObjectInspector result = cachedUnionStructObjectInspector
264        .get(structObjectInspectors);
265    if (result == null) {
266      result = new UnionStructObjectInspector(structObjectInspectors);
267      cachedUnionStructObjectInspector.put(structObjectInspectors, result);
268    }
269    return result;
270  }
271
272  static HashMap<ArrayList<Object>, ColumnarStructObjectInspector> cachedColumnarStructObjectInspector = new HashMap<ArrayList<Object>, ColumnarStructObjectInspector>();
273
274  public static ColumnarStructObjectInspector getColumnarStructObjectInspector(
275      List<String> structFieldNames,
276      List<ObjectInspector> structFieldObjectInspectors, Text nullSequence) {
277    ArrayList<Object> signature = new ArrayList<Object>();
278    signature.add(structFieldNames);
279    signature.add(structFieldObjectInspectors);
280    signature.add(nullSequence.toString());
281    ColumnarStructObjectInspector result = cachedColumnarStructObjectInspector
282        .get(signature);
283    if (result == null) {
284      result = new ColumnarStructObjectInspector(structFieldNames,
285          structFieldObjectInspectors, nullSequence);
286      cachedColumnarStructObjectInspector.put(signature, result);
287    }
288    return result;
289  }
290
291  private ObjectInspectorFactory() {
292    // prevent instantiation
293  }
294
295}