/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



import com.sun.star.lib.uno.helper.Factory;
import com.sun.star.lang.XInitialization;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.lang.XSingleComponentFactory;
import com.sun.star.lang.XMultiServiceFactory;
import com.sun.star.lang.XServiceInfo;
import com.sun.star.lang.XTypeProvider;
import com.sun.star.lib.uno.helper.WeakBase;
import com.sun.star.registry.XRegistryKey;
import com.sun.star.uno.Type;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XInterface;
import com.sun.star.uno.XWeak;
import com.sun.star.uno.XComponentContext;
import org.openoffice.*;

// additional interfaces used by the implementation
import com.sun.star.sheet.XSpreadsheetDocument;
import com.sun.star.sheet.XSpreadsheet;
import com.sun.star.sheet.XCellRangeMovement;
import com.sun.star.sheet.XFunctionAccess;
import com.sun.star.container.XIndexAccess;
import com.sun.star.table.XCellRange;
import com.sun.star.table.XCell;
import com.sun.star.table.CellAddress;
import com.sun.star.table.CellRangeAddress;
import com.sun.star.table.XColumnRowRange;
import com.sun.star.table.XTableRows;
import com.sun.star.beans.XPropertySet;
import com.sun.star.text.XTextRange;
import com.sun.star.text.XSimpleText;
import com.sun.star.text.XTextCursor;
import com.sun.star.text.XText;
import com.sun.star.text.XTextField;

import java.util.GregorianCalendar;
import java.util.Calendar;
import java.util.Vector;
import java.util.Arrays;

/** This class capsulates the class, that implements the minimal component, a
 * factory for creating the service (<CODE>__getServiceFactory</CODE>) and a
 * method, that writes the information into the given registry key
 * (<CODE>__writeRegistryServiceInfo</CODE>).
 */
public class ToDo {

    /** This class implements the component. At least the interfaces
     * XInterface, XTypeProvider, and XWeak implemented by the helper class
     * WeakBase and XServiceInfo should be provided by the service.
     */
    public static class ToDoImpl extends WeakBase implements XServiceInfo, XToDo {

        /** The service name, that must be used to get an instance of this service.
         */
        private static final String __serviceName = "org.openoffice.ToDo";

        /** The initial component contextr, that gives access to
         * the service manager, supported singletons, ...
         * It's often later used
         */
        private XComponentContext m_cmpCtx;

        /** The service manager, that gives access to all registered services.
         * It's often later used
         */
        private XMultiComponentFactory m_xMCF;

        // Implementation helper variables
        static private final int INT_COLUMN_FEATURE = 0;
        static private final int INT_COLUMN_COMMENT = 1;
        static private final int INT_COLUMN_NEEDEDDAYS = 2;
        static private final int INT_COLUMN_STARTDATE = 3;
        static private final int INT_COLUMN_START_DAY_OF_WEEK = 4;
        static private final int INT_COLUMN_ENDDATE = 5;
        static private final int INT_COLUMN_END_DAY_OF_WEEK = 6;
        static private final int INT_COLUMN_DUEDATE = 7;
        static private final int INT_COLUMN_STATUS = 8;

        static private final int INT_ROW_FROM = 14; // 8

        static private final int INT_ROW_HOLIDAYS_START = 4;
        static private final int INT_COLUMN_HOLIDAYS_START = 7; // 10

        static private final String STRING_SEPARATOR = "/";


        /** The constructor of the inner class has a XComponenContext parameter.
         * @param xCompContext the initial component context
         */
        public ToDoImpl(XComponentContext xCompContext) {
            try {
                m_cmpCtx = xCompContext;
                m_xMCF = m_cmpCtx.getServiceManager();
            }
            catch( Exception e ) {
                e.printStackTrace(System.err);
            }
        }

        /** This method returns an array of all supported service names.
         * @return Array of supported service names.
         */
        public String[] getSupportedServiceNames() {
            return getServiceNames();
        }

        public static String[] getServiceNames() {
            String[] sSupportedServiceNames = { __serviceName };
            return sSupportedServiceNames;
        }

        /** This method returns true, if the given service will be
         * supported by the component.
         * @param sService Service name.
         * @return True, if the given service name will be supported.
         */
        public boolean supportsService(String sServiceName) {
            return sServiceName.equals( __serviceName );
        }

