    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}