1 package jfun.yan.xml; 2 3 import jfun.yan.Binder; 4 import jfun.yan.Component; 5 import jfun.yan.Components; 6 import jfun.yan.Creator; 7 import jfun.yan.LazyComponent; 8 9 abstract class Thunk implements Closure { 10 private Object obj = null; 11 private boolean entered = false; 12 private final Object key; 13 private final Location loc; 14 15 public Thunk(Object name, Location loc) { 16 this.loc = loc; 17 this.key = name; 18 } 19 public synchronized Object get() { 20 if(entered){ 21 return lazy(); 23 } 24 if(obj==null){ 25 entered = true; 26 try{ 27 obj = evaluate(); 28 } 29 finally{ 30 entered = false; 31 } 32 } 33 return obj; 34 } 35 abstract Object evaluate(); 36 37 private Component getLazyComponent(){ 38 return Components.fromLazy(new LazyComponent(){ 39 public Component eval(){ 40 final Object c = get(); 41 if(c instanceof Component){ 42 return (Component)c; 43 } 44 else{ 45 throw new ConfigurationException("Component expected, " 46 + NutsUtils.getTypeName(c) + " encountered", loc); 47 } 48 } 49 public Class getType(){ 50 return null; 51 } 52 }, key); 53 } 54 private Binder getLazyBinder(){ 55 return new Binder(){ 56 public Creator bind(Object v) throws Throwable { 57 final Object b = get(); 58 if(b instanceof Binder){ 59 return ((Binder)b).bind(v); 60 } 61 else{ 62 throw new ConfigurationException("Binder expected, " 63 + NutsUtils.getTypeName(b) + " encountered", loc); 64 } 65 } 66 }; 67 } 68 private final Object lazy(){ 69 final Class type = getType(); 70 if(Component.class.isAssignableFrom(type)){ 71 return getLazyComponent(); 73 } 74 else if(Binder.class.isAssignableFrom(type)){ 75 return getLazyBinder(); 76 } 77 else{ 78 throw new ConfigurationException( 79 "recursive dependency for "+key, loc); 80 } 81 } 82 } 83 | Popular Tags |