001/* 002 * Copyright 2002-2014 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.expression.spel.support; 018 019import java.math.BigDecimal; 020import java.math.BigInteger; 021 022import org.springframework.expression.TypeComparator; 023import org.springframework.expression.spel.SpelEvaluationException; 024import org.springframework.expression.spel.SpelMessage; 025import org.springframework.util.NumberUtils; 026 027/** 028 * A simple basic {@link TypeComparator} implementation. 029 * It supports comparison of Numbers and types implementing Comparable. 030 * 031 * @author Andy Clement 032 * @author Juergen Hoeller 033 * @author Giovanni Dall'Oglio Risso 034 * @since 3.0 035 */ 036public class StandardTypeComparator implements TypeComparator { 037 038 @Override 039 public boolean canCompare(Object left, Object right) { 040 if (left == null || right == null) { 041 return true; 042 } 043 if (left instanceof Number && right instanceof Number) { 044 return true; 045 } 046 if (left instanceof Comparable) { 047 return true; 048 } 049 return false; 050 } 051 052 @Override 053 @SuppressWarnings("unchecked") 054 public int compare(Object left, Object right) throws SpelEvaluationException { 055 // If one is null, check if the other is 056 if (left == null) { 057 return (right == null ? 0 : -1); 058 } 059 else if (right == null) { 060 return 1; // left cannot be null at this point 061 } 062 063 // Basic number comparisons 064 if (left instanceof Number && right instanceof Number) { 065 Number leftNumber = (Number) left; 066 Number rightNumber = (Number) right; 067 068 if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) { 069 BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class); 070 BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class); 071 return leftBigDecimal.compareTo(rightBigDecimal); 072 } 073 else if (leftNumber instanceof Double || rightNumber instanceof Double) { 074 return Double.compare(leftNumber.doubleValue(), rightNumber.doubleValue()); 075 } 076 else if (leftNumber instanceof Float || rightNumber instanceof Float) { 077 return Float.compare(leftNumber.floatValue(), rightNumber.floatValue()); 078 } 079 else if (leftNumber instanceof BigInteger || rightNumber instanceof BigInteger) { 080 BigInteger leftBigInteger = NumberUtils.convertNumberToTargetClass(leftNumber, BigInteger.class); 081 BigInteger rightBigInteger = NumberUtils.convertNumberToTargetClass(rightNumber, BigInteger.class); 082 return leftBigInteger.compareTo(rightBigInteger); 083 } 084 else if (leftNumber instanceof Long || rightNumber instanceof Long) { 085 // Don't call Long.compare here - only available on JDK 1.7+ 086 return compare(leftNumber.longValue(), rightNumber.longValue()); 087 } 088 else if (leftNumber instanceof Integer || rightNumber instanceof Integer) { 089 // Don't call Integer.compare here - only available on JDK 1.7+ 090 return compare(leftNumber.intValue(), rightNumber.intValue()); 091 } 092 else if (leftNumber instanceof Short || rightNumber instanceof Short) { 093 // Don't call Short.compare here - only available on JDK 1.7+ 094 return compare(leftNumber.shortValue(), rightNumber.shortValue()); 095 } 096 else if (leftNumber instanceof Byte || rightNumber instanceof Byte) { 097 // Don't call Short.compare here - only available on JDK 1.7+ 098 return compare(leftNumber.byteValue(), rightNumber.byteValue()); 099 } 100 else { 101 // Unknown Number subtypes -> best guess is double multiplication 102 return Double.compare(leftNumber.doubleValue(), rightNumber.doubleValue()); 103 } 104 } 105 106 try { 107 if (left instanceof Comparable) { 108 return ((Comparable<Object>) left).compareTo(right); 109 } 110 } 111 catch (ClassCastException ex) { 112 throw new SpelEvaluationException(ex, SpelMessage.NOT_COMPARABLE, left.getClass(), right.getClass()); 113 } 114 115 throw new SpelEvaluationException(SpelMessage.NOT_COMPARABLE, left.getClass(), right.getClass()); 116 } 117 118 119 private static int compare(long x, long y) { 120 return (x < y ? -1 : (x > y ? 1 : 0)); 121 } 122 123 private static int compare(int x, int y) { 124 return (x < y ? -1 : (x > y ? 1 : 0)); 125 } 126 127 private static int compare(short x, short y) { 128 return x - y; 129 } 130 131 private static int compare(byte x, byte y) { 132 return x - y; 133 } 134 135}