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}