    001package com.hammurapi.common;
    002
    003import java.util.ArrayList;
    004import java.util.Collection;
    005import java.util.Collections;
    006import java.util.Iterator;
    007
    008import com.hammurapi.extract.And;
    009import com.hammurapi.extract.Predicate;
    010
    011public class SingletonChainingContext<ST> implements MutableContext {
    012
    013        private Class<ST> type;
    014        private ST service;
    015        private Context chain;
    016
    017        public SingletonChainingContext(Class<ST> type, ST service, Context chain) {
    018                this.type = type;
    019                this.service = service;
    020                this.chain = chain;
    021        }
    022
    023        public void bind(String name, Object obj) {
    024                if (chain instanceof MutableContext) {
    025                        ((MutableContext) chain).bind(name, obj);
    026                } else {
    027                        throw new IllegalStateException("Chain context is not mutable");
    028                }
    029        }
    030
    031        public <T> void register(Class<? super T> type, T service) {
    032                if (chain instanceof MutableContext) {
    033                        ((MutableContext) chain).register(type, service);
    034                } else {
    035                        throw new IllegalStateException("Chain context is not mutable");
    036                }
    037        }
    038
    039        public Object unbind(String name) {
    040                if (chain instanceof MutableContext) {
    041                        return ((MutableContext) chain).unbind(name);
    042                } else {
    043                        throw new IllegalStateException("Chain context is not mutable");
    044                }
    045        }
    046
    047        public <T> void unregister(Class<? super T> type, T service) {
    048                if (chain instanceof MutableContext) {
    049                        ((MutableContext) chain).unregister(type, service);
    050                } else {
    051                        throw new IllegalStateException("Chain context is not mutable");
    052                }
    053        }
    054
    055        public Object lookup(String name) {
    056                return chain==null ? null : chain.lookup(name);
    057        }
    058
    059        @SuppressWarnings("unchecked")
    060        public <T> T lookup(Class<T> serviceClass, Predicate<T, Context>... selectors) {
    061                And<T, Context> and = new And<T, Context>(0, null, selectors);
    062                if (serviceClass.equals(type) && and.extract(this, null, (T) service)) {
    063                        return (T) service;
    064                }
    065
    066                return chain==null ? null : chain.lookup(serviceClass, selectors);
    067        }
    068
    069        @SuppressWarnings("unchecked")
    070        public <T> Iterator<T> lookupAll(Class<T> serviceClass, Predicate<T, Context>... selectors) {
    071                And<T, Context> and = new And<T, Context>(0, null, selectors);
    072                if (serviceClass.equals(type) &&  and.extract(this, null, (T) service)) {
    073                        Collection<T> c = new ArrayList<T>();
    074                        c.add((T) service);
    075                        if (chain!=null) {
    076                                Iterator<T> it = chain.lookupAll(serviceClass, selectors);
    077                                while (it.hasNext()) {
    078                                        c.add(it.next());
    079                                }
    080                        }
    081                        return c.iterator();
    082                }
    083                return (Iterator<T>) (chain==null ? Collections.emptyList().iterator() : chain.lookupAll(serviceClass, selectors));
    084        }
    085
    086}