blob: 687a67bf816ec1d4c240ad4c326bdd7edd2d37fe [file] [log] [blame]
/**
* 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.hcatalog.data;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.Map.Entry;
public abstract class DataType {
public static final byte NULL = 1;
public static final byte BOOLEAN = 5;
public static final byte BYTE = 6;
public static final byte INTEGER = 10;
public static final byte SHORT = 11;
public static final byte LONG = 15;
public static final byte FLOAT = 20;
public static final byte DOUBLE = 25;
public static final byte STRING = 55;
public static final byte BINARY = 60;
public static final byte MAP = 100;
public static final byte STRUCT = 110;
public static final byte LIST = 120;
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;
}
Class<?> clazz = o.getClass();
// Try to put the most common first
if (clazz == String.class) {
return STRING;
} else if (clazz == Integer.class) {
return INTEGER;
} else if (clazz == Long.class) {
return LONG;
} else if (clazz == Float.class) {
return FLOAT;
} else if (clazz == Double.class) {
return DOUBLE;
} else if (clazz == Boolean.class) {
return BOOLEAN;
} else if (clazz == Byte.class) {
return BYTE;
} else if (clazz == Short.class) {
return SHORT;
} else if (o instanceof List<?>) {
return LIST;
} else if (o instanceof Map<?, ?>) {
return MAP;
} else if (o instanceof byte[]) {
return BINARY;
} else {
return ERROR;
}
}
public static int compare(Object o1, Object o2) {
return compare(o1, o2, findType(o1), findType(o2));
}
public static int compare(Object o1, Object o2, byte dt1, byte dt2) {
if (dt1 == dt2) {
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 STRING:
return ((String) o1).compareTo((String) o2);
case SHORT:
return ((Short) o1).compareTo((Short) o2);
case BINARY:
return compareByteArray((byte[]) o1, (byte[]) o2);
case LIST:
List<?> l1 = (List<?>) o1;
List<?> l2 = (List<?>) o2;
int len = l1.size();
if (len != l2.size()) {
return len - l2.size();
} else {
for (int i = 0; i < len; i++) {
int cmpVal = compare(l1.get(i), l2.get(i));
if (cmpVal != 0) {
return cmpVal;
}
}
return 0;
}
case MAP: {
Map<?, ?> m1 = (Map<?, ?>) o1;
Map<?, ?> m2 = (Map<?, ?>) 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<Object, Object> tm1 = new TreeMap<Object, Object>(m1);
TreeMap<Object, Object> tm2 = new TreeMap<Object, Object>(m2);
Iterator<Entry<Object, Object>> i1 = tm1.entrySet().iterator();
Iterator<Entry<Object, Object>> i2 = tm2.entrySet().iterator();
while (i1.hasNext()) {
Map.Entry<Object, Object> entry1 = i1.next();
Map.Entry<Object, Object> entry2 = i2.next();
int c = compare(entry1.getValue(), entry2.getValue());
if (c != 0) {
return c;
} else {
c = compare(entry1.getValue(), entry2.getValue());
if (c != 0) {
return c;
}
}
}
return 0;
}
}
default:
throw new RuntimeException("Unkown type " + dt1 +
" in compare");
}
} else {
return dt1 < dt2 ? -1 : 1;
}
}
private static int compareByteArray(byte[] o1, byte[] o2) {
for (int i = 0; i < o1.length; i++) {
if (i == o2.length) {
return 1;
}
if (o1[i] == o2[i]) {
continue;
}
if (o1[i] > o1[i]) {
return 1;
} else {
return -1;
}
}
//bytes in o1 are same as o2
//in case o2 was longer
if (o2.length > o1.length) {
return -1;
}
return 0; //equals
}
}