/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.pig.data;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

import org.apache.hadoop.io.WritableComparable;
import org.apache.pig.PigException;
import org.apache.pig.ResourceSchema;
import org.apache.pig.backend.executionengine.ExecException;
import org.apache.pig.builtin.ToDate;
import org.apache.pig.classification.InterfaceAudience;
import org.apache.pig.classification.InterfaceStability;
import org.apache.pig.impl.logicalLayer.FrontendException;
import org.apache.pig.impl.logicalLayer.schema.Schema;
import org.apache.pig.impl.logicalLayer.schema.SchemaMergeException;
import org.joda.time.DateTime;


/**
 * A class of static final values used to encode data type and a number of
 * static helper functions for manipulating data objects.  The data type
 * values could be
 * done as an enumeration, but it is done as byte codes instead to save
 * creating objects.
 */
@InterfaceAudience.Public
@InterfaceStability.Stable
public class DataType {
    // IMPORTANT! This list can be used to record values of data on disk,
    // so do not change the values.  You may strand user data.
    // IMPORTANT! Order matters here, as compare() below uses the order to
    // order unlike datatypes.  Don't change this ordering.
    // Spaced unevenly to leave room for new entries without changing
    // values or creating order issues.
    public static final byte UNKNOWN   =   0;
    public static final byte NULL      =   1;
    public static final byte BOOLEAN   =   5;
    public static final byte BYTE      =   6; // internal use only
    public static final byte INTEGER   =  10;
    public static final byte LONG      =  15;
    public static final byte FLOAT     =  20;
    public static final byte DOUBLE    =  25;
    public static final byte DATETIME  =  30;
    public static final byte BYTEARRAY =  50;
    public static final byte CHARARRAY =  55;
    public static final byte BIGINTEGER =  65;
    public static final byte BIGDECIMAL =  70;
    /**
     * Internal use only.
     */
    public static final byte BIGCHARARRAY =  60; //internal use only; for storing/loading chararray bigger than 64K characters in BinStorage
    public static final byte MAP       = 100;
    public static final byte TUPLE     = 110;
    public static final byte BAG       = 120;

    /**
     * Internal use only; used to store WriteableComparable objects
     * for creating ordered index in MergeJoin. Expecting a object that
     * implements Writable interface and has default constructor
     */
    public static final byte GENERIC_WRITABLECOMPARABLE = 123;

    /**
     * Internal use only.
     */
    public static final byte INTERNALMAP = 127; // internal use only; for maps that are object->object.  Used by FindQuantiles.
    public static final byte ERROR     =  -1;

    /**
     * Determine the datatype of an object.
     * @param o Object to test.
     * @return byte code of the type, or ERROR if we don't know.
     */
    public static byte findType(Object o) {
        if (o == null) {
            return NULL;
        }

        // Try to put the most common first
        if (o instanceof DataByteArray) {
            return BYTEARRAY;
        } else if (o instanceof String) {
            return CHARARRAY;
        } else if (o instanceof Tuple) {
            return TUPLE;
        } else if (o instanceof DataBag) {
            return BAG;
        } else if (o instanceof Integer) {
            return INTEGER;
        } else if (o instanceof Long) {
            return LONG;
        } else if (o instanceof InternalMap) {
            return INTERNALMAP;
        } else if (o instanceof Map) {
            return MAP;
        } else if (o instanceof Float) {
            return FLOAT;
        } else if (o instanceof Double) {
            return DOUBLE;
        } else if (o instanceof Boolean) {
            return BOOLEAN;
        } else if (o instanceof DateTime) {
            return DATETIME;
        } else if (o instanceof Byte) {
            return BYTE;
        } else if (o instanceof BigInteger) {
            return BIGINTEGER;
        } else if (o instanceof BigDecimal) {
            return BIGDECIMAL;
        } else if (o instanceof WritableComparable) {
            return GENERIC_WRITABLECOMPARABLE;
        } else {return ERROR;}
    }

    /**
     * Given a Type object determine the data type it represents.  This isn't
     * cheap, as it uses reflection, so use sparingly.
     * @param t Type to examine
     * @return byte code of the type, or ERROR if we don't know.
     */
    public static byte findType(Type t) {
        if (t == null) {
            return NULL;
        }

        // Try to put the most common first
        if (t == DataByteArray.class) {
            return BYTEARRAY;
        } else if (t == String.class) {
            return CHARARRAY;
        } else if (t == Integer.class) {
            return INTEGER;
        } else if (t == Long.class) {
            return LONG;
        } else if (t == Float.class) {
            return FLOAT;
        } else if (t == Double.class) {
            return DOUBLE;
        } else if (t == Boolean.class) {
            return BOOLEAN;
        } else if (t == Byte.class) {
            return BYTE;
        } else if (t == BigInteger.class) {
            return BIGINTEGER;
        } else if (t == BigDecimal.class) {
            return BIGDECIMAL;
        } else if (t == DateTime.class) {
            return DATETIME;
        } else if (t == InternalMap.class) {
            return INTERNALMAP;
        } else {
            // Might be a tuple or a bag, need to check the interfaces it
            // implements
            if (t instanceof Class) {
                return extractTypeFromClass(t);
            }else if (t instanceof ParameterizedType){
                ParameterizedType impl=(ParameterizedType)t;
                Class c=(Class)impl.getRawType();
                return extractTypeFromClass(c);
            }
            return ERROR;
        }
    }

    private static byte extractTypeFromClass(Type t) {
        Class c = (Class)t;
        Class[] ioeInterfaces = c.getInterfaces();
        Class[] interfaces = null;
        if(c.isInterface()){
            interfaces = new Class[ioeInterfaces.length+1];
            interfaces[0] = c;
            for (int i = 1; i < interfaces.length; i++) {
             interfaces[i] = ioeInterfaces[i-1];
            }
        }  else {
            interfaces = ioeInterfaces;
        }
        boolean matchedWritableComparable = false;
        for (int i = 0; i < interfaces.length; i++) {
            if (interfaces[i].getName().equals("org.apache.pig.data.Tuple")) {
                return TUPLE;
            } else if (interfaces[i].getName().equals("org.apache.pig.data.DataBag")) {
                return BAG;
            } else if (interfaces[i].getName().equals("java.util.Map")) {
                return MAP;
            } else if (interfaces[i].getName().equals("org.apache.hadoop.io.WritableComparable")) {
                // use GENERIC_WRITABLECOMPARABLE type only as last resort
                matchedWritableComparable = true;
                    }
        }
        if(matchedWritableComparable) {
            return GENERIC_WRITABLECOMPARABLE;
        }

        return ERROR;
    }

    /**
     * Return the number of types Pig knows about.
     * @return number of types
     */
    public static int numTypes(){
        byte[] types = genAllTypes();
        return types.length;
    }

    /**
     * Get an array of all type values.
     * @return byte array with an entry for each type.
     */
    public static byte[] genAllTypes(){
        byte[] types = { DataType.BAG, DataType.BIGCHARARRAY, DataType.BOOLEAN, DataType.BYTE, DataType.BYTEARRAY,
                DataType.CHARARRAY, DataType.DOUBLE, DataType.FLOAT, DataType.DATETIME,
                DataType.GENERIC_WRITABLECOMPARABLE,
                DataType.INTEGER, DataType.INTERNALMAP,
                DataType.LONG, DataType.MAP, DataType.TUPLE, DataType.BIGINTEGER, DataType.BIGDECIMAL};
        return types;
    }

