/*
 * 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.idnode;

import java.util.Map;

import woolpack.factory.FactoryUtils;
import woolpack.fn.FixFn;
import woolpack.fn.Fn;
import woolpack.id.IdContext;
import woolpack.id.IdUtils;
import woolpack.xml.NodeContext;
import woolpack.xml.XmlUtils;

/**
 * 識別子とノードのコンテキストを操作するユーティリティです。
 * 型推論で表記を簡略するためのスタティックメソッドと変数を含みます。
 * 
 * @author nakamura
 *
 */
public final class IdNodeUtils {
	private IdNodeUtils() {
	}

	/**
	 * ノードをキャッシュする{@link Fn}を返します。
	 * @param <C>
	 * @param <E>
	 * @param map キャッシュに使用するマップ。
	 * @param maker ノードを生成する委譲先。
	 * @return ノードをキャッシュする{@link Fn}。
	 */
	public static <C extends NodeContext & IdContext, E extends Exception> Fn<C, Void, E> cache(
			final Map<String, Object> map,
			final Fn<? super C, ?, ? extends E> maker) {
		return FactoryUtils.cache(
				new FixFn<C, Map<String, Object>, E>(map),
				IdUtils.<E>getId(),
				maker,
				XmlUtils.NODE_EL
		);
	}

	/**
	 * HTML の内部フレームを流し込む関数を生成します。
	 * 各フレームをマージする際にターゲットの HTML HEAD タグを残します。
	 * Struts の Tiles プラグインのようにレイアウトを制御するために使用します。
	 * @param <C>
	 * @param <E>
	 * @param frameId 親 HTML の id。
	 * @param targetName {@link IdContext#getId()}で生成された DOM ノードを流し込む"//iframe[\@name]"の値。
	 * @param nodeMaker ノードを作成する委譲先。
	 * @param idConverter "//iframe[[\@src]"のidに変換するための変換器。
	 * @return 関数。
	 */
	public static <C extends NodeContext & IdContext, E extends Exception> Fn<C, Void, E> insertIFrame(
			final String frameId,
			final String targetName,
			final Fn<C, Void, ? extends E> nodeMaker,
			final Fn<String, String, ? extends E> idConverter) {
		return new IFrameInserter<C, E>(frameId, targetName, nodeMaker, idConverter);
	}
}
