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}