private ObjectInspector solveOi(ObjectInspector arg) {

    switch (arg.getCategory()) {
      case PRIMITIVE:

        // VOID, BOOLEAN, BYTE, SHORT, INT, LONG, FLOAT, DOUBLE, STRING, TIMESTAMP, BINARY, DECIMAL,
        // UNKNOWN
        PrimitiveObjectInspector poi = (PrimitiveObjectInspector) arg;
        return PrimitiveObjectInspectorFactory.getPrimitiveJavaObjectInspector(
            poi.getPrimitiveCategory());
      case LIST:
        return ObjectInspectorFactory.getStandardListObjectInspector(
            solveOi(((ListObjectInspector) arg).getListElementObjectInspector()));
      case MAP:
        return ObjectInspectorFactory.getStandardMapObjectInspector(
            solveOi(((MapObjectInspector) arg).getMapKeyObjectInspector()),
            solveOi(((MapObjectInspector) arg).getMapValueObjectInspector()));
      case STRUCT:
        StructObjectInspector soi = (StructObjectInspector) arg;
        int size = soi.getAllStructFieldRefs().size();
        ArrayList<String> fnl = new ArrayList<String>(size);
        ArrayList<ObjectInspector> foil = new ArrayList<ObjectInspector>(size);

        for (StructField sf : ((StructObjectInspector) arg).getAllStructFieldRefs()) {
          fnl.add(sf.getFieldName());
          foil.add(solveOi(sf.getFieldObjectInspector()));
        }

        return JsonStructObjectInspector.getJsonStructObjectInspector(fnl, foil);
      default:
        return arg;
    }
  }
 public static ConstantObjectInspector getConstantObjectInspector(
     ObjectInspector oi, Object value) {
   if (oi instanceof ConstantObjectInspector) {
     return (ConstantObjectInspector) oi;
   }
   ObjectInspector writableOI = getStandardObjectInspector(oi, ObjectInspectorCopyOption.WRITABLE);
   Object writableValue = ObjectInspectorConverters.getConverter(oi, writableOI).convert(value);
   switch (writableOI.getCategory()) {
     case PRIMITIVE:
       PrimitiveObjectInspector poi = (PrimitiveObjectInspector) oi;
       return PrimitiveObjectInspectorFactory.getPrimitiveWritableConstantObjectInspector(
           poi.getTypeInfo(), writableValue);
     case LIST:
       ListObjectInspector loi = (ListObjectInspector) oi;
       return ObjectInspectorFactory.getStandardConstantListObjectInspector(
           getStandardObjectInspector(
               loi.getListElementObjectInspector(), ObjectInspectorCopyOption.WRITABLE),
           (List<?>) writableValue);
     case MAP:
       MapObjectInspector moi = (MapObjectInspector) oi;
       return ObjectInspectorFactory.getStandardConstantMapObjectInspector(
           getStandardObjectInspector(
               moi.getMapKeyObjectInspector(), ObjectInspectorCopyOption.WRITABLE),
           getStandardObjectInspector(
               moi.getMapValueObjectInspector(), ObjectInspectorCopyOption.WRITABLE),
           (Map<?, ?>) writableValue);
     default:
       throw new IllegalArgumentException(
           writableOI.getCategory() + " not yet supported for constant OI");
   }
 }
  /**
   * This method is only intended to be used by Utilities class in this package. The reason that
   * this method is not recursive by itself is because we want to allow recursive types.
   */
  @Override
  protected void init(Class<?> objectClass, ObjectInspectorFactory.ObjectInspectorOptions options) {
    verifyObjectClassType(objectClass);
    this.objectClass = objectClass;
    final Field fieldMetaData;

    try {
      fieldMetaData = objectClass.getDeclaredField(FIELD_METADATA_MAP);
      assert (Map.class.isAssignableFrom(fieldMetaData.getType()));
      fieldMetaData.setAccessible(true);
    } catch (NoSuchFieldException e) {
      throw new RuntimeException("Unable to find field metadata for thrift union field ", e);
    }

    try {
      final Map<? extends TFieldIdEnum, FieldMetaData> fieldMap =
          (Map<? extends TFieldIdEnum, FieldMetaData>) fieldMetaData.get(null);
      fields = new ArrayList<StandardStructObjectInspector.MyField>(fieldMap.size());
      this.ois = new ArrayList<ObjectInspector>();
      for (Map.Entry<? extends TFieldIdEnum, FieldMetaData> metadata : fieldMap.entrySet()) {
        int fieldId = metadata.getKey().getThriftFieldId();
        String fieldName = metadata.getValue().fieldName;
        final Type fieldType = ThriftObjectInspectorUtils.getFieldType(objectClass, fieldName);
        final ObjectInspector reflectionObjectInspector =
            ObjectInspectorFactory.getReflectionObjectInspector(fieldType, options);
        fields.add(
            new StandardStructObjectInspector.MyField(
                fieldId, fieldName, reflectionObjectInspector));
        this.ois.add(reflectionObjectInspector);
      }
    } catch (IllegalAccessException e) {
      throw new RuntimeException("Unable to find field metadata for thrift union field ", e);
    }
  }
 /** Get the type name of the Java class. */
 public static String getTypeNameFromJavaClass(Type t) {
   try {
     ObjectInspector oi =
         ObjectInspectorFactory.getReflectionObjectInspector(t, ObjectInspectorOptions.JAVA);
     return oi.getTypeName();
   } catch (Throwable e) {
     LOG.info(StringUtils.stringifyException(e));
     return "unknown";
   }
 }
  public void testUnionStructObjectInspector() throws Throwable {
    try {
      ArrayList<String> fieldNames1 = new ArrayList<String>();
      fieldNames1.add("firstInteger");
      fieldNames1.add("secondString");
      fieldNames1.add("thirdBoolean");
      ArrayList<ObjectInspector> fieldObjectInspectors1 = new ArrayList<ObjectInspector>();
      fieldObjectInspectors1.add(PrimitiveObjectInspectorFactory.javaIntObjectInspector);
      fieldObjectInspectors1.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
      fieldObjectInspectors1.add(PrimitiveObjectInspectorFactory.javaBooleanObjectInspector);
      StandardStructObjectInspector soi1 =
          ObjectInspectorFactory.getStandardStructObjectInspector(
              fieldNames1, fieldObjectInspectors1);

      ArrayList<String> fieldNames2 = new ArrayList<String>();
      fieldNames2.add("fourthDouble");
      fieldNames2.add("fifthLong");
      ArrayList<ObjectInspector> fieldObjectInspectors2 = new ArrayList<ObjectInspector>();
      fieldObjectInspectors2.add(PrimitiveObjectInspectorFactory.javaDoubleObjectInspector);
      fieldObjectInspectors2.add(PrimitiveObjectInspectorFactory.javaLongObjectInspector);
      StandardStructObjectInspector soi2 =
          ObjectInspectorFactory.getStandardStructObjectInspector(
              fieldNames2, fieldObjectInspectors2);

      UnionStructObjectInspector usoi1 =
          ObjectInspectorFactory.getUnionStructObjectInspector(
              Arrays.asList(new StructObjectInspector[] {soi1, soi2}));
      UnionStructObjectInspector usoi2 =
          ObjectInspectorFactory.getUnionStructObjectInspector(
              Arrays.asList(new StructObjectInspector[] {soi1, soi2}));

      assertEquals(usoi1, usoi2);

      // metadata
      assertEquals(Category.STRUCT, usoi1.getCategory());
      List<? extends StructField> fields = usoi1.getAllStructFieldRefs();
      assertEquals(5, fields.size());
      for (int i = 0; i < 5; i++) {
        if (i <= 2) {
          assertEquals(fieldNames1.get(i).toLowerCase(), fields.get(i).getFieldName());
          assertEquals(fieldObjectInspectors1.get(i), fields.get(i).getFieldObjectInspector());
        } else {
          assertEquals(fieldNames2.get(i - 3).toLowerCase(), fields.get(i).getFieldName());
          assertEquals(fieldObjectInspectors2.get(i - 3), fields.get(i).getFieldObjectInspector());
        }
      }
      assertEquals(fields.get(1), usoi1.getStructFieldRef("secondString"));
      assertEquals(fields.get(4), usoi1.getStructFieldRef("fifthLong"));

      // null
      for (int i = 0; i < 5; i++) {
        assertNull(usoi1.getStructFieldData(null, fields.get(i)));
      }

      // real struct
      ArrayList<Object> struct1 = new ArrayList<Object>(3);
      struct1.add(1);
      struct1.add("two");
      struct1.add(true);
      ArrayList<Object> struct2 = new ArrayList<Object>(2);
      struct2.add(1.0);
      struct2.add(new Long(111));
      ArrayList<Object> struct = new ArrayList<Object>(2);
      struct.add(struct1);
      struct.add(struct2);
      ArrayList<Object> all = new ArrayList<Object>(5);
      all.addAll(struct1);
      all.addAll(struct2);

      for (int i = 0; i < 5; i++) {
        assertEquals(all.get(i), usoi1.getStructFieldData(struct, fields.get(i)));
      }
    } catch (Throwable e) {
      e.printStackTrace();
      throw e;
    }
  }
 public static ObjectInspector getStandardObjectInspector(
     ObjectInspector oi, ObjectInspectorCopyOption objectInspectorOption) {
   ObjectInspector result = null;
   switch (oi.getCategory()) {
     case PRIMITIVE:
       {
         PrimitiveObjectInspector poi = (PrimitiveObjectInspector) oi;
         switch (objectInspectorOption) {
           case DEFAULT:
             {
               if (poi.preferWritable()) {
                 result =
                     PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(
                         poi.getTypeInfo());
               } else {
                 result =
                     PrimitiveObjectInspectorFactory.getPrimitiveJavaObjectInspector(
                         poi.getTypeInfo());
               }
               break;
             }
           case JAVA:
             {
               result =
                   PrimitiveObjectInspectorFactory.getPrimitiveJavaObjectInspector(
                       poi.getTypeInfo());
               break;
             }
           case WRITABLE:
             result =
                 PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(
                     poi.getTypeInfo());
             break;
         }
         break;
       }
     case LIST:
       {
         ListObjectInspector loi = (ListObjectInspector) oi;
         result =
             ObjectInspectorFactory.getStandardListObjectInspector(
                 getStandardObjectInspector(
                     loi.getListElementObjectInspector(), objectInspectorOption));
         break;
       }
     case MAP:
       {
         MapObjectInspector moi = (MapObjectInspector) oi;
         result =
             ObjectInspectorFactory.getStandardMapObjectInspector(
                 getStandardObjectInspector(moi.getMapKeyObjectInspector(), objectInspectorOption),
                 getStandardObjectInspector(
                     moi.getMapValueObjectInspector(), objectInspectorOption));
         break;
       }
     case STRUCT:
       {
         StructObjectInspector soi = (StructObjectInspector) oi;
         List<? extends StructField> fields = soi.getAllStructFieldRefs();
         List<String> fieldNames = new ArrayList<String>(fields.size());
         List<ObjectInspector> fieldObjectInspectors =
             new ArrayList<ObjectInspector>(fields.size());
         for (StructField f : fields) {
           fieldNames.add(f.getFieldName());
           fieldObjectInspectors.add(
               getStandardObjectInspector(f.getFieldObjectInspector(), objectInspectorOption));
         }
         result =
             ObjectInspectorFactory.getStandardStructObjectInspector(
                 fieldNames, fieldObjectInspectors);
         break;
       }
     case UNION:
       {
         UnionObjectInspector uoi = (UnionObjectInspector) oi;
         List<ObjectInspector> ois = new ArrayList<ObjectInspector>();
         for (ObjectInspector eoi : uoi.getObjectInspectors()) {
           ois.add(getStandardObjectInspector(eoi, objectInspectorOption));
         }
         result = ObjectInspectorFactory.getStandardUnionObjectInspector(ois);
         break;
       }
     default:
       {
         throw new RuntimeException("Unknown ObjectInspector category!");
       }
   }
   return result;
 }