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

import org.opengion.fukurou.util.StringUtil;
import org.opengion.hayabusa.common.HybsSystem;
import org.opengion.hayabusa.common.HybsSystemException;
import org.opengion.hayabusa.db.DBTableModel;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;

import org.jfree.chart.LegendItemSource;
import org.jfree.data.jdbc.JDBCPieDataset;
import org.jfree.data.jdbc.JDBCXYDataset;
import org.jfree.data.general.Dataset;
import org.jfree.data.general.DefaultValueDataset;

import org.jfree.data.category.DefaultCategoryDataset;
// import org.jfree.data.xy.DefaultXYDataset;
import org.jfree.data.xy.CategoryTableXYDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.DefaultKeyedValues;


/**
 * <p>ChartFactory は、Dataset および、Renderer のオブジェクトを構築するファクトリクラスです。
 * JFreeChart では、各種オブジェクトの組み合わせで、色々なグラフを作成できます。
 * ここでは、簡易的にオブジェクトを構築できるように、一つのキーワードによって、各種作成する
 * オブジェクトのキーワードを関連付けておきます。
 *
 * <table>
 * <tr><th> チャートタイプ    </th><th> レンデラー(org.jfree.chart.renderer.) </th><th> Dataset  </th></tr>
 * <tr><td> HybsLine          </td><td> org.opengion.hayabusa.io.HybsLineRenderer  </td><td> Category </td></tr>
 * <tr><td> HybsBar           </td><td> org.opengion.hayabusa.io.HybsBarRenderer   </td><td> Category </td></tr>
 * <tr><td> HybsStackedBar    </td><td> org.opengion.hayabusa.io.HybsStackedBarRenderer  </td><td> Category </td></tr>
 * <tr><td> Area              </td><td> category.AreaRenderer                 </td><td> Category </td></tr>
 * <tr><td> Bar               </td><td> category.BarRenderer                  </td><td> Category </td></tr>
 * <tr><td> Bar3D             </td><td> category.BarRenderer3D                </td><td> Category </td></tr>
 * <tr><td> BoxAndWhisker     </td><td> category.BoxAndWhiskerRenderer        </td><td> Category </td></tr>
 * <tr><td> CategoryStep      </td><td> category.CategoryStepRenderer         </td><td> Category </td></tr>
 * <tr><td> Gantt             </td><td> category.GanttRenderer                </td><td> Category </td></tr>
 * <tr><td> GroupedStackedBar </td><td> category.GroupedStackedBarRenderer    </td><td> Category </td></tr>
 * <tr><td> IntervalBar       </td><td> category.IntervalBarRenderer          </td><td> Category </td></tr>
 * <tr><td> LayeredBar        </td><td> category.LayeredBarRenderer           </td><td> Category </td></tr>
 * <tr><td> Level             </td><td> category.LevelRenderer                </td><td> Category </td></tr>
 * <tr><td> LineAndShape      </td><td> category.LineAndShapeRenderer         </td><td> Category </td></tr>
 * <tr><td> Line3D            </td><td> category.LineRenderer3D               </td><td> Category </td></tr>
 * <tr><td> MinMax            </td><td> category.MinMaxCategoryRenderer       </td><td> Category </td></tr>
 * <tr><td> StackedArea       </td><td> category.StackedAreaRenderer          </td><td> Category </td></tr>
 * <tr><td> StackedBar        </td><td> category.StackedBarRenderer           </td><td> Category </td></tr>
 * <tr><td> StackedBar3D      </td><td> category.StackedBarRenderer3D         </td><td> Category </td></tr>
 * <tr><td> WaterfallBar      </td><td> category.WaterfallBarRenderer         </td><td> Category </td></tr>
 * <tr><td> CyclicXYItem      </td><td> xy.CyclicXYItemRenderer               </td><td> XY       </td></tr>
 * <tr><td> HighLow           </td><td> xy.HighLowRenderer                    </td><td> XY       </td></tr>
 * <tr><td> StackedXYArea     </td><td> xy.StackedXYAreaRenderer              </td><td> XY       </td></tr>
 * <tr><td> StackedXYArea2    </td><td> xy.StackedXYAreaRenderer2             </td><td> XY       </td></tr>
 * <tr><td> StandardXYItem    </td><td> xy.StandardXYItemRenderer             </td><td> XY       </td></tr>
 * <tr><td> XYArea            </td><td> xy.XYAreaRenderer                     </td><td> XY       </td></tr>
 * <tr><td> XYArea2           </td><td> xy.XYAreaRenderer2                    </td><td> XY       </td></tr>
 * <tr><td> XYBlock           </td><td> xy.XYBlockRenderer                    </td><td> XY       </td></tr>
 * <tr><td> XYBubble          </td><td> xy.XYBubbleRenderer                   </td><td> XY       </td></tr>
 * <tr><td> XYDifference      </td><td> xy.XYDifferenceRenderer               </td><td> XY       </td></tr>
 * <tr><td> XYDot             </td><td> xy.XYDotRenderer                      </td><td> XY       </td></tr>
 * <tr><td> XYError           </td><td> xy.XYErrorRenderer                    </td><td> XY       </td></tr>
 * <tr><td> XYLine3D          </td><td> xy.XYLine3DRenderer                   </td><td> XY       </td></tr>
 * <tr><td> XYLineAndShape    </td><td> xy.XYLineAndShapeRenderer             </td><td> XY       </td></tr>
 * <tr><td> XYStepArea        </td><td> xy.XYStepAreaRenderer                 </td><td> XY       </td></tr>
 * <tr><td> XYStep            </td><td> xy.XYStepRenderer                     </td><td> XY       </td></tr>
 * <tr><td> Meter             </td><td> null                                  </td><td> Value    </td></tr>
 * <tr><td> MultiplePie       </td><td> null                                  </td><td> Category </td></tr>
 * <tr><td> Pie               </td><td> null                                  </td><td> Pie      </td></tr>
 * <tr><td> Pie3D             </td><td> null                                  </td><td> Pie      </td></tr>
 * <tr><td> Ring              </td><td> null                                  </td><td> Pie      </td></tr>
 * <tr><td> SpiderWeb         </td><td> null                                  </td><td> Category </td></tr>
 * <tr><td> Thermometer       </td><td> null                                  </td><td> Value    </td></tr>
 * </table>
 *
 * @version  0.9.0	2007/06/21
 * @author	 Kazuhiko Hasegawa
 * @since	 JDK1.1,
 */