    private static String[] genAllTypeNames(){
        String[] names = { "BAG", "BIGCHARARRAY", "BOOLEAN", "BYTE", "BYTEARRAY",
                "CHARARRAY", "DOUBLE", "FLOAT", "DATETIME",
                "GENERIC_WRITABLECOMPARABLE",
                "INTEGER",
                "INTERNALMAP",
                "LONG",
                "MAP",
                "TUPLE",
                "BIGINTEGER",
                "BIGDECIMAL"
            };
        return names;
    }

    /**
     * Get a map of type values to type names.
     * @return map
     */
    public static Map<Byte, String> genTypeToNameMap(){
        byte[] types = genAllTypes();
        String[] names = genAllTypeNames();
        Map<Byte,String> ret = new HashMap<Byte, String>();
        for(int i=0;i<types.length;i++){
            ret.put(types[i], names[i]);
        }
        return ret;
    }

    /**
     * Get a map of type names to type values.
     * @return map
     */
    public static Map<String, Byte> genNameToTypeMap(){
        byte[] types = genAllTypes();
        String[] names = genAllTypeNames();
        Map<String, Byte> ret = new HashMap<String, Byte>();
        for(int i=0;i<types.length;i++){
            ret.put(names[i], types[i]);
        }
        return ret;
    }

    /**
     * Get the type name.
     * @param o Object to test.
     * @return type name, as a String.
     */
    public static String findTypeName(Object o) {
        return findTypeName(findType(o));
    }

    /**
     * Get the type name from the type byte code
     * @param dt Type byte code
     * @return type name, as a String.
     */
    public static String findTypeName(byte dt) {
        switch (dt) {
        case NULL:      return "NULL";
        case BOOLEAN:   return "boolean";
        case BYTE:      return "byte";
        case INTEGER:   return "int";
        case BIGINTEGER:                    return "biginteger";
        case BIGDECIMAL:                    return "bigdecimal";
        case LONG:      return "long";
        case FLOAT:     return "float";
        case DOUBLE:    return "double";
        case DATETIME:  return "datetime";
        case BYTEARRAY: return "bytearray";
        case BIGCHARARRAY: return "bigchararray";
        case CHARARRAY: return "chararray";
        case MAP:       return "map";
        case INTERNALMAP: return "internalmap";
        case TUPLE:     return "tuple";
        case BAG:       return "bag";
        case GENERIC_WRITABLECOMPARABLE: return "generic_writablecomparable";
        default: return "Unknown";
        }
    }
    
    public static Class<?> findTypeClass(byte dt) {
        switch (dt) {
        case NULL:      return Void.TYPE;
        case BOOLEAN:   return Boolean.TYPE;
        case BYTE:      return Byte.TYPE;
        case INTEGER:   return Integer.TYPE;
        case BIGINTEGER:                    return BigInteger.class;
        case BIGDECIMAL:                    return BigDecimal.class;
        case LONG:      return Long.TYPE;
        case FLOAT:     return Float.TYPE;
        case DOUBLE:    return Double.TYPE;
        case DATETIME:  return DateTime.class;
        case BYTEARRAY: return DataByteArray.class;
        case BIGCHARARRAY: return String.class;
        case CHARARRAY: return String.class;
        case MAP:       return Map.class;
        case INTERNALMAP: return InternalMap.class;
        case TUPLE:     return Tuple.class;
        case BAG:       return DataBag.class;
        case GENERIC_WRITABLECOMPARABLE: return WritableComparable.class;
        default: throw new RuntimeException("Invalid type has no corresponding class: " + dt);
        }
    }

    /**
     * Get the type code from the type name 
     * @param name Type name
     * @return type code
     */
    public static byte findTypeByName(String name) {
        if (name == null) return NULL;
        else if ("boolean".equalsIgnoreCase(name)) return BOOLEAN;
        else if ("byte".equalsIgnoreCase(name)) return BYTE;
        else if ("int".equalsIgnoreCase(name)) return INTEGER;
        else if ("biginteger".equalsIgnoreCase(name)) return BIGINTEGER;
        else if ("bigdecimal".equalsIgnoreCase(name)) return BIGDECIMAL;
        else if ("long".equalsIgnoreCase(name)) return LONG;
        else if ("float".equalsIgnoreCase(name)) return FLOAT;
        else if ("double".equalsIgnoreCase(name)) return DOUBLE;
        else if ("datetime".equalsIgnoreCase(name)) return DATETIME;
        else if ("bytearray".equalsIgnoreCase(name)) return BYTEARRAY;
        else if ("bigchararray".equalsIgnoreCase(name)) return BIGCHARARRAY;
        else if ("chararray".equalsIgnoreCase(name)) return CHARARRAY;
        else if ("map".equalsIgnoreCase(name)) return MAP;
        else if ("internalmap".equalsIgnoreCase(name)) return INTERNALMAP;
        else if ("tuple".equalsIgnoreCase(name)) return TUPLE;
        else if ("bag".equalsIgnoreCase(name)) return BAG;
        else if ("generic_writablecomparable".equalsIgnoreCase(name)) return GENERIC_WRITABLECOMPARABLE;
        else return UNKNOWN;
    }


    /**
     * Determine whether the this data type is complex.
     * @param dataType Data type code to test.
     * @return true if dataType is bag, tuple, or map.
     */
    public static boolean isComplex(byte dataType) {
        return ((dataType == BAG) || (dataType == TUPLE) ||
            (dataType == MAP) || (dataType == INTERNALMAP));
    }

    /**
     * Determine whether the object is complex or atomic.
     * @param o Object to determine type of.
     * @return true if dataType is bag, tuple, or map.
     */
    public static boolean isComplex(Object o) {
        return isComplex(findType(o));
    }

    /**
     * Determine whether the this data type is atomic.
     * @param dataType Data type code to test.
     * @return true if dataType is bytearray, bigchararray, chararray, integer, long,
     * float, or boolean.
     */
    public static boolean isAtomic(byte dataType) {
        return ((dataType == BYTEARRAY) ||
                (dataType == CHARARRAY) ||
                (dataType == BIGCHARARRAY) ||
                (dataType == INTEGER) ||
                (dataType == BIGINTEGER) ||
                (dataType == BIGDECIMAL) ||
                (dataType == LONG) ||
                (dataType == FLOAT) ||
                (dataType == DOUBLE) ||
                (dataType == BOOLEAN) ||
                (dataType == BYTE) ||
                (dataType == DATETIME) ||
                (dataType == GENERIC_WRITABLECOMPARABLE));
    }

    /**
     * Determine whether the this data type is atomic.
     * @param o Object to determine type of.
     * @return true if dataType is bytearray, chararray, integer, long,
     * float, or boolean.
     */
    public static boolean isAtomic(Object o) {
        return isAtomic(findType(o));
    }

