/*
 * Copyright (c) 2009 OrangeSignal.com All rights reserved.
 * 
 * これは Apache ライセンス Version 2.0 (以下、このライセンスと記述) に
 * 従っています。このライセンスに準拠する場合以外、このファイルを使用
 * してはなりません。このライセンスのコピーは以下から入手できます。
 * 
 * http://www.apache.org/licenses/LICENSE-2.0.txt
 * 
 * 適用可能な法律がある、あるいは文書によって明記されている場合を除き、
 * このライセンスの下で配布されているソフトウェアは、明示的であるか暗黙の
 * うちであるかを問わず、「保証やあらゆる種類の条件を含んでおらず」、
 * 「あるがまま」の状態で提供されるものとします。
 * このライセンスが適用される特定の許諾と制限については、このライセンス
 * を参照してください。
 */

package jp.sf.orangesignal.ta.data;

import java.util.Calendar;
import java.util.Date;
import java.util.Map;

/**
 * データ項目群情報を提供します。
 * 
 * @author 杉澤 浩二
 * @since 2.1
 */
public interface DatasetSource {

	/**
	 * 唯一の名前と日時データの関連付けを返します。
	 * 名前と日時データの関連付けが見つからない場合や複数存在する場合は例外をスローします。
	 * 
	 * @return 唯一の名前と日時データの関連付け
	 * @throws IllegalStateException 名前と日時データの関連付けが複数存在する場合
	 */
	public Map.Entry<String, Date[]> getUniqueDateEntry();

	/**
	 * 指定された名前に関連付けられた日時データを返します。
	 * 指定された名前に関連付けられた日時データが存在しない場合は <code>null</code> を返します。
	 * 
	 * @param name 名前
	 * @return 日時データ。または <code>null</code>
	 */
	public Date[] getDate(String name);

	/**
	 * 名前と日時データのマップを返します。
	 * 
	 * @return 名前と日時データのマップ
	 */
	public Map<String, Date[]> getDateMap();

	/**
	 * 唯一の名前と数値データの関連付けを返します。
	 * 名前と数値データの関連付けが見つからない場合や複数存在する場合は例外をスローします。
	 * 
	 * @return 唯一の名前と数値データの関連付け
	 * @throws IllegalStateException 名前と数値データの関連付けが複数存在する場合
	 */
	public Map.Entry<String, Number[]> getUniqueNumberEntry();

	/**
	 * 指定された名前に関連付けられた数値データを返します。
	 * 指定された名前に関連付けられた数値データが存在しない場合は <code>null</code> を返します。
	 * 
	 * @param name 名前
	 * @return 数値データ。または <code>null</code>
	 */
	public Number[] getNumber(String name);

	/**
	 * 名前と数値データのマップを返します。
	 * 
	 * @return 名前と数値データのマップ
	 */
	public Map<String, Number[]> getNumberMap();

	/**
	 * 指定された名前に関連付けられた日時書式文字列情報を返します。
	 * 指定された名前に関連付けられた日時書式文字列情報が存在しない場合は <code>null</code> を返します。
	 * 
	 * @param name 名前
	 * @return 日時書式文字列情報。または <code>null</code>
	 */
	public DateFormatConfig getDateFormatConfig(String name);

	/**
	 * 指定された名前に関連付けられた数値/通貨書式文字列情報を返します。
	 * 指定された名前に関連付けられた数値/通貨書式文字列情報が存在しない場合は <code>null</code> を返します。
	 * 
	 * @param name 名前
	 * @return 数値/通貨書式文字列情報。または <code>null</code>
	 */
	public NumberFormatConfig getNumberFormatConfig(String name);

	/**
	 * 指定された名前に関連付けられた日時精度単位変換の種類を返します。
	 * 指定された名前に関連付けられた日時精度単位変換の種類が存在しない場合は <code>null</code> を返します。
	 * 
	 * @param key 名前
	 * @return 日時精度単位変換の種類。または <code>null</code>
	 */
	public CompressType getCompressType(String key);

	/**
	 * 名前と日時精度単位変換の種類のマップを返します。
	 * 
	 * @return 名前と日時精度単位変換の種類のマップ
	 */
	public Map<String, CompressType> getCompressTypeMap();

	/**
	 * このクラスに有効な日時精度単位変換の種類が存在するかどうかを返します。
	 * 
	 * @return 有効な日時精度単位変換の種類が存在するかどうか
	 */
	public boolean isCompressable();

