1 10 11 package org.mmbase.util; 12 13 import java.util.*; 14 import java.lang.reflect.*; 15 import java.text.Collator ; 16 import org.mmbase.cache.Cache; 17 import org.mmbase.util.logging.*; 18 import org.mmbase.datatypes.StringDataType; 19 20 34 public class SortedBundle { 35 36 private static final Logger log = Logging.getLoggerInstance(SortedBundle.class); 37 38 41 public static final Class NO_WRAPPER = null; 42 45 public static final Comparator NO_COMPARATOR = null; 46 49 public static final Map NO_CONSTANTSPROVIDER = null; 50 51 private static Cache knownResources = new Cache(100) { 53 public String getName() { 54 return "ConstantBundles"; 55 } 56 public String getDescription() { 57 return "A cache for constant bundles, to avoid a lot of reflection."; 58 } 59 }; 60 61 static { 62 knownResources.putCache(); 63 } 64 65 68 69 public static class ValueWrapper implements Comparable { 70 private final Object key; 71 private final Object value; 72 private final Comparator com; 73 public ValueWrapper(Object k, Comparable v) { 74 key = k; 75 value = v; 76 com = null; 77 } 78 public ValueWrapper(Object k, Object v, Comparator c) { 79 key = k; 80 value = v; 81 com = c; 82 } 83 public int compareTo(Object o) { 84 ValueWrapper other = (ValueWrapper) o; 85 int result = 86 com != null ? com.compare(value, other.value) : 87 ((Comparable ) value).compareTo(other.value); 88 if (result != 0) return result; 89 if (key instanceof Comparable ) { 90 return ((Comparable ) key).compareTo(other.key); 91 } else { 92 return 0; 93 } 94 } 95 public boolean equals(Object o) { 96 if (o == this) return true; 97 if (o == null) return false; 98 if (getClass() == o.getClass()) { 99 ValueWrapper other = (ValueWrapper) o; 100 return key.equals(other.key) && (value == null ? other.value == null : value.equals(other.value)); 101 } 102 return false; 103 } 104 public String toString() { 105 return Casting.toString(key); 106 } 107 public Object getKey() { 108 return key; 109 } 110 113 public int hashCode() { 114 int result = 0; 115 result = HashCodeUtil.hashCode(result, key); 116 result = HashCodeUtil.hashCode(result, value); 117 result = HashCodeUtil.hashCode(result, com); 118 return result; 119 } 120 } 121 122 123 139 public static SortedMap getResource(final String baseName, Locale locale, final ClassLoader loader, final Map constantsProvider, final Class wrapper, Comparator comparator) { 140 String resourceKey = baseName + '/' + locale + (constantsProvider == null ? "" : "" + constantsProvider.hashCode()) + "/" + (comparator == null ? "" : "" + comparator.hashCode()) + "/" + (wrapper == null ? "" : wrapper.getName()); 141 SortedMap m = (SortedMap) knownResources.get(resourceKey); 142 if (locale == null) locale = LocalizedString.getDefault(); 143 144 if (m == null) { ResourceBundle bundle; 146 if (loader == null) { 147 bundle = ResourceBundle.getBundle(baseName, locale); 148 } else { 149 bundle = ResourceBundle.getBundle(baseName, locale, loader); 150 } 151 if (comparator == null && wrapper != null && ! Comparable .class.isAssignableFrom(wrapper)) { 152 if (wrapper.equals(Boolean .class)) { 153 comparator = new Comparator() { 155 public int compare(Object o1, Object o2) { 156 if (o1 instanceof Boolean && o2 instanceof Boolean ) { 157 return 158 o1.equals(Boolean.FALSE) ? 159 (o2.equals(Boolean.FALSE) ? 0 : -1) : 160 (o2.equals(Boolean.TRUE) ? 1 : 0); 161 } 162 return o1.hashCode() - o2.hashCode(); 163 } 164 }; 165 } else { 166 throw new IllegalArgumentException ("Key wrapper " + wrapper + " is not Comparable"); 167 } 168 } 169 170 m = new TreeMap(comparator); 171 172 Enumeration keys = bundle.getKeys(); 173 while (keys.hasMoreElements()) { 174 String bundleKey = (String ) keys.nextElement(); 175 Object value = bundle.getObject(bundleKey); 176 Object key = castKey(bundleKey, value, constantsProvider, wrapper, locale); 177 if (key == null) continue; 178 m.put(key, value); 179 } 180 m = Collections.unmodifiableSortedMap(m); 181 knownResources.put(resourceKey, m); 182 } 183 return m; 184 } 185 186 187 public static Object castKey(final String bundleKey, final Object value, final Map constantsProvider, final Class wrapper) { 188 return castKey(bundleKey, value, constantsProvider, wrapper, null); 189 } 190 194 protected static Object castKey(final String bundleKey, final Object value, final Map constantsProvider, final Class wrapper, final Locale locale) { 195 if (bundleKey == null) return null; 196 Object key; 197 200 Map provider = constantsProvider; int lastDot = bundleKey.lastIndexOf('.'); 202 if (lastDot > 0) { 203 Class providerClass; 204 String className = bundleKey.substring(0, lastDot); 205 try { 206 providerClass = Class.forName(className); 207 provider = getConstantsProvider(providerClass); 208 } catch (ClassNotFoundException cnfe) { 209 if (log.isDebugEnabled()) { 210 log.debug("No class found with name " + className + " found from " + bundleKey); 211 } 212 } 213 } 214 215 if (provider != null) { 216 key = provider.get(bundleKey.toUpperCase()); 217 if (key == null) key = bundleKey; 218 } else { 219 key = bundleKey; 220 } 221 222 if (wrapper != null && ! wrapper.isAssignableFrom(key.getClass())) { 223 try { 224 if (ValueWrapper.class.isAssignableFrom(wrapper)) { 225 log.debug("wrapper is a valueWrapper"); 226 if (locale == null) { 227 Constructor c = wrapper.getConstructor(new Class [] { Object .class, Comparable .class }); 228 key = c.newInstance(new Object [] { key, (Comparable ) value}); 229 } else { 230 Constructor c = wrapper.getConstructor(new Class [] { Object .class, Object .class, Comparator.class }); 231 Collator comp = Collator.getInstance(locale); 232 comp.setStrength(Collator.PRIMARY); 233 key = c.newInstance(new Object [] { key, value, comp}); 234 } 235 } else if (Number .class.isAssignableFrom(wrapper)) { 236 if (key instanceof String ) { 237 if (StringDataType.DOUBLE_PATTERN.matcher((String ) key).matches()) { 238 key = Casting.toType(wrapper, key); 239 } 240 } else { 241 key = Casting.toType(wrapper, key); 242 log.debug("wrapper is a Number, that can simply be cast " + value + " --> " + key + "(" + wrapper + ")"); 243 } 244 } else if (Boolean .class.isAssignableFrom(wrapper)) { 245 if (key instanceof String ) { 246 if (StringDataType.BOOLEAN_PATTERN.matcher((String ) key).matches()) { 247 key = Casting.toType(wrapper, key); 248 } 249 } else { 250 key = Casting.toType(wrapper, key); 251 log.debug("wrapper is a Boolean, that can simply be cast " + value + " --> " + key + "(" + wrapper + ")"); 252 } 253 254 } else { 255 log.debug("wrapper is unrecognized, suppose constructor " + key.getClass()); 256 Constructor c = wrapper.getConstructor(new Class [] {key.getClass()}); 257 key = c.newInstance(new Object [] { key }); 258 } 259 } catch (NoSuchMethodException nsme) { 260 log.warn(nsme.getClass().getName() + ". Could not convert " + key.getClass().getName() + " " + key + " to " + wrapper.getName() + " : " + nsme.getMessage() + " locale " + locale); 261 } catch (SecurityException se) { 262 log.error(se.getClass().getName() + ". Could not convert " + key.getClass().getName() + " " + key + " to " + wrapper.getName() + " : " + se.getMessage()); 263 } catch (InstantiationException ie) { 264 log.error(ie.getClass().getName() + ". Could not convert " + key.getClass().getName() + " " + key + " to " + wrapper.getName() + " : " + ie.getMessage()); 265 } catch (InvocationTargetException ite) { 266 log.debug(ite.getClass().getName() + ". Could not convert " + key.getClass().getName() + " " + key + " to " + wrapper.getName() + " : " + ite.getMessage()); 267 } catch (IllegalAccessException iae) { 268 log.error(iae.getClass().getName() + ". Could not convert " + key.getClass().getName() + " " + key + " to " + wrapper.getName() + " : " + iae.getMessage()); 269 } 270 } 271 return key; 272 } 273 274 278 public static HashMap getConstantsProvider(Class clazz) { 279 if (clazz == null) return null; 280 HashMap map = new HashMap(); 281 fillConstantsProvider(clazz, map); 282 return map; 283 } 284 private static void fillConstantsProvider(Class clazz, HashMap map) { 285 while(clazz != null) { 286 Field[] fields = clazz.getDeclaredFields(); 287 for (int i = 0 ; i < fields.length; i++) { 288 Field constant = fields[i]; 289 if (Modifier.isStatic(constant.getModifiers())) { 290 String key = constant.getName().toUpperCase(); 291 if (! map.containsKey(key)) { try { 293 Object value = constant.get(null); 294 map.put(key, value); 295 } catch (IllegalAccessException ieae) { 296 log.debug("The java constant with name " + key + " is not accessible"); 297 } 298 } 299 } 300 } 301 Class [] interfaces = clazz.getInterfaces(); 302 for (int i = 0 ; i < interfaces.length; i ++) { 303 fillConstantsProvider(interfaces[i], map); 304 } 305 clazz = clazz.getSuperclass(); 306 } 307 } 308 } 309 | Popular Tags |