    /**
     * Determine whether the this object can have a schema.
     * @param o Object to determine if it has a schema
     * @return true if the type can have a valid schema (i.e., bag or tuple)
     */
    public static boolean isSchemaType(Object o) {
        return isSchemaType(findType(o));
    }

    /**
     * Determine whether the this data type can have a schema.
     * @param dataType dataType to determine if it has a schema
     * @return true if the type can have a valid schema (i.e., bag or tuple)
     */
    public static boolean isSchemaType(byte dataType) {
        return ((dataType == BAG) || (dataType == TUPLE) || dataType == MAP);
    }

    /**
    /**
     * Compare two objects to each other.  This function is necessary
     * because there's no super class that implements compareTo.  This
     * function provides an (arbitrary) ordering of objects of different
     * types as follows:  NULL &lt; BOOLEAN &lt; BYTE &lt; INTEGER &lt; LONG &lt;
     * FLOAT &lt; DOUBLE &lt; DATETIME &lt; BYTEARRAY &lt; STRING &lt; MAP &lt;
     * TUPLE &lt; BAG.  No other functions should implement this cross
     * object logic.  They should call this function for it instead.
     * @param o1 First object
     * @param o2 Second object
     * @return -1 if o1 is less, 0 if they are equal, 1 if o2 is less.
     */
    public static int compare(Object o1, Object o2) {

        byte dt1 = findType(o1);
        byte dt2 = findType(o2);
        return compare(o1, o2, dt1, dt2);
    }

    /**
     * Same as {@link #compare(Object, Object)}, but does not use reflection to determine the type
     * of passed in objects, relying instead on the caller to provide the appropriate values, as
     * determined by {@link DataType#findType(Object)}.
     *
     * Use this version in cases where multiple objects of the same type have to be repeatedly compared.
     * @param o1 first object
     * @param o2 second object
     * @param dt1 type, as byte value, of o1
     * @param dt2 type, as byte value, of o2
     * @return -1 if o1 is &lt; o2, 0 if they are equal, 1 if o1 &gt; o2
     */
    @SuppressWarnings("unchecked")
    public static int compare(Object o1, Object o2, byte dt1, byte dt2) {
        if (dt1 == dt2) {
            if(o1 == null) {
                if(o2 == null) {
                    return 0;
                } else {
                    return -1;
                }
            } else {
                if(o2 == null) {
                    return 1;
                }
            }
            switch (dt1) {
            case NULL:
                return 0;

            case BOOLEAN:
                return ((Boolean)o1).compareTo((Boolean)o2);

            case BYTE:
                return ((Byte)o1).compareTo((Byte)o2);

            case INTEGER:
                return ((Integer)o1).compareTo((Integer)o2);

            case LONG:
                return ((Long)o1).compareTo((Long)o2);

            case FLOAT:
                return ((Float)o1).compareTo((Float)o2);

            case DOUBLE:
                return ((Double)o1).compareTo((Double)o2);

            case DATETIME:
                return ((DateTime)o1).compareTo((DateTime)o2);

            case BYTEARRAY:
                return ((DataByteArray)o1).compareTo(o2);

            case CHARARRAY:
                return ((String)o1).compareTo((String)o2);

            case BIGINTEGER:
                return ((BigInteger)o1).compareTo((BigInteger)o2);

            case BIGDECIMAL:
                return ((BigDecimal)o1).compareTo((BigDecimal)o2);

            case MAP: {
                Map<String, Object> m1 = (Map<String, Object>)o1;
                Map<String, Object> m2 = (Map<String, Object>)o2;
                int sz1 = m1.size();
                int sz2 = m2.size();
                if (sz1 < sz2) {
                    return -1;
                } else if (sz1 > sz2) {
                    return 1;
                } else {
                    // This is bad, but we have to sort the keys of the maps in order
                    // to be commutative.
                    TreeMap<String, Object> tm1 = new TreeMap<String, Object>(m1);
                    TreeMap<String, Object> tm2 = new TreeMap<String, Object>(m2);
                    Iterator<Map.Entry<String, Object> > i1 =
                        tm1.entrySet().iterator();
                    Iterator<Map.Entry<String, Object> > i2 =
                        tm2.entrySet().iterator();
                    while (i1.hasNext()) {
                        Map.Entry<String, Object> entry1 = i1.next();
                        Map.Entry<String, Object> entry2 = i2.next();
                        int c = entry1.getKey().compareTo(entry2.getKey());
                        if (c != 0) {
                            return c;
                        } else {
                            c = compare(entry1.getValue(), entry2.getValue());
                            if (c != 0) {
                                return c;
                            }
                        }
                    }
                    return 0;
                }
                      }

            case GENERIC_WRITABLECOMPARABLE:
                return ((Comparable)o1).compareTo(o2);

            case INTERNALMAP:
                return -1;  // Don't think anyway will want to do this.

            case TUPLE:
                return ((Tuple)o1).compareTo(o2);

            case BAG:
                return ((DataBag)o1).compareTo(o2);


            default:
                throw new RuntimeException("Unkown type " + dt1 +
                    " in compare");
            }
        } else if (dt1 < dt2) {
            return -1;
        } else {
            return 1;
        }
    }

    public static byte[] toBytes(Object o) throws ExecException {
        return toBytes(o, findType(o));
    }

    @SuppressWarnings("unchecked")
    public static byte[] toBytes(Object o, byte type) throws ExecException {
        switch (type) {
        case BOOLEAN:
            //return ((Boolean) o).booleanValue() ? new byte[] {1} : new byte[] {0};
            return ((Boolean) o).toString().getBytes();
        case BYTE:
            return new byte[] {((Byte) o)};

        case BIGINTEGER:
        case BIGDECIMAL:
        case INTEGER:
        case DOUBLE:
        case FLOAT:
        case LONG:
            return ((Number) o).toString().getBytes();

        case DATETIME:
            return ((DateTime) o).toString().getBytes();

        case CHARARRAY:
            return ((String) o).getBytes();
        case MAP:
            return mapToString((Map<String, Object>) o).getBytes();
        case TUPLE:
            return ((Tuple) o).toString().getBytes();
        case BYTEARRAY:
            return ((DataByteArray) o).get();
        case BAG:
            return ((DataBag) o).toString().getBytes();
        case NULL:
            return null;
        default:
            int errCode = 1071;
            String msg = "Cannot convert a " + findTypeName(o) +
            " to a ByteArray";
            throw new ExecException(msg, errCode, PigException.INPUT);

        }
    }

