package org.maachang.rimdb.index ;

import org.maachang.rimdb.util.NList;


/**
 * 行インデックス.
 * この情報は、32単位で行位置を区分けし、それに対して、
 * インデックス行の情報を格納している.
 * この情報の使い方として、Andでの絞り込みに対して、
 * 検索範囲が大なり、小なりなどの巨大な検索件数になる場合に
 * おいて、対象AND元の行数を元に、インデックス項番が一致する
 * 条件をAND対象にするための情報である.
 * 
 * @version 2014/07/02
 * @author  masahito suzuki
 * @since   rimdb-1.00
 */
public final class LineIndex {
    private final Object[] index ;
    
    /**
     * コンストラクタ.
     * @param line 対象の行情報を設定します.
     * @param max 全体長を設定します.
     */
    public LineIndex( final int[][] line,int max ) {
        int[] lm ;
        int i,j,lenJ,k ;
        NList list ;
        int len = line.length ;
        Object[] n = new Object[ ( max >> 5 ) + ( ( ( max & 31 ) != 0 ) ? 1 : 0 ) ] ;
        for( i = 0 ; i < len ; i ++ ) {
            lm = line[ i ] ;
            lenJ = lm.length ;
            for( j = 0 ; j < lenJ ; j ++ ) {
                if( ( list = (NList)n[ k = lm[ j ] >> 5 ] ) == null ) {
                    list = new NList() ;
                    n[ k ] = list ;
                }
                list.add( i ) ;
            }
        }
        len = n.length ;
        for( i = 0 ; i < len ; i ++ ) {
            list = (NList)n[ i ] ;
            list.sort() ;
            lenJ = list.size() ;
            n[ i ] = list.getArray() ;
        }
        this.index = n ;
    }
    
    /**
     * int配列で指定位置の条件を取得.
     * @param maskNo 行マスク項番を設定します.
     * @return int[] 数字条件が返却されます.
     */
    public final int[] getArray( final int maskNo ) {
        return (int[])index[ maskNo ] ;
    }
    
    /**
     * 指定条件のIndex項番を検索.
     * @param array getArrayで取得した内容を設定します.
     * @param no 対象のIndex項番を設定します.
     * @return int 検索項番が返却されます.
     *             -1の場合、存在しません.
     */
    public final int search( final int[] array,final int no ) {
        return IndexUtil.searchInt( array,no ) ;
    }
    
    /**
     * 大なり検索.
     * @param eq イコール条件を含める場合は設定します.
     * @param array getArrayで取得した内容を設定します.
     * @param no 対象のIndex項番を設定します.
     * @return int 検索項番が返却されます.
     *             -1の場合、存在しません.
     */
    public final int searchBig( final boolean eq,int[] array,final int no ) {
        if( eq ) {
            return IndexUtil.searchIntBS( true,array,no ) ;
        }
        else {
            int n = IndexUtil.searchIntBS( true,array,no ) ;
            if( n == no && (++n) >= array.length ) {
                return -1 ;
            }
            return n ;
        }
    }
    
    /**
     * 小なり検索.
     * @param eq 一致を許可する場合には[true]をセットします.
     * @param key 対象のキーを設定します.
     * @return int インデックス番号が返却されます.
     */
    public final int searchSmall( final boolean eq,int[] array,final int no ) {
        if( eq ) {
            return IndexUtil.searchIntBS( false,array,no ) ;
        }
        else {
            int n = IndexUtil.searchIntBS( false,array,no ) ;
            if( n == no && (--n) < 0 ) {
                return -1 ;
            }
            return n ;
        }
    }
    
}