public class ChartFactory {

	private static final String PLOT_SUB = "org.opengion.hayabusa.io.ChartPlot_" ;

	private static volatile ChartPlot plot_cat = null ;
	private static volatile ChartPlot plot_xy  = null ;
	private static volatile ChartPlot plot_pie = null ;

	private static final Object lock = new Object();

	/**
	 * デフォルトコンストラクタを private 化しておきます。
	 *
	 */
	private ChartFactory() {}

	/**
	 * Connection と query 文字列から、Dataset オブジェクトを作成します。
	 *
	 * 引数のtypeは、内部定義の TYPE_RENDERER_MAP マップで関連付けられたキーワード
	 * より、対象とするチャート特性を取得します。(getTypeRenderer)
	 * その TypeRenderer#getDatasetType() メソッドの値を元に、Dataset クラスは、
	 * "org.jfree.data.jdbc.JDBCXXXXDataset" の XXXX の箇所を特定します。
	 * 現状は、Category , Pie , XY の３種類 ＋ Valueデータセットが選択されます。
	 *
	 * @og.rev 3.8.9.2 (2007/07/28) HybsJDBCCategoryDataset 追加
	 * @og.rev 5.3.0.0 (2010/12/01) その他のDataset 追加
	 *
	 * @param	conn Connection Dataset の取得先のコネクション
	 * @param	query  String 取得するクエリー文字列
	 * @param	type String Dataset オブジェクトの作成元を求めるキーワード
	 * @return Dataset オブジェクト
	 *
	 * @see     #getTypeRenderer( String )
	 * @see     #newDataset( DBTableModel ,String )
	 * @throws SQLException
	 */
	public static final Dataset newDataset( final Connection conn,final String query,final String type )
									throws SQLException {
		final Dataset dataset ;

		TypeRenderer rend = getTypeRenderer( type );

		String dsType = rend.getDatasetType();
		if( "Category".equalsIgnoreCase( dsType ) ) {
			dataset = new HybsJDBCCategoryDataset2( conn, query );		// series の横持ち
		}
		else if( "XY".equalsIgnoreCase( dsType ) ) {
			dataset = new JDBCXYDataset( conn, query );
		}
		else if( "Pie".equalsIgnoreCase( dsType ) ) {
			dataset = new JDBCPieDataset( conn, query );
		}
		else if( "Value".equalsIgnoreCase( dsType ) ) {
			dataset = new DefaultValueDataset();
		}
		// 5.3.0.0 (2010/12/01) その他のDataset 追加
		else if( "GanttCategory".equalsIgnoreCase( dsType ) ) {
			dataset = new HybsJDBCCategoryDataset2( conn, query );		// 代替
		}
		else if( "IntervalCategory".equalsIgnoreCase( dsType ) ) {
			dataset = new HybsJDBCCategoryDataset2( conn, query );		// 代替
		}
		else if( "StatisticalCategory".equalsIgnoreCase( dsType ) ) {
			dataset = new HybsJDBCCategoryDataset2( conn, query );		// 代替
		}
		else {
			String errMsg = "Category,Pie,XY,Value 以外のDataset はサポートしていません。[" + dsType + "]";
			throw new HybsSystemException( errMsg );
		}

		return dataset ;
	}