    /**
     * Force a data object to a Boolean, if possible. Any numeric type can be
     * forced to a Boolean, as well as CharArray, ByteArray. Complex types
     * cannot be forced to a Boolean. This isn't particularly efficient, so if
     * you already <b>know</b> that the object you have is a Boolean you should
     * just cast it.
     *
     * @param o
     *            object to cast
     * @param type
     *            of the object you are casting
     * @return The object as a Boolean.
     * @throws ExecException
     *             if the type can't be forced to a Boolean.
     */
    public static Boolean toBoolean(Object o, byte type) throws ExecException {
        try {
            switch (type) {
            case NULL:
                return null;
            case BOOLEAN:
                return (Boolean) o;
            case BYTE:
                return Boolean.valueOf(((Byte) o).byteValue() != 0);
            case INTEGER:
                return Boolean.valueOf(((Integer) o).intValue() != 0);
            case LONG:
                return Boolean.valueOf(((Long) o).longValue() != 0L);
            case BIGINTEGER:
                return Boolean.valueOf(!BigInteger.ZERO.equals(((BigInteger) o)));
            case BIGDECIMAL:
                return Boolean.valueOf(!BigDecimal.ZERO.equals(((BigDecimal) o)));
            case FLOAT:
                return Boolean.valueOf(((Float) o).floatValue() != 0.0F);
            case DOUBLE:
                return Boolean.valueOf(((Double) o).doubleValue() != 0.0D);
            case BYTEARRAY:
                String str = ((DataByteArray) o).toString();
                if (str.equalsIgnoreCase("true")) {
                    return Boolean.TRUE;
                } else if (str.equalsIgnoreCase("false")) {
                    return Boolean.FALSE;
                } else {
                    return null;
                }
            case CHARARRAY:
                if (((String) o).equalsIgnoreCase("true")) {
                    return Boolean.TRUE;
                } else if (((String) o).equalsIgnoreCase("false")) {
                    return Boolean.FALSE;
                } else {
                    return null;
                }
            case DATETIME:
            case MAP:
            case INTERNALMAP:
            case TUPLE:
            case BAG:
            case UNKNOWN:
            default:
                int errCode = 1071;
                String msg = "Cannot convert a " + findTypeName(o) + " to a Boolean";
                throw new ExecException(msg, errCode, PigException.INPUT);
            }
        } catch (ClassCastException cce) {
            throw cce;
        } catch (ExecException ee) {
            throw ee;
        } catch (NumberFormatException nfe) {
            int errCode = 1074;
            String msg = "Problem with formatting. Could not convert " + o + " to Float.";
            throw new ExecException(msg, errCode, PigException.INPUT, nfe);
        } catch (Exception e) {
            int errCode = 2054;
            String msg = "Internal error. Could not convert " + o + " to Float.";
            throw new ExecException(msg, errCode, PigException.BUG);
        }
    }

    public static Boolean toBoolean(Object o) throws ExecException {
        return toBoolean(o, findType(o));
    }

    /**
     * Force a data object to an Integer, if possible.  Any numeric type
     * can be forced to an Integer (though precision may be lost), as well
     * as CharArray, ByteArray, or Boolean.  Complex types cannot be
     * forced to an Integer.  This isn't particularly efficient, so if you
     * already <b>know</b> that the object you have is an Integer you
     * should just cast it.
     * @param o object to cast
     * @param type of the object you are casting
     * @return The object as an Integer.
     * @throws ExecException if the type can't be forced to an Integer.
     */
    public static Integer toInteger(Object o,byte type) throws ExecException {
        try {
            switch (type) {
            case BOOLEAN:
                if (((Boolean)o) == true) {
                    return Integer.valueOf(1);
                } else {
                    return Integer.valueOf(0);
                }

            case BYTE:
                return Integer.valueOf(((Byte)o).intValue());

            case INTEGER:
                return (Integer)o;

            case LONG:
                return Integer.valueOf(((Long)o).intValue());

            case FLOAT:
                return Integer.valueOf(((Float)o).intValue());

            case DOUBLE:
                return Integer.valueOf(((Double)o).intValue());

            case BYTEARRAY:
                return Integer.valueOf(((DataByteArray)o).toString());

            case CHARARRAY:
                return Integer.valueOf((String)o);

            case BIGINTEGER:
                return Integer.valueOf(((BigInteger)o).intValue());

            case BIGDECIMAL:
                return Integer.valueOf(((BigDecimal)o).intValue());

            case NULL:
                return null;

            case DATETIME:
                return Integer.valueOf(Long.valueOf(((DateTime)o).getMillis()).intValue());

            case MAP:
            case INTERNALMAP:
            case TUPLE:
            case BAG:
            case UNKNOWN:
            default:
                int errCode = 1071;
                String msg = "Cannot convert a " + findTypeName(o) +
                " to an Integer";
                throw new ExecException(msg, errCode, PigException.INPUT);
            }
        } catch (ClassCastException cce) {
            throw cce;
        } catch (ExecException ee) {
            throw ee;
        } catch (NumberFormatException nfe) {
            int errCode = 1074;
            String msg = "Problem with formatting. Could not convert " + o + " to Integer.";
            throw new ExecException(msg, errCode, PigException.INPUT, nfe);
        } catch (Exception e) {
            int errCode = 2054;
            String msg = "Internal error. Could not convert " + o + " to Integer.";
            throw new ExecException(msg, errCode, PigException.BUG);
        }
    }

    /**
     * Force a data object to an Integer, if possible.  Any numeric type
     * can be forced to an Integer (though precision may be lost), as well
     * as CharArray, ByteArray, or Boolean.  Complex types cannot be
     * forced to an Integer.  This isn't particularly efficient, so if you
     * already <b>know</b> that the object you have is an Integer you
     * should just cast it.  Unlike {@link #toInteger(Object, byte)} this
     * method will first determine the type of o and then do the cast.
     * Use {@link #toInteger(Object, byte)} if you already know the type.
     * @param o object to cast
     * @return The object as an Integer.
     * @throws ExecException if the type can't be forced to an Integer.
     */
    public static Integer toInteger(Object o) throws ExecException {
        return toInteger(o, findType(o));
    }

    /**
     * Force a data object to a Long, if possible.  Any numeric type
     * can be forced to a Long (though precision may be lost), as well
     * as CharArray, ByteArray, or Boolean.  Complex types cannot be
     * forced to a Long.  This isn't particularly efficient, so if you
     * already <b>know</b> that the object you have is a Long you
     * should just cast it.
     * @param o object to cast
     * @param type of the object you are casting
     * @return The object as a Long.
     * @throws ExecException if the type can't be forced to a Long.
     */
    public static Long toLong(Object o,byte type) throws ExecException {
        try {
            switch (type) {
            case BOOLEAN:
                if (((Boolean)o) == true) {
                    return Long.valueOf(1);
                } else {
                    return Long.valueOf(0);
                }

            case BYTE:
                return Long.valueOf(((Byte)o).longValue());

            case INTEGER:
                return Long.valueOf(((Integer)o).longValue());

            case LONG:
                return (Long)o;

            case FLOAT:
                return Long.valueOf(((Float)o).longValue());

            case DOUBLE:
                return Long.valueOf(((Double)o).longValue());

            case BYTEARRAY:
                return Long.valueOf(((DataByteArray)o).toString());

            case CHARARRAY:
                return Long.valueOf((String)o);

            case BIGINTEGER:
                return Long.valueOf(((BigInteger)o).longValue());

            case BIGDECIMAL:
                return Long.valueOf(((BigDecimal)o).longValue());

            case NULL:
                return null;

            case DATETIME:
                return Long.valueOf(((DateTime)o).getMillis());
            case MAP:
            case INTERNALMAP:
            case TUPLE:
            case BAG:
            case UNKNOWN:
            default:
                int errCode = 1071;
                String msg = "Cannot convert a " + findTypeName(o) +
                " to a Long";
                throw new ExecException(msg, errCode, PigException.INPUT);
            }
        } catch (ClassCastException cce) {
            throw cce;
        } catch (ExecException ee) {
            throw ee;
        } catch (NumberFormatException nfe) {
            int errCode = 1074;
            String msg = "Problem with formatting. Could not convert " + o + " to Long.";
            throw new ExecException(msg, errCode, PigException.INPUT, nfe);
        } catch (Exception e) {
            int errCode = 2054;
            String msg = "Internal error. Could not convert " + o + " to Long.";
            throw new ExecException(msg, errCode, PigException.BUG);
        }

    }

