LazyPropertyKey.java 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. package gnu.mapping;
  2. /** A property whose value can be found lazily.
  3. * The property is initialized with a specifier string, which must have the
  4. * form of either:
  5. * <ol>
  6. * <li> {@code "ClassName:fieldName"}: In this case {@code "fieldName"} must
  7. * be the name of a static field in {@code "ClassName"}, of type {@code T}.
  8. * <li> {@code "*ClassName:methodName"}: In this case {@code "methodName"}
  9. * must be the name of a static method that takes one parameter
  10. * (the {@code PropertySet}), and returns an object of type {@code T}.
  11. * </ol>
  12. */
  13. public class LazyPropertyKey<T> extends PropertyKey<T>
  14. {
  15. public LazyPropertyKey(String name)
  16. {
  17. super(name);
  18. }
  19. @SuppressWarnings("unchecked")
  20. @Override
  21. public T get(PropertySet container, T defaultValue)
  22. {
  23. Object raw = container.getProperty((Object) this, (Object) defaultValue);
  24. if (raw instanceof String)
  25. {
  26. String str = (String) raw;
  27. boolean factory = false;
  28. int cstart = str.charAt(0) == '*' ? 1 : 0;
  29. int colon = str.indexOf(':');
  30. if (colon <= cstart || colon >= str.length() - 1)
  31. throw new RuntimeException("lazy property "+this+" must have the form \"ClassName:fieldName\" or \"ClassName:staticMethodName\"");
  32. java.lang.reflect.Method method = null;
  33. String cname = str.substring(cstart, colon);
  34. String mname = str.substring(colon+1);
  35. T result;
  36. try
  37. {
  38. /* #ifdef JAVA2 */
  39. Class clas = Class.forName(cname, true,
  40. container.getClass().getClassLoader());
  41. /* #else */
  42. // Class clas = Class.forName(cname);
  43. /* #endif */
  44. if (cstart == 0)
  45. {
  46. result = (T) clas.getField(mname).get(null);
  47. }
  48. else
  49. {
  50. result = (T) clas.getDeclaredMethod(mname, new Class[] { Object.class })
  51. .invoke(null, container);
  52. }
  53. }
  54. catch (Exception ex)
  55. {
  56. throw new RuntimeException("lazy property "+this+" has specifier \""+str+"\" but there is no such "+(cstart==0?"field":"method"), ex);
  57. }
  58. container.setProperty(this, result);
  59. return result;
  60. }
  61. return (T) raw;
  62. }
  63. public void set (PropertySet container, String specifier)
  64. {
  65. container.setProperty(this, specifier);
  66. }
  67. }