/* * Copyright 2011 Future Systems * * Licensed 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.araqne.logdb; import java.net.Inet4Address; import java.net.Inet6Address; import java.util.Comparator; import java.util.Date; import java.util.Map; import org.araqne.logdb.query.command.NumberUtil; public class ObjectComparator implements Comparator<Object> { private static enum typeGroup { NULL, BOOLEAN, NUM, DATE, IPV4, IPV6, STRING, ARRAY, MAP, BLOB, ELSE }; @Override public int compare(Object o1, Object o2) { typeGroup o1TypeGroup = getTypeGroup(o1); typeGroup o2TypeGroup = getTypeGroup(o2); int cmpResult = o1TypeGroup.compareTo(o2TypeGroup); if (cmpResult == 0) { if (o1TypeGroup == typeGroup.NULL) return 0; else if (o1TypeGroup == typeGroup.NUM) return compareNum(o1, o2); else if (o1TypeGroup == typeGroup.STRING) return compareString(o1, o2); else if (o1TypeGroup == typeGroup.ARRAY) return compareArray(o1, o2); else if (o1TypeGroup == typeGroup.IPV4) return compareIpv4(o1, o2); else if (o1TypeGroup == typeGroup.BOOLEAN) return compareBool(o1, o2); else if (o1TypeGroup == typeGroup.DATE) return compareDate(o1, o2); else if (o1TypeGroup == typeGroup.IPV6) return compareIpv6(o1, o2); else if (o1TypeGroup == typeGroup.MAP) return compareMap(o1, o2); else if (o1TypeGroup == typeGroup.BLOB) return compareBlob(o1, o2); else return compareElse(o1, o2); } else { return cmpResult; } } private typeGroup getTypeGroup(Object o1) { if (o1 == null) return typeGroup.NULL; else if (o1 instanceof Long || o1 instanceof Integer || o1 instanceof Short || o1 instanceof Double || o1 instanceof Float) return typeGroup.NUM; else if (o1 instanceof String) return typeGroup.STRING; else if (o1 instanceof Object[]) return typeGroup.ARRAY; else if (o1 instanceof Inet4Address) return typeGroup.IPV4; else if (o1 instanceof Boolean) return typeGroup.BOOLEAN; else if (o1 instanceof Date) return typeGroup.DATE; else if (o1 instanceof Inet6Address) return typeGroup.IPV6; else if (o1 instanceof Map) return typeGroup.MAP; else if (o1 instanceof byte[]) return typeGroup.BLOB; else return typeGroup.ELSE; } @SuppressWarnings({ "unchecked", "rawtypes" }) private int compareElse(Object o1, Object o2) { if (o1 instanceof Comparable) { try { return ((Comparable) o1).compareTo(o2); } catch (Throwable t) { } } String o1ClassName = o1.getClass().getName(); String o2ClassName = o2.getClass().getName(); return o1ClassName.compareTo(o2ClassName); } private int compareBlob(Object o1, Object o2) { byte[] blob1 = (byte[]) o1; byte[] blob2 = (byte[]) o2; int min = Math.min(blob1.length, blob2.length); for (int i = 0; i < min; i++) { if (blob1[i] < blob2[i]) return -1; else if (blob1[i] > blob2[i]) return 1; } int lhs = blob1.length; int rhs = blob2.length; if (lhs == rhs) { return 0; } else { return lhs < rhs ? -1 : 1; } } private int compareMap(Object o1, Object o2) { // Map is not supported. // return 0 for all map. return 0; } private int compareArray(Object o1, Object o2) { Object[] arr1 = (Object[]) o1; Object[] arr2 = (Object[]) o2; int min = Math.min(arr1.length, arr2.length); for (int i = 0; i < min; i++) { int cmp = compare(arr1[i], arr2[i]); if (cmp != 0) return cmp; } if (arr1.length == arr2.length) { return 0; } else { return arr1.length < arr2.length ? -1 : 1; } } private int compareString(Object o1, Object o2) { String string1 = (String) o1; String string2 = (String) o2; return string1.compareToIgnoreCase(string2); } private int compareIpv4(Object o1, Object o2) { byte[] ip1 = ((Inet4Address) o1).getAddress(); byte[] ip2 = ((Inet4Address) o2).getAddress(); for (int i = 0; i < 4; i++) { if (ip1[i] != ip2[i]) { return ip1[i] < ip2[i] ? -1 : 1; } } return 0; } private int compareIpv6(Object o1, Object o2) { byte[] ip1 = ((Inet6Address) o1).getAddress(); byte[] ip2 = ((Inet6Address) o2).getAddress(); for (int i = 0; i < 16; i++) { if (ip1[i] != ip2[i]) { return ip1[i] < ip2[i] ? -1 : 1; } } return 0; } private int compareBool(Object o1, Object o2) { Boolean bool1 = (Boolean) o1; Boolean bool2 = (Boolean) o2; return bool1.compareTo(bool2); } private int compareNum(Object o1, Object o2) { if (!NumberUtil.isFloat(o1) && !NumberUtil.isFloat(o2)) { long lhs = 0; if (o1 instanceof Long) lhs = (Long) o1; else if (o1 instanceof Integer) lhs = (Integer) o1; else if (o1 instanceof Short) lhs = (Short) o1; long rhs = 0; if (o2 instanceof Long) rhs = (Long) o2; else if (o2 instanceof Integer) rhs = (Integer) o2; else if (o2 instanceof Short) rhs = (Short) o2; if (lhs == rhs) { return 0; } else { return lhs < rhs ? -1 : 1; } } else { double lhs = 0; if (o1 instanceof Double) lhs = (Double) o1; else if (o1 instanceof Integer) lhs = (Integer) o1; else if (o1 instanceof Long) lhs = (Long) o1; else if (o1 instanceof Short) lhs = (Short) o1; else if (o1 instanceof Float) lhs = (Float) o1; double rhs = 0; if (o2 instanceof Double) rhs = (Double) o2; else if (o2 instanceof Integer) rhs = (Integer) o2; else if (o2 instanceof Long) rhs = (Long) o2; else if (o2 instanceof Short) rhs = (Short) o2; else if (o2 instanceof Float) rhs = (Float) o2; return Double.compare(lhs, rhs); } } private int compareDate(Object o1, Object o2) { long lhs = ((Date) o1).getTime(); long rhs = ((Date) o2).getTime(); if (lhs == rhs) { return 0; } else { return lhs < rhs ? -1 : 1; } } }