        /** Return the class name of the component.
         * @return Class name of the component.
         */
        public String getImplementationName() {
            return ToDoImpl.class.getName();
        }

        /** For every bug/feature listed in a spreadsheet document this method
         * calculates the start date, day of week of the start date, the end date
         * and the day of week of the end date. All calculations are dependent
         * on the values of "Needed Days", "Due Date" and "Status". The columns
         * "Needed Days" and "Status" are mandatory. The first feature/bug should
         * be placed in row nine. The date to start the calculation should be
         * placed in cell C6. The private holidays should be placed in cell K4/K5
         * and below. All rows will be calculated up to the first empty cell in
         * the first column. If a cell in the column "Due Date" will be colored
         * red, you should take a look at your entries.
         * @param aInstance Spreadsheet document.
         * @throws com.sun.star.uno.RuntimeException This exception could occur
         *                                           at every interface method.
         */
        public void recalc( java.lang.Object aInstance )
            throws com.sun.star.uno.RuntimeException {
            try {
                // Querying for the interface XSpreadsheetDocument
                XSpreadsheetDocument xspreadsheetdocument =
                    ( XSpreadsheetDocument ) UnoRuntime.queryInterface(
                        XSpreadsheetDocument.class, aInstance );

                // Querying for the interface XIndexAccess
                XIndexAccess xindexaccess = ( XIndexAccess )
                    UnoRuntime.queryInterface( XIndexAccess.class,
                                               xspreadsheetdocument.getSheets() );

                // Getting the first XSpreadsheet
                XSpreadsheet xspreadsheet = (XSpreadsheet)UnoRuntime.queryInterface(
                    XSpreadsheet.class, xindexaccess.getByIndex( 0 ));

                // Querying for the interface XCellRange on the XSpeadsheet
                XCellRange xcellrange = ( XCellRange )
                UnoRuntime.queryInterface( XCellRange.class, xspreadsheet );

                /* Getting the Gregorian calendar with the date on which to start
                   the calculation */
                GregorianCalendar gregCalAbsoluteStartDate =
                    this.getGregorianCalendarFromString(this.getStringFromCell(
                                                            xcellrange, 5, 2 ) );
                gregCalAbsoluteStartDate.add( Calendar.DATE, -1 );

                // Set the start date with the absolute start date
                GregorianCalendar gregCalStartDate =
                (GregorianCalendar) gregCalAbsoluteStartDate.clone();

                /* Creating the service FunctionAccess, which allows generic
                   access to all spreadsheet functions */
                Object objectFunctionAccess =
                    m_xMCF.createInstanceWithContext(
                        "com.sun.star.sheet.FunctionAccess", m_cmpCtx );

                // Querying for the interface XFunctionAccess on service
                // FunctionAccess
                XFunctionAccess xfunctionaccess = (XFunctionAccess)
                    UnoRuntime.queryInterface(XFunctionAccess.class,
                                              objectFunctionAccess );

                // Creating vector for holidays
                Vector vectorHolidays = new Vector();

                // Get the Official Holidays
                this.getOfficialHolidays( vectorHolidays, xcellrange,
                                          xfunctionaccess,
                                          gregCalStartDate.get(
                                              Calendar.YEAR ) );

                // Get the private holidays
                this.getPrivateHolidays(vectorHolidays, xcellrange,
                                        xfunctionaccess);

                // Getting the object array of holidays
                Object[] objectSortedHolidays = vectorHolidays.toArray();

                // Sorting the holidays
                Arrays.sort( objectSortedHolidays );

                // Collect the Official Holidays and the private holidays
                Object [][]objectHolidays =
                new Object[][] { objectSortedHolidays };

                // Row index
                int intRowTo = this.INT_ROW_FROM - 1;

                // Getting the feature of the first cell
                String sFeature = this.getStringFromCell(xcellrange,
                                                         intRowTo + 1,
                                                         this.INT_COLUMN_FEATURE);

                // Determine the last row with an entry in the first column
                while ( ( sFeature != null ) &&
                        ( !sFeature.equals( "" ) ) ) {
                    intRowTo++;
                    sFeature = this.getStringFromCell( xcellrange,
                    intRowTo + 1, this.INT_COLUMN_FEATURE );
                }

                // Setting the last row to be calculated
                final int INT_ROW_TO = intRowTo + 1;

                // Deleting cells which will be recalculated
                for ( int intRow = this.INT_ROW_FROM; intRow < INT_ROW_TO + 5;
                      intRow++ ) {
                    for ( int intColumn = this.INT_COLUMN_STARTDATE;
                          intColumn <= this.INT_COLUMN_END_DAY_OF_WEEK;
                          intColumn++ ) {
                        this.setStringToCell(xcellrange, intRow, intColumn, "");
                    }
                }

                /* Clearing the background color of the due date cells and setting
                   the hyperlink to the bugtracker */
                for (int intRow = this.INT_ROW_FROM; intRow < INT_ROW_TO; intRow++)
                {
                    // Querying for the interface XPropertySet for the cell
                    // providing the due date
                    XPropertySet xpropertyset = ( XPropertySet )
                        UnoRuntime.queryInterface(XPropertySet.class,
                                                  xcellrange.getCellByPosition(
                                                      this.INT_COLUMN_DUEDATE,
                                                      intRow ));

                    // Changing the background color of the cell to white
                    xpropertyset.setPropertyValue( "CellBackColor",
                    new Integer( 16777215 ) );

                    // Getting the cell of the bug id
                    XCell xcell = xcellrange.getCellByPosition(
                    this.INT_COLUMN_FEATURE, intRow );

                    // Querying for the interface XSimpleText
                    XSimpleText xsimpletext = ( XSimpleText )
                    UnoRuntime.queryInterface( XSimpleText.class, xcell );

                    // Getting the text cursor
                    XTextCursor xtextcursor = xsimpletext.createTextCursor();

                    // Querying for the interface XTextRange
                    XTextRange xtextrange = ( XTextRange )
                    UnoRuntime.queryInterface( XTextRange.class, xtextcursor );

                    // Getting the bug ID from the cell
                    String sBugID = xtextrange.getString();
                    if ( !sBugID.startsWith(
                             "http://www.openoffice.org/issues/show_bug.cgi?id=") ) {
                        String sBugIDLink =
                            "http://www.openoffice.org/issues/show_bug.cgi?id=" + sBugID;

                        // Querying for the interface XMultiServiceFactory
                        XMultiServiceFactory xMSFTextField =
                            (XMultiServiceFactory)UnoRuntime.queryInterface(
                                XMultiServiceFactory.class, aInstance );

                        // Creating an instance of the text field URL
                        Object objectTextField =
                            xMSFTextField.createInstance(
                                "com.sun.star.text.TextField.URL" );

                        // Querying for the interface XTextField
                        XTextField xtextfield = ( XTextField )
                            UnoRuntime.queryInterface( XTextField.class,
                                                       objectTextField );

                        // Querying for the interface XPropertySet
                        XPropertySet xpropertysetTextField = ( XPropertySet )
                            UnoRuntime.queryInterface( XPropertySet.class,
                                                       xtextfield );

                        // Setting the URL
                        xpropertysetTextField.setPropertyValue( "URL",
                                                                sBugIDLink );

                        // Setting the representation of the URL
                        xpropertysetTextField.setPropertyValue( "Representation",
                                                                sBugID );

                        // Querying for the interface XText
                        XText xtext = ( XText )UnoRuntime.queryInterface(
                            XText.class, xcell );

                        // Delete cell content
                        xtextrange.setString( "" );

                        // Inserting the text field URL to the cell
                        xtext.insertTextContent( xtextrange, xtextfield, false );
                    }
                }

                // Processing all features/bugs in the table
                for (int intRow = this.INT_ROW_FROM; intRow < INT_ROW_TO; intRow++)
                {
                    // Getting the cell of the column "Needed Days" in the
                    // current row
                    XCell xcell = xcellrange.getCellByPosition(
                        INT_COLUMN_NEEDEDDAYS, intRow );

                    // Getting the number of needed days to perform the feature
                    int intNeededDays = (int) Math.round( xcell.getValue() );

                    // Getting the content of a specified cell
                    String sStatus = this.getStringFromCell( xcellrange,
                    intRow, this.INT_COLUMN_STATUS );

                    /* Testing if the number of needed days is greater than
                       zero and if
                       the status is not "done" */
                    if ( ( intNeededDays > 0 )
                         && !( sStatus.toLowerCase().trim().equals("done")) ) {
                        // Getting the start date after a specified number of
                        // workdays
                        gregCalStartDate = this.getWorkday(
                            gregCalStartDate, 1, objectHolidays,
                            xfunctionaccess );

                        // Getting a string with the date format jjjj-mm-dd from
                        // the Gregorian calendar
                        String sDate = this.getStringFromGregorianCalendar(
                            gregCalStartDate );

                        // Set the start date in the specified cell of the table
                        this.setStringToCell(xcellrange, intRow,
                                             this.INT_COLUMN_STARTDATE, sDate);

                        // For the start day set the day of week in the specified
                        // cell of the table
                        this.setDayOfWeek( gregCalStartDate,
                                           xcellrange, intRow,
                                           this.INT_COLUMN_START_DAY_OF_WEEK );

                        // Getting the end date after a specified number of workdays
                        GregorianCalendar gregCalEndDate =
                            this.getWorkday( gregCalStartDate,
                                             intNeededDays - 1,
                                             objectHolidays, xfunctionaccess );

                        // Creating a string with the date format jjjj-mm-dd
                        sDate = this.getStringFromGregorianCalendar(
                            gregCalEndDate );

                        // Set the end date in the specified cell of the table
                        this.setStringToCell( xcellrange, intRow,
                                              this.INT_COLUMN_ENDDATE, sDate );

                        // For the end day set the day of week in the specified
                        // cell of the table
                        this.setDayOfWeek(gregCalEndDate, xcellrange,
                                          intRow, this.INT_COLUMN_END_DAY_OF_WEEK);

                        // Set the initial date for the next loop
                        gregCalStartDate = ( GregorianCalendar )
                            gregCalEndDate.clone();

                        // Get the due date from the table
                        String sDueDate = this.getStringFromCell(
                            xcellrange, intRow, this.INT_COLUMN_DUEDATE );

                        // Testing if the due date is not empty
                        if ( !sDueDate.equals( "" ) ) {
                            GregorianCalendar gregCalDueDate =
                                this.getGregorianCalendarFromString(sDueDate);

                            // Testing if the due date is before the calculated
                            // end date
                            if ( gregCalDueDate.before(
                                     gregCalEndDate ) ) {
                                /* Getting the date when the processing of the
                                   feature/bug should
                                   be started at the latest */
                                GregorianCalendar gregCalLatestDateToStart =
                                    this.getWorkday(gregCalDueDate,
                                                    -( intNeededDays - 1 ),
                                                    objectHolidays,
                                                    xfunctionaccess);

                                // Begin with the current row
                                int intRowToInsert = intRow;

                                // Get the start date for the feature/bug in the
                                // current row
                                GregorianCalendar gregCalPreviousStartDate =
                                    this.getGregorianCalendarFromString(
                                        this.getStringFromCell(
                                            xcellrange, intRowToInsert,
                                            this.INT_COLUMN_STARTDATE ) );

                                // Testing if we have to search for an earlier date
                                // to begin
                                while ((gregCalLatestDateToStart.before(
                                            gregCalPreviousStartDate)) &&
                                        (INT_ROW_FROM != intRowToInsert)) {
                                    // Decrease the row
                                    intRowToInsert--;

                                    // Get the start date for the feature/bug in
                                    // the current row
                                    String sStartDate = this.getStringFromCell(
                                        xcellrange, intRowToInsert,
                                        this.INT_COLUMN_STARTDATE );

                                    // Search until a valid start date is found
                                    while ( sStartDate.equals( "" ) ) {
                                        // Decrease the row
                                        intRowToInsert--;

                                        // Get the start date for the feature/bug
                                        // in the current row
                                        sStartDate = this.getStringFromCell(
                                            xcellrange, intRowToInsert,
                                            this.INT_COLUMN_STARTDATE );
                                    }

                                    // Get the GregorianCalender format for the
                                    // start date
                                    gregCalPreviousStartDate =
                                        this.getGregorianCalendarFromString(
                                            sStartDate );
                                }

                                // Getting the cell of the column "Needed Days"
                                // in the row where to insert
                                XCell xcellNeededDaysWhereToInsert =
                                    xcellrange.getCellByPosition(
                                        INT_COLUMN_NEEDEDDAYS, intRowToInsert );
                                // Getting the number of needed days to perform
                                // the feature
                                int intNeededDaysWhereToInsert = (int)
                                    Math.round(
                                        xcellNeededDaysWhereToInsert.getValue());

                                GregorianCalendar gregCalPreviousNewEndDate =
                                    this.getWorkday(gregCalPreviousStartDate,
                                                    intNeededDays - 1 +
                                                    intNeededDaysWhereToInsert,
                                                    objectHolidays,
                                                    xfunctionaccess);
                                String sPreviousDueDate = this.getStringFromCell(
                                    xcellrange, intRowToInsert,
                                    this.INT_COLUMN_DUEDATE );

                                GregorianCalendar gregCalPreviousDueDate = null;

                                if ( !sPreviousDueDate.equals( "" ) ) {
                                    gregCalPreviousDueDate =
                                        this.getGregorianCalendarFromString(
                                            sPreviousDueDate );
                                }

                                if ( ( intRowToInsert == intRow ) ||
                                     ( gregCalPreviousNewEndDate.after(
                                         gregCalPreviousDueDate ) ) ) {
                                    // Querying for the interface XPropertySet for
                                    // the cell providing the due date
                                    XPropertySet xpropertyset = ( XPropertySet )
                                        UnoRuntime.queryInterface(
                                            XPropertySet.class,
                                            xcellrange.getCellByPosition(
                                                this.INT_COLUMN_DUEDATE,
                                                intRow ) );

                                    // Changing the background color of the cell
                                    // to red
                                    xpropertyset.setPropertyValue(
                                        "CellBackColor", new Integer( 16711680 ) );
                                } else {
                                    // Querying for the interface XColumnRowRange
                                    // on the XCellRange
                                    XColumnRowRange xcolumnrowrange =
                                        ( XColumnRowRange)UnoRuntime.queryInterface(
                                            XColumnRowRange.class, xcellrange );
                                    // Inserting one row to the table
                                    XTableRows xTableRows =
                                        xcolumnrowrange.getRows();
                                    xTableRows.insertByIndex( intRowToInsert, 1 );

                                    // Querying for the interface
                                    // XCellRangeMovement on XCellRange
                                    XCellRangeMovement xcellrangemovement =
                                      (XCellRangeMovement)UnoRuntime.queryInterface(
                                          XCellRangeMovement.class, xcellrange );

                                    // Creating the cell address of the destination
                                    CellAddress celladdress = new CellAddress();
                                    celladdress.Sheet = 0;
                                    celladdress.Column = 0;
                                    celladdress.Row = intRowToInsert;

                                    // Creating the cell range of the source
                                    CellRangeAddress cellrangeaddress =
                                    new CellRangeAddress();
                                    cellrangeaddress.Sheet = 0;
                                    cellrangeaddress.StartColumn = 0;
                                    cellrangeaddress.StartRow = intRow + 1;
                                    cellrangeaddress.EndColumn = 8;
                                    cellrangeaddress.EndRow = intRow + 1;

                                    // Moves the cell range to another position in
                                    // the document
                                    xcellrangemovement.moveRange(celladdress,
                                                                 cellrangeaddress);

                                    // Removing the row not needed anymore
                                    xcolumnrowrange.getRows().removeByIndex(intRow
                                                                            + 1, 1);

                                    // Set the current row, because we want to
                                    // recalculate all rows below
                                    intRow = intRowToInsert - 1;

                                    // Tests at which line we want to insert
                                    if ( intRow >= this.INT_ROW_FROM ) {
                                        // Get the start date
                                        gregCalStartDate =
                                            this.getGregorianCalendarFromString(
                                                this.getStringFromCell( xcellrange,
                                                   intRow,this.INT_COLUMN_ENDDATE));
                                    }
                                    else {
                                        // Set the start date with the absolute s
                                        // tart date
                                        gregCalStartDate = (GregorianCalendar)
                                            gregCalAbsoluteStartDate.clone();
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch( Exception exception ) {
                showExceptionMessage( exception );
            }
        }

        /** Getting a string from a Gregorian calendar.
         * @param gregCal Date to be converted.
         * @return string (converted Gregorian calendar).
         */
        public String getStringFromGregorianCalendar( GregorianCalendar gregCal ) {
            String sDate = ( gregCal.get( Calendar.MONTH ) + 1 )
                + STRING_SEPARATOR + gregCal.get( Calendar.DATE )
//                + STRING_SEPARATOR + ( gregCal.get( Calendar.MONTH ) + 1 )
                + STRING_SEPARATOR + gregCal.get( Calendar.YEAR );

            return sDate;
        }

        /** Getting a GregorianCalendar from a string.
         * @param sDate String to be converted.
         * @return The result of the converting of the string.
         */
        public GregorianCalendar getGregorianCalendarFromString( String sDate ) {
            int []intDateValue = this.getDateValuesFromString( sDate );

            return( new GregorianCalendar( intDateValue[ 2 ], intDateValue[ 0 ],
                                           intDateValue[ 1 ] ) );
        }

        /** Getting the day, month and year from a string.
         * @param sDate String to be parsed.
         * @return Returns an array of integer variables.
         */
        public int[] getDateValuesFromString( String sDate) {
            int[] intDateValues = new int[ 3 ];

            int intPositionFirstTag = sDate.indexOf( STRING_SEPARATOR );
            int intPositionSecondTag = sDate.indexOf(STRING_SEPARATOR,
                                                     intPositionFirstTag + 1);

            // Getting the value of the month
            intDateValues[ 0 ] = Integer.parseInt(
                sDate.substring(0, intPositionFirstTag)) - 1;
            // Getting the value of the day
            intDateValues[ 1 ] = Integer.parseInt(
                sDate.substring(intPositionFirstTag + 1, intPositionSecondTag));
            // Getting the value of the year
            intDateValues[ 2 ] = Integer.parseInt(
                sDate.substring(intPositionSecondTag + 1, sDate.length()));

            return intDateValues;
        }

        /** Getting a content from a specified cell.
         * @param xcellrange Providing access to cells.
         * @param intRow Number of row.
         * @param intColumn Number of column.
         * @return String from the specified cell.
         */
        public String getStringFromCell( XCellRange xcellrange, int intRow,
                                         int intColumn ) {
            XTextRange xtextrangeStartDate = null;

            try {
                // Getting the cell holding the information about the start date
                XCell xcellStartDate = xcellrange.getCellByPosition(intColumn,
                                                                    intRow);
                // Querying for the interface XTextRange on the XCell
                xtextrangeStartDate = (XTextRange)
                    UnoRuntime.queryInterface(XTextRange.class, xcellStartDate);
            }
            catch( Exception exception ) {
                this.showExceptionMessage( exception );
            }

            // Getting the start date
            return xtextrangeStartDate.getString().trim();
        }

        /** Writing a specified string to a specified cell.
         * @param xcellrange Providing access to the cells.
         * @param intRow Number of row.
         * @param intColumn Number of column.
         * @param sDate Date to write to the cell.
         */
        public void setStringToCell( XCellRange xcellrange, int intRow,
                                     int intColumn, String sDate ) {
            try {
                // Getting the cell holding the information on the day to start
                XCell xcellStartDate = xcellrange.getCellByPosition(intColumn,
                                                                    intRow);
                // Querying for the interface XTextRange on the XCell
                XTextRange xtextrange = (XTextRange)
                    UnoRuntime.queryInterface(XTextRange.class, xcellStartDate);
                // Setting the new start date
                xtextrange.setString( sDate );
            }
            catch( Exception exception ) {
                this.showExceptionMessage( exception );
            }
        }

        /** Calculates the week of day and calls the method "setStringToCell".
         * @param gregCal Day to be written to the cell.
         * @param xcellrange Providing access to the cells.
         * @param intRow Number of row.
         * @param intColumn Number of column.
         */
        public void setDayOfWeek( GregorianCalendar gregCal,
                                  XCellRange xcellrange, int intRow,
                                  int intColumn) {
            int intDayOfWeek = gregCal.get( Calendar.DAY_OF_WEEK );
            String sDayOfWeek = "";
            if ( intDayOfWeek == Calendar.MONDAY ) {
                sDayOfWeek = "MON";
            } else if ( intDayOfWeek == Calendar.TUESDAY ) {
                sDayOfWeek = "TUE";
            } else if ( intDayOfWeek == Calendar.WEDNESDAY ) {
                sDayOfWeek = "WED";
            } else if ( intDayOfWeek == Calendar.THURSDAY ) {
                sDayOfWeek = "THU";
            } else if ( intDayOfWeek == Calendar.FRIDAY ) {
                sDayOfWeek = "FRI";
            }

            this.setStringToCell( xcellrange, intRow, intColumn,
            sDayOfWeek );
        }

        /** Calculates the dates of the official holidays with help of Calc
         * functions.
         * @param vectorHolidays Holding all holidays.
         * @param xcellrange Providing the cells.
         * @param xfunctionaccess Provides access to functions of the Calc.
         * @param intYear Year to calculate the official holidays.
         */
        public void getOfficialHolidays(
        Vector vectorHolidays,
        XCellRange xcellrange,
        XFunctionAccess xfunctionaccess,
        int intYear ) {
            try {
                // Official Holidays for how many years?
                final int intHowManyYears = 2;

                // Get the Official Holiday for two years
                for ( int intNumberOfYear = 0;
                      intNumberOfYear <= ( intHowManyYears - 1 );
                      intNumberOfYear++ ) {
                    intYear += intNumberOfYear;

                    // Getting the Easter Sunday
                    Double dEasterSunday = ( Double )
                        xfunctionaccess.callFunction(
                            "EASTERSUNDAY", new Object[] { new Integer(intYear) });

                    int intEasterSunday = (int)Math.round(
                        dEasterSunday.doubleValue());

                    // New-year
                    vectorHolidays.addElement( xfunctionaccess.callFunction(
                                                   "DATE",
                                                   new Object[] {
                                                       new Integer( intYear ),
                                                       new Integer( 1 ),
                                                       new Integer( 1 ) } ));

                    // Good Friday
                    vectorHolidays.addElement(
                    new Double( intEasterSunday - 2 ) );

                    // Easter Monday
                    vectorHolidays.addElement(
                    new Double( intEasterSunday + 1 ) );

                    // Labour Day
                    vectorHolidays.addElement( xfunctionaccess.callFunction(
                                                   "DATE",
                                                   new Object[] {
                                                       new Integer( intYear ),
                                                       new Integer( 5 ),
                                                       new Integer( 1 ) } ));

                    // Ascension Day
                    vectorHolidays.addElement(new Double(intEasterSunday + 39 ));

                    // Pentecost Monday
                    vectorHolidays.addElement(new Double(intEasterSunday + 50 ));

                    // German Unification
                    vectorHolidays.addElement( xfunctionaccess.callFunction(
                                                   "DATE",
                                                   new Object[] {
                                                       new Integer( intYear ),
                                                       new Integer( 10 ),
                                                       new Integer( 3 ) } ));

                    // Christmas Day First
                    vectorHolidays.addElement( xfunctionaccess.callFunction(
                                                   "DATE",
                                                   new Object[] {
                                                       new Integer( intYear ),
                                                       new Integer( 12 ),
                                                       new Integer( 25 ) } ));

                    // Christmas Day Second
                    vectorHolidays.addElement( xfunctionaccess.callFunction(
                                                   "DATE",
                                                   new Object[] {
                                                       new Integer( intYear ),
                                                       new Integer( 12 ),
                                                       new Integer( 26 ) } ));
                }
            }
            catch( Exception exception ) {
                this.showExceptionMessage( exception );
            }
        }

        /** Returns the serial number of the date before or after a specified
         * number of workdays.
         * @param gregCalStartDate Date to start with the calculation.
         * @param intDays Number of workdays (e.g. 5 or -3).
         * @param objectHolidays Private and public holidays to take into account.
         * @param xfunctionaccess Allows to call functions from the Calc.
         * @return The gregorian date before or after a specified number of
         *         workdays.
         */
        public GregorianCalendar getWorkday(
            GregorianCalendar gregCalStartDate,
            int intDays, Object[][] objectHolidays,
            XFunctionAccess xfunctionaccess ) {
            GregorianCalendar gregCalWorkday = null;

            try {
                // Getting the value of the start date
                Double dDate = ( Double ) xfunctionaccess.callFunction(
                    "DATE",
                    new Object[] {
                        new Integer( gregCalStartDate.get( Calendar.YEAR ) ),
                        new Integer( gregCalStartDate.get( Calendar.MONTH ) + 1 ),
                        new Integer( gregCalStartDate.get( Calendar.DATE ) )
                    } );

                Double dWorkday = ( Double ) xfunctionaccess.callFunction(
                "com.sun.star.sheet.addin.Analysis.getWorkday",
                new Object[] { dDate, new Integer( intDays ), objectHolidays } );

                Double dYear = ( Double ) xfunctionaccess.callFunction(
                    "YEAR", new Object[] { dWorkday } );
                Double dMonth = ( Double ) xfunctionaccess.callFunction(
                    "MONTH", new Object[] { dWorkday } );
                Double dDay = ( Double ) xfunctionaccess.callFunction(
                    "DAY", new Object[] { dWorkday } );

                gregCalWorkday = new GregorianCalendar(
                dYear.intValue(),
                dMonth.intValue() - 1,
                dDay.intValue() );
            }
            catch( Exception exception ) {
                this.showExceptionMessage( exception );
            }

            return gregCalWorkday;
        }

        /** Getting the holidays from the spreadsheet.
         * @param vectorHolidays Holding all holidays.
         * @param xcellrange Providing the cells.
         * @param xfunctionaccess Provides the access to functions of the Calc.
         */
        public void getPrivateHolidays( Vector vectorHolidays,
                                        XCellRange xcellrange,
                                        XFunctionAccess xfunctionaccess ) {
            try {
                int intRow = this.INT_ROW_HOLIDAYS_START;
                int intColumn = this.INT_COLUMN_HOLIDAYS_START;

                double dHolidayStart = xcellrange.getCellByPosition(
                    intColumn, intRow ).getValue();

                double dHolidayEnd = xcellrange.getCellByPosition(
                    intColumn + 1, intRow ).getValue();

                while ( dHolidayStart != 0 ) {
                    if ( dHolidayEnd == 0 ) {
                        vectorHolidays.addElement(
                            new Integer( (int) Math.round(
                                             dHolidayStart ) ) );
                    }
                    else {
                        for ( int intHoliday = (int) Math.round(
                                  dHolidayStart );
                              intHoliday <= (int) Math.round( dHolidayEnd );
                              intHoliday++ ) {
                            vectorHolidays.addElement( new Double( intHoliday ) );
                        }
                    }

                    intRow++;
                    dHolidayStart = xcellrange.getCellByPosition(
                        intColumn, intRow).getValue();
                    dHolidayEnd = xcellrange.getCellByPosition(
                        intColumn + 1, intRow).getValue();
                }
            }
            catch( Exception exception ) {
                this.showExceptionMessage( exception );
            }
        }

        /** Showing the stack trace in a JOptionPane.
         * @param sMessage The message to show.
         */
        public void showMessage( String sMessage ) {
            javax.swing.JFrame jframe = new javax.swing.JFrame();
            jframe.setLocation(100, 100);
            jframe.setSize(300, 200);
            jframe.setVisible(true);
            javax.swing.JOptionPane.showMessageDialog(
                jframe, sMessage, "Debugging information",
                javax.swing.JOptionPane.INFORMATION_MESSAGE);
            jframe.dispose();
        }

        /** Writing the stack trace from an exception to a string and calling
         * the method showMessage() with this string.
         * @param exception The occurred exception.
         * @see showMessage
         */
        public void showExceptionMessage( Exception exception ) {
            java.io.StringWriter swriter = new java.io.StringWriter();
            java.io.PrintWriter printwriter =
                new java.io.PrintWriter( swriter );
            exception.printStackTrace( printwriter);
            System.err.println( exception );
            this.showMessage( swriter.getBuffer().substring(0) );
        }
    }

    /**
     * Gives a factory for creating the service.
     * This method is called by the <code>JavaLoader</code>
     * <p>
     * @return  returns a <code>XSingleComponentFactory</code> for creating
     *          the component
     * @param   sImplName the name of the implementation for which a
     *          service is desired
     * @see     com.sun.star.comp.loader.JavaLoader
     */
    public static XSingleComponentFactory __getComponentFactory(String sImplName) {
        XSingleComponentFactory xFactory = null;

        if ( sImplName.equals( ToDoImpl.class.getName() ) )
            xFactory = Factory.createComponentFactory(ToDoImpl.class,
                                                      ToDoImpl.getServiceNames());

        return xFactory;
    }

    /**
     * Writes the service information into the given registry key.
     * This method is called by the <code>JavaLoader</code>
     * <p>
     * @return  returns true if the operation succeeded
     * @param   regKey the registryKey
     * @see     com.sun.star.comp.loader.JavaLoader
     */
    // This method not longer necessary since OOo 3.4 where the component registration
    // was changed to passive component registration. For more details see
    // https://wiki.openoffice.org/wiki/Passive_Component_Registration

//     public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) {
//         return Factory.writeRegistryServiceInfo(ToDoImpl.class.getName(),
//                                                 ToDoImpl.getServiceNames(), regKey);
//     }
}

