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

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

import woolpack.fn.Fn;

/**
 * 値一覧とラベル一覧をマージして、値とラベルの{@link LinkedHashMap}を生成する{@link Fn}です。
 * {@link woolpack.html.SelectRemaker}や
 * {@link woolpack.html.RadioRemaker}を使用して
 * HTML のラジオボタン・チェックボックス・セレクトを再生成するための準備段階で使用します。
 * このクラスでは例えば次の設定内容から
 * 「part.hobby={0:bycycle, 1:car, 2:bike, 3:spacecraft}」を
 * 生成することができます。
 * <table border="1"><tr><td>
 * part.hobby.value=0,1,2,3<br/>
 * part.hobby.label=bycycle,car,bike,spacecraft
 * </td></tr></table>
 * 
 * @author nakamura
 * 
 * @param <E>
 */
public class ToLinkedHashMap<E extends Exception> implements Fn<ConfigContext, Void, E> {
	private String newMapListPosition;
	private String valueSourcePosition;
	private String labelSourcePosition;
	private String separator;

	/**
	 * @param newMapListPosition
	 *            変換後の{@link LinkedHashMap}を格納する
	 *            {@link ConfigContext#getConfig()}上の位置。
	 * @param valueSourcePosition 値一覧を取得する{@link ConfigContext#getConfig()}上の位置。
	 * @param labelSourcePosition ラベル一覧を取得する{@link ConfigContext#getConfig()}上の位置。
	 * @param separator 一覧(値・ラベル)それぞれ値・ラベルに分解するためのセパレータ。
	 */
	public ToLinkedHashMap(
			final String newMapListPosition,
			final String valueSourcePosition,
			final String labelSourcePosition,
			final String separator) {
		this.newMapListPosition = newMapListPosition;
		this.valueSourcePosition = valueSourcePosition;
		this.labelSourcePosition = labelSourcePosition;
		this.separator = separator;
	}

	/**
	 * @throws ClassCastExcpeption 一覧(値・ラベル)のいずれかが文字列でない場合。
	 * @throws ArrayIndexOutOfBoundsException 一覧(値・ラベル)の分割後の要素数が一致しない場合。
	 */
	public Void exec(final ConfigContext context) {
		final String[] valueArray = ((String) context.getConfig().get(valueSourcePosition)).split(separator);
		final String[] labelArray = ((String) context.getConfig().get(labelSourcePosition)).split(separator);
		if (valueArray.length != labelArray.length) {
			throw new ArrayIndexOutOfBoundsException("length unmatch : "
					+ valueSourcePosition + " and " + labelSourcePosition);
		}
		final Map<String, String> map = new LinkedHashMap<String, String>();
		for (int i = 0; i < valueArray.length; i++) {
			map.put(valueArray[i], labelArray[i]);
		}
		context.getConfig().put(newMapListPosition, Collections.unmodifiableMap(map));
		return null;
	}

	public String getLabelSourcePosition() {
		return labelSourcePosition;
	}
	public void setLabelSourcePosition(final String labelSourcePosition) {
		this.labelSourcePosition = labelSourcePosition;
	}
	public String getNewMapListPosition() {
		return newMapListPosition;
	}
	public void setNewMapListPosition(final String newMapListPosition) {
		this.newMapListPosition = newMapListPosition;
	}
	public String getSeparator() {
		return separator;
	}
	public void setSeparator(final String separator) {
		this.separator = separator;
	}
	public String getValueSourcePosition() {
		return valueSourcePosition;
	}
	public void setValueSourcePosition(final String valueSourcePosition) {
		this.valueSourcePosition = valueSourcePosition;
	}
}
