1 12 13 package mondrian.olap; 14 15 import java.util.*; 16 17 28 public class EnumeratedValues<V extends EnumeratedValues.Value> 29 implements Cloneable 30 { 31 32 private Map<String , V> valuesByName = new LinkedHashMap<String , V>(); 33 34 35 private int min = Integer.MAX_VALUE; 36 37 38 private int max = Integer.MIN_VALUE; 39 40 42 44 private Value[] ordinalToValueMap; 45 private static final String [] emptyStringArray = new String [0]; 46 47 50 public EnumeratedValues() { 51 } 52 53 56 public EnumeratedValues(V[] values) { 57 for (V value : values) { 58 register(value); 59 } 60 makeImmutable(); 61 } 62 63 67 public EnumeratedValues(String [] names) { 68 for (int i = 0; i < names.length; i++) { 69 register((V) new BasicValue(names[i], i, names[i])); 70 } 71 makeImmutable(); 72 } 73 74 78 public EnumeratedValues(String [] names, int[] codes) { 79 for (int i = 0; i < names.length; i++) { 80 register((V) new BasicValue(names[i], codes[i], names[i])); 81 } 82 makeImmutable(); 83 } 84 85 89 public EnumeratedValues(String [] names, int[] codes, String [] descriptions) { 90 for (int i = 0; i < names.length; i++) { 91 register((V) new BasicValue(names[i], codes[i], descriptions[i])); 92 } 93 makeImmutable(); 94 } 95 96 public EnumeratedValues(Class <? extends Enum > clazz) { 97 throw new UnsupportedOperationException (); 98 } 99 100 public EnumeratedValues<V> clone() { 101 EnumeratedValues clone; 102 try { 103 clone = (EnumeratedValues) super.clone(); 104 } catch (CloneNotSupportedException ex) { 105 throw Util.newInternal(ex, "error while cloning " + this); 106 } 107 clone.valuesByName = new HashMap<String , Value>(valuesByName); 108 clone.ordinalToValueMap = null; 109 return clone; 110 } 111 112 116 public EnumeratedValues getMutableClone() { 117 return clone(); 118 } 119 120 127 public void register(V value) { 128 assert value != null : "pre: value != null"; 129 Util.assertPrecondition(!isImmutable(), "isImmutable()"); 130 final String name = value.getName(); 131 Util.assertPrecondition(name != null, "value.getName() != null"); 132 Value old = valuesByName.put(name, value); 133 if (old != null) { 134 throw Util.newInternal("Enumeration already contained a value '" + old.getName() + "'"); 135 } 136 final int ordinal = value.getOrdinal(); 137 min = Math.min(min,ordinal); 138 max = Math.max(max,ordinal); 139 } 140 141 144 public void makeImmutable() { 145 ordinalToValueMap = new Value[1 + max - min]; 146 for (Value value : valuesByName.values()) { 147 final int index = value.getOrdinal() - min; 148 if (ordinalToValueMap[index] != null) { 149 throw Util.newInternal( 150 "Enumeration has more than one value with ordinal " + 151 value.getOrdinal()); 152 } 153 ordinalToValueMap[index] = value; 154 } 155 } 156 157 public final boolean isImmutable() { 158 return (ordinalToValueMap != null); 159 } 160 161 164 public final int getMin() { 165 return min; 166 } 167 168 171 public final int getMax() { 172 return max; 173 } 174 175 187 public final boolean isValid(int ordinal) { 188 if ((ordinal < min) || (ordinal > max)) { 189 return false; 190 } 191 if (getName(ordinal) == null) { 192 return false; 193 } 194 return true; 195 } 196 197 203 public final V getValue(int ordinal) { 204 Util.assertPrecondition(isImmutable()); 205 206 return (V) ordinalToValueMap[ordinal - min]; 207 } 208 209 215 public final String getName(int ordinal) { 216 Util.assertPrecondition(isImmutable()); 217 218 final Value value = ordinalToValueMap[ordinal - min]; 219 return (value == null) ? null : value.getName(); 220 } 221 222 228 public final String getDescription(int ordinal) 229 { 230 Util.assertPrecondition(isImmutable()); 231 232 final Value value = ordinalToValueMap[ordinal - min]; 233 return (value == null) ? null : value.getDescription(); 234 } 235 236 241 public final int getOrdinal(String name) { 242 return getValue(name, true).getOrdinal(); 243 } 244 245 253 public V getValue(String name, final boolean fail) { 254 final V value = valuesByName.get(name); 255 if (value == null && fail) { 256 throw new Error ("Unknown enum name: " + name); 257 } 258 return value; 259 } 260 261 269 public V getValueIgnoreCase(String name, boolean fail) { 270 for (Value value : ordinalToValueMap) { 271 if (value != null && value.getName().equalsIgnoreCase(name)) { 272 return (V) value; 273 } 274 } 275 if (fail) { 276 throw new Error ("Unknown enum name: " + name); 277 } 278 return null; 279 } 280 281 284 public String [] getNames() { 285 return valuesByName.keySet().toArray(emptyStringArray); 286 } 287 288 291 public List<V> getValuesSortedByName() { 292 List<V> list = new ArrayList<V>(); 293 final String [] names = getNames(); 294 Arrays.sort(names); 295 for (String name : names) { 296 list.add(getValue(name, true)); 297 } 298 return list; 299 } 300 301 305 public RuntimeException badValue(int ordinal) { 306 return Util.newInternal("bad value " + ordinal + "(" + 307 getName(ordinal) + ") for enumeration '" + 308 getClass().getName() + "'"); 309 } 310 311 315 public RuntimeException unexpected(V value) { 316 return Util.newInternal("Was not expecting value '" + value + 317 "' for enumeration '" + getClass().getName() + 318 "' in this context"); 319 } 320 321 326 public interface Value { 327 String getName(); 328 int getOrdinal(); 329 String getDescription(); 330 } 331 332 336 public static class BasicValue implements Value { 337 public final String name; 338 public final int ordinal; 339 public final String description; 340 341 344 public BasicValue(String name, int ordinal, String description) { 345 Util.assertPrecondition(name != null, "name != null"); 346 this.name = name; 347 this.ordinal = ordinal; 348 this.description = description; 349 } 350 351 public String getName() { 352 return name; 353 } 354 355 public int getOrdinal() { 356 return ordinal; 357 } 358 359 public String getDescription() { 360 return description; 361 } 362 363 366 public String toString() { 367 return name; 368 } 369 370 377 public boolean equals(String s) { 378 return super.equals(s); 379 } 380 381 396 public RuntimeException unexpected() { 397 return Util.newInternal("Value " + name + " of class " + 398 getClass() + " unexpected here"); 399 } 400 } 401 402 } 403 404 | Popular Tags |