/*
 * JBoss, Home of Professional Open Source.
 * See the COPYRIGHT.txt file distributed with this work for information
 * regarding copyright ownership.  Some portions may be licensed
 * to Red Hat, Inc. under one or more contributor license agreements.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 * Modified by
 * @author  Data Virtuality GmbH
 * @date    $Date$
 *  
 */

package org.teiid.common.buffer;

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


/**
 * Represents a set of indexed tuples.  The {@link #getBeginRow beginning row}
 * is the first row contained in this batch; if it equals "1" then it is the
 * first row of the tuple source, otherwise this is a batch of intermediate
 * tuples.  The {@link #getEndRow ending row} is the last row contained in 
 * this tuple batch; it is equal to the beginning row plus the 
 * {@link #getRowCount number of rows} contained in this batch, minus one.
 */
public class TupleBatch {
	
	// EXTENSION
	// ISSUE: DVCORE-2441
	// FIXED BY: Roman Pedchenko
	// DATE: 2014.10.23
	// ADOPTED FROM: https://issues.jboss.org/browse/TEIID-247, 2166, 2151, 2234, 2581, 2571, 2369, 1386, 2226, 2233, 2224, 2225, 2257
	// private static final long serialVersionUID = 6304443387337336957L;
	public static final byte NOT_TERMINATED = 0;
	public static final byte TERMINATED = 1;
	public static final byte ITERATION_TERMINATED = 2;
	// END EXTENSION
	
	private int rowOffset;    
    protected List<List<?>> tuples;
    
    // Optional state
    // EXTENSION
    // ISSUE: DVCORE-2441
    // FIXED BY: Roman Pedchenko
    // DATE: 2014.10.23
    // ADOPTED FROM: https://issues.jboss.org/browse/TEIID-247, 2166, 2151, 2234, 2581, 2571, 2369, 1386, 2226, 2233, 2224, 2225, 2257
    // private boolean terminationFlag = false;
    private byte terminationFlag = NOT_TERMINATED;
    // END EXTENSION
    
    /** Required to honor Externalizable contract */
    public TupleBatch() {
    }
    
    /**
     * Constructor
     * @param beginRow indicates the row of the tuple source which is the
     * first row contained in this batch
     * @param tuples array of List objects, each of which is
     * a single tuple
     */
    public TupleBatch(int beginRow, List<?>[] tuples) {
        this.rowOffset = beginRow;
        this.tuples = Arrays.asList(tuples);
    }

    /**
     * Constructor
     * @param beginRow indicates the row of the tuple source which is the
     * first row contained in this batch
     * @param listOfTupleLists List containing List objects, each of which is
     * a single tuple
     */
    // EXTENSION
    // ISSUE: DVCORE-2441
    // FIXED BY: Roman Pedchenko
    // DATE: 2014.10.23
    // ADOPTED FROM: https://issues.jboss.org/browse/TEIID-247, 2166, 2151, 2234, 2581, 2571, 2369, 1386, 2226, 2233, 2224, 2225, 2257
    // public TupleBatch(int beginRow, List listOfTupleLists) {
    public TupleBatch(int beginRow, List<? extends List<?>> listOfTupleLists) {
    // END EXTENSION
        this.rowOffset = beginRow;
        // EXTENSION
        // ISSUE: DVCORE-2441
        // FIXED BY: Roman Pedchenko
        // DATE: 2014.10.23
        // ADOPTED FROM: https://issues.jboss.org/browse/TEIID-247, 2166, 2151, 2234, 2581, 2571, 2369, 1386, 2226, 2233, 2224, 2225, 2257
        // this.tuples = new ArrayList(listOfTupleLists);
        this.tuples = new ArrayList<List<?>>(listOfTupleLists);
        // END EXTENSION
    }

    /**
     * Return the number of the first row of the tuple source that is
     * contained in this batch (one-based).
     * @return the first row contained in this tuple batch
     */
    public int getBeginRow() {
        return rowOffset;
    }
    
    /**
     * Return number of the last row of the tuple source that is contained in 
     * this batch (one-based).
     * @return the last row contained in this tuple batch
     */
    public int getEndRow() {
        return rowOffset + tuples.size() - 1;
    }
    