	/**
	 * 指定されたデータ項目群をこのクラスのデータ項目群へマージします。
	 * 
	 * @param items データ項目群情報
	 * @param matchType 日時の突合せ方法
	 * @return このオブジェクトへの参照
	 * @throws IllegalArgumentException データ項目群または日時の突合せ方法に <code>null<code> が指定された場合
	 * @throws IllegalStateException 指定されたデータ項目群またはこのクラスから唯一の名前と日時データの関連付けを取得できなかった場合。
	 */
	public DatasetSource merge(DatasetSource items, MergeMatchType matchType);

	/**
	 * 指定されたデータ項目群をこのクラスのデータ項目群へマージします。
	 * 
	 * @param items データ項目群情報
	 * @param matchType 日時の突合せ方法
	 * @param fillType 隙間調整の種類
	 * @param fill 隙間調整値
	 * @return このオブジェクトへの参照
	 * @throws IllegalArgumentException データ項目群または日時の突合せ方法に <code>null<code> が指定された場合
	 * @throws IllegalStateException 指定されたデータ項目群またはこのクラスから唯一の名前と日時データの関連付けを取得できなかった場合。
	 */
	public DatasetSource merge(DatasetSource items, MergeMatchType matchType, MergeGapFillType fillType, Number fill);

	/**
	 * このクラスのデータ項目群を指定された日時精度単位へ変換して返します。
	 * このクラスに有効な日時精度単位変換の種類が存在しない場合は何も行いません。
	 * 
	 * @param unit 変換する日時精度単位
	 * @return このオブジェクトへの参照
	 * @throws IllegalStateException このクラスから唯一の名前と日時データの関連付けを取得できなかった場合。
	 */
	public DatasetSource compress(int unit);

	/**
	 * このクラスのデータ項目群を指定された日時精度単位へ変換して返します。
	 * このクラスに有効な日時精度単位変換の種類が存在しない場合は何も行いません。
	 * 
	 * @param unit 変換する日時精度単位
	 * @param calendar 日時精度単位変換で日時の基準とするカレンダーオブジェクト
	 * @return このオブジェクトへの参照
	 * @throws IllegalStateException このクラスから唯一の名前と日時データの関連付けを取得できなかった場合。
	 */
	public DatasetSource compress(int unit, Calendar calendar);

	/**
	 * このクラスのデータ項目群を指定された日時精度単位へ変換して返します。
	 * このクラスに有効な日時精度単位変換の種類が存在しない場合は何も行いません。
	 * 
	 * @param unit 変換する日時精度単位
	 * @param calendar 日時精度単位変換で日時の基準とするカレンダーオブジェクト
	 * @param truncater 変換する日時精度単位へ日時の区切りを判断する基準
	 * @return このオブジェクトへの参照
	 * @throws IllegalStateException このクラスから唯一の名前と日時データの関連付けを取得できなかった場合。
	 */
	public DatasetSource compress(int unit, Calendar calendar, DateTruncater truncater);

	/**
	 * 指定された名前に関連付けられた数値データを株式分割データとして、指定された数値データ群の株式分割計算を行います。<p>
	 * 株式分割計算を行う数値データの名前群を省略した場合は、株式分割データ以外のすべての数値データを対象に株式分割計算を行います。
	 * 
	 * @param key 株式分割データの名前
	 * @param names 株式分割計算を行う数値データの名前群
	 * @return このオブジェクトへの参照
	 * @throws IllegalArgumentException 指定された株式分割データの名前が不正な場合
	 * @since 2.2
	 */
	public DatasetSource split(String key, String... names);

	/**
	 * 指定されたデータセットへデータを設定する {@link DatasetBuilder} の新しいインスタンスを作成します。
	 * 
	 * @param dataset データセット
	 * @return {@link DatasetBuilder} の新しいインスタンス
	 * @throws IllegalArgumentException データセットに <code>null</code> が指定された場合
	 */
	public <T> DatasetBuilder<T> bind(T dataset);

	/**
	 * 指定されたデータセットクラスの型でデータセットを構築する {@link DatasetBuilder} の新しいインスタンスを作成します。
	 * 
	 * @param datasetClass データセットクラスの型
	 * @return {@link DatasetBuilder} の新しいインスタンス
	 * @throws IllegalArgumentException データセットクラスの型に <code>null</code> が指定された場合
	 * @throws DatasetPreparationException 指定されたデータセットクラスをインスタンス化できない場合
	 * @throws SecurityException
	 */
	public <T> DatasetBuilder<T> build(Class<T> datasetClass);

}