@Override public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { if (arguments.length < 2) { throw new UDFArgumentLengthException( "The function ELT(N,str1,str2,str3,...) needs at least two arguments."); } for (int i = 0; i < arguments.length; i++) { Category category = arguments[i].getCategory(); if (category != Category.PRIMITIVE) { throw new UDFArgumentTypeException( i, "The " + GenericUDFUtils.getOrdinal(i + 1) + " argument of function ELT is expected to a " + Category.PRIMITIVE.toString().toLowerCase() + " type, but " + category.toString().toLowerCase() + " is found"); } } converters = new ObjectInspectorConverters.Converter[arguments.length]; for (int i = 0; i < arguments.length; i++) { if (i == 0) { converters[i] = ObjectInspectorConverters.getConverter( arguments[i], PrimitiveObjectInspectorFactory.writableIntObjectInspector); } else { converters[i] = ObjectInspectorConverters.getConverter( arguments[i], PrimitiveObjectInspectorFactory.writableStringObjectInspector); } } return PrimitiveObjectInspectorFactory.writableStringObjectInspector; }
/** * Compares two types identified by the given object inspectors. This method compares the types as * follows: * * <ol> * <li>If the given inspectors do not belong to same category, the result is negative. * <li>If the given inspectors are for <code>PRIMITIVE</code> type, the result is the comparison * of their type names. * <li>If the given inspectors are for <code>LIST</code> type, then the result is recursive call * to compare the type of list elements. * <li>If the given inspectors are <code>MAP</code> type, then the result is a recursive call to * compare the map key and value types. * <li>If the given inspectors are <code>STRUCT</code> type, then the result is negative if they * do not have the same number of fields. If they do have the same number of fields, the * result is a recursive call to compare each of the field types. * <li>If none of the above, the result is negative. * </ol> * * @param o1 * @param o2 * @return true if the given object inspectors represent the same types. */ public static boolean compareTypes(ObjectInspector o1, ObjectInspector o2) { Category c1 = o1.getCategory(); Category c2 = o2.getCategory(); // Return false if categories are not equal if (!c1.equals(c2)) { return false; } // If both categories are primitive return the comparison of type names. if (c1.equals(Category.PRIMITIVE)) { return o1.getTypeName().equals(o2.getTypeName()); } // If lists, recursively compare the list element types if (c1.equals(Category.LIST)) { ObjectInspector child1 = ((ListObjectInspector) o1).getListElementObjectInspector(); ObjectInspector child2 = ((ListObjectInspector) o2).getListElementObjectInspector(); return compareTypes(child1, child2); } // If maps, recursively compare the key and value types if (c1.equals(Category.MAP)) { MapObjectInspector mapOI1 = (MapObjectInspector) o1; MapObjectInspector mapOI2 = (MapObjectInspector) o2; ObjectInspector childKey1 = mapOI1.getMapKeyObjectInspector(); ObjectInspector childKey2 = mapOI2.getMapKeyObjectInspector(); if (compareTypes(childKey1, childKey2)) { ObjectInspector childVal1 = mapOI1.getMapValueObjectInspector(); ObjectInspector childVal2 = mapOI2.getMapValueObjectInspector(); if (compareTypes(childVal1, childVal2)) { return true; } } return false; } // If structs, recursively compare the fields if (c1.equals(Category.STRUCT)) { StructObjectInspector structOI1 = (StructObjectInspector) o1; StructObjectInspector structOI2 = (StructObjectInspector) o2; List<? extends StructField> childFieldsList1 = structOI1.getAllStructFieldRefs(); List<? extends StructField> childFieldsList2 = structOI2.getAllStructFieldRefs(); if (childFieldsList1 == null && childFieldsList2 == null) { return true; } else if (childFieldsList1 == null || childFieldsList2 == null) { return false; } else if (childFieldsList1.size() != childFieldsList2.size()) { return false; } Iterator<? extends StructField> it1 = childFieldsList1.iterator(); Iterator<? extends StructField> it2 = childFieldsList2.iterator(); while (it1.hasNext()) { StructField field1 = it1.next(); StructField field2 = it2.next(); if (!compareTypes(field1.getFieldObjectInspector(), field2.getFieldObjectInspector())) { return false; } } return true; } if (c1.equals(Category.UNION)) { UnionObjectInspector uoi1 = (UnionObjectInspector) o1; UnionObjectInspector uoi2 = (UnionObjectInspector) o2; List<ObjectInspector> ois1 = uoi1.getObjectInspectors(); List<ObjectInspector> ois2 = uoi2.getObjectInspectors(); if (ois1 == null && ois2 == null) { return true; } else if (ois1 == null || ois2 == null) { return false; } else if (ois1.size() != ois2.size()) { return false; } Iterator<? extends ObjectInspector> it1 = ois1.iterator(); Iterator<? extends ObjectInspector> it2 = ois2.iterator(); while (it1.hasNext()) { if (!compareTypes(it1.next(), it2.next())) { return false; } } return true; } // Unknown category throw new RuntimeException("Unknown category encountered: " + c1); }