	/**
	 * DBTableModel オブジェクトから、Dataset オブジェクトを作成します。
	 *
	 * 引数のtypeは、内部定義の TYPE_RENDERER_MAP マップで関連付けられたキーワード
	 * より、対象とするチャート特性を取得します。(getTypeRenderer)
	 * その TypeRenderer#getDatasetType() メソッドの値を元に、Dataset クラスを作成します。
	 * 
	 * 現状は、Category , Pie , XY の３種類 ＋ Valueデータセットが選択されます。
	 *
	 * @og.rev 5.3.0.0 (2010/12/01) 新規追加
	 *
	 * @param	table DBTableModel Dataset の取得先のテーブルモデル
	 * @param	type String Dataset オブジェクトの作成元を求めるキーワード
	 * @return Dataset オブジェクト
	 *
	 * @see     #getTypeRenderer( String )
	 * @see     #newDataset( Connection ,String ,String )
	 */
	public static final Dataset newDataset( final DBTableModel table , final String type ) {
		final Dataset dataset ;

		TypeRenderer rend = getTypeRenderer( type );
		int clmNo = table.getColumnCount();
		int rowNo = table.getRowCount();

		String dsType = rend.getDatasetType();
		if( "Category".equalsIgnoreCase( dsType ) ) {
			// select key,val1,val2,val3 ･･･ from ･･･

			DefaultCategoryDataset cDataset = new DefaultCategoryDataset();		// series の横持ち
			String[] seri = table.getNames();		// ２番目(アドレス=1)から、データのシリーズ名称が始まる
			for( int row=0; row<rowNo; row++ ) {
				String   clmKey = table.getValue( row,0 );	// １番目(アドレス=0)はカラムの設定値
				String[] vals   = table.getValues( row );
				for( int clm=1; clm<clmNo; clm++ ) {		// ２番目(アドレス=1)からカラムデータを取得
					String sval = vals[clm];
					double val  = ( sval == null || sval.length() == 0 ) ? 0.0d : Double.parseDouble( sval ) ;
					cDataset.addValue( val , seri[clm] , clmKey );
				}
			}
			dataset = cDataset;
		}
		else if( "XY".equalsIgnoreCase( dsType ) ) {
			// select valx,valy from ･･･

			CategoryTableXYDataset xyDataset = new CategoryTableXYDataset() ;
			String[] seri = table.getNames();		// ２番目(アドレス=1)から、データのシリーズ名称が始まる
			for( int row=0; row<rowNo; row++ ) {
				String[] vals   = table.getValues( row );
				double rval = ( vals[0] == null || vals[0].length() == 0 ) ? 0.0d : Double.parseDouble( vals[0] );
				for( int clm=1; clm<clmNo; clm++ ) {		// ２番目(アドレス=1)からカラムデータを取得
					String sval = vals[clm];
					double val  = ( sval == null || sval.length() == 0 ) ? 0.0d : Double.parseDouble( sval ) ;
					xyDataset.add( rval,val,seri[clm] );
				}
			}

			dataset = xyDataset;
		}
		else if( "Pie".equalsIgnoreCase( dsType ) ) {
			// select key,val from ･･･

			DefaultKeyedValues keyVal = new DefaultKeyedValues();
			for( int row=0; row<rowNo; row++ ) {
				String[] vals   = table.getValues( row );

				String key  = vals[0];	// KEY項目
				String sval = vals[1];	// VALUE項目
				double val = ( sval == null || sval.length() == 0 ) ? 0.0d : Double.parseDouble( sval ) ;
				keyVal.addValue( key ,val );
			}
			dataset = new DefaultPieDataset( keyVal );
		}
		else if( "Value".equalsIgnoreCase( dsType ) ) {
			// Value は、オブジェクトを作成するだけ。値は、markValues を ChartDataset.java で設定
			dataset = new DefaultValueDataset();
		}
		// 5.3.0.0 (2010/12/01) その他のDataset 追加
	//	else if( "GanttCategory".equalsIgnoreCase( dsType ) ) {
	//		dataset = new TaskSeriesCollection();
	//	}
	//	else if( "IntervalCategory".equalsIgnoreCase( dsType ) ) {
	//		dataset = new DefaultIntervalCategoryDataset( String[] seriesNames, Number[][] starts, Number[][] ends) ;
	//	}
	//	else if( "StatisticalCategory".equalsIgnoreCase( dsType ) ) {
	//		dataset = new DefaultStatisticalCategoryDataset();
	//	}
	//	else if( "Wind".equalsIgnoreCase( dsType ) ) {
	//		dataset = new DefaultWindDataset(java.lang.String[] seriesNames, java.lang.Object[][][] data);
	//	}
	//	else if( "OHLC".equalsIgnoreCase( dsType ) ) {
	//		dataset = new DefaultOHLCDataset(java.lang.Comparable key, OHLCDataItem[] data);
	//	}
	//	else if( "BoxAndWhiskerXY".equalsIgnoreCase( dsType ) ) {
	//		dataset = new org.jfree.data.statistics.DefaultBoxAndWhiskerXYDataset(java.lang.Comparable seriesKey);
	//	}
//		else if( "WaferMap".equalsIgnoreCase( dsType ) ) {
//			dataset = new JDBCXYDataset( conn, query );
//		}
//		else if( "float2".equalsIgnoreCase( dsType ) ) {
//			float[][] を返すので、ここでは使えない。
//		}
		else {
			String errMsg = "Category,Pie,XY,Value 以外のDataset はサポートしていません。[" + dsType + "]";
			throw new HybsSystemException( errMsg );
		}

		return dataset ;
	}

