001package jmri.util; 002 003/** 004 * Compare values. 005 * 006 * @author Daniel Bergqvist Copyright 2022 007 */ 008public class CompareUtil { 009 010 public static enum CompareType { 011 NumberOrString(Bundle.getMessage("CompareUtil_CompareType_NumberOrString")), 012 String(Bundle.getMessage("CompareUtil_CompareType_String")), 013 Number(Bundle.getMessage("CompareUtil_CompareType_Number")); 014 015 private final String _text; 016 017 private CompareType(String text) { 018 this._text = text; 019 } 020 021 @Override 022 public String toString() { 023 return _text; 024 } 025 026 } 027 028 public static enum CompareOperation { 029 LessThan(Bundle.getMessage("CompareUtil_CompareOperation_LessThan")), 030 LessThanOrEqual(Bundle.getMessage("CompareUtil_CompareOperation_LessThanOrEqual")), 031 Equal(Bundle.getMessage("CompareUtil_CompareOperation_Equal")), 032 GreaterThanOrEqual(Bundle.getMessage("CompareUtil_CompareOperation_GreaterThanOrEqual")), 033 GreaterThan(Bundle.getMessage("CompareUtil_CompareOperation_GreaterThan")), 034 NotEqual(Bundle.getMessage("CompareUtil_CompareOperation_NotEqual")); 035 036 private final String _text; 037 038 private CompareOperation(String text) { 039 this._text = text; 040 } 041 042 @Override 043 public String toString() { 044 return _text; 045 } 046 047 } 048 049 050 /** 051 * Compare two values. 052 * 053 * @param type the type 054 * @param oper the operation 055 * @param value1 left side of the comparison 056 * @param value2 right side of the comparison 057 * @param caseInsensitive true if comparison should be case insensitive; 058 * false otherwise 059 * @return true if values compare per _memoryOperation; false otherwise 060 */ 061 public static boolean compare(CompareType type, CompareOperation oper, Object value1, Object value2, boolean caseInsensitive) { 062 switch (type) // both are numbers 063 { 064 case NumberOrString: 065 return compareNumber(false, oper, value1, value2, caseInsensitive); 066 case String: 067 return compareString(oper, value1, value2, caseInsensitive); 068 case Number: 069 return compareNumber(true, oper, value1, value2, caseInsensitive); 070 default: 071 throw new IllegalArgumentException("type has unknown value: "+type.name()); 072 } 073 } 074 075 /** 076 * Compare two values. 077 * 078 * @param oper the operation 079 * @param value1 left side of the comparison 080 * @param value2 right side of the comparison 081 * @param caseInsensitive true if comparison should be case insensitive; 082 * false otherwise 083 * @return true if values compare per _memoryOperation; false otherwise 084 */ 085 public static boolean compareString(CompareOperation oper, Object value1, Object value2, boolean caseInsensitive) { 086 String s1; 087 String s2; 088 if (value1 == null) { 089 return value2 == null; 090 } else { 091 if (value2 == null) { 092 return false; 093 } 094 s1 = value1.toString().trim(); 095 s2 = value2.toString().trim(); 096 } 097 int compare; 098 if (caseInsensitive) { 099 compare = s1.compareToIgnoreCase(s2); 100 } else { 101 compare = s1.compareTo(s2); 102 } 103 switch (oper) { 104 case LessThan: 105 if (compare < 0) { 106 return true; 107 } 108 break; 109 case LessThanOrEqual: 110 if (compare <= 0) { 111 return true; 112 } 113 break; 114 case Equal: 115 if (compare == 0) { 116 return true; 117 } 118 break; 119 case NotEqual: 120 if (compare != 0) { 121 return true; 122 } 123 break; 124 case GreaterThanOrEqual: 125 if (compare >= 0) { 126 return true; 127 } 128 break; 129 case GreaterThan: 130 if (compare > 0) { 131 return true; 132 } 133 break; 134 default: 135 throw new IllegalArgumentException("oper has unknown value: "+oper.name()); 136 } 137 return false; 138 } 139 140 /** 141 * Compare two values. 142 * 143 * @param requireNumber true if two numbers are required, false otherwise 144 * @param oper the operation 145 * @param value1 left side of the comparison 146 * @param value2 right side of the comparison 147 * @param caseInsensitive true if comparison should be case insensitive; 148 * false otherwise 149 * @return true if values compare per _memoryOperation; false otherwise 150 */ 151 public static boolean compareNumber(boolean requireNumber, CompareOperation oper, Object value1, Object value2, boolean caseInsensitive) { 152 String s1; 153 String s2; 154 if (value1 == null) { 155 return value2 == null; 156 } else { 157 if (value2 == null) { 158 return false; 159 } 160 s1 = value1.toString().trim(); 161 s2 = value2.toString().trim(); 162 } 163 try { 164 double n1; 165 if (value1 instanceof Number) { 166 n1 = ((Number)value1).doubleValue(); 167 } else { 168 n1 = Double.parseDouble(s1); 169 } 170 try { 171 double n2; 172 if (value2 instanceof Number) { 173 n2 = ((Number)value2).doubleValue(); 174 } else { 175 n2 = Double.parseDouble(s2); 176 } 177 log.debug("Compare numbers: n1= {} to n2= {}", n1, n2); 178 switch (oper) // both are numbers 179 { 180 case LessThan: 181 return (n1 < n2); 182 case LessThanOrEqual: 183 return (n1 <= n2); 184 case Equal: 185 return (n1 == n2); 186 case NotEqual: 187 return (n1 != n2); 188 case GreaterThanOrEqual: 189 return (n1 >= n2); 190 case GreaterThan: 191 return (n1 > n2); 192 default: 193 throw new IllegalArgumentException("oper has unknown value: "+oper.name()); 194 } 195 } catch (NumberFormatException nfe) { 196 if (requireNumber) throw new IllegalArgumentException( 197 Bundle.getMessage("CompareUtil_Error_Value1IsNotANumber", value1)); 198 return oper == CompareOperation.NotEqual; // n1 is a number, n2 is not 199 } 200 } catch (NumberFormatException nfe) { 201 try { 202 Integer.parseInt(s2); 203 if (requireNumber) throw new IllegalArgumentException( 204 Bundle.getMessage("CompareUtil_Error_Value1IsNotANumber", value1)); 205 return oper == CompareOperation.NotEqual; // n1 is not a number, n2 is 206 } catch (NumberFormatException ex) { // OK neither a number 207 if (requireNumber) throw new IllegalArgumentException( 208 Bundle.getMessage("CompareUtil_Error_NeitherValueIsNumber", value1, value2)); 209 } 210 } 211 212 // If here, neither value is a number and it's not required. 213 return compareString(oper, value1, value2, caseInsensitive); 214 } 215 216 217 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CompareUtil.class); 218 219}