org.apache.poi.hssf.model.Workbook

public class Workbook implements Model
{
    private static final int   DEBUG       = POILogger.DEBUG;

    /**
     * constant used to set the "codepage" wherever "codepage" is set in records
     * (which is duplciated in more than one record)
     */

    private final static short CODEPAGE    = ( short ) 0x4b0;

    /**
     * this contains the Worksheet record objects
     */
    protected WorkbookRecordList        records     = new WorkbookRecordList();

    /**
     * this contains a reference to the SSTRecord so that new stings can be added
     * to it.
     */
    protected SSTRecord        sst         = null;

    /**
     * Holds the Extern Sheet with references to bound sheets
     */
    protected ExternSheetRecord externSheet= null;

    /**
     * holds the "boundsheet" records (aka bundlesheet) so that they can have their
     * reference to their "BOF" marker
     */
    protected ArrayList        boundsheets = new ArrayList();

    protected ArrayList        formats = new ArrayList();

    protected ArrayList        names = new ArrayList();

    private DrawingManager drawingManager;

    private static POILogger   log = POILogFactory.getLogger(Workbook.class);

    /**
     * Creates new Workbook with no intitialization --useless right now
     * @see #createWorkbook(List)
     */
    public Workbook() {
    }

    /**
     * read support  for low level
     * API.  Pass in an array of Record objects, A Workbook
     * object is constructed and passed back with all of its initialization set
     * to the passed in records and references to those records held. Unlike Sheet
     * workbook does not use an offset (its assumed to be 0) since its first in a file.
     * If you need an offset then construct a new array with a 0 offset or write your
     * own ;-p.
     *
     * @param recs an array of Record objects
     * @return Workbook object
     */
    public static Workbook createWorkbook(List recs) {
        if (log.check( POILogger.DEBUG ))
            log.log(DEBUG, "Workbook (readfile) created with reclen=",
                    new Integer(recs.size()));
        Workbook  retval  = new Workbook();
        ArrayList records = new ArrayList(recs.size() / 3);

        for (int k = 0; k < recs.size(); k++) {
            Record rec = ( Record ) recs.get(k);

            if (rec.getSid() == EOFRecord.sid) {
                records.add(rec);
                if (log.check( POILogger.DEBUG ))
                    log.log(DEBUG, "found workbook eof record at " + k);
                break;
            }
            switch (rec.getSid()) {

                case BoundSheetRecord.sid :
                    if (log.check( POILogger.DEBUG ))
                        log.log(DEBUG, "found boundsheet record at " + k);
                    retval.boundsheets.add(rec);
                    retval.records.setBspos( k );
                    break;

                case SSTRecord.sid :
                    if (log.check( POILogger.DEBUG ))
                        log.log(DEBUG, "found sst record at " + k);
                    retval.sst = ( SSTRecord ) rec;
                    break;

                case FontRecord.sid :
                    if (log.check( POILogger.DEBUG ))
                        log.log(DEBUG, "found font record at " + k);
                    retval.records.setFontpos( k );
                    retval.numfonts++;
                    break;

                case ExtendedFormatRecord.sid :
                    if (log.check( POILogger.DEBUG ))
                        log.log(DEBUG, "found XF record at " + k);
                    retval.records.setXfpos( k );
                    retval.numxfs++;
                    break;

                case TabIdRecord.sid :
                    if (log.check( POILogger.DEBUG ))
                        log.log(DEBUG, "found tabid record at " + k);
                    retval.records.setTabpos( k );
                    break;

                case ProtectRecord.sid :
                    if (log.check( POILogger.DEBUG ))
                        log.log(DEBUG, "found protect record at " + k);
                    retval.records.setProtpos( k );
                    break;

                case BackupRecord.sid :
                    if (log.check( POILogger.DEBUG ))
                        log.log(DEBUG, "found backup record at " + k);
                    retval.records.setBackuppos( k );
                    break;
                case ExternSheetRecord.sid :
                    if (log.check( POILogger.DEBUG ))
                        log.log(DEBUG, "found extern sheet record at " + k);
                    retval.externSheet = ( ExternSheetRecord ) rec;
                    break;
                case NameRecord.sid :
                    if (log.check( POILogger.DEBUG ))
                        log.log(DEBUG, "found name record at " + k);
                    retval.names.add(rec);
                    break;
                case SupBookRecord.sid :
                    if (log.check( POILogger.DEBUG ))
                        log.log(DEBUG, "found SupBook record at " + k);
                    break;
                case FormatRecord.sid :
                    if (log.check( POILogger.DEBUG ))
                        log.log(DEBUG, "found format record at " + k);
                    retval.formats.add(rec);
                    retval.maxformatid = retval.maxformatid >= ((FormatRecord)rec).getIndexCode() ? retval.maxformatid : ((FormatRecord)rec).getIndexCode();
                    break;
                case DateWindow1904Record.sid :
                    if (log.check( POILogger.DEBUG ))
                        log.log(DEBUG, "found datewindow1904 record at " + k);
                    retval.uses1904datewindowing = ((DateWindow1904Record)rec).getWindowing() == 1;
                    break;
                case PaletteRecord.sid:
                    if (log.check( POILogger.DEBUG ))
                        log.log(DEBUG, "found palette record at " + k);
                    retval.records.setPalettepos( k );
                default :
            }
            records.add(rec);
        }

        retval.records.setRecords(records);
        if (log.check( POILogger.DEBUG ))
            log.log(DEBUG, "exit create workbook from existing file function");
        return retval;
    }

    /**
     * Creates an empty workbook object with three blank sheets and all the empty
     * fields.  Use this to create a workbook from scratch.
     */
    public static Workbook createWorkbook()
    {
        if (log.check( POILogger.DEBUG ))
            log.log( DEBUG, "creating new workbook from scratch" );
        Workbook retval = new Workbook();
        ArrayList records = new ArrayList( 30 );
        ArrayList formats = new ArrayList( 8 );

        records.add( retval.createBOF() );
        records.add( retval.createInterfaceHdr() );
        records.add( retval.createMMS() );
        records.add( retval.createInterfaceEnd() );
        records.add( retval.createWriteAccess() );
        records.add( retval.createCodepage() );
        records.add( retval.createDSF() );
        records.add( retval.createTabId() );
        retval.records.setTabpos( records.size() - 1 );
        records.add( retval.createFnGroupCount() );
        records.add( retval.createWindowProtect() );
        records.add( retval.createProtect() );
        retval.records.setProtpos( records.size() - 1 );
        records.add( retval.createPassword() );
        records.add( retval.createProtectionRev4() );
        records.add( retval.createPasswordRev4() );
        records.add( retval.createWindowOne() );
        records.add( retval.createBackup() );
        retval.records.setBackuppos( records.size() - 1 );
        records.add( retval.createHideObj() );
        records.add( retval.createDateWindow1904() );
        records.add( retval.createPrecision() );
        records.add( retval.createRefreshAll() );
        records.add( retval.createBookBool() );
        records.add( retval.createFont() );
        records.add( retval.createFont() );
        records.add( retval.createFont() );
        records.add( retval.createFont() );
        retval.numfonts = 4;

        for ( int i = 0; i <= 7; i++ )
        {
            Record rec;
            rec = retval.createFormat( i );
            retval.maxformatid = retval.maxformatid >= ( (FormatRecord) rec ).getIndexCode() ? retval.maxformatid : ( (FormatRecord) rec ).getIndexCode();
            formats.add( rec );
            records.add( rec );
        }
        retval.formats = formats;

        for ( int k = 0; k < 21; k++ )
        {
            records.add( retval.createExtendedFormat( k ) );
            retval.numxfs++;
        }
        retval.records.setXfpos( records.size() - 1 );
        for ( int k = 0; k < 6; k++ )
        {
            records.add( retval.createStyle( k ) );
        }
        records.add( retval.createUseSelFS() );
        for ( int k = 0; k < 1; k++ ){
            BoundSheetRecord bsr =
                    (BoundSheetRecord) retval.createBoundSheet( k );

            records.add( bsr );
            retval.boundsheets.add( bsr );
            retval.records.setBspos( records.size() - 1 );
        }
        records.add( retval.createCountry() );
        retval.sst = (SSTRecord) retval.createSST();
        records.add( retval.sst );
        records.add( retval.createExtendedSST() );

        records.add( retval.createEOF() );
        retval.records.setRecords(records);
        if (log.check( POILogger.DEBUG ))
            log.log( DEBUG, "exit create new workbook from scratch" );
        return retval;
    }

	/**Retrieves the Builtin NameRecord that matches the name and index
	 * There shouldn't be too many names to make the sequential search too slow
	 * @param name byte representation of the builtin name to match
	 * @param sheetIndex Index to match
	 * @return null if no builtin NameRecord matches
	 */
	public NameRecord getSpecificBuiltinRecord(byte name, int sheetIndex)
	{
	    Iterator iterator = names.iterator();
	    while (iterator.hasNext()) {
	        NameRecord record = ( NameRecord ) iterator.next();

	        if (record.getBuiltInName() == name && record.getIndexToSheet() == sheetIndex) {
	            return record;
	        }
	    }

	    return null;

	}

	/**
	 * Removes the specified Builtin NameRecord that matches the name and index
	 * @param name byte representation of the builtin to match
	 * @param sheetIndex zero-based sheet reference
	 */
	public void removeBuiltinRecord(byte name, int sheetIndex) {
		NameRecord record = getSpecificBuiltinRecord(name, sheetIndex);
		if (record != null) {
			names.remove(record);
		}

	}