	/**
	 * TypeRenderer オブジェクトを作成します。
	 *
	 * 引数のtypeは、内部定義の TYPE_RENDERER_MAP マップで関連付けられたキーワード
	 * より、対象とするチャート特性を取得します。
	 * typeは、org.jfree.chart.renderer.XXXX.YYYYRenderer のYYYY とほぼ一致します。
	 * TYPE_RENDERER_MAP マップには、XXXX.YYYYRenderer 部分が定義されています。
	 * XXXX は、category と xy が定義されており、それ以外のレンデラーは null に
	 * なっています。Pie 関係は、レンデラーではなく、Plot と対応します。
	 * ただし、個々に設定情報が異なる為、ChartPlot_Pie クラスで個別対応しています。
	 *
	 * @param	type String Renderer オブジェクトの作成元を求めるキーワード
	 * @return TypeRenderer オブジェクト
	 */
	public static final TypeRenderer getTypeRenderer( final String type ) {
		TypeRenderer rend = TYPE_RENDERER_MAP.get( type );

		if( rend == null ) {
			String errMsg = "指定のタイプに該当する Renderer はサポートしていません。[" + type + "]"
					+ HybsSystem.CR
					+ "Key=" + Arrays.toString( TYPE_RENDERER_MAP.keySet().toArray( new String[TYPE_RENDERER_MAP.size()] ) );
			throw new HybsSystemException( errMsg );
		}

		return rend ;
	}

