001package com.hammurapi.extract;
002
003import java.util.Iterator;
004import java.util.ServiceLoader;
005
006import com.hammurapi.extract.scripting.ScriptingExtractorFactory;
007
008
009/**
010 * Extractor factory service. Creates scripted extractors and predicates.
011 * The service is discoverable using the Java Service Loader framework.
012 * @author Pavel Vlasov.
013 *
014 */
015public interface ExtractorFactory {
016        
017        /**
018         * Binding for context object.
019         */
020        String CONTEXT_BINDING = "eCtx";
021        
022        /**
023         * Binding for arguments arrray if parameter names are not provided.
024         */
025        String ARGS_BINDING = "args";
026
027        /**
028         * This instance uses the service loading framework to discover
029         * extractor factory providers. It iterates over the providers and
030         * invokes provider's createExtractor() methods until it gets not null
031         * result which is returned from the method.
032         * If there are no providers supporting given language, then null is returned.
033         */
034        ExtractorFactory INSTANCE = new ExtractorFactory() {
035                
036                private ScriptingExtractorFactory sef = new ScriptingExtractorFactory();
037
038                public <T, V, C> Extractor<T, V, C> createExtractor(String language, String code, String[] parameterNames, Class<T>[] parameterTypes, Class<V> valueType, Class<C> contextType, ClassLoader classLoader) {
039                        ServiceLoader<ExtractorFactory> sl = classLoader==null ? ServiceLoader.load(ExtractorFactory.class) : ServiceLoader.load(ExtractorFactory.class, classLoader);
040                        Iterator<ExtractorFactory> efi = sl.iterator();
041                        while (efi.hasNext()) {
042                                Extractor<T, V, C> ret = efi.next().createExtractor(language, code, parameterNames, parameterTypes, valueType, contextType, classLoader);
043                                if (ret!=null) {
044                                        return ret;
045                                }
046                        }
047                        return sef.createExtractor(language, code, parameterNames, parameterTypes, valueType, contextType, classLoader);
048                }
049                
050                public <T, C> Predicate<T, C> createPredicate(String language, String code, String[] parameterNames, Class<T>[] parameterTypes, Class<C> contextType, ClassLoader classLoader) {
051                        ServiceLoader<ExtractorFactory> sl = classLoader==null ? ServiceLoader.load(ExtractorFactory.class) : ServiceLoader.load(ExtractorFactory.class, classLoader);
052                        Iterator<ExtractorFactory> efi = sl.iterator();
053                        while (efi.hasNext()) {
054                                Predicate<T, C> ret = efi.next().createPredicate(language, code, parameterNames, parameterTypes, contextType, classLoader);
055                                if (ret!=null) {
056                                        return ret;
057                                }
058                        }
059                        return sef.createPredicate(language, code, parameterNames, parameterTypes, contextType, classLoader);
060                }
061                
062        };
063        
064        /**
065         * Creates extractor.
066         * @param <T> Source objects type.
067         * @param <V> Value type.
068         * @param language Extractor language.
069         * @param code Extractor code.
070         * @param parameterTypes Extractor parameter types.
071         * @param valueType Extractor value type. If this type is Boolean then the factory
072         * shall return Predicate.
073         * @param classLoader Class loader to use for script evaluation.
074         * @return Extractor or null if this factory doesn't support given language.
075         */
076        <T, V, C> Extractor<T, V, C> createExtractor(String language, String code, String[] parameterNames, Class<T>[] parameterTypes, Class<V> valueType, Class<C> contextType, ClassLoader classLoader);
077
078        /**
079         * Creates extractor.
080         * @param <T> Source objects type.
081         * @param language Extractor language.
082         * @param code Extractor code.
083         * @param parameterTypes Extractor parameter types.
084         * @param valueType Extractor value type. If this type is Boolean then the factory
085         * shall return Predicate.
086         * @param classLoader Class loader to use for script evaluation.
087         * @return Extractor or null if this factory doesn't support given language.
088         */
089        <T, C> Predicate<T, C> createPredicate(String language, String code, String[] parameterNames, Class<T>[] parameterTypes, Class<C> contextType, ClassLoader classLoader);
090}