    /**
     * Force a data object to a Long, if possible.  Any numeric type
     * can be forced to a Long (though precision may be lost), as well
     * as CharArray, ByteArray, or Boolean.  Complex types cannot be
     * forced to an Long.  This isn't particularly efficient, so if you
     * already <b>know</b> that the object you have is a Long you
     * should just cast it.  Unlike {@link #toLong(Object, byte)} this
     * method will first determine the type of o and then do the cast.
     * Use {@link #toLong(Object, byte)} if you already know the type.
     * @param o object to cast
     * @return The object as a Long.
     * @throws ExecException if the type can't be forced to an Long.
     */
    public static Long toLong(Object o) throws ExecException {
        return toLong(o, findType(o));
    }

    /**
     * Force a data object to a Float, if possible.  Any numeric type
     * can be forced to a Float (though precision may be lost), as well
     * as CharArray, ByteArray.  Complex types cannot be
     * forced to a Float.  This isn't particularly efficient, so if you
     * already <b>know</b> that the object you have is a Float you
     * should just cast it.
     * @param o object to cast
     * @param type of the object you are casting
     * @return The object as a Float.
     * @throws ExecException if the type can't be forced to a Float.
     */
    public static Float toFloat(Object o,byte type) throws ExecException {
        try {
            switch (type) {
            case BOOLEAN:
                return (Boolean) o ? Float.valueOf(1.0F) : Float.valueOf(0.0F);

            case INTEGER:
                return new Float(((Integer)o).floatValue());

            case LONG:
                return new Float(((Long)o).floatValue());

            case FLOAT:
                return (Float)o;

            case DOUBLE:
                return new Float(((Double)o).floatValue());

             case DATETIME:
                 return new Float(Long.valueOf(((DateTime)o).getMillis()).floatValue());

            case BYTEARRAY:
                return Float.valueOf(((DataByteArray)o).toString());

            case CHARARRAY:
                return Float.valueOf((String)o);

             case BIGINTEGER:
                return Float.valueOf(((BigInteger)o).floatValue());

            case BIGDECIMAL:
                return Float.valueOf(((BigDecimal)o).floatValue());

            case NULL:
                return null;

            case BYTE:
            case MAP:
            case INTERNALMAP:
            case TUPLE:
            case BAG:
            case UNKNOWN:
            default:
                int errCode = 1071;
                String msg = "Cannot convert a " + findTypeName(o) +
                " to a Float";
                throw new ExecException(msg, errCode, PigException.INPUT);
            }
        } catch (ClassCastException cce) {
            throw cce;
        } catch (ExecException ee) {
            throw ee;
        } catch (NumberFormatException nfe) {
            int errCode = 1074;
            String msg = "Problem with formatting. Could not convert " + o + " to Float.";
            throw new ExecException(msg, errCode, PigException.INPUT, nfe);
        } catch (Exception e) {
            int errCode = 2054;
            String msg = "Internal error. Could not convert " + o + " to Float.";
            throw new ExecException(msg, errCode, PigException.BUG);
        }
    }

    /**
     * Force a data object to a Float, if possible.  Any numeric type
     * can be forced to a Float (though precision may be lost), as well
     * as CharArray, ByteArray, or Boolean.  Complex types cannot be
     * forced to an Float.  This isn't particularly efficient, so if you
     * already <b>know</b> that the object you have is a Float you
     * should just cast it.  Unlike {@link #toFloat(Object, byte)} this
     * method will first determine the type of o and then do the cast.
     * Use {@link #toFloat(Object, byte)} if you already know the type.
     * @param o object to cast
     * @return The object as a Float.
     * @throws ExecException if the type can't be forced to an Float.
     */
    public static Float toFloat(Object o) throws ExecException {
        return toFloat(o, findType(o));
    }

    /**
     * Force a data object to a Double, if possible.  Any numeric type
     * can be forced to a Double, as well
     * as CharArray, ByteArray.  Complex types cannot be
     * forced to a Double.  This isn't particularly efficient, so if you
     * already <b>know</b> that the object you have is a Double you
     * should just cast it.
     * @param o object to cast
     * @param type of the object you are casting
     * @return The object as a Double.
     * @throws ExecException if the type can't be forced to a Double.
     */
    public static Double toDouble(Object o,byte type) throws ExecException {
        try {
            switch (type) {
            case BOOLEAN:
                return (Boolean) o ? Double.valueOf(1.0D) : Double.valueOf(0.0D);

            case INTEGER:
                return new Double(((Integer)o).doubleValue());

            case LONG:
                return new Double(((Long)o).doubleValue());

            case FLOAT:
                return new Double(((Float)o).doubleValue());

            case DOUBLE:
                return (Double)o;

            case DATETIME:
                return new Double(Long.valueOf(((DateTime)o).getMillis()).doubleValue());

            case BYTEARRAY:
                return Double.valueOf(((DataByteArray)o).toString());

            case CHARARRAY:
                return Double.valueOf((String)o);

            case BIGINTEGER:
                return Double.valueOf(((BigInteger)o).doubleValue());

            case BIGDECIMAL:
                return Double.valueOf(((BigDecimal)o).doubleValue());

            case NULL:
                return null;

            case BYTE:
            case MAP:
            case INTERNALMAP:
            case TUPLE:
            case BAG:
            case UNKNOWN:
            default:
                int errCode = 1071;
                String msg = "Cannot convert a " + findTypeName(o) +
                " to a Double";
                throw new ExecException(msg, errCode, PigException.INPUT);
            }
        } catch (ClassCastException cce) {
            throw cce;
        } catch (ExecException ee) {
            throw ee;
        } catch (NumberFormatException nfe) {
            int errCode = 1074;
            String msg = "Problem with formatting. Could not convert " + o + " to Double.";
            throw new ExecException(msg, errCode, PigException.INPUT, nfe);
        } catch (Exception e) {
            int errCode = 2054;
            String msg = "Internal error. Could not convert " + o + " to Double.";
            throw new ExecException(msg, errCode, PigException.BUG);
        }
    }