	/**
	 * ChartPlot オブジェクトを作成します。
	 *
	 * ChartPlot オブジェクトは、ChartPlot インターフェースを継承した
	 * サブクラスで、"org.opengion.hayabusa.io.ChartPlot_XXXX になります。
	 * XXXX には、Category , Pie , XY が指定できます。
	 *
	 * @og.rev 4.0.0.0 (2007/11/29) ChartPlot のサブクラスを動的に作成、キャッシュします。
	 * @og.rev 5.3.0.0 (2010/12/01) xxxPlot対応
	 *
	 * @param	type String Renderer オブジェクトの作成元を求めるキーワード
	 * @return ChartPlot オブジェクト
	 */
	public static final ChartPlot newChartPlot( final String type ) {

		final ChartPlot plot ;

		TypeRenderer rend = TYPE_RENDERER_MAP.get( type );

//		String dsType = rend.getDatasetType();
		String pltType = rend.getPlotType();			// 5.3.0.0 (2010/12/01) xxxPlot対応
//		if( "Category".equalsIgnoreCase( dsType ) ) {
		if( "Category".equalsIgnoreCase( pltType ) ) {
			synchronized( lock ) {
				if( plot_cat == null ) {
//					plot_cat = (ChartPlot)StringUtil.newInstance( PLOT_SUB + dsType ) ;
					plot_cat = (ChartPlot)StringUtil.newInstance( PLOT_SUB + pltType ) ;
				}
			}
			plot = plot_cat;
		}
//		else if( "XY".equalsIgnoreCase( dsType ) ) {
		else if( "XY".equalsIgnoreCase( pltType ) ) {
			synchronized( lock ) {
				if( plot_xy == null ) {
//					plot_xy = (ChartPlot)StringUtil.newInstance( PLOT_SUB + dsType ) ;
					plot_xy = (ChartPlot)StringUtil.newInstance( PLOT_SUB + pltType ) ;
				}
			}
			plot = plot_xy;
		}
		else {
			synchronized( lock ) {
				if( plot_pie == null ) {
//					plot_pie = (ChartPlot)StringUtil.newInstance( PLOT_SUB + dsType ) ;
					plot_pie = (ChartPlot)StringUtil.newInstance( PLOT_SUB + "Pie" ) ;
				}
			}
			plot = plot_pie;
		}

		return plot ;
	}

	/**
	 * 引数タイプに応じたレンデラーやデータセットを規定します。
	 */
	private static final Map<String,TypeRenderer> TYPE_RENDERER_MAP = new HashMap<String,TypeRenderer>();

