001package com.hammurapi.common; 002 003import java.util.ArrayList; 004import java.util.Collection; 005import java.util.Collections; 006import java.util.HashMap; 007import java.util.Iterator; 008import java.util.Map; 009 010import com.hammurapi.extract.And; 011import com.hammurapi.extract.Predicate; 012 013/** 014 * Simple context implementation. 015 * @author Pavel Vlasov 016 * 017 */ 018public class SimpleMutableContext implements MutableContext { 019 020 private Map<String, Object> bindings = new HashMap<String, Object>(); 021 private Map<Class<?>, Collection<?>> services = new HashMap<Class<?>, Collection<?>>(); 022 private Context[] chain; 023 024 public SimpleMutableContext(Context... chain) { 025 this.chain = chain; 026 } 027 028 /** 029 * @param classLoader ClassLoader for services. Can be null. 030 * @param bindings Name bindings. Can be null. 031 */ 032 public SimpleMutableContext(Map<Class<?>, Collection<?>> services, Map<String, ?> bindings, Context... chain) { 033 this(chain); 034 if (services!=null) { 035 this.services.putAll(services); 036 } 037 038 if (bindings!=null) { 039 this.bindings.putAll(bindings); 040 } 041 } 042 043 public synchronized void bind(String name, Object value) { 044 bindings.put(name, value); 045 } 046 047 public synchronized Object unbind(String name) { 048 return bindings.remove(name); 049 } 050 051 @SuppressWarnings("unchecked") 052 public synchronized <T> void register(Class<? super T> serviceType, T service) { 053 Collection<Object> sl = (Collection<Object>) services.get(serviceType); 054 if (sl==null) { 055 sl = new ArrayList<Object>(); 056 services.put(serviceType, sl); 057 } 058 sl.add(service); 059 } 060 061 public synchronized <T> void unregister(Class<? super T> serviceType, T service) { 062 Collection<?> sl = services.get(serviceType); 063 if (sl!=null) { 064 sl.remove(service); 065 if (sl.isEmpty()) { 066 services.remove(serviceType); 067 } 068 } 069 } 070 071 public Object lookup(String name) { 072 Object ret = bindings.get(name); 073 if (ret==null) { 074 for (Context cc: chain) { 075 ret = cc==null ? null : cc.lookup(name); 076 if (ret!=null) { 077 break; 078 } 079 } 080 } 081 return ret; 082 } 083 084 @SuppressWarnings("unchecked") 085 public <T> T lookup(Class<T> serviceClass, Predicate<T, Context>... selectors) { 086 Collection<?> sl = services.get(serviceClass); 087 088 if (sl!=null) { 089 Iterator<?> sit = sl.iterator(); 090 And<T, Context> and = new And<T, Context>(0, null, selectors); 091 while (sit.hasNext()) { 092 T service = (T) sit.next(); 093 if (and.extract(this, null, service)) { 094 return service; 095 } 096 } 097 } 098 099 for (Context cc: chain) { 100 T ret = cc==null ? null : cc.lookup(serviceClass, selectors); 101 if (ret!=null) { 102 return ret; 103 } 104 } 105 106 return null; 107 } 108 109 @SuppressWarnings("unchecked") 110 public <T> Iterator<T> lookupAll(Class<T> serviceClass, Predicate<T, Context>... selectors) { 111 Collection<?> sl = services.get(serviceClass); 112 And<T, Context> and = new And<T, Context>(0, null, selectors); 113 Collection<T> ret = new ArrayList<T>(); 114 if (sl!=null) { 115 Iterator<?> sit = sl.iterator(); 116 while (sit.hasNext()) { 117 T service = (T) sit.next(); 118 if (and.extract(this, null, service)) { 119 ret.add(service); 120 } 121 } 122 } 123 124 for (Context cc: chain) { 125 Iterator<T> cit = cc==null ? null : cc.lookupAll(serviceClass, selectors); 126 if (cit!=null) { 127 while (cit.hasNext()) { 128 ret.add(cit.next()); 129 } 130 } 131 } 132 133 134 return (Iterator<T>) ret.iterator(); 135 } 136 137}