    /**
     * Force a data object to a DateTime, if possible. Only CharArray, ByteArray
     * can be forced to a DateTime. Numeric types and complex types
     * cannot be forced to a DateTime. This isn't particularly efficient, so if
     * you already <b>know</b> that the object you have is a DateTime you should
     * just cast it.
     *
     * @param o
     *            object to cast
     * @param type
     *            of the object you are casting
     * @return The object as a Boolean.
     * @throws ExecException
     *             if the type can't be forced to a Boolean.
     */
    public static DateTime toDateTime(Object o, byte type) throws ExecException {
        try {
            switch (type) {
            case NULL:
                return null;
            case BYTEARRAY:
                return new DateTime(((DataByteArray) o).toString());
            case CHARARRAY:
                // the string can contain just date part or date part plus time part
                return ToDate.extractDateTime((String) o);
            case INTEGER:
                return new DateTime(((Integer) o).longValue());
            case LONG:
                return new DateTime(((Long) o).longValue());
            case FLOAT:
                return new DateTime(((Float) o).longValue());
            case DOUBLE:
                return new DateTime(((Double) o).longValue());
            case BIGINTEGER:
                return new DateTime(((BigInteger) o).longValue());
            case BIGDECIMAL:
                return new DateTime(((BigDecimal) o).longValue());
            case DATETIME:
                return (DateTime) o;

            case BOOLEAN:
            case BYTE:
            case MAP:
            case INTERNALMAP:
            case TUPLE:
            case BAG:
            case UNKNOWN:
            default:
                int errCode = 1071;
                String msg = "Cannot convert a " + findTypeName(o) + " to a DateTime";
                throw new ExecException(msg, errCode, PigException.INPUT);
            }
        } catch (ClassCastException cce) {
            throw cce;
        } catch (ExecException ee) {
            throw ee;
        } catch (NumberFormatException nfe) {
            int errCode = 1074;
            String msg = "Problem with formatting. Could not convert " + o + " to DateTime.";
            throw new ExecException(msg, errCode, PigException.INPUT, nfe);
        } catch (Exception e) {
            int errCode = 2054;
            String msg = "Internal error. Could not convert " + o + " to DateTime.";
            throw new ExecException(msg, errCode, PigException.BUG);
        }
    }

    public static DateTime toDateTime(Object o) throws ExecException {
        return toDateTime(o, findType(o));
    }

    /**
     * Force a data object to a Double, if possible.  Any numeric type
     * can be forced to a Double, as well
     * as CharArray, ByteArray, or Boolean.  Complex types cannot be
     * forced to an Double.  This isn't particularly efficient, so if you
     * already <b>know</b> that the object you have is a Double you
     * should just cast it.  Unlike {@link #toDouble(Object, byte)} this
     * method will first determine the type of o and then do the cast.
     * Use {@link #toDouble(Object, byte)} if you already know the type.
     * @param o object to cast
     * @return The object as a Double.
     * @throws ExecException if the type can't be forced to an Double.
     */
    public static Double toDouble(Object o) throws ExecException {
        return toDouble(o, findType(o));
    }

    public static BigInteger toBigInteger(Object o) throws ExecException {
        return toBigInteger(o, findType(o));
    }

    public static BigInteger toBigInteger(Object o,byte type) throws ExecException {
        try {
            switch (type) {
            case BOOLEAN:
                return (Boolean) o ? BigInteger.ONE : BigInteger.ZERO;

            case INTEGER:
                return BigInteger.valueOf(((Integer)o).longValue());

            case LONG:
                return BigInteger.valueOf(((Long)o).longValue());

            case FLOAT:
                return BigInteger.valueOf(((Float)o).longValue());

            case DOUBLE:
                return BigInteger.valueOf(((Double)o).longValue());

            case BYTEARRAY:
                return new BigInteger(((DataByteArray)o).toString());

            case CHARARRAY:
                return new BigInteger((String)o);

            case BIGINTEGER:
                return (BigInteger)o;

            case BIGDECIMAL:
                return ((BigDecimal)o).toBigInteger();

            case DATETIME:
                return BigInteger.valueOf(((DateTime)o).getMillis());

            case NULL:
                return null;

            case BYTE:
            case MAP:
            case INTERNALMAP:
            case TUPLE:
            case BAG:
            case UNKNOWN:
            default:
                int errCode = 1071;
                String msg = "Cannot convert a " + findTypeName(o) +
                " to a BigInteger.";
                throw new ExecException(msg, errCode, PigException.INPUT);
            }
        } catch (ClassCastException cce) {
            throw cce;
        } catch (ExecException ee) {
            throw ee;
        } catch (NumberFormatException nfe) {
            int errCode = 1074;
            String msg = "Problem with formatting. Could not convert " + o + " to BigInteger.";
            throw new ExecException(msg, errCode, PigException.INPUT, nfe);
        } catch (Exception e) {
            int errCode = 2054;
            String msg = "Internal error. Could not convert " + o + " to BigInteger.";
            throw new ExecException(msg, errCode, PigException.BUG);
        }
    }

    public static BigDecimal toBigDecimal(Object o) throws ExecException {
        return toBigDecimal(o, findType(o));
    }

    public static BigDecimal toBigDecimal(Object o,byte type) throws ExecException {
        try {
            switch (type) {
            case BOOLEAN:
                return (Boolean) o ? BigDecimal.ONE : BigDecimal.ZERO;

            case INTEGER:
                return BigDecimal.valueOf(((Integer)o).longValue());

            case LONG:
                return BigDecimal.valueOf(((Long)o).longValue());

            case FLOAT:
                return BigDecimal.valueOf(((Float)o).doubleValue());

            case DOUBLE:
                return BigDecimal.valueOf(((Double)o).doubleValue());

            case BYTEARRAY:
                return new BigDecimal(((DataByteArray)o).toString());

            case CHARARRAY:
                return new BigDecimal((String)o);

            case BIGINTEGER:
                return new BigDecimal((BigInteger)o);

            case BIGDECIMAL:
                return (BigDecimal)o;

            case DATETIME:
                return BigDecimal.valueOf(((DateTime)o).getMillis());

            case NULL:
                return null;

            case BYTE:
            case MAP:
            case INTERNALMAP:
            case TUPLE:
            case BAG:
            case UNKNOWN:
            default:
                int errCode = 1071;
                String msg = "Cannot convert a " + findTypeName(o) +
                " to a BigDecimal.";
                throw new ExecException(msg, errCode, PigException.INPUT);
            }
        } catch (ClassCastException cce) {
            throw cce;
        } catch (ExecException ee) {
            throw ee;
        } catch (NumberFormatException nfe) {
            int errCode = 1074;
            String msg = "Problem with formatting. Could not convert " + o + " to BigDecimal.";
            throw new ExecException(msg, errCode, PigException.INPUT, nfe);
        } catch (Exception e) {
            int errCode = 2054;
            String msg = "Internal error. Could not convert " + o + " to BigDecimal.";
            throw new ExecException(msg, errCode, PigException.BUG);
        }
    }