	// 4.1.1.0 (2008/02/04) HybsBar 追加
	// 5.3.0.0 (2010/12/01) xxxPlot 追加、データ内容修正、コメント部対応
	static {
		String[][] data = new String[][] {
			// キーワード						xxxRenderer										xxxDataset					xxxPlot
		    {  "HybsLine"					, "HybsLineRenderer"							, "Category"				, "Category"	}
		  , {  "HybsBar"					, "HybsBarRenderer"								, "Category"				, "Category"	}
		  , {  "HybsStackedBar"				, "HybsStackedBarRenderer"						, "Category"				, "Category"	}
		  , {  "Area"						, "category.AreaRenderer"						, "Category"				, "Category"	}
		  , {  "Bar"						, "category.BarRenderer"						, "Category"				, "Category"	}
		  , {  "Bar3D" 						, "category.BarRenderer3D"						, "Category"				, "Category"	}
	//	  , {  "BoxAndWhisker" 				, "category.BoxAndWhiskerRenderer"				, "BoxAndWhisker"			, "Category"	}
		  , {  "CategoryStep"				, "category.CategoryStepRenderer"				, "Category"				, "Category"	}
	//	  , {  "Gantt" 						, "category.GanttRenderer"						, "GanttCategory"			, "Category"	}
		  , {  "GroupedStackedBar" 			, "category.GroupedStackedBarRenderer"			, "Category"				, "Category"	}
	//	  , {  "IntervalBar"				, "category.IntervalBarRenderer"				, "IntervalCategory"		, "Category"	}
		  , {  "LayeredBar"					, "category.LayeredBarRenderer" 				, "Category"				, "Category"	}
		  , {  "Level" 						, "category.LevelRenderer"						, "Category"				, "Category"	}
		  , {  "LineAndShape"				, "category.LineAndShapeRenderer"				, "Category"				, "Category"	}
		  , {  "Line3D"						, "category.LineRenderer3D" 					, "Category"				, "Category"	}
		  , {  "MinMax"						, "category.MinMaxCategoryRenderer" 			, "Category"				, "Category"	}
		  , {  "StackedArea"				, "category.StackedAreaRenderer"				, "Category"				, "Category"	}
		  , {  "StackedBar"					, "category.StackedBarRenderer" 				, "Category"				, "Category"	}
		  , {  "StackedBar3D"				, "category.StackedBarRenderer3D"				, "Category"				, "Category"	}
	//	  , {  "StatisticalBar"				, "category.StatisticalBarRenderer" 			, "StatisticalCategory" 	, "Category"	}
		  , {  "StatisticalLineAndShape"	, "category.StatisticalLineAndShapeRenderer"	, "Category"				, "Category"	}
		  , {  "WaterfallBar"				, "category.WaterfallBarRenderer"				, "Category"				, "Category"	}
	//	  , {  "Candlestick"				, "xy.CandlestickRenderer"						, "OHLC" 					, "XY"			}
		  , {  "ClusteredXYBar"				, "xy.ClusteredXYBarRenderer"					, "XY"						, "XY"			}
		  , {  "CyclicXYItem"				, "xy.CyclicXYItemRenderer" 					, "XY"						, "XY"			}
		  , {  "Deviation" 					, "xy.DeviationRenderer"						, "XY"						, "XY"			}
	//	  , {  "HighLow"					, "xy.HighLowRenderer"							, "XY"						, "XY"			}
		  , {  "StackedXYArea" 				, "xy.StackedXYAreaRenderer"					, "XY"						, "XY"			}
		  , {  "StackedXYArea2"				, "xy.StackedXYAreaRenderer2"					, "XY"						, "XY"			}
		  , {  "StackedXYBar"				, "xy.StackedXYBarRenderer" 					, "XY"						, "XY"			}
		  , {  "StandardXYItem"				, "xy.StandardXYItemRenderer"					, "XY"						, "XY"			}
	//	  , {  "WindItem"					, "xy.WindItemRenderer" 						, "Wind" 					, "XY"			}
		  , {  "XYArea"						, "xy.XYAreaRenderer"							, "XY"						, "XY"			}
		  , {  "XYArea2"					, "xy.XYAreaRenderer2"							, "XY"						, "XY"			}
		  , {  "XYBar" 						, "xy.XYBarRenderer"							, "XY"						, "XY"			}
		  , {  "XYBlock"					, "xy.XYBlockRenderer"							, "XY"						, "XY"			}
	//	  , {  "XYBoxAndWhisker"			, "xy.XYBoxAndWhiskerRenderer"					, "BoxAndWhiskerXY" 		, "XY"			}
		  , {  "XYBubble"					, "xy.XYBubbleRenderer" 						, "XY"						, "XY"			}
		  , {  "XYDifference"				, "xy.XYDifferenceRenderer" 					, "XY"						, "XY"			}
		  , {  "XYDot" 						, "xy.XYDotRenderer"							, "XY"						, "XY"			}
		  , {  "XYError"					, "xy.XYErrorRenderer"							, "XY"						, "XY"			}
		  , {  "XYLine3D"					, "xy.XYLine3DRenderer" 						, "XY"						, "XY"			}
		  , {  "XYLineAndShape"				, "xy.XYLineAndShapeRenderer"					, "XY"						, "XY"			}
		  , {  "XYStepArea"					, "xy.XYStepAreaRenderer"						, "XY"						, "XY"			}
		  , {  "XYStep"						, "xy.XYStepRenderer"							, "XY"						, "XY"			}
		  , {  "YInterval" 					, "xy.YIntervalRenderer"						, "XY"						, "XY"			}
	//	  , {  "PolarItem" 					, "DefaultPolarItemRenderer"					, "XY"						, "Polar"		}
	//	  , {  "WaferMap"					, "WaferMapRenderer"							, "WaferMap"				, "WaferMap"	}
		  , {  "Compass"					,  null 										, "Value"					, "Compass"		}
// 廃止	  , {  "Contour"					,  null 										, "Contour"					, "Contour"		}
	//	  , {  "FastScatter"				,  null 										, "float2"					, "FastScatter"	}
		  , {  "Meter" 						,  null 										, "Value"					, "Meter"		}
		  , {  "MultiplePie"				,  null 										, "Category"				, "MultiplePie"	}
		  , {  "Pie"						,  null 										, "Pie"						, "Pie"	 		}
		  , {  "Pie3D" 						,  null 										, "Pie"						, "Pie"	 		}
		  , {  "Ring"						,  null 										, "Pie"						, "Ring"		}
		  , {  "SpiderWeb" 					,  null 										, "Category"				, "SpiderWeb"	}
		  , {  "Thermometer"				,  null 										, "Value"					, "Thermometer"	}
		};

		for( int i=0; i<data.length; i++ ) {
//			TYPE_RENDERER_MAP.put( data[i][0],new TypeRenderer( data[i][0],data[i][1],data[i][2] ) );
			TYPE_RENDERER_MAP.put( data[i][0],new TypeRenderer( data[i][0],data[i][1],data[i][2],data[i][3] ) );
		}
	}
}

