001/* 002 * To change this template, choose Tools | Templates 003 * and open the template in the editor. 004 */ 005package com.nativelibs4java.util; 006 007import java.util.*; 008 009/** 010 * Methods to ease conversion between EnumValue-annotated enums and their integer value. 011 * @author ochafik 012 */ 013public class EnumValues { 014 015 private static class Cache<E extends Enum<?>> { 016 017 final Map<Long, E> enumsByValue = new LinkedHashMap<Long, E>(); 018 final Map<E, Long> valuesByEnum = new LinkedHashMap<E, Long>(); 019 020 public Cache(Class<E> enumClass) { 021 022 if (ValuedEnum.class.isAssignableFrom(enumClass)) { 023 for (E e : enumClass.getEnumConstants()) { 024 long value = ((ValuedEnum)e).value(); 025 enumsByValue.put(value, e); 026 valuesByEnum.put(e, value); 027 } 028 } else { 029 for (E e : enumClass.getEnumConstants()) { 030 EnumValue ev = null; 031 try { 032 ev = enumClass.getField(e.name()).getAnnotation(EnumValue.class); 033 } catch (Exception ex) { 034 throw new RuntimeException(ex); 035 } 036 if (ev == null) { 037 throw new IllegalArgumentException("Enum value is not annotated with the " + EnumValue.class.getName() + " annotation : " + e); 038 } 039 long value = ev.value(); 040 enumsByValue.put(value, e); 041 valuesByEnum.put(e, value); 042 } 043 } 044 } 045 } 046 private static final Map<Class<? extends Enum<?>>, Cache<?>> caches = new HashMap<Class<? extends Enum<?>>, Cache<?>>(); 047 048 @SuppressWarnings("unchecked") 049 private static synchronized <E extends Enum<?>> Cache<E> getCache(Class<E> enumClass) { 050 Cache<E> cache = (Cache<E>) caches.get(enumClass); 051 if (cache == null) { 052 caches.put(enumClass, cache = new Cache(enumClass)); 053 } 054 return cache; 055 } 056 057 /** 058 * Get the first enum item in enum class E which EnumValue value is equal to value 059 * @param <E> type of the enum 060 * @param value 061 * @param enumClass 062 * @return first enum item with matching value, null if there is no matching enum item 063 */ 064 public static <E extends Enum<E>> E getEnum(long value, Class<E> enumClass) { 065 return getCache(enumClass).enumsByValue.get(value); 066 } 067 068 /** 069 * Get the set of all the enum item in enum class E which EnumValue value flags are all present in value 070 * @param <E> type of the enum 071 * @param value 072 * @param enumClass 073 * @return enum items with matching value flags 074 */ 075 public static <E extends Enum<E>> EnumSet<E> getEnumSet(long value, Class<E> enumClass) { 076 EnumSet<E> set = EnumSet.noneOf(enumClass); 077 for (Map.Entry<Long, E> pair : getCache(enumClass).enumsByValue.entrySet()) { 078 long ev = pair.getKey(); 079 if ((ev & value) == ev) { 080 set.add(pair.getValue()); 081 } 082 } 083 return set; 084 } 085 086 /** 087 * Get the integer value associated with an enum item 088 * @see EnumValue 089 * @param enumItem 090 * @return the numeric value of the enum 091 */ 092 @SuppressWarnings("unchecked") 093 public static <E extends Enum<?>> long getValue(E enumItem) { 094 return getCache((Class<E>) enumItem.getDeclaringClass()).valuesByEnum.get(enumItem); 095 } 096 097 /** 098 * Get the integer value resulting from ORing all the values of all the enum items present in the enum set. 099 * @see EnumValues#getValue(java.lang.Enum) 100 * @see EnumValue 101 * @param set the EnumSet to process 102 * @return the OR of all the values of the enums in the set 103 */ 104 public static <E extends Enum<E>> long getValue(EnumSet<E> set) { 105 long v = 0; 106 for (E e : set) { 107 v |= getValue(e); 108 } 109 return v; 110 } 111}