    public int getNumRecords() {
        return records.size();
    }

    /**
     * gets the font record at the given index in the font table.  Remember
     * "There is No Four" (someone at M$ must have gone to Rocky Horror one too
     * many times)
     *
     * @param idx the index to look at (0 or greater but NOT 4)
     * @return FontRecord located at the given index
     */

    public FontRecord getFontRecordAt(int idx) {
        int index = idx;

        if (index > 4) {
        }
        if (index > (numfonts - 1)) {
            throw new ArrayIndexOutOfBoundsException(
            "There are only " + numfonts
            + " font records, you asked for " + idx);
        }
        FontRecord retval =
        ( FontRecord ) records.get((records.getFontpos() - (numfonts - 1)) + index);

        return retval;
    }

    /**
     * creates a new font record and adds it to the "font table".  This causes the
     * boundsheets to move down one, extended formats to move down (so this function moves
     * those pointers as well)
     *
     * @return FontRecord that was just created
     */

    public FontRecord createNewFont() {
        FontRecord rec = ( FontRecord ) createFont();

        records.add(records.getFontpos()+1, rec);
        records.setFontpos( records.getFontpos() + 1 );
        numfonts++;
        return rec;
    }

    /**
     * gets the number of font records
     *
     * @return   number of font records in the "font table"
     */

    public int getNumberOfFontRecords() {
        return numfonts;
    }

    /**
     * Sets the BOF for a given sheet
     *
     * @param sheetnum the number of the sheet to set the positing of the bof for
     * @param pos the actual bof position
     */

    public void setSheetBof(int sheetnum, int pos) {
        if (log.check( POILogger.DEBUG ))
            log.log(DEBUG, "setting bof for sheetnum =", new Integer(sheetnum),
                " at pos=", new Integer(pos));
        checkSheets(sheetnum);
        (( BoundSheetRecord ) boundsheets.get(sheetnum))
        .setPositionOfBof(pos);
    }

    /**
     * Returns the position of the backup record.
     */

    public BackupRecord getBackupRecord() {
        return ( BackupRecord ) records.get(records.getBackuppos());
    }

    /**
     * sets the name for a given sheet.  If the boundsheet record doesn't exist and
     * its only one more than we have, go ahead and create it.  If its > 1 more than
     * we have, except
     *
     * @param sheetnum the sheet number (0 based)
     * @param sheetname the name for the sheet
     */

    public void setSheetName(int sheetnum, String sheetname ) {
        setSheetName( sheetnum, sheetname, (byte)0 );
    }

    public void setSheetName(int sheetnum, String sheetname, short encoding ) {
        checkSheets(sheetnum);
        BoundSheetRecord sheet = (BoundSheetRecord)boundsheets.get( sheetnum );
        sheet.setSheetname(sheetname);
        sheet.setSheetnameLength( (byte)sheetname.length() );
		sheet.setCompressedUnicodeFlag( (byte)encoding );
    }

    	/**
	 * sets the order of appearance for a given sheet.
	 *
	 * @param sheetname the name of the sheet to reorder
	 * @param pos the position that we want to insert the sheet into (0 based)
	 */

    public void setSheetOrder(String sheetname, int pos ) {
	int sheetNumber = getSheetIndex(sheetname);
	boundsheets.add(pos, boundsheets.remove(sheetNumber));
    }

    /**
     * gets the name for a given sheet.
     *
     * @param sheetnum the sheet number (0 based)
     * @return sheetname the name for the sheet
     */

    public String getSheetName(int sheetnum) {
        return (( BoundSheetRecord ) boundsheets.get(sheetnum))
        .getSheetname();
    }

    /**
     * get the sheet's index
     * @param name  sheet name
     * @return sheet index or -1 if it was not found.
     */

    public int getSheetIndex(String name) {
        int retval = -1;

        for (int k = 0; k < boundsheets.size(); k++) {
            String sheet = getSheetName(k);

            if (sheet.equalsIgnoreCase(name)) {
                retval = k;
                break;
            }
        }
        return retval;
    }

    /**
     * if we're trying to address one more sheet than we have, go ahead and add it!  if we're
     * trying to address >1 more than we have throw an exception!
     */

    private void checkSheets(int sheetnum) {
            if ((boundsheets.size() + 1) <= sheetnum) {
                throw new RuntimeException("Sheet number out of bounds!");
            }
            BoundSheetRecord bsr = (BoundSheetRecord ) createBoundSheet(sheetnum);

            records.add(records.getBspos()+1, bsr);
            records.setBspos( records.getBspos() + 1 );
            boundsheets.add(bsr);
            fixTabIdRecord();

    }

    public void removeSheet(int sheetnum) {
        if (boundsheets.size() > sheetnum) {
            records.remove(records.getBspos() - (boundsheets.size() - 1) + sheetnum);
            boundsheets.remove(sheetnum);
            fixTabIdRecord();
        }
    }

    /**
     * make the tabid record look like the current situation.
     *
     */
    private void fixTabIdRecord() {
        TabIdRecord tir = ( TabIdRecord ) records.get(records.getTabpos());
        short[]     tia = new short[ boundsheets.size() ];

        for (short k = 0; k < tia.length; k++) {
            tia[ k ] = k;
        }
        tir.setTabIdArray(tia);
    }

    /**
     * returns the number of boundsheet objects contained in this workbook.
     *
     * @return number of BoundSheet records
     */

    public int getNumSheets() {
        if (log.check( POILogger.DEBUG ))
            log.log(DEBUG, "getNumSheets=", new Integer(boundsheets.size()));
        return boundsheets.size();
    }

    /**
     * get the number of ExtendedFormat records contained in this workbook.
     *
     * @return int count of ExtendedFormat records
     */

    public int getNumExFormats() {
        if (log.check( POILogger.DEBUG ))
            log.log(DEBUG, "getXF=", new Integer(numxfs));
        return numxfs;
    }

    /**
     * gets the ExtendedFormatRecord at the given 0-based index
     *
     * @param index of the Extended format record (0-based)
     * @return ExtendedFormatRecord at the given index
     */

    public ExtendedFormatRecord getExFormatAt(int index) {
        int xfptr = records.getXfpos() - (numxfs - 1);

        xfptr += index;
        ExtendedFormatRecord retval =
        ( ExtendedFormatRecord ) records.get(xfptr);

        return retval;
    }

    /**
     * creates a new Cell-type Extneded Format Record and adds it to the end of
     *  ExtendedFormatRecords collection
     *
     * @return ExtendedFormatRecord that was created
     */

    public ExtendedFormatRecord createCellXF() {
        ExtendedFormatRecord xf = createExtendedFormat();

        records.add(records.getXfpos()+1, xf);
        records.setXfpos( records.getXfpos() + 1 );
        numxfs++;
        return xf;
    }

    /**
     * Adds a string to the SST table and returns its index (if its a duplicate
     * just returns its index and update the counts)
     *
     * @param string the string to be added to the SSTRecord
     * @param use16bits whether to use utf 16 or false for compressed unicode
     * @return index of the string within the SSTRecord
     */

    public int addSSTString(String string, boolean use16bits) {
        if (log.check( POILogger.DEBUG ))
            log.log(DEBUG, "insert to sst string='", string, "' and use16bits= ",
        new Boolean(use16bits));
        if (sst == null) {
            insertSST();
        }
        return sst.addString(string, use16bits);
    }

    /**
     * Adds a string to the SST table and returns its index (if its a duplicate
     * just returns its index and update the counts) ASSUMES compressed unicode
     * (meaning 8bit)
     *
     * @param string the string to be added to the SSTRecord
     *
     * @return index of the string within the SSTRecord
     */

    public int addSSTString(String string) {
        return addSSTString(string, false);
    }

    /**
     * given an index into the SST table, this function returns the corresponding String value
     * @return String containing the SST String
     */

    public String getSSTString(int str) {
        if (sst == null) {
            insertSST();
        }
        String retval = sst.getString(str);

        if (log.check( POILogger.DEBUG ))
            log.log(DEBUG, "Returning SST for index=", new Integer(str),
                " String= ", retval);
        return retval;
    }

    /**
     * use this function to add a Shared String Table to an existing sheet (say
     * generated by a different java api) without an sst....
     * @see #createSST()
     * @see org.apache.poi.hssf.record.SSTRecord
     */

    public void insertSST() {
        if (log.check( POILogger.DEBUG ))
            log.log(DEBUG, "creating new SST via insertSST!");
        sst = ( SSTRecord ) createSST();
        records.add(records.size() - 1, createExtendedSST());
        records.add(records.size() - 2, sst);
    }

    /**
     * Serializes all records int the worksheet section into a big byte array. Use
     * this to write the Workbook out.
     *
     * @return byte array containing the HSSF-only portions of the POIFS file.
     */

    /**
     * Serializes all records int the worksheet section into a big byte array. Use
     * this to write the Workbook out.
     * @param offset of the data to be written
     * @param data array of bytes to write this to
     */

    public int serialize( int offset, byte[] data )
    {
        if (log.check( POILogger.DEBUG ))
            log.log( DEBUG, "Serializing Workbook with offsets" );

        int pos = 0;

        SSTRecord sst = null;
        int sstPos = 0;
        for ( int k = 0; k < records.size(); k++ )
        {

            Record record = records.get( k );
            if ( record.getSid() != RecalcIdRecord.sid || ( (RecalcIdRecord) record ).isNeeded() )
            {
                if (record instanceof SSTRecord)
                {
                    sst = (SSTRecord)record;
                    sstPos = pos;
                }
                if (record.getSid() == ExtSSTRecord.sid && sst != null)
                {
                    record = sst.createExtSSTRecord(sstPos + offset);
                }
            }
        }
        if (log.check( POILogger.DEBUG ))
            log.log( DEBUG, "Exiting serialize workbook" );
        return pos;
    }