/**
 * 引数タイプに応じたレンデラーやデータセットを管理します。
 *
 * タイプ、レンデラー、データセット の組み合わせで、構築するオブジェクトが異なります。
 */
final class TypeRenderer {
	private static final String REND_CLASS = "org.jfree.chart.renderer." ;
	private static final String HYBS_CLASS = "org.opengion.hayabusa.io." ;		// 4.1.1.0 (2008/02/04)

	private final String type ;
	private final String rend ;		// org.jfree.chart.renderer 以降の文字列
	private final String dtset ;	// org.opengion.hayabusa.io 以降の文字列
	private final String plot ;		// 以降の文字列

	/**
	 * TypeRenderer オブジェクトを作成します。
	 *
	 * チャートタイプ は、外部からチャートを指定するのに便利なように、キー化
	 * されています。このキーに基づいて、ChartFactory クラスの
	 * チャートタイプ変換表に基づいて、レンデラーや、データセットを作成します。
	 * このクラスは、これらの変換表の個々の属性を管理しています。
	 *
	 * @og.rev 5.3.0.0 (2010/12/01) plot 追加
	 *
	 * @param	type     String チャートのタイプを区別する文字列
	 * @param	renderer String チャートのタイプに応じたレンデラーのキー文字列
	 * @param	dtset    String チャートのタイプに応じたデータセットのキー文字列
	 * @param	plot     String チャートのタイプに応じたプロットのキー文字列
	 */
//	public TypeRenderer( final String type,final String renderer,final String dtset ) {
	public TypeRenderer( final String type,final String renderer,final String dtset,final String plot ) {
		this.type  = type ;
		this.rend  = renderer ;
		this.dtset = dtset ;
		this.plot  = plot ;			// 5.3.0.0 (2010/12/01) plot 追加
	}

	/**
	 * チャートのタイプを区別する文字列を返します。
	 *
	 * @return	String チャートのタイプを区別する文字列
	 */
	public String getType() { return type; }

	/**
	 * チャートのタイプに応じたレンデラーのキー文字列を返します。
	 *
	 * @return	String チャートのタイプに応じたレンデラーのキー文字列
	 */
	public String getRendererType() { return rend; }

	/**
	 * チャートのタイプに応じたレンデラーオブジェクトを返します。
	 *
	 * org.jfree.chart.renderer パッケージのサブモジュールのレンデラークラスを
	 * 先に登録してある レンデラーのキー文字列 と合成して、クラスを動的に作成します。
	 *
	 * @og.rev 4.1.1.0 (2008/02/04) Barチャート追加
	 * @og.rev 5.3.0.0 (2010/12/01) レンデラーが null の場合の対応
	 *
	 * @return	LegendItemSource チャートのタイプに応じたレンデラーオブジェクト(存在しない場合は、null)
	 */
	public LegendItemSource getRenderer() {
		if( rend == null ) { return null; }		// 5.3.0.0 (2010/12/01)

		String key ;
		if( type.startsWith( "Hybs" ) ) {
			key = HYBS_CLASS + rend ;
		}
		else {
			key = REND_CLASS + rend ;
		}

		return (LegendItemSource)StringUtil.newInstance( key ) ;
	}

	/**
	 * チャートのタイプに応じたデータセットのキー文字列を返します。
	 *
	 * @return	String チャートのタイプに応じたデータセットのキー文字列
	 */
	public String getDatasetType() { return dtset; }

	/**
	 * チャートのタイプに応じたプロットのキー文字列を返します。
	 *
	 * @og.rev 5.3.0.0 (2010/12/01) 新規追加
	 *
	 * @return	String チャートのタイプに応じたプロットのキー文字列
	 */
	public String getPlotType() { return plot; }
}
