package daruma.wfs.filter.predicates;

import daruma.wfs.filter.PredicateDescription;
import daruma.wfs.filter.predicates.IntegratedPredicateDescription;
import daruma.wfs.filter.predicates.PropertyComparationPredicateDescription;
import daruma.wfs.filter.predicates.ImmidiateValueBooleanDescription;
import daruma.wfs.filter.predicates.LogicalPredicateDescription;
import daruma.wfs.filter.predicates.GeometryPredicateDescription;

import daruma.geometry.TransformationContext;

import daruma.xml.util.XMLParseErrorException;

import org.w3c.dom.Element;
import org.w3c.dom.Node;

import daruma.storage_manager.StorageManager;
import daruma.storage_manager.type_definition.TypeDefinition;


//======================================================================
/**
 * Filter ノードの述語記述の統合クラス。
 */
public class IntegratedPredicateDescription extends PredicateDescription
{
    //--------------------------------------------------
    /**
     * 利用可能なタグかどうかをチェック
     */
    public static boolean isAcceptablePredicate( String  localName )
    {
	return
	    (PropertyComparationPredicateDescription
	     .isAcceptablePredicate( localName )
	     || GeometryPredicateDescription
	     .isAcceptablePredicate( localName )
	     || ImmidiateValueBooleanDescription
	     .isAcceptablePredicate( localName )
	     || LogicalPredicateDescription
	     .isAcceptablePredicate( localName ) );
    }

    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    /* メンバ変数
     */
    private String sqlExpression; /// 配下の filter の SQL 表現を格納 

    //--------------------------------------------------
    /**
     * コンストラクタ
     * 一気に SQL まで作ってしまう。（ちょっと違和感）
     */
    public IntegratedPredicateDescription( Element  element ,
					   TypeDefinition  type ,
					   TransformationContext  trans ,
					   StorageManager  storage )
	throws XMLParseErrorException
    {
	super( storage , type , trans );

	this.sqlExpression = this.createSQLExpression( element );
    }

    //--------------------------------------------------
    /**
     * SQL 表現を取得
     */
    public String getSQLExpression()
    {
	return( this.sqlExpression );
    }

    //--------------------------------------------------
    /**
     * SQL 表現を構築
     */
    public String createSQLExpression( Element  element )
	throws XMLParseErrorException
    {
	String	localName = element.getLocalName();

	PredicateDescription child = null ;

	if ( PropertyComparationPredicateDescription
	     .isAcceptablePredicate( localName ) )
	{
	    child = 
		new PropertyComparationPredicateDescription
		( element ,
		  super.getTypeDefinition() ,
		  super.getTransformationContext() ,
		  super.getStorage() ) ;
	}
	else if ( GeometryPredicateDescription
		  .isAcceptablePredicate( localName ) )
	{
	    child = 
		new GeometryPredicateDescription
		( element ,
		  super.getTypeDefinition() ,
		  super.getTransformationContext() ,
		  super.getStorage() ) ;
	}
	else if ( ImmidiateValueBooleanDescription
		  .isAcceptablePredicate( localName ) )
	{
	    child = 
		new ImmidiateValueBooleanDescription
		( element ,
		  super.getTypeDefinition() ,
		  super.getTransformationContext() ,
		  super.getStorage() ) ;
	}
	else if ( LogicalPredicateDescription
		  .isAcceptablePredicate( localName ) )
	{
	    child =
		new LogicalPredicateDescription
		( element ,
		  super.getTypeDefinition() ,
		  super.getTransformationContext() ,
		  super.getStorage() ) ;
	}
	else
	{
	    throw new XMLParseErrorException
		( "cannot handle filter \"" + localName + "\"" );
	}

	this.addChild(child) ;

	return child.getSQLExpression() ;

    }

    //--------------------------------------------------
    /**
     * 詳細チェック
     * 地理検索などのチェックを精密に行う、2nd pass の処理
     */
    public boolean detailedCheck(Node feature) 
    	throws XMLParseErrorException
    {
	if(this.numberOfChildren() > 0) {
	    return this.getChild(0).detailedCheck(feature) ;
	} else {
	    return true ;
	}
    }
}