    public int getSize()
    {
        int retval = 0;

        SSTRecord sst = null;
        for ( int k = 0; k < records.size(); k++ )
        {
            Record record = records.get( k );
            if ( record.getSid() != RecalcIdRecord.sid || ( (RecalcIdRecord) record ).isNeeded() )
            {
                if (record instanceof SSTRecord)
                    sst = (SSTRecord)record;
                if (record.getSid() == ExtSSTRecord.sid && sst != null)
                    retval += sst.calcExtSSTRecordSize();
                else
                    retval += record.getRecordSize();
            }
        }
        return retval;
    }

    /**
     * creates the BOF record
     * @see org.apache.poi.hssf.record.BOFRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a BOFRecord
     */

    protected Record createBOF() {
        BOFRecord retval = new BOFRecord();

        retval.setVersion(( short ) 0x600);
        retval.setType(( short ) 5);
        retval.setBuild(( short ) 0x10d3);

        retval.setBuildYear(( short ) 1996);
        retval.setRequiredVersion(0x6);
        return retval;
    }

    /**
     * creates the InterfaceHdr record
     * @see org.apache.poi.hssf.record.InterfaceHdrRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a InterfaceHdrRecord
     */

    protected Record createInterfaceHdr() {
        InterfaceHdrRecord retval = new InterfaceHdrRecord();

        retval.setCodepage(CODEPAGE);
        return retval;
    }

    /**
     * creates an MMS record
     * @see org.apache.poi.hssf.record.MMSRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a MMSRecord
     */

    protected Record createMMS() {
        MMSRecord retval = new MMSRecord();

        retval.setAddMenuCount(( byte ) 0);
        retval.setDelMenuCount(( byte ) 0);
        return retval;
    }

    /**
     * creates the InterfaceEnd record
     * @see org.apache.poi.hssf.record.InterfaceEndRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a InterfaceEndRecord
     */

    protected Record createInterfaceEnd() {
        return new InterfaceEndRecord();
    }

    /**
     * creates the WriteAccess record containing the logged in user's name
     * @see org.apache.poi.hssf.record.WriteAccessRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a WriteAccessRecord
     */

    protected Record createWriteAccess() {
        WriteAccessRecord retval = new WriteAccessRecord();

        retval.setUsername(System.getProperty("user.name"));
        return retval;
    }

    /**
     * creates the Codepage record containing the constant stored in CODEPAGE
     * @see org.apache.poi.hssf.record.CodepageRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a CodepageRecord
     */

    protected Record createCodepage() {
        CodepageRecord retval = new CodepageRecord();

        retval.setCodepage(CODEPAGE);
        return retval;
    }

    /**
     * creates the DSF record containing a 0 since HSSF can't even create Dual Stream Files
     * @see org.apache.poi.hssf.record.DSFRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a DSFRecord
     */

    protected Record createDSF() {
        DSFRecord retval = new DSFRecord();

        retval.setDsf();
        return retval;
    }

    /**
     * creates the TabId record containing an array of 0,1,2.  This release of HSSF
     * always has the default three sheets, no less, no more.
     * @see org.apache.poi.hssf.record.TabIdRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a TabIdRecord
     */

    protected Record createTabId() {
        TabIdRecord retval     = new TabIdRecord();
        short[]     tabidarray = {
            0
        };

        retval.setTabIdArray(tabidarray);
        return retval;
    }

    /**
     * creates the FnGroupCount record containing the Magic number constant of 14.
     * @see org.apache.poi.hssf.record.FnGroupCountRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a FnGroupCountRecord
     */

    protected Record createFnGroupCount() {
        FnGroupCountRecord retval = new FnGroupCountRecord();

        retval.setCount(( short ) 14);
        return retval;
    }

    /**
     * creates the WindowProtect record with protect set to false.
     * @see org.apache.poi.hssf.record.WindowProtectRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a WindowProtectRecord
     */

    protected Record createWindowProtect() {
        WindowProtectRecord retval = new WindowProtectRecord();

        retval.setProtect();
    }

    /**
     * creates the Protect record with protect set to false.
     * @see org.apache.poi.hssf.record.ProtectRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a ProtectRecord
     */

    protected Record createProtect() {
        ProtectRecord retval = new ProtectRecord();

        retval.setProtect();
    }

    /**
     * creates the Password record with password set to 0.
     * @see org.apache.poi.hssf.record.PasswordRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a PasswordRecord
     */

    protected Record createPassword() {
        PasswordRecord retval = new PasswordRecord();

        return retval;
    }

    /**
     * creates the ProtectionRev4 record with protect set to false.
     * @see org.apache.poi.hssf.record.ProtectionRev4Record
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a ProtectionRev4Record
     */

    protected Record createProtectionRev4() {
        ProtectionRev4Record retval = new ProtectionRev4Record();

        retval.setProtect(false);
        return retval;
    }

    /**
     * creates the PasswordRev4 record with password set to 0.
     * @see org.apache.poi.hssf.record.PasswordRev4Record
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a PasswordRev4Record
     */

    protected Record createPasswordRev4() {
        PasswordRev4Record retval = new PasswordRev4Record();

        return retval;
    }

    /**
     * creates the WindowOne record with the following magic values: <P>
     * horizontal hold - 0x168 <P>
     * vertical hold   - 0x10e <P>
     * width           - 0x3a5c <P>
     * height          - 0x23be <P>
     * options         - 0x38 <P>
     * selected tab    - 0 <P>
     * displayed tab   - 0 <P>
     * num selected tab- 0 <P>
     * tab width ratio - 0x258 <P>
     * @see org.apache.poi.hssf.record.WindowOneRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a WindowOneRecord
     */

    protected Record createWindowOne() {
        WindowOneRecord retval = new WindowOneRecord();

        retval.setHorizontalHold(( short ) 0x168);
        retval.setVerticalHold(( short ) 0x10e);
        retval.setWidth(( short ) 0x3a5c);
        retval.setHeight(( short ) 0x23be);
        retval.setOptions(( short ) 0x38);
        retval.setSelectedTab(( short ) 0x0);
        retval.setDisplayedTab(( short ) 0x0);
        retval.setNumSelectedTabs(( short ) 1);
        retval.setTabWidthRatio(( short ) 0x258);
        return retval;
    }

    /**
     * creates the Backup record with backup set to 0. (loose the data, who cares)
     * @see org.apache.poi.hssf.record.BackupRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a BackupRecord
     */

    protected Record createBackup() {
        BackupRecord retval = new BackupRecord();

        retval.setBackup();
        return retval;
    }

    /**
     * creates the HideObj record with hide object set to 0. (don't hide)
     * @see org.apache.poi.hssf.record.HideObjRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a HideObjRecord
     */

    protected Record createHideObj() {
        HideObjRecord retval = new HideObjRecord();

        return retval;
    }

    /**
     * creates the DateWindow1904 record with windowing set to 0. (don't window)
     * @see org.apache.poi.hssf.record.DateWindow1904Record
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a DateWindow1904Record
     */

    protected Record createDateWindow1904() {
        DateWindow1904Record retval = new DateWindow1904Record();

        retval.setWindowing();
        return retval;
    }

    /**
     * creates the Precision record with precision set to true. (full precision)
     * @see org.apache.poi.hssf.record.PrecisionRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a PrecisionRecord
     */

    protected Record createPrecision() {
        PrecisionRecord retval = new PrecisionRecord();

        retval.setFullPrecision();
        return retval;
    }

    /**
     * creates the RefreshAll record with refreshAll set to true. (refresh all calcs)
     * @see org.apache.poi.hssf.record.RefreshAllRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a RefreshAllRecord
     */

    protected Record createRefreshAll() {
        RefreshAllRecord retval = new RefreshAllRecord();

        retval.setRefreshAll(false);
        return retval;
    }

    /**
     * creates the BookBool record with saveLinkValues set to 0. (don't save link values)
     * @see org.apache.poi.hssf.record.BookBoolRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a BookBoolRecord
     */

    protected Record createBookBool() {
        BookBoolRecord retval = new BookBoolRecord();

        retval.setSaveLinkValues(( short ) 0);
        return retval;
    }

    /**
     * creates a Font record with the following magic values: <P>
     * fontheight           = 0xc8<P>
     * attributes           = 0x0<P>
     * color palette index  = 0x7fff<P>
     * bold weight          = 0x190<P>
     * Font Name Length     = 5 <P>
     * Font Name            = Arial <P>
     *
     * @see org.apache.poi.hssf.record.FontRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a FontRecord
     */

