001package com.hammurapi.common;
002
003import java.util.ArrayList;
004import java.util.Collection;
005import java.util.Collections;
006import java.util.Iterator;
007import java.util.Map;
008import java.util.ServiceLoader;
009
010import com.hammurapi.extract.And;
011import com.hammurapi.extract.Predicate;
012
013/**
014 * Default context uses ServiceLoader to find services in 
015 * a given classloader and map of bindings.
016 * @author Pavel Vlasov
017 *
018 */
019public class DefaultContext implements Context {
020        
021        private ClassLoader classLoader;
022        private Map<String, Object> bindings;
023
024        /**
025         * @param classLoader ClassLoader for services. Can be null.
026         * @param bindings Name bindings. Can be null.
027         */
028        public DefaultContext(ClassLoader classLoader, Map<String, Object> bindings) {
029                this.classLoader = classLoader==null ? this.getClass().getClassLoader() : classLoader;
030                this.bindings = bindings;
031        }
032
033        public Object lookup(String name) {
034                return bindings==null ? null : bindings.get(name);
035        }
036
037        public <T> T lookup(Class<T> serviceClass, Predicate<T, Context>... selectors) {              
038                ServiceLoader<T> sl = ServiceLoader.load(serviceClass, classLoader);
039                Iterator<T> sit = sl.iterator();          
040                And<T, Context> and = new And<T, Context>(0, null, selectors);
041                while (sit.hasNext()) {
042                        T service = sit.next();
043                        if (and.extract(this, null, service)) {
044                                return service;
045                        }
046                }
047                return null;
048        }
049
050        public <T> Iterator<T> lookupAll(Class<T> serviceClass, Predicate<T, Context>... selectors) {
051                ServiceLoader<T> sl = ServiceLoader.load(serviceClass, classLoader);
052                And<T, Context> and = new And<T, Context>(0, null, selectors);
053                Collection<T> ret = new ArrayList<T>();
054                Iterator<T> sit = sl.iterator();          
055                while (sit.hasNext()) {
056                        T service = sit.next();
057                        if (and.extract(this, null, service)) {
058                                ret.add(service);
059                        }
060                }
061                return Collections.unmodifiableCollection(ret).iterator();
062        }
063
064}