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

import java.util.List;
import java.util.ArrayList;

/**
 * LineModelFilter は、フィルター条件をチェックして、LineModel のフィルタリング
 * を判定する実装クラスです。
 * フィルター条件 には、パッケージプライベートな、FilterOperation enum を
 * 指定します。
 *
 * 注意：このクラスは、同期処理されていません。
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class LineModelFilter {
	private final List<FilterOperation> opes = new ArrayList<FilterOperation>();
	private final List<String> clms = new ArrayList<String>();
	private final List<String> vals = new ArrayList<String>();
	private int[] clmNo = null;	// 最初の LineModel で構築します。
	private int   size  = 0;

	/**
	 * フィルター条件を指定します。
	 * オペレータには、FilterOperation enum を 使用してください。
	 * 指定できません。
	 *
	 * @param   ope フィルター条件のオペレーション(PREFIX, SUFFIX, INSTR, EQUALS, MATCH, UNMATCH)
	 * @param   clm 条件判定するカラム名
	 * @param   val 条件値
	 */
	public void add( final FilterOperation ope,final String clm,final String val ) {
	//	if( OPERATOR.indexOf( ope ) < 0 ) {
	//		String errMsg = "オペレータには、prefix,suffix,instr,equals,match,unmatch 以外は指定できません。" ;
	//		throw new RuntimeException( errMsg );
	//	}

		opes.add( ope );
		clms.add( clm );
		vals.add( val );
	}

	/**
	 * LineModelを指定して、条件にマッチするか、チェックします。
	 *
	 * @param	data	処理対象のLineModel
	 *
	 * @return  演算結果がすべて成立する場合:true/不成立:false
	 */
	public boolean filter( final LineModel data ) {
		if( clmNo == null ) {
			size  = clms.size();
			clmNo = new int[size];
			for( int i=0; i<size; i++ ) {
				clmNo[i] = data.getColumnNo( clms.get(i) );
			}
		}

		boolean exist = true;
		for( int i=0; i<size; i++ ) {
			Object value = data.getValue(clmNo[i]);
			if( value == null ) { exist = false; break; }

			FilterOperation ope = opes.get(i);
			String clmData = String.valueOf( value );
			String argment = vals.get(i);

			final boolean flag ;
			switch( ope ) {
				case PREFIX:	flag = clmData.startsWith( argment );	break;
				case SUFFIX:	flag = clmData.endsWith( argment );		break;
				case INSTR:		flag = clmData.contains( argment );		break;
				case EQUALS:	flag = clmData.equalsIgnoreCase( argment ); break;
				case MATCH:		flag = clmData.matches( argment );		break;
				case UNMATCH:	flag = ! clmData.matches( argment );	break;
				default :		flag = false;							break;
			}

			if( !flag ) { exist = false; break; }
		}
		return exist;
	}

	/**
	 * このオブジェクトの内部文字列表現を返します。
	 *
	 * オペレーション(カラム,値) の羅列 です。
	 *
	 * @return 内部文字列表現
	 */
	@Override
	public String toString() {
		int size = opes.size();
		StringBuilder rtn = new StringBuilder();
		for( int i=0; i<size; i++ ) {
			rtn.append( opes.get(i) ).append( '(' );
			rtn.append( clms.get(i) ).append( ',' );
			rtn.append( vals.get(i) ).append( ") + " );
		}
		return rtn.toString();
	}
}

/**
 * フィルター条件のオペレーションの列挙型です。
 * オペレータには、PREFIX, SUFFIX, INSTR, EQUALS, MATCH, UNMATCH を
 * 定義しています。
 */
enum FilterOperation {
	PREFIX, SUFFIX, INSTR, EQUALS, MATCH, UNMATCH
}
