/*
 * Copyright (c) 2009 The openGion Project.
 *
 * 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 org.opengion.fukurou.util;

import java.util.Map;
// import java.util.WeakHashMap;
import java.util.Collections;							// 6.4.1.1 (2016/01/16)
import java.util.LinkedHashMap;							// 6.4.3.3 (2016/03/04)

/**
 * HybsLoaderを生成するためのファクトリクラスです。
 * HybsLoaderは、ソースディレクトリをキーとして、キャッシュされます。
 *
 * @og.rev 5.1.1.0 (2009/12/01) 新規作成
 * @og.rev 6.4.3.3 (2016/03/04) キャッシュを、WeakHashMapから、LinkedHashMap(固定容量) に変更します。
 * @og.group 業務ロジック
 *
 * @version 5.0
 * @author Hiroki Nakamura
 * @since JDK1.6,
 */
public final class HybsLoaderFactory {

//	/** 6.4.3.1 (2016/02/12) Collections.synchronizedMap で同期処理を行います。  */
//	private static final Map<String,HybsLoader> LOADER_MAP = Collections.synchronizedMap( new WeakHashMap<>() );		// 6.4.1.1 (2016/01/16) loaderMap → LOADER_MAP refactoring
//	private static final Map<String,HybsLoader> LOADER_MAP = Collections.synchronizedMap( new WeakHashMap<>() );		// 6.4.1.1 (2016/01/16) loaderMap → LOADER_MAP refactoring

	private static final int SIZE = 1000;		// 6.4.3.3 (2016/03/04) 固定容量の指定。

	/**
	 * LinkedHashMap は、反復順序を持つMapインタフェースで、データ件数を固定に設定します。
	 * ここでは、マップに新しいマッピングが追加されると、自動的に古いマッピングを削除するポリシーを
	 * 適用するために、removeEldestEntry(Map.Entry)メソッドをオーバーライドしています。 
	 * 古いマッピングの定義は、コンストラクタの、順序付けモードで指定でき、アクセス順ならtrue、挿入順ならfalse です。
	 * ここでは、固定の個数分だけ、キャッシュし、あふれた古い分は、順次キャッシュから追い出されていきます。
	 * Collections.synchronizedMap で、同期処理を行います。
	 */
	private static final Map<String,HybsLoader> LOADER_MAP = Collections.synchronizedMap( new LinkedHashMap<String,HybsLoader>( SIZE*2,0.75f,true ) {		// アクセス順
		private static final long serialVersionUID = 643320160304L ;
		/**
		 * このマップが一番古いエントリを削除するはずの場合にtrueを返します。
		 *
		 * @og.rev 6.4.3.3 (2016/03/04) キャッシュを、世代交代のWeakHashMapから、LinkedHashMap(固定容量) に変更します。
		 *
		 * @param	eldest	もっとも以前にマップに挿入されたエントリ
		 *
		 * @return	もっとも古いエントリをマップから削除すべき場合はtrue。そのエントリを保持すべき場合はfalse
		 */
		@Override
		protected boolean removeEldestEntry( final Map.Entry<String,HybsLoader> eldest ) {
			return size() > SIZE;
		}
	} );

	/**
	 * オブジェクトの生成を禁止します。
	 */
	private HybsLoaderFactory() {}

	/**
	 * HybsLoaderオブジェクトを取得します。
	 *
	 * @og.rev 6.4.3.1 (2016/02/12) Collections.synchronizedMap に置き換え。
	 * @og.rev 6.4.3.3 (2016/03/04) Map#computeIfAbsent で対応する。
	 *
	 * @param option HybsLoaderを生成するための設定情報
	 *
	 * @return HybsLoaderオブジェクト
	 */
	public static HybsLoader getLoader( final HybsLoaderConfig option ) {
		// Map#computeIfAbsent ： 戻り値は、既存の、または計算された値。追加有り、置換なし、削除なし
		return LOADER_MAP.computeIfAbsent( option.getSrcDir() , k -> new HybsLoader( option ) );

//		HybsLoader loader = null;
////		synchronized( HybsLoaderFactory.class ) {
//			loader = LOADER_MAP.get( option.getSrcDir() );
//			if( loader == null ) {
//				loader = new HybsLoader( option );
//			}
//			LOADER_MAP.put( option.getSrcDir(), loader );
////		}
//		return loader;
	}
}
