/*
 * Copyright 2006 Takahiro Nakamura.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package woolpack.factory;

import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;

import woolpack.el.EL;
import woolpack.el.GettingEL;
import woolpack.fn.Fn;

/**
 * ユーティリティです。
 * 型推論で表記を簡略するためのスタティックメソッドを含みます。
 * @author nakamura
 *
 */
public final class FactoryUtils {
	/**
	 * {@link LinkedHashMap}を生成する{@link Fn}です。
	 */
	public static final Fn<Object, Map<String, Object>, RuntimeException> LINKED_MAP_FACTORY = new Fn<Object, Map<String, Object>, RuntimeException>() {
		public Map<String, Object> exec(final Object c) {
			return new LinkedHashMap<String, Object>();
		}
	};

	private FactoryUtils() {
	}
	
	public static <C, K, E extends Exception> MapCache<C, K, E> cache(
			final Fn<? super C, ? extends Map<? super K, Object>, ? extends E> mapGetter,
			final Fn<? super C, K, ? extends E> keyGetter,
			final Fn<? super C, ?, ? extends E> maker) {
		return new MapCache<C, K, E>(mapGetter, keyGetter, maker);
	}
	
	public static <C, K, E extends Exception> ConcurrentMapCache<C, K, E> concurrentCache(
			final Fn<? super C, ? extends ConcurrentMap<? super K, Object>, ? extends E> mapGetter,
			final Fn<? super C, K, ? extends E> keyGetter,
			final Fn<? super C, ?, ? extends E> maker) {
		return new ConcurrentMapCache<C, K, E>(mapGetter, keyGetter, maker);
	}
	
	public static <C, K, E extends Exception> SideEffectMapCache<C, K, E> cache(
			final Fn<? super C, ? extends Map<? super K, Object>, ? extends E> mapGetter,
			final Fn<? super C, ? extends K, ? extends E> keyGetter,
			final Fn<? super C, ?, ? extends E> maker,
			final EL el) {
		return new SideEffectMapCache<C, K, E>(mapGetter, keyGetter, maker, el);
	}
	
	public static <C, K, E extends Exception> SideEffectConcurrentMapCache<C, K, E> concurrentCache(
			final Fn<? super C, ? extends ConcurrentMap<? super K, Object>, ? extends E> mapGetter,
			final Fn<? super C, ? extends K, ? extends E> keyGetter,
			final Fn<? super C, ?, ? extends E> maker,
			final EL el) {
		return new SideEffectConcurrentMapCache<C, K, E>(mapGetter, keyGetter, maker, el);
	}

	public static GettingELFn<RuntimeException> doEL(final GettingEL gettingEL) {
		return new GettingELFn<RuntimeException>(gettingEL);
	}

	public static <C> InputStreamReaderFactory<C> inputStreamReaderFactory(
			final Fn<? super C, ? extends InputStream, ? extends IOException> inputStreamFactory,
			final String charset) {
		return new InputStreamReaderFactory<C>(inputStreamFactory, charset);
	}

	public static <R> NewInstanceFactory<R> newInstance(final Class<R> clazz) {
		return new NewInstanceFactory<R>(clazz);
	}

	public static StringInputStreamFactory stringInputStreamFactory(final String charset, final String s) {
		return new StringInputStreamFactory(charset, s);
	}

	public static StringReaderFactory<RuntimeException> stringReaderFactory(final String s) {
		return new StringReaderFactory<RuntimeException>(s);
	}
}