    /**
     * Force a data object to a String, if possible.  Any simple (atomic) type
     * can be forced to a String including ByteArray.  Complex types cannot be
     * forced to a String.  This isn't particularly efficient, so if you
     * already <b>know</b> that the object you have is a String you
     * should just cast it.
     * @param o object to cast
     * @param type of the object you are casting
     * @return The object as a String.
     * @throws ExecException if the type can't be forced to a String.
     */
    public static String toString(Object o,byte type) throws ExecException {
        try {
            switch (type) {
            case INTEGER:
                return ((Integer)o).toString();

            case LONG:
                return ((Long)o).toString();

            case FLOAT:
                return ((Float)o).toString();

            case DOUBLE:
                return ((Double)o).toString();

            case DATETIME:
                return ((DateTime)o).toString();

            case BYTEARRAY:
                return ((DataByteArray)o).toString();

            case CHARARRAY:
                return ((String)o);

            case BIGINTEGER:
                return ((BigInteger)o).toString();

            case BIGDECIMAL:
                return ((BigDecimal)o).toString();

            case NULL:
                return null;

            case BOOLEAN:
                return ((Boolean)o).toString();

            case BYTE:
                return ((Byte)o).toString();

            case MAP:
            case INTERNALMAP:
            case TUPLE:
            case BAG:
            case UNKNOWN:
            default:
                int errCode = 1071;
                String msg = "Cannot convert a " + findTypeName(o) +
                " to a String";
                throw new ExecException(msg, errCode, PigException.INPUT);
            }
        } catch (ClassCastException cce) {
            throw cce;
        } catch (ExecException ee) {
            throw ee;
        } catch (Exception e) {
            int errCode = 2054;
            String msg = "Internal error. Could not convert " + o + " to String.";
            throw new ExecException(msg, errCode, PigException.BUG);
        }
    }

    /**
     * Force a data object to a String, if possible.  Any simple (atomic) type
     * can be forced to a String including ByteArray.  Complex types cannot be
     * forced to a String.  This isn't particularly efficient, so if you
     * already <b>know</b> that the object you have is a String you
     * should just cast it.  Unlike {@link #toString(Object, byte)} this
     * method will first determine the type of o and then do the cast.
     * Use {@link #toString(Object, byte)} if you already know the type.
     * @param o object to cast
     * @return The object as a String.
     * @throws ExecException if the type can't be forced to a String.
     */
    public static String toString(Object o) throws ExecException {
        return toString(o, findType(o));
    }

    /**
     * If this object is a map, return it as a map.
     * This isn't particularly efficient, so if you
     * already <b>know</b> that the object you have is a Map you
     * should just cast it.
     * @param o object to cast
     * @return The object as a Map.
     * @throws ExecException if the type can't be forced to a Double.
     */
    @SuppressWarnings("unchecked")
    public static Map<String, Object> toMap(Object o) throws ExecException {
        if (o == null) {
            return null;
        }

        if (o instanceof Map && !(o instanceof InternalMap)) {
            try {
                return (Map<String, Object>)o;
            } catch (Exception e) {
                int errCode = 2054;
                String msg = "Internal error. Could not convert " + o + " to Map.";
                throw new ExecException(msg, errCode, PigException.BUG);
            }
        } else {
            int errCode = 1071;
            String msg = "Cannot convert a " + findTypeName(o) +
            " to a Map";
            throw new ExecException(msg, errCode, PigException.INPUT);
        }
    }

    /**
     * If this object is a tuple, return it as a tuple.
     * This isn't particularly efficient, so if you
     * already <b>know</b> that the object you have is a Tuple you
     * should just cast it.
     * @param o object to cast
     * @return The object as a Double.
     * @throws ExecException if the type can't be forced to a Double.
     */
    public static Tuple toTuple(Object o) throws ExecException {
        if (o == null) {
            return null;
        }

        if (o instanceof Tuple) {
            try {
                return (Tuple)o;
            } catch (Exception e) {
                int errCode = 2054;
                String msg = "Internal error. Could not convert " + o + " to Tuple.";
                throw new ExecException(msg, errCode, PigException.BUG);
            }
        } else {
            int errCode = 1071;
            String msg = "Cannot convert a " + findTypeName(o) +
            " to a Tuple";
            throw new ExecException(msg, errCode, PigException.INPUT);
        }
    }

    /**
     * If this object is a bag, return it as a bag.
     * This isn't particularly efficient, so if you
     * already <b>know</b> that the object you have is a bag you
     * should just cast it.
     * @param o object to cast
     * @return The object as a Double.
     * @throws ExecException if the type can't be forced to a Double.
     */
    public static DataBag toBag(Object o) throws ExecException {
        if (o == null) {
            return null;
        }

        if (o instanceof DataBag) {
            try {
                return (DataBag)o;
            } catch (Exception e) {
                int errCode = 2054;
                String msg = "Internal error. Could not convert " + o + " to Bag.";
                throw new ExecException(msg, errCode, PigException.BUG);
            }
        } else {
            int errCode = 1071;
            String msg = "Cannot convert a " + findTypeName(o) +
            " to a DataBag";
            throw new ExecException(msg, errCode, PigException.INPUT);
        }
    }

    /**
     * Purely for debugging
     */
    public static void spillTupleContents(Tuple t, String label) {
        System.out.print("Tuple " + label + " ");
        Iterator<Object> i = t.getAll().iterator();
        for (int j = 0; i.hasNext(); j++) {
            System.out.print(j + ":" + i.next().getClass().getName() + " ");
        }
        System.out.println(t.toString());
    }

    /**
     * Determine if this type is a numeric type.
     * @param t type (as byte value) to test
     * @return true if this is a numeric type, false otherwise
     */
    public static boolean isNumberType(byte t) {
        switch (t) {
            case INTEGER:       return true ;
            case LONG:          return true ;
            case FLOAT:         return true ;
            case DOUBLE:        return true ;
            case BIGINTEGER:    return true ;
            case BIGDECIMAL:    return true ;
            default:            return false ;
        }
    }

    /**
     * Determine if this is a type that can work can be done on.
     * @param t type (as a byte value) to test
     * @return false if the type is unknown, null, or error; true otherwise.
     */
    public static boolean isUsableType(byte t) {
        switch (t) {
            case UNKNOWN:    return false ;
            case NULL:       return false ;
            case ERROR:      return false ;
            default :return true ;
        }
    }

    /**
     * Test if one type can cast to the other.
     * @param castType data type of the cast type
     * @param inputType data type of the input
     * @return true or false
     */
    public static boolean castable(byte castType, byte inputType) {
        // Only legal types can be cast to
        if ( (!DataType.isUsableType(castType)) ||
             (!DataType.isUsableType(inputType)) ) {
            return false;
        }

        // Same type is castable
        if (castType==inputType) {
            return true;
        }

        // Numerical type is castable
        if ( (DataType.isNumberType(castType)) &&
             (DataType.isNumberType(inputType)) ) {
            return true;
        }

        // databyte can cast to anything
        if (inputType == DataType.BYTEARRAY) {
            return true;
        }

        // Cast numerical type to string, or vice versa is valid
        if (DataType.isNumberType(inputType)&&castType==DataType.CHARARRAY ||
                DataType.isNumberType(castType)&&inputType==DataType.CHARARRAY)
            return true;

        // else return false
        return false;
    }

