package com.hammurapi.extract.scripting;

import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;

import com.hammurapi.extract.Extractor;
import com.hammurapi.extract.ExtractorFactory;
import com.hammurapi.extract.Predicate;

public class ScriptingExtractorFactory implements ExtractorFactory {

	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) {

		ScriptEngineManager sem = new ScriptEngineManager(classLoader==null ? contextType.getClassLoader() : classLoader);
		for (ScriptEngineFactory sef: sem.getEngineFactories()) {
			if (sef.getLanguageName().equals(language)) {
				ScriptingExtractor<T, V, C> scriptingExtractor = new ScriptingExtractor<T, V, C>(code, sef, parameterNames);
				return scriptingExtractor;
			}
		}

		// Trying engine names
		for (ScriptEngineFactory sef: sem.getEngineFactories()) {
			for (String en: sef.getNames()) {
				if (en.equals(language)) {
					ScriptingExtractor<T, V, C> scriptingExtractor = new ScriptingExtractor<T, V, C>(code, sef, parameterNames);
					return scriptingExtractor;
				}
			}
		}			

		return null;
	}
	
	public <T, C> Predicate<T, C> createPredicate(
			String language,
			String code, 
			String[] parameterNames, 
			Class<T>[] parameterTypes,
			Class<C> contextType,
			ClassLoader classLoader) {

		ScriptEngineManager sem = new ScriptEngineManager(classLoader==null ? contextType.getClassLoader() : classLoader);
		for (ScriptEngineFactory sef: sem.getEngineFactories()) {
			if (sef.getLanguageName().equals(language)) {
				ScriptingPredicate<T, C> scriptingPredicate = new ScriptingPredicate<T, C>(code, sef, parameterNames);
				return scriptingPredicate;
			}
		}

		// Trying engine names
		for (ScriptEngineFactory sef: sem.getEngineFactories()) {
			for (String en: sef.getNames()) {
				if (en.equals(language)) {
					ScriptingPredicate<T, C> scriptingPredicate = new ScriptingPredicate<T, C>(code, sef, parameterNames);
					return scriptingPredicate;
				}
			}
		}			

		return null;
	}
	
	
}