    protected Record createFont() {
        FontRecord retval = new FontRecord();

        retval.setFontHeight(( short ) 0xc8);
        retval.setAttributes(( short ) 0x0);
        retval.setColorPaletteIndex(( short ) 0x7fff);
        retval.setBoldWeight(( short ) 0x190);
        retval.setFontNameLength(( byte ) 5);
        retval.setFontName("Arial");
        return retval;

    /**
     * Creates a FormatRecord object
     * @param id    the number of the format record to create (meaning its position in
     *        a file as M$ Excel would create it.)
     * @return record containing a FormatRecord
     * @see org.apache.poi.hssf.record.FormatRecord
     * @see org.apache.poi.hssf.record.Record
     */

        switch (id) {

            case 0 :
                retval.setIndexCode(( short ) 5);
                retval.setFormatStringLength(( byte ) 0x17);
                retval.setFormatString("\"$\"#,##0_);\\(\"$\"#,##0\\)");
                break;

            case 1 :
                retval.setIndexCode(( short ) 6);
                retval.setFormatStringLength(( byte ) 0x1c);
                retval.setFormatString("\"$\"#,##0_);[Red]\\(\"$\"#,##0\\)");
                break;

            case 2 :
                retval.setIndexCode(( short ) 7);
                retval.setFormatStringLength(( byte ) 0x1d);
                retval.setFormatString("\"$\"#,##0.00_);\\(\"$\"#,##0.00\\)");
                break;

            case 3 :
                retval.setIndexCode(( short ) 8);
                retval.setFormatStringLength(( byte ) 0x22);
                retval.setFormatString(
                "\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)");
                break;

            case 4 :
                retval.setIndexCode(( short ) 0x2a);
                retval.setFormatStringLength(( byte ) 0x32);
                retval.setFormatString(
                "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)");
                break;

            case 5 :
                retval.setIndexCode(( short ) 0x29);
                retval.setFormatStringLength(( byte ) 0x29);
                retval.setFormatString(
                "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)");
                break;

            case 6 :
                retval.setIndexCode(( short ) 0x2c);
                retval.setFormatStringLength(( byte ) 0x3a);
                retval.setFormatString(
                "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)");
                break;

            case 7 :
                retval.setIndexCode(( short ) 0x2b);
                retval.setFormatStringLength(( byte ) 0x31);
                retval.setFormatString(
                "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)");
                break;
        }
        return retval;

    /**
     * Creates an ExtendedFormatRecord object
     * @param id    the number of the extended format record to create (meaning its position in
     *        a file as MS Excel would create it.)
     *
     * @return record containing an ExtendedFormatRecord
     * @see org.apache.poi.hssf.record.ExtendedFormatRecord
     * @see org.apache.poi.hssf.record.Record
     */

        ExtendedFormatRecord retval = new ExtendedFormatRecord();

        switch (id) {

            case 0 :
                retval.setFontIndex(( short ) 0);
                retval.setFormatIndex(( short ) 0);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 1 :
                retval.setFontIndex(( short ) 1);
                retval.setFormatIndex(( short ) 0);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff400);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 2 :
                retval.setFontIndex(( short ) 1);
                retval.setFormatIndex(( short ) 0);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff400);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 3 :
                retval.setFontIndex(( short ) 2);
                retval.setFormatIndex(( short ) 0);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff400);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 4 :
                retval.setFontIndex(( short ) 2);
                retval.setFormatIndex(( short ) 0);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff400);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 5 :
                retval.setFontIndex(( short ) 0);
                retval.setFormatIndex(( short ) 0);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff400);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 6 :
                retval.setFontIndex(( short ) 0);
                retval.setFormatIndex(( short ) 0);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff400);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 7 :
                retval.setFontIndex(( short ) 0);
                retval.setFormatIndex(( short ) 0);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff400);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 8 :
                retval.setFontIndex(( short ) 0);
                retval.setFormatIndex(( short ) 0);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff400);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 9 :
                retval.setFontIndex(( short ) 0);
                retval.setFormatIndex(( short ) 0);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff400);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 10 :
                retval.setFontIndex(( short ) 0);
                retval.setFormatIndex(( short ) 0);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff400);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 11 :
                retval.setFontIndex(( short ) 0);
                retval.setFormatIndex(( short ) 0);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff400);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 12 :
                retval.setFontIndex(( short ) 0);
                retval.setFormatIndex(( short ) 0);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff400);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 13 :
                retval.setFontIndex(( short ) 0);
                retval.setFormatIndex(( short ) 0);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff400);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 14 :
                retval.setFontIndex(( short ) 0);
                retval.setFormatIndex(( short ) 0);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff400);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 15 :
                retval.setFontIndex(( short ) 0);
                retval.setFormatIndex(( short ) 0);
                retval.setCellOptions(( short ) 0x1);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0x0);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 16 :
                retval.setFontIndex(( short ) 1);
                retval.setFormatIndex(( short ) 0x2b);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff800);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 17 :
                retval.setFontIndex(( short ) 1);
                retval.setFormatIndex(( short ) 0x29);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff800);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 18 :
                retval.setFontIndex(( short ) 1);
                retval.setFormatIndex(( short ) 0x2c);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff800);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 19 :
                retval.setFontIndex(( short ) 1);
                retval.setFormatIndex(( short ) 0x2a);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff800);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 20 :
                retval.setFontIndex(( short ) 1);
                retval.setFormatIndex(( short ) 0x9);
                retval.setCellOptions(( short ) 0xfffffff5);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0xfffff800);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 21 :
                retval.setFontIndex(( short ) 5);
                retval.setFormatIndex(( short ) 0x0);
                retval.setCellOptions(( short ) 0x1);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0x800);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 22 :
                retval.setFontIndex(( short ) 6);
                retval.setFormatIndex(( short ) 0x0);
                retval.setCellOptions(( short ) 0x1);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0x5c00);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 23 :
                retval.setFontIndex(( short ) 0);
                retval.setFormatIndex(( short ) 0x31);
                retval.setCellOptions(( short ) 0x1);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0x5c00);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 24 :
                retval.setFontIndex(( short ) 0);
                retval.setFormatIndex(( short ) 0x8);
                retval.setCellOptions(( short ) 0x1);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0x5c00);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;

            case 25 :
                retval.setFontIndex(( short ) 6);
                retval.setFormatIndex(( short ) 0x8);
                retval.setCellOptions(( short ) 0x1);
                retval.setAlignmentOptions(( short ) 0x20);
                retval.setIndentionOptions(( short ) 0x5c00);
                retval.setBorderOptions(( short ) 0);
                retval.setPaletteOptions(( short ) 0);
                retval.setAdtlPaletteOptions(( short ) 0);
                retval.setFillPaletteOptions(( short ) 0x20c0);
                break;
        }
        return retval;
    }

    /**
     * creates an default cell type ExtendedFormatRecord object.
     * @return ExtendedFormatRecord with intial defaults (cell-type)
     */

    protected ExtendedFormatRecord createExtendedFormat() {
        ExtendedFormatRecord retval = new ExtendedFormatRecord();

        retval.setFontIndex(( short ) 0);
        retval.setFormatIndex(( short ) 0x0);
        retval.setCellOptions(( short ) 0x1);
        retval.setAlignmentOptions(( short ) 0x20);
        retval.setIndentionOptions(( short ) 0);
        retval.setBorderOptions(( short ) 0);
        retval.setPaletteOptions(( short ) 0);
        retval.setAdtlPaletteOptions(( short ) 0);
        retval.setFillPaletteOptions(( short ) 0x20c0);
        retval.setTopBorderPaletteIdx(HSSFColor.BLACK.index);
        retval.setBottomBorderPaletteIdx(HSSFColor.BLACK.index);
        retval.setLeftBorderPaletteIdx(HSSFColor.BLACK.index);
        retval.setRightBorderPaletteIdx(HSSFColor.BLACK.index);
        return retval;

    /**
     * Creates a StyleRecord object
     * @param id        the number of the style record to create (meaning its position in
     *                  a file as MS Excel would create it.
     * @return record containing a StyleRecord
     * @see org.apache.poi.hssf.record.StyleRecord
     * @see org.apache.poi.hssf.record.Record
     */

        StyleRecord retval = new StyleRecord();

        switch (id) {

            case 0 :
                retval.setIndex(( short ) 0xffff8010);
                retval.setBuiltin(( byte ) 3);
                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
                break;

            case 1 :
                retval.setIndex(( short ) 0xffff8011);
                retval.setBuiltin(( byte ) 6);
                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
                break;

            case 2 :
                retval.setIndex(( short ) 0xffff8012);
                retval.setBuiltin(( byte ) 4);
                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
                break;

            case 3 :
                retval.setIndex(( short ) 0xffff8013);
                retval.setBuiltin(( byte ) 7);
                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
                break;

            case 4 :
                retval.setIndex(( short ) 0xffff8000);
                retval.setBuiltin(( byte ) 0);
                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
                break;

            case 5 :
                retval.setIndex(( short ) 0xffff8014);
                retval.setBuiltin(( byte ) 5);
                retval.setOutlineStyleLevel(( byte ) 0xffffffff);
                break;
        }
        return retval;
    }

    /**
     * Creates a palette record initialized to the default palette
     * @return a PaletteRecord instance populated with the default colors
     * @see org.apache.poi.hssf.record.PaletteRecord
     */
    protected PaletteRecord createPalette()
    {
        return new PaletteRecord(PaletteRecord.sid);
    }

    /**
     * Creates the UseSelFS object with the use natural language flag set to 0 (false)
     * @return record containing a UseSelFSRecord
     * @see org.apache.poi.hssf.record.UseSelFSRecord
     * @see org.apache.poi.hssf.record.Record
     */

    protected Record createUseSelFS() {
        UseSelFSRecord retval = new UseSelFSRecord();

        retval.setFlag(( short ) 0);
        return retval;

    /**
     * create a "bound sheet" or "bundlesheet" (depending who you ask) record
     * Always sets the sheet's bof to 0.  You'll need to set that yourself.
     * @param id either sheet 0,1 or 2.
     * @return record containing a BoundSheetRecord
     * @see org.apache.poi.hssf.record.BoundSheetRecord
     * @see org.apache.poi.hssf.record.Record
     */

        BoundSheetRecord retval = new BoundSheetRecord();

        switch (id) {

            case 0 :
                retval.setOptionFlags(( short ) 0);
                retval.setSheetnameLength(( byte ) 0x6);
                retval.setCompressedUnicodeFlag(( byte ) 0);
                retval.setSheetname("Sheet1");
                break;

            case 1 :
                retval.setOptionFlags(( short ) 0);
                retval.setSheetnameLength(( byte ) 0x6);
                retval.setCompressedUnicodeFlag(( byte ) 0);
                retval.setSheetname("Sheet2");
                break;

            case 2 :
                retval.setOptionFlags(( short ) 0);
                retval.setSheetnameLength(( byte ) 0x6);
                retval.setCompressedUnicodeFlag(( byte ) 0);
                retval.setSheetname("Sheet3");
                break;
        }
        return retval;

    /**
     * Creates the Country record with the default country set to 1
     * and current country set to 7 in case of russian locale ("ru_RU") and 1 otherwise
     * @return record containing a CountryRecord
     * @see org.apache.poi.hssf.record.CountryRecord
     * @see org.apache.poi.hssf.record.Record
     */

        CountryRecord retval = new CountryRecord();

        retval.setDefaultCountry(( short ) 1);

        if ( Locale.getDefault().toString().equals( "ru_RU" ) ) {
	        retval.setCurrentCountry(( short ) 7);
        }
        else {
	        retval.setCurrentCountry(( short ) 1);
        }

        return retval;
    }

    /**
     * Creates the SST record with no strings and the unique/num string set to 0
     * @return record containing a SSTRecord
     * @see org.apache.poi.hssf.record.SSTRecord
     * @see org.apache.poi.hssf.record.Record
     */

    protected Record createSST() {
        return new SSTRecord();
    }

    /**
     * Creates the ExtendedSST record with numstrings per bucket set to 0x8.  HSSF
     * doesn't yet know what to do with this thing, but we create it with nothing in
     * it hardly just to make Excel happy and our sheets look like Excel's
     *
     * @return record containing an ExtSSTRecord
     * @see org.apache.poi.hssf.record.ExtSSTRecord
     * @see org.apache.poi.hssf.record.Record
     */

    protected Record createExtendedSST() {
        ExtSSTRecord retval = new ExtSSTRecord();

        retval.setNumStringsPerBucket(( short ) 0x8);
        return retval;
    }

    /**
     * creates the EOF record
     * @see org.apache.poi.hssf.record.EOFRecord
     * @see org.apache.poi.hssf.record.Record
     * @return record containing a EOFRecord
     */

    protected Record createEOF() {
        return new EOFRecord();
    }

    public SheetReferences getSheetReferences() {
        SheetReferences refs = new SheetReferences();

        if (externSheet != null) {
            for (int k = 0; k < externSheet.getNumOfREFStructures(); k++) {

                String sheetName = findSheetNameFromExternSheet((short)k);
                refs.addSheetReference(sheetName, k);

            }
        }
        return refs;
    }

    /** finds the sheet name by his extern sheet index
     * @param num extern sheet index
     * @return sheet name
     */
    public String findSheetNameFromExternSheet(short num){
        String result="";

        short indexToSheet = externSheet.getREFRecordAt(num).getIndexToFirstSupBook();
            result = getSheetName(indexToSheet);

        return result;
    }

    /**
     * Finds the sheet index for a particular external sheet number.
     * @param externSheetNumber     The external sheet number to convert
     * @return  The index to the sheet found.
     */
    public int getSheetIndexFromExternSheetIndex(int externSheetNumber)
    {
        if (externSheetNumber >= externSheet.getNumOfREFStructures())
            return -1;
        else
            return externSheet.getREFRecordAt(externSheetNumber).getIndexToFirstSupBook();
    }

    /** returns the extern sheet number for specific sheet number ,
     *  if this sheet doesn't exist in extern sheet , add it
     * @param sheetNumber sheet number
     * @return index to extern sheet
     */
    public short checkExternSheet(int sheetNumber){

        int i = 0;
        boolean flag = false;
        short result = 0;

        if (externSheet == null) {
            externSheet = createExternSheet();
        }

        while (i < externSheet.getNumOfREFStructures() && !flag){
            ExternSheetSubRecord record = externSheet.getREFRecordAt(i);

            if (record.getIndexToFirstSupBook() ==  sheetNumber &&
            record.getIndexToLastSupBook() == sheetNumber){
                flag = true;
                result = (short) i;
            }

            ++i;
        }

        if (!flag) {
            result = addSheetIndexToExternSheet((short) sheetNumber);
        }

        return result;
    }

    private short addSheetIndexToExternSheet(short sheetNumber){
        short result;

        ExternSheetSubRecord record = new ExternSheetSubRecord();
        record.setIndexToFirstSupBook(sheetNumber);
        record.setIndexToLastSupBook(sheetNumber);
        externSheet.addREFRecord(record);
        externSheet.setNumOfREFStructures((short)(externSheet.getNumOfREFStructures() + 1));
        result = (short)(externSheet.getNumOfREFStructures() - 1);

        return result;
    }

    /** gets the total number of names
     * @return number of names
     */
    public int getNumNames(){
        int result = names.size();

        return result;
    }

    /** gets the name record
     * @param index name index
     * @return name record
     */
    public NameRecord getNameRecord(int index){
        NameRecord result = (NameRecord) names.get(index);

        return result;

    }

    /** creates new name
     * @return new name record
     */
    public NameRecord createName(){

        NameRecord name = new NameRecord();

        int idx = findFirstRecordLocBySid(ExternSheetRecord.sid);
        if (idx == -1) idx = findFirstRecordLocBySid(SupBookRecord.sid);
        if (idx == -1) idx = findFirstRecordLocBySid(CountryRecord.sid);

        records.add(idx+names.size()+1, name);
        names.add(name);

        return name;
    }

    /** creates new name
     * @return new name record
     */
    public NameRecord addName(NameRecord name)
    {
        int idx = findFirstRecordLocBySid(ExternSheetRecord.sid);
        if (idx == -1) idx = findFirstRecordLocBySid(SupBookRecord.sid);
        if (idx == -1) idx = findFirstRecordLocBySid(CountryRecord.sid);
        records.add(idx+names.size()+1, name);
        names.add(name);

        return name;
    }

	/**Generates a NameRecord to represent a built-in region
	 * @return a new NameRecord unless the index is invalid
	 */
	public NameRecord createBuiltInName(byte builtInName, int index)
	{
		if (index == -1 || index+1 > (int)Short.MAX_VALUE)
			throw new IllegalArgumentException("Index is not valid ["+index+"]");

		NameRecord name = new NameRecord(builtInName, (short)(index));

		addName(name);

		return name;
	}

    /** removes the name
     * @param namenum name index
     */
    public void removeName(int namenum){
        if (names.size() > namenum) {
            int idx = findFirstRecordLocBySid(NameRecord.sid);
            records.remove(idx + namenum);
            names.remove(namenum);
        }

    }

    /** creates a new extern sheet record
     * @return the new extern sheet record
     */
    protected ExternSheetRecord createExternSheet(){
        ExternSheetRecord externSheet = new ExternSheetRecord();

        int idx = findFirstRecordLocBySid(CountryRecord.sid);

        records.add(idx+1, externSheet);

        SupBookRecord supbook = new SupBookRecord();

        supbook.setNumberOfSheets((short)getNumSheets());

        records.add(idx+1, supbook);

        return externSheet;
    }

    /**
     * Returns a format index that matches the passed in format.  It does not tie into HSSFDataFormat.
     * @param format the format string
     * @param createIfNotFound creates a new format if format not found
     * @return the format id of a format that matches or -1 if none found and createIfNotFound
     */
    public short getFormat(String format, boolean createIfNotFound) {
	Iterator iterator;
	for (iterator = formats.iterator(); iterator.hasNext();) {
	    FormatRecord r = (FormatRecord)iterator.next();
	    if (r.getFormatString().equals(format)) {
		return r.getIndexCode();
	    }
	}

	if (createIfNotFound) {
	    return createFormat(format);
	}

	return -1;
    }

    /**
     * Returns the list of FormatRecords in the workbook.
     * @return ArrayList of FormatRecords in the notebook
     */
    public ArrayList getFormats() {
	return formats;
    }

    /**
     * Creates a FormatRecord, inserts it, and returns the index code.
     * @param format the format string
     * @return the index code of the format record.
     * @see org.apache.poi.hssf.record.FormatRecord
     * @see org.apache.poi.hssf.record.Record
     */
    public short createFormat( String format )
    {
        FormatRecord rec = new FormatRecord();
        rec.setIndexCode( maxformatid );
        rec.setFormatStringLength( (byte) format.length() );
        rec.setFormatString( format );

        int pos = 0;
        while ( pos < records.size() && records.get( pos ).getSid() != FormatRecord.sid )
            pos++;
        pos += formats.size();
        formats.add( rec );
        records.add( pos, rec );
        return maxformatid;
    }

    /**
     * Returns the first occurance of a record matching a particular sid.
     */
    public Record findFirstRecordBySid(short sid) {
        for (Iterator iterator = records.iterator(); iterator.hasNext(); ) {
            Record record = ( Record ) iterator.next();

            if (record.getSid() == sid) {
                return record;
            }
        }
        return null;
    }

    /**
     * Returns the index of a record matching a particular sid.
     * @param sid   The sid of the record to match
     * @return      The index of -1 if no match made.
     */
    public int findFirstRecordLocBySid(short sid) {
        int index = 0;
        for (Iterator iterator = records.iterator(); iterator.hasNext(); ) {
            Record record = ( Record ) iterator.next();

            if (record.getSid() == sid) {
                return index;
            }
            index ++;
        }
        return -1;
    }

    /**
     * Returns the next occurance of a record matching a particular sid.
     */
    public Record findNextRecordBySid(short sid, int pos) {
        int matches = 0;
        for (Iterator iterator = records.iterator(); iterator.hasNext(); ) {
            Record record = ( Record ) iterator.next();

            if (record.getSid() == sid) {
                if (matches++ == pos)
                    return record;
            }
        }
        return null;
    }

    public List getRecords()
    {
        return records.getRecords();
    }

    /**
    * Whether date windowing is based on 1/2/1904 or 1/1/1900.
    * Some versions of Excel (Mac) can save workbooks using 1904 date windowing.
    *
    * @return true if using 1904 date windowing
    */
    public boolean isUsing1904DateWindowing() {
        return uses1904datewindowing;
    }

    /**
     * Returns the custom palette in use for this workbook; if a custom palette record
     * does not exist, then it is created.
     */
    public PaletteRecord getCustomPalette()
    {
      PaletteRecord palette;
      int palettePos = records.getPalettepos();
      if (palettePos != -1) {
        Record rec = records.get(palettePos);
        if (rec instanceof PaletteRecord) {
          palette = (PaletteRecord) rec;
        } else throw new RuntimeException("InternalError: Expected PaletteRecord but got a '"+rec+"'");
      }
      else
      {
          palette = createPalette();
          records.add(1, palette);
          records.setPalettepos(1);
      }
      return palette;
    }

    /**
     * Creates a drawing group record.  If it already exists then it's left
     * alone.
     */
    public void createDrawingGroup()
    {
        int dggLoc = findFirstRecordLocBySid(EscherContainerRecord.DGG_CONTAINER);
        if (dggLoc == -1)
        {
            EscherContainerRecord dggContainer = new EscherContainerRecord();
            EscherDggRecord dgg = new EscherDggRecord();
            EscherOptRecord opt = new EscherOptRecord();
            EscherSplitMenuColorsRecord splitMenuColors = new EscherSplitMenuColorsRecord();

            dggContainer.setRecordId((short) 0xF000);
            dggContainer.setOptions((short) 0x000F);
            dgg.setRecordId(EscherDggRecord.RECORD_ID);
            dgg.setOptions((short)0x0000);
            dgg.setShapeIdMax(1024);
            dgg.setNumShapesSaved(0);
            dgg.setDrawingsSaved(0);
            dgg.setFileIdClusters(new EscherDggRecord.FileIdCluster[] {} );
            drawingManager = new DrawingManager(dgg);
            opt.setRecordId((short) 0xF00B);
            opt.setOptions((short) 0x0033);
            opt.addEscherProperty( new EscherBoolProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 524296) );
            opt.addEscherProperty( new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, 134217737) );
            opt.addEscherProperty( new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, 134217792) );
            splitMenuColors.setRecordId((short) 0xF11E);
            splitMenuColors.setOptions((short) 0x0040);
            splitMenuColors.setColor1(0x0800000D);
            splitMenuColors.setColor2(0x0800000C);
            splitMenuColors.setColor3(0x08000017);
            splitMenuColors.setColor4(0x100000F7);

            dggContainer.addChildRecord(dgg);
            dggContainer.addChildRecord(opt);
            dggContainer.addChildRecord(splitMenuColors);

            DrawingGroupRecord drawingGroup = new DrawingGroupRecord();
            drawingGroup.addEscherRecord(dggContainer);
            int loc = findFirstRecordLocBySid(CountryRecord.sid);
            getRecords().add(loc+1, drawingGroup);
        }
    }

    public DrawingManager getDrawingManager()
    {
        return drawingManager;

FUNC_DECL RETURN IF LOOP LOOP LOOP LOOP VAR_DECL VAR_DECL VAR_DECL IF CALL CALL CALL CALL CALL ASSIGN CALL BINARY_OP CALL BINARY_OP CALL BINARY_OP ASSIGN BINARY_OP ASSIGN CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL VAR_DECL LITERAL_ANCHOR CALL LITERAL_ANCHOR BINARY_OP LITERAL_ANCHOR VAR_DECL LITERAL_ANCHOR LITERAL_ANCHOR CALL CALL CALL CALL CALL CALL CALL CALL CALL BINARY_OP CALL CALL CALL CALL CALL BINARY_OP CALL CALL CALL BINARY_OP CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL LITERAL_ANCHOR CALL CALL CALL CALL LITERAL_ANCHOR CALL LITERAL_ANCHOR LITERAL_ANCHOR CALL CALL LITERAL_ANCHOR CALL CALL ASSIGN ASSIGN LITERAL_ANCHOR LITERAL_ANCHOR CALL LITERAL_ANCHOR CALL LITERAL_ANCHOR CALL LITERAL_ANCHOR LITERAL_ANCHOR LITERAL_ANCHOR BINARY_OP CALL CALL COND_EXPR CALL LITERAL_ANCHOR CALL CALL BINARY_OP

    public int getNumRecords() {
        return records.size();

    public int getNumberOfFontRecords() {
        return numfonts;

FUNC_DECL IF PARAM PARAM CALL CALL CALL CALL CALL LITERAL_ANCHOR CALL LITERAL_ANCHOR

    public BackupRecord getBackupRecord() {
        return ( BackupRecord ) records.get(records.getBackuppos());

    public void setSheetName(int sheetnum, String sheetname ) {
        setSheetName( sheetnum, sheetname, (byte)0 );

FUNC_DECL VAR_DECL PARAM PARAM PARAM CALL CALL CALL CALL CALL CALL

FUNC_DECL VAR_DECL PARAM PARAM CALL CALL CALL

    public String getSheetName(int sheetnum) {
        return (( BoundSheetRecord ) boundsheets.get(sheetnum))

FUNC_DECL RETURN IF CALL CALL CALL CALL LITERAL_ANCHOR CALL

FUNC_DECL RETURN IF CALL CALL CALL LITERAL_ANCHOR

FUNC_DECL RETURN IF IF PARAM PARAM CALL BINARY_OP CALL LITERAL_ANCHOR CALL CALL CALL LITERAL_ANCHOR LITERAL_ANCHOR

    public int addSSTString(String string) {
        return addSSTString(string, false);

    protected Record createInterfaceEnd() {
        return new InterfaceEndRecord();

    protected Record createDSF() {
        DSFRecord retval = new DSFRecord();

        retval.setDsf();
        return retval;

    protected Record createProtect() {
        ProtectRecord retval = new ProtectRecord();

        retval.setProtect();

    protected Record createPassword() {
        PasswordRecord retval = new PasswordRecord();

        return retval;

    protected Record createPasswordRev4() {
        PasswordRev4Record retval = new PasswordRev4Record();

        return retval;

    protected Record createHideObj() {
        HideObjRecord retval = new HideObjRecord();

        return retval;

    protected PaletteRecord createPalette()
    {
        return new PaletteRecord(PaletteRecord.sid);

    protected Record createSST() {
        return new SSTRecord();

    protected Record createEOF() {
        return new EOFRecord();

FUNC_DECL IF PARAM RETURN RETURN BINARY_OP CALL LITERAL_ANCHOR CALL CALL

    public int getNumNames(){
        int result = names.size();

        return result;

FUNC_DECL RETURN IF LOOP VAR_DECL PARAM PARAM LITERAL_ANCHOR CALL ASSIGN RETURN IF VAR_DECL CALL CALL CALL RETURN CALL CALL CALL

    public ArrayList getFormats() {
	return formats;

FUNC_DECL RETURN LOOP VAR_DECL VAR_DECL PARAM CALL CALL ASSIGN BINARY_OP CALL CALL CALL CALL BINARY_OP BINARY_OP LITERAL_ANCHOR CALL CALL CALL CALL CALL

FUNC_DECL RETURN LOOP PARAM LITERAL_ANCHOR CALL IF VAR_DECL BINARY_OP CALL RETURN CALL CALL

    public List getRecords()
    {
        return records.getRecords();

    public boolean isUsing1904DateWindowing() {
        return uses1904datewindowing;

    public DrawingManager getDrawingManager()
    {
        return drawingManager;


gnu.regexp.RETokenBackRef

final class RETokenBackRef extends REToken {
  private int num;
  private boolean insens;

  RETokenBackRef(int subIndex, int num, boolean insens) {
    super(subIndex);
    this.num = num;
    this.insens = insens;
  }

  // should implement getMinimumLength() -- any ideas?

    boolean match(CharIndexed input, REMatch mymatch) {
	int b,e;
	b = mymatch.start[num];
	e = mymatch.end[num];
	if ((b==-1)||(e==-1)) return false; // this shouldn't happen, but...
	for (int i=b; i<e; i++) {
	    if (input.charAt(mymatch.index+i-b) != input.charAt(i)) {
		return false;
	    }
	}
	mymatch.index += e-b;
	return next(input, mymatch);
    }

    void dump(StringBuffer os) {
	os.append('\\').append(num);

FUNC_DECL PARAM PARAM PARAM ASSIGN ASSIGN


org.apache.poi.hssf.record.FooterRecord

public class FooterRecord
    extends Record
{
    public final static short sid = 0x15;
    private byte              field_1_footer_len;
    private String            field_2_footer;

    public FooterRecord()
    {
    }

    /**
     * Constructs a FooterRecord record and sets its fields appropriately.
     *
     * @param id     id must be 0x15 or an exception will be throw upon validation
     * @param size  the size of the data area of the record
     * @param data  data of the record (should not contain sid/len)
     */

    public FooterRecord(short id, short size, byte [] data)
    {
        super(id, size, data);
    }

    /**
     * Constructs a FooterRecord record and sets its fields appropriately.
     *
     * @param id     id must be 0x15 or an exception will be throw upon validation
     * @param size  the size of the data area of the record
     * @param data  data of the record (should not contain sid/len)
     * @param offset of the record's data
     */

    public FooterRecord(short id, short size, byte [] data, int offset)
    {
        super(id, size, data, offset);
    }

    protected void validateSid(short id)
    {
        if (id != sid)
        {
            throw new RecordFormatException("NOT A FooterRECORD");
        }
    }

    protected void fillFields(byte [] data, short size, int offset)
    {
        if (size > 0)
        {
            field_1_footer_len = data[ 0 + offset ];
                                            LittleEndian.ubyteToInt( field_1_footer_len );
        }
    }

    /**
     * set the length of the footer string
     *
     * @param len  length of the footer string
     * @see #setFooter(String)
     */

    public void setFooterLength(byte len)
    {
        field_1_footer_len = len;
    }

    /**
     * set the footer string
     *
     * @param footer string to display
     * @see #setFooterLength(byte)
     */

    public void setFooter(String footer)
    {
        field_2_footer = footer;
    }

    /**
     * get the length of the footer string
     *
     * @return length of the footer string
     * @see #getFooter()
     */

    public short getFooterLength()
    {
    }

    /**
     * get the footer string
     *
     * @return footer string to display
     * @see #getFooterLength()
     */

    public String getFooter()
    {
        return field_2_footer;
    }

    public String toString()
    {
        StringBuffer buffer = new StringBuffer();

        buffer.append("[FOOTER]\n");
        buffer.append("    .footerlen      = ")
            .append(Integer.toHexString(getFooterLength())).append("\n");
        buffer.append("    .footer         = ").append(getFooter())
            .append("\n");
        buffer.append("[/FOOTER]\n");
        return buffer.toString();
    }

    public int serialize(int offset, byte [] data)
    {
        int len = 4;

        if (getFooterLength() > 0)
        {
        }
        LittleEndian.putShort(data, 0 + offset, sid);
        LittleEndian.putShort(data, 2 + offset,
                              ( short ) ((len - 4) + getFooterLength()));
        if (getFooterLength() > 0)
        {
            data[ 4 + offset ] = (byte)getFooterLength();
        }
        return getRecordSize();
    }

    public int getRecordSize()
    {
        int retval = 4;

        if (getFooterLength() > 0)
        {
        }
        return retval + getFooterLength();
    }

    public short getSid()
    {
        return this.sid;


public class Function2Args extends FunctionOneArg
{

  /** The second argument passed to the function (at index 1).
   *  @serial  */
  Expression m_arg1;

  /**
   * Return the second argument passed to the function (at index 1).
   *
   * @return An expression that represents the second argument passed to the
   *         function.
   */
  public Expression getArg1()
  {
    return m_arg1;
  }

  /**
   * This function is used to fixup variables from QNames to stack frame
   * indexes at stylesheet build time.
   * @param vars List of QNames that correspond to variables.  This list
   * should be searched backwards for the first qualified name that
   * corresponds to the variable reference qname.  The position of the
   * QName in the vector from the start of the vector will be its position
   * in the stack frame (but variables above the globalsTop value will need
   * to be offset to the current stack frame).
   */
  public void fixupVariables(java.util.Vector vars, int globalsSize)
  {
    super.fixupVariables(vars, globalsSize);
    if(null != m_arg1)
      m_arg1.fixupVariables(vars, globalsSize);
  }

  /**
   * Set an argument expression for a function.  This method is called by the
   * XPath compiler.
   *
   * @param arg non-null expression that represents the argument.
   * @param argNum The argument number index.
   *
   * @throws WrongNumberArgsException If the argNum parameter is greater than 1.
   */
  public void setArg(Expression arg, int argNum)
          throws WrongNumberArgsException
  {

    if (argNum == 0)
      super.setArg(arg, argNum);
    else if (1 == argNum)
    {
      m_arg1 = arg;
      arg.exprSetParent(this);
    }
    else
		  reportWrongNumberArgs();
  }

  /**
   * Check that the number of arguments passed to this function is correct.
   *
   *
   * @param argNum The number of arguments that is being passed to the function.
   *
   * @throws WrongNumberArgsException
   */
  public void checkNumberArgs(int argNum) throws WrongNumberArgsException
  {
    if (argNum != 2)
      reportWrongNumberArgs();
  }

  /**
   * Constructs and throws a WrongNumberArgException with the appropriate
   * message for this function object.
   *
   * @throws WrongNumberArgsException
   */
  protected void reportWrongNumberArgs() throws WrongNumberArgsException {
      throw new WrongNumberArgsException(XSLMessages.createXPATHMessage("two", null));
  }

  /**
   * Tell if this expression or it's subexpressions can traverse outside
   * the current subtree.
   *
   * @return true if traversal outside the context node's subtree can occur.
   */
   public boolean canTraverseOutsideSubtree()
   {
    return super.canTraverseOutsideSubtree()
    ? true : m_arg1.canTraverseOutsideSubtree();
   }

  class Arg1Owner implements ExpressionOwner
  {
    /**
     * @see ExpressionOwner#getExpression()
     */
    public Expression getExpression()
    {
      return m_arg1;
    }

    /**
     * @see ExpressionOwner#setExpression(Expression)
     */
    public void setExpression(Expression exp)
    {
    	exp.exprSetParent(Function2Args.this);
    	m_arg1 = exp;
    }
  }

  /**
   * @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
   */
  public void callArgVisitors(XPathVisitor visitor)
  {
  	super.callArgVisitors(visitor);
  	if(null != m_arg1)
  		m_arg1.callVisitors(new Arg1Owner(), visitor);
  }

  /**
   * @see Expression#deepEquals(Expression)
   */
  public boolean deepEquals(Expression expr)
  {
  	if(!super.deepEquals(expr))
  		return false;

  	if(null != m_arg1)
  	{
  		if(null == ((Function2Args)expr).m_arg1)
  			return false;

  		if(!m_arg1.deepEquals(((Function2Args)expr).m_arg1))
  			return false;
  	}
  	else if(null != ((Function2Args)expr).m_arg1)
  		return false;

  	return true;


org.gjt.sp.jedit.bsh.EvalError

public class EvalError extends Exception
{
	SimpleNode node;

	// Note: no way to mutate the Throwable message, must maintain our own
	String message;

	CallStack callstack;

	public EvalError( String s, SimpleNode node, CallStack callstack ) {
		setMessage(s);
		this.node = node;
		// freeze the callstack for the stack trace.
		if ( callstack != null )
			this.callstack = callstack.copy();
	}

	/**
		Print the error with line number and stack trace.
	*/
	public String toString()
	{
		String trace;
		if ( node != null )
			trace = " : at Line: "+ node.getLineNumber()
				+ " : in file: "+ node.getSourceFile()
				+ " : "+node.getText();
		else
			// Users should not normally see this.
			trace = ": <at unknown location>";

		if ( callstack != null )
			trace = trace +"\n" + getScriptStackTrace();

		return getMessage() + trace;
	}

	/**
		Re-throw the error, prepending the specified message.
	*/
	public void reThrow( String msg )
		throws EvalError
	{
		prependMessage( msg );
		throw this;
	}

	/**
		The error has trace info associated with it.
		i.e. It has an AST node that can print its location and source text.
	*/
	SimpleNode getNode() {
		return node;
	}

	void setNode( SimpleNode node ) {
		this.node = node;
	}

	public String getErrorText() {
		if ( node != null )
			return node.getText() ;
		else
			return "<unknown error>";
	}

	public int getErrorLineNumber() {
		if ( node != null )
			return node.getLineNumber() ;
		else
			return -1;
	}

	public String getErrorSourceFile() {
		if ( node != null )
			return node.getSourceFile() ;
		else
			return "<unknown file>";
	}

	public String getScriptStackTrace()
	{
		if ( callstack == null )
			return "<Unknown>";

		String trace = "";
		CallStack stack = callstack.copy();
		while ( stack.depth() > 0 )
		{
			NameSpace ns = stack.pop();
			SimpleNode node = ns.getNode();
			if ( ns.isMethod )
			{
				trace = trace + "\nCalled from method: " + ns.getName();
				if ( node != null )
					trace += " : at Line: "+ node.getLineNumber()
						+ " : in file: "+ node.getSourceFile()
						+ " : "+node.getText();
			}
		}

		return trace;
	}

	/**
		@see #toString() for a full display of the information
	*/
	public String getMessage() { return message; }

	public void setMessage( String s ) { message = s; }

	/**
		Prepend the message if it is non-null.
	*/
	protected void prependMessage( String s )
	{
		if ( s == null )
			return;

		if ( message == null )
			message = s;
		else
			message = s + " : "+ message;

FUNC_DECL IF PARAM PARAM PARAM BINARY_OP ASSIGN CALL ASSIGN LITERAL_ANCHOR CALL


org.apache.tools.ant.taskdefs.Checksum

public class Checksum extends MatchingTask implements Condition {
    /**
     * File for which checksum is to be calculated.
     */
    private File file = null;
    /**
     * MessageDigest algorithm to be used.
     */
    private String algorithm = "MD5";
    /**
     * MessageDigest Algorithm provider
     */
    private String provider = null;
    /**
     * File Extension that is be to used to create or identify
     * destination file
     */
    private String fileext;
    /**
     * Holds generated checksum and gets set as a Project Property.
     */
    private String property;
    /**
     * Whether or not to create a new file.
     * Defaults to false.
     */
    private boolean forceOverwrite;
    /**
     * Contains the result of a checksum verification. ("true" or "false")
     */
    private String verifyProperty;
    /**
     * Vector to hold source file sets.
     */
    private Vector filesets = new Vector();
    /**
     * Stores SourceFile, DestFile pairs and SourceFile, Property String pairs.
     */
    private Hashtable includeFileMap = new Hashtable();
    /**
     * Message Digest instance
     */
    private MessageDigest messageDigest;
    /**
     * is this task being used as a nested condition element?
     */
    private boolean isCondition;
    /**
     * Size of the read buffer to use.
     */
    private int readBufferSize = 8 * 1024;

    /**
     * Sets the file for which the checksum is to be calculated.
     */
    public void setFile(File file) {
        this.file = file;
    }

    /**
     * Specifies the algorithm to be used to compute the checksum.
     * Defaults to "MD5". Other popular algorithms like "SHA" may be used as well.
     */
    public void setAlgorithm(String algorithm) {
        this.algorithm = algorithm;
    }

    /**
     * Sets the MessageDigest algorithm provider to be used
     * to calculate the checksum.
     */
    public void setProvider(String provider) {
        this.provider = provider;
    }

    /**
     * Sets the file extension that is be to used to
     * create or identify destination file.
     */
    public void setFileext(String fileext) {
        this.fileext = fileext;
    }

    /**
     * Sets the property to hold the generated checksum.
     */
    public void setProperty(String property) {
        this.property = property;
    }

    /**
     * Sets the verify property.  This project property holds
     * the result of a checksum verification - "true" or "false"
     */
    public void setVerifyproperty(String verifyProperty) {
        this.verifyProperty = verifyProperty;
    }

    /**
     * Whether or not to overwrite existing file irrespective of
     * whether it is newer than
     * the source file.  Defaults to false.
     */
    public void setForceOverwrite(boolean forceOverwrite) {
        this.forceOverwrite = forceOverwrite;
    }

    /**
     * The size of the read buffer to use.
     */
    public void setReadBufferSize(int size) {
        this.readBufferSize = size;
    }

    /**
     * Files to generate checksums for.
     */
    public void addFileset(FileSet set) {
        filesets.addElement(set);
    }

    /**
     * Calculate the checksum(s).
     */
    public void execute() throws BuildException {
        isCondition = false;
        boolean value = validateAndExecute();
        if (verifyProperty != null) {
            project.setNewProperty(verifyProperty,
                                new Boolean(value).toString());
        }
    }

    /**
     * Calculate the checksum(s)
     *
     * @return Returns true if the checksum verification test passed,
     * false otherwise.
     */
    public boolean eval() throws BuildException {
        isCondition = true;
        return validateAndExecute();
    }

    /**
     * Validate attributes and get down to business.
     */
    private boolean validateAndExecute() throws BuildException {
        String savedFileExt = fileext;

        if (file == null && filesets.size() == 0) {
            throw new BuildException(
                "Specify at least one source - a file or a fileset.");
        }

        if (file != null && file.exists() && file.isDirectory()) {
            throw new BuildException(
                "Checksum cannot be generated for directories");
        }

        if (property != null && fileext != null) {
            throw new BuildException(
                "Property and FileExt cannot co-exist.");
        }

        if (property != null) {
            if (forceOverwrite) {
                throw new BuildException(
                    "ForceOverwrite cannot be used when Property is specified");
            }

            if (file != null) {
                if (filesets.size() > 0) {
                    throw new BuildException("Multiple files cannot be used "
                        + "when Property is specified");
                }
            } else {
                if (filesets.size() > 1) {
                    throw new BuildException("Multiple files cannot be used "
                        + "when Property is specified");
                }
            }
        }

        if (verifyProperty != null) {
            isCondition = true;
        }

        if (verifyProperty != null && forceOverwrite) {
            throw new BuildException(
                "VerifyProperty and ForceOverwrite cannot co-exist.");
        }

        if (isCondition && forceOverwrite) {
            throw new BuildException("ForceOverwrite cannot be used when "
                + "conditions are being used.");
        }

        messageDigest = null;
        if (provider != null) {
            try {
                messageDigest = MessageDigest.getInstance(algorithm, provider);
            } catch (NoSuchAlgorithmException noalgo) {
                throw new BuildException(noalgo, location);
            } catch (NoSuchProviderException noprovider) {
                throw new BuildException(noprovider, location);
            }
        } else {
            try {
                messageDigest = MessageDigest.getInstance(algorithm);
            } catch (NoSuchAlgorithmException noalgo) {
                throw new BuildException(noalgo, location);
            }
        }

        if (messageDigest == null) {
            throw new BuildException("Unable to create Message Digest",
                location);
        }

        if (fileext == null) {
            fileext = "." + algorithm;
        } else if (fileext.trim().length() == 0) {
            throw new BuildException(
                "File extension when specified must not be an empty string");
        }

        try {
            addToIncludeFileMap(file);

            int sizeofFileSet = filesets.size();
            for (int i = 0; i < sizeofFileSet; i++) {
                FileSet fs = (FileSet) filesets.elementAt(i);
                DirectoryScanner ds = fs.getDirectoryScanner(project);
                String[] srcFiles = ds.getIncludedFiles();
                for (int j = 0; j < srcFiles.length; j++) {
                    File src = new File(fs.getDir(project), srcFiles[j]);
                    addToIncludeFileMap(src);
                }
            }

            return generateChecksums();
        } finally {
            fileext = savedFileExt;
            includeFileMap.clear();
        }
    }

    /**
     * Add key-value pair to the hashtable upon which
     * to later operate upon.
     */
    private void addToIncludeFileMap(File file) throws BuildException {
        if (file != null) {
            if (file.exists()) {
                if (property == null) {
                    File dest
                        = new File(file.getParent(), file.getName() + fileext);
                    if (forceOverwrite || isCondition ||
                        (file.lastModified() > dest.lastModified())) {
                        includeFileMap.put(file, dest);
                    } else {
                        log(file + " omitted as " + dest + " is up to date.",
                            Project.MSG_VERBOSE);
                    }
                } else {
                    includeFileMap.put(file, property);
                }
            } else {
                String message = "Could not find file "
                                 + file.getAbsolutePath()
                                 + " to generate checksum for.";
                log(message);
                throw new BuildException(message, location);
            }
        }
    }

    /**
     * Generate checksum(s) using the message digest created earlier.
     */
    private boolean generateChecksums() throws BuildException {
        boolean checksumMatches = true;
        FileInputStream fis = null;
        FileOutputStream fos = null;
        byte[] buf = new byte[readBufferSize];
        try {
            for (Enumeration e = includeFileMap.keys(); e.hasMoreElements();) {
                messageDigest.reset();
                File src = (File) e.nextElement();
                if (!isCondition) {
                    log("Calculating " + algorithm + " checksum for " + src);
                }
                fis = new FileInputStream(src);
                DigestInputStream dis = new DigestInputStream(fis,
                                                              messageDigest);
                while (dis.read(buf, 0, readBufferSize) != -1) {
                    ;
                }
                dis.close();
                fis.close();
                fis = null;
                byte[] fileDigest = messageDigest.digest ();
                StringBuffer checksumSb = new StringBuffer();
                for (int i = 0; i < fileDigest.length; i++) {
                    String hexStr = Integer.toHexString(0x00ff & fileDigest[i]);
                    if (hexStr.length() < 2) {
                        checksumSb.append("0");
                    }
                    checksumSb.append(hexStr);
                }
                String checksum = checksumSb.toString();
                Object destination = includeFileMap.get(src);
                if (destination instanceof java.lang.String) {
                    String prop = (String) destination;
                    if (isCondition) {
                        checksumMatches = checksumMatches &&
                            checksum.equals(property);
                    } else {
                        project.setNewProperty(prop, checksum);
                    }
                } else if (destination instanceof java.io.File) {
                    if (isCondition) {
                        File existingFile = (File) destination;
                        if (existingFile.exists()) {
                            fis = new FileInputStream(existingFile);
                            InputStreamReader isr = new InputStreamReader(fis);
                            BufferedReader br = new BufferedReader(isr);
                            String suppliedChecksum = br.readLine();
                            fis.close();
                            fis = null;
                            br.close();
                            isr.close();
                            checksumMatches = checksumMatches &&
                                checksum.equals(suppliedChecksum);
                        } else {
                            checksumMatches = false;
                        }
                    } else {
                        File dest = (File) destination;
                        fos = new FileOutputStream(dest);
                        fos.write(checksum.getBytes());
                        fos.close();
                        fos = null;
                    }
                }
            }
        } catch (Exception e) {
            throw new BuildException(e, location);
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {}
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {}
            }
        }
        return checksumMatches;