    /**
     * Merge types if possible.  Merging types means finding a type that one
     * or both types can be upcast to.
     * @param type1
     * @param type2
     * @return the merged type, or DataType.ERROR if not successful
     */
    public static byte mergeType(byte type1, byte type2) {
        // Only legal types can be merged
        if ( (!DataType.isUsableType(type1)) ||
             (!DataType.isUsableType(type2)) ) {
            return DataType.ERROR ;
        }

        // Same type is OK
        if (type1==type2) {
            return type1 ;
        }

        // Both are number so we return the bigger type
        if ( (DataType.isNumberType(type1)) &&
             (DataType.isNumberType(type2)) ) {
            return type1>type2 ? type1:type2 ;
        }

        // One is bytearray and the other is (number or chararray)
        if (type1 == DataType.BYTEARRAY) {
            return type2 ;
        }

        if (type2 == DataType.BYTEARRAY) {
            return type1 ;
        }

        // else return just ERROR
        return DataType.ERROR ;
    }

    /**
     * Given a map, turn it into a String.
     * @param m map
     * @return string representation of the map
     */
    public static String mapToString(Map<String, Object> m) {
        boolean hasNext = false;
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for(Map.Entry<String, Object> e: m.entrySet()) {
            if(hasNext) {
                sb.append(",");
            } else {
                hasNext = true;
            }
            sb.append(e.getKey());
            sb.append("#");
            Object val = e.getValue();
            if(val != null) {
                sb.append(val.toString());
            }
        }
        sb.append("]");
        return sb.toString();
    }

    /**
     * Test whether two byte arrays (Java byte arrays not Pig byte arrays) are
     * equal.  I have no idea why we have this function.
     * @param lhs byte array 1
     * @param rhs byte array 2
     * @return true if both are null or the two are the same length and have
     * the same bytes.
     */
    public static boolean equalByteArrays(byte[] lhs, byte[] rhs) {
        if(lhs == null && rhs == null) {
            return true;
        }
        if(lhs == null || rhs == null) {
            return false;
        }
        if(lhs.length != rhs.length) {
            return false;
        }
        for(int i = 0; i < lhs.length; ++i) {
            if(lhs[i] != rhs[i]) {
                return false;
            }
        }
        return true;
    }


    /**
     * Utility method that determines the schema from the passed in dataType.
     * If the dataType is Bag or Tuple, then we need to determine the schemas inside this dataType;
     * for this we iterate through the fields inside this field. This method works both for raw objects
     * and ResourceSchema.ResourceFieldSchema field descriptions; the specific behavior is determined by the klass
     * parameter.
     * @param dataType  DataType.CHARARRAY, DataType.TUPLE, and so on
     * @param fieldIter iterator over the fields if this is a tuple or a bag
     * @param fieldNum number of fields inside the field if a tuple
     * @param klass  should be Object or ResourceSchema.ResourceFieldSchema
     * @return
     * @throws ExecException
     * @throws FrontendException
     * @throws SchemaMergeException
     */
    @SuppressWarnings("deprecation")
    private static Schema.FieldSchema determineFieldSchema(byte dataType, Iterator fieldIter,
            long fieldNum, Class klass ) throws ExecException, FrontendException, SchemaMergeException {
        switch (dataType) {
        case NULL:
            return new Schema.FieldSchema(null, BYTEARRAY);

        case BOOLEAN:
        case INTEGER:
        case LONG:
        case FLOAT:
        case DOUBLE:
        case BIGINTEGER:
        case BIGDECIMAL:
        case DATETIME:
        case BYTEARRAY:
        case CHARARRAY:
        case MAP:
            return new Schema.FieldSchema(null, dataType);
        case TUPLE: {
            Schema schema = null;
            if(fieldNum != 0) {
                schema = new Schema();
                for(int i = 0; i < fieldNum; ++i) {
                    schema.add(determineFieldSchema(klass.cast(fieldIter.next())));
                }
            }
            return new Schema.FieldSchema(null, schema, TUPLE);
        }

        case BAG: {
            Schema schema = null;
            Schema bagSchema = null;

            if(fieldNum != 0) {
                ArrayList<Schema> schemas = new ArrayList<Schema>();
                while (fieldIter.hasNext() ) {
                    schemas.add(determineFieldSchema(klass.cast(fieldIter.next())).schema);
                }
                schema = schemas.get(0);
                if(null == schema) {
                    Schema.FieldSchema tupleFs = new Schema.FieldSchema(null, null, TUPLE);
                    bagSchema = new Schema(tupleFs);
                    bagSchema.setTwoLevelAccessRequired(true);
                    return new Schema.FieldSchema(null, bagSchema, BAG);
                }
                int schemaSize = schema.size();

                for(int i = 1; i < schemas.size(); ++i) {
                    Schema currSchema = schemas.get(i);
                    if((null == currSchema) || (currSchema.size() != schemaSize)) {
                        Schema.FieldSchema tupleFs = new Schema.FieldSchema(null, null, TUPLE);
                        bagSchema = new Schema(tupleFs);
                        bagSchema.setTwoLevelAccessRequired(true);
                        return new Schema.FieldSchema(null, bagSchema, BAG);
                    }
                    schema = Schema.mergeSchema(schema, currSchema, false, false, false);
                }
                Schema.FieldSchema tupleFs = new Schema.FieldSchema(null, schema, TUPLE);
                bagSchema = new Schema(tupleFs);
                // since this schema has tuple field schema which internally
                // has a list of field schemas for the actual items in the bag
                // an access to any field in the bag is a  two level access
                bagSchema.setTwoLevelAccessRequired(true);
            }
            return new Schema.FieldSchema(null, bagSchema, BAG);
        }
        default: {
            int errCode = 1073;
            String msg = "Cannot determine field schema";
            throw new ExecException(msg, errCode, PigException.INPUT);
        }

        }
    }

    /***
     * Determine the field schema of an ResourceFieldSchema
     * @param rcFieldSchema the rcFieldSchema we want translated
     * @return the field schema corresponding to the object
     * @throws ExecException,FrontendException,SchemaMergeException
     */
    public static Schema.FieldSchema determineFieldSchema(ResourceSchema.ResourceFieldSchema rcFieldSchema)
        throws ExecException, FrontendException, SchemaMergeException {
        byte dt = rcFieldSchema.getType();
        Iterator<ResourceSchema.ResourceFieldSchema> fieldIter = null;
        long fieldNum = 0;
        if (dt == TUPLE || dt == BAG ) {
            fieldIter = Arrays.asList(rcFieldSchema.getSchema().getFields()).iterator();
            fieldNum = rcFieldSchema.getSchema().getFields().length;
        }
        return determineFieldSchema(dt, fieldIter, fieldNum, ResourceSchema.ResourceFieldSchema.class);
    }


    /***
     * Determine the field schema of an object
     * @param o the object whose field schema is to be determined
     * @return the field schema corresponding to the object
     * @throws ExecException,FrontendException,SchemaMergeException
     */
    public static Schema.FieldSchema determineFieldSchema(Object o)
        throws ExecException, FrontendException, SchemaMergeException {
        byte dt = findType(o);
        Iterator fieldIter = null;
        long fieldNum = 0;
        if ( dt == TUPLE ) {
            fieldIter = ((Tuple) o).getAll().iterator();
            fieldNum = ((Tuple) o).size();
        } else if ( dt == BAG ) {
            fieldNum = ((DataBag) o).size();
            fieldIter = ((DataBag)o).iterator();
        }
        return determineFieldSchema(dt, fieldIter, fieldNum, Object.class);
    }
}