    /**
     * Return the number of rows contained in this tuple batch
     * @return the number of rows contained in this tuple batch
     */
    public int getRowCount() {
        return tuples.size();
    }
        
    /**
     * Return the tuple at the given index (one-based).
     * @return the tuple at the given index
     */
    // EXTENSION
    // ISSUE: DVCORE-2441
    // FIXED BY: Roman Pedchenko
    // DATE: 2014.10.23
    // ADOPTED FROM: https://issues.jboss.org/browse/TEIID-247, 2166, 2151, 2234, 2581, 2571, 2369, 1386, 2226, 2233, 2224, 2225, 2257
    // public List getTuple(int rowIndex) {
    public List<?> getTuple(int rowIndex) {
    // END EXTENSION
        int index = rowIndex-rowOffset;
        if (index < 0 || index >= tuples.size())
        	return null;
		return tuples.get(index);
    }
    
    public List<List<?>> getTuples() {
		return tuples;
	}
    
    /**
     * Get all tuples 
     * @return All tuples
     */
    // EXTENSION
    // ISSUE: DVCORE-2441
    // FIXED BY: Roman Pedchenko
    // DATE: 2014.10.23
    // ADOPTED FROM: https://issues.jboss.org/browse/TEIID-247, 2166, 2151, 2234, 2581, 2571, 2369, 1386, 2226, 2233, 2224, 2225, 2257
    // public List[] getAllTuples() { 
    public List<?>[] getAllTuples() { 
    // END EXTENSION
    	return tuples.toArray(new List[tuples.size()]);    
    }

    /**
     * Check whether this batch is the last in a series of batches.
     * @return True if this batch is last
     */
    public boolean getTerminationFlag() {
        // EXTENSION
        // ISSUE: DVCORE-2441
        // FIXED BY: Roman Pedchenko
        // DATE: 2014.10.23
        // ADOPTED FROM: https://issues.jboss.org/browse/TEIID-247, 2166, 2151, 2234, 2581, 2571, 2369, 1386, 2226, 2233, 2224, 2225, 2257
        // return this.terminationFlag;    
        return this.terminationFlag == TERMINATED;    
        // END EXTENSION
    }
    
    /**
     * Set whether this batch is the last in a series of batches.
     * @param terminationFlag True if last
     */
    public void setTerminationFlag(boolean terminationFlag) {
        // EXTENSION
        // ISSUE: DVCORE-2441
        // FIXED BY: Roman Pedchenko
        // DATE: 2014.10.23
        // ADOPTED FROM: https://issues.jboss.org/browse/TEIID-247, 2166, 2151, 2234, 2581, 2571, 2369, 1386, 2226, 2233, 2224, 2225, 2257
        // this.terminationFlag = terminationFlag;    
        this.terminationFlag = terminationFlag?TERMINATED:NOT_TERMINATED;    
        // END EXTENSION
    }
    
    // EXTENSION
    // ISSUE: DVCORE-2441
    // FIXED BY: Roman Pedchenko
    // DATE: 2014.10.23
    // ADOPTED FROM: https://issues.jboss.org/browse/TEIID-247, 2166, 2151, 2234, 2581, 2571, 2369, 1386, 2226, 2233, 2224, 2225, 2257
    public void setTermination(byte val) {
    	this.terminationFlag = val;
    }
    
    public byte getTermination() {
    	return this.terminationFlag;
    }
    
    // END EXTENSION
    public boolean containsRow(int row) {
    	return rowOffset <= row && getEndRow() >= row;
    }
    
    /**
     * Return a String describing this object
     * @param String representation of this TupleBatch
     */
    public String toString() {
        StringBuffer s = new StringBuffer();
        s.append("TupleBatch; beginning row="); //$NON-NLS-1$
        s.append(rowOffset);
        s.append(", number of rows="); //$NON-NLS-1$
        s.append(tuples.size());
        s.append(", lastBatch="); //$NON-NLS-1$
        s.append(this.terminationFlag);
        return s.toString();
    }

    public void setRowOffset(int rowOffset) {
		this.rowOffset = rowOffset;
	}
}

