xref: /aoo42x/main/odk/examples/java/ToDo/ToDo.java (revision 62edf1a8)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 import com.sun.star.lib.uno.helper.Factory;
25 import com.sun.star.lang.XInitialization;
26 import com.sun.star.lang.XMultiComponentFactory;
27 import com.sun.star.lang.XSingleComponentFactory;
28 import com.sun.star.lang.XMultiServiceFactory;
29 import com.sun.star.lang.XServiceInfo;
30 import com.sun.star.lang.XTypeProvider;
31 import com.sun.star.lib.uno.helper.WeakBase;
32 import com.sun.star.registry.XRegistryKey;
33 import com.sun.star.uno.Type;
34 import com.sun.star.uno.UnoRuntime;
35 import com.sun.star.uno.XInterface;
36 import com.sun.star.uno.XWeak;
37 import com.sun.star.uno.XComponentContext;
38 import org.openoffice.*;
39 
40 // additional interfaces used by the implementation
41 import com.sun.star.sheet.XSpreadsheetDocument;
42 import com.sun.star.sheet.XSpreadsheet;
43 import com.sun.star.sheet.XCellRangeMovement;
44 import com.sun.star.sheet.XFunctionAccess;
45 import com.sun.star.container.XIndexAccess;
46 import com.sun.star.table.XCellRange;
47 import com.sun.star.table.XCell;
48 import com.sun.star.table.CellAddress;
49 import com.sun.star.table.CellRangeAddress;
50 import com.sun.star.table.XColumnRowRange;
51 import com.sun.star.table.XTableRows;
52 import com.sun.star.beans.XPropertySet;
53 import com.sun.star.text.XTextRange;
54 import com.sun.star.text.XSimpleText;
55 import com.sun.star.text.XTextCursor;
56 import com.sun.star.text.XText;
57 import com.sun.star.text.XTextField;
58 
59 import java.util.GregorianCalendar;
60 import java.util.Calendar;
61 import java.util.Vector;
62 import java.util.Arrays;
63 
64 /** This class capsulates the class, that implements the minimal component, a
65  * factory for creating the service (<CODE>__getServiceFactory</CODE>) and a
66  * method, that writes the information into the given registry key
67  * (<CODE>__writeRegistryServiceInfo</CODE>).
68  */
69 public class ToDo {
70 
71     /** This class implements the component. At least the interfaces
72      * XInterface, XTypeProvider, and XWeak implemented by the helper class
73      * WeakBase and XServiceInfo should be provided by the service.
74      */
75     public static class ToDoImpl extends WeakBase implements XServiceInfo, XToDo {
76 
77         /** The service name, that must be used to get an instance of this service.
78          */
79         private static final String __serviceName = "org.openoffice.ToDo";
80 
81         /** The initial component contextr, that gives access to
82          * the service manager, supported singletons, ...
83          * It's often later used
84          */
85         private XComponentContext m_cmpCtx;
86 
87         /** The service manager, that gives access to all registered services.
88          * It's often later used
89          */
90         private XMultiComponentFactory m_xMCF;
91 
92         // Implementation helper variables
93         static private final int INT_COLUMN_FEATURE = 0;
94         static private final int INT_COLUMN_COMMENT = 1;
95         static private final int INT_COLUMN_NEEDEDDAYS = 2;
96         static private final int INT_COLUMN_STARTDATE = 3;
97         static private final int INT_COLUMN_START_DAY_OF_WEEK = 4;
98         static private final int INT_COLUMN_ENDDATE = 5;
99         static private final int INT_COLUMN_END_DAY_OF_WEEK = 6;
100         static private final int INT_COLUMN_DUEDATE = 7;
101         static private final int INT_COLUMN_STATUS = 8;
102 
103         static private final int INT_ROW_FROM = 14; // 8
104 
105         static private final int INT_ROW_HOLIDAYS_START = 4;
106         static private final int INT_COLUMN_HOLIDAYS_START = 7; // 10
107 
108         static private final String STRING_SEPARATOR = "/";
109 
110 
111         /** The constructor of the inner class has a XComponenContext parameter.
112          * @param xCompContext the initial component context
113          */
ToDoImpl(XComponentContext xCompContext)114         public ToDoImpl(XComponentContext xCompContext) {
115             try {
116                 m_cmpCtx = xCompContext;
117                 m_xMCF = m_cmpCtx.getServiceManager();
118             }
119             catch( Exception e ) {
120                 e.printStackTrace(System.err);
121             }
122         }
123 
124         /** This method returns an array of all supported service names.
125          * @return Array of supported service names.
126          */
getSupportedServiceNames()127         public String[] getSupportedServiceNames() {
128             return getServiceNames();
129         }
130 
getServiceNames()131         public static String[] getServiceNames() {
132             String[] sSupportedServiceNames = { __serviceName };
133             return sSupportedServiceNames;
134         }
135 
136         /** This method returns true, if the given service will be
137          * supported by the component.
138          * @param sService Service name.
139          * @return True, if the given service name will be supported.
140          */
supportsService(String sServiceName)141         public boolean supportsService(String sServiceName) {
142             return sServiceName.equals( __serviceName );
143         }
144 
145         /** Return the class name of the component.
146          * @return Class name of the component.
147          */
getImplementationName()148         public String getImplementationName() {
149             return ToDoImpl.class.getName();
150         }
151 
152         /** For every bug/feature listed in a spreadsheet document this method
153          * calculates the start date, day of week of the start date, the end date
154          * and the day of week of the end date. All calculations are dependent
155          * on the values of "Needed Days", "Due Date" and "Status". The columns
156          * "Needed Days" and "Status" are mandatory. The first feature/bug should
157          * be placed in row nine. The date to start the calculation should be
158          * placed in cell C6. The private holidays should be placed in cell K4/K5
159          * and below. All rows will be calculated up to the first empty cell in
160          * the first column. If a cell in the column "Due Date" will be colored
161          * red, you should take a look at your entries.
162          * @param aInstance Spreadsheet document.
163          * @throws com.sun.star.uno.RuntimeException This exception could occur
164          *                                           at every interface method.
165          */
recalc( java.lang.Object aInstance )166         public void recalc( java.lang.Object aInstance )
167             throws com.sun.star.uno.RuntimeException {
168             try {
169                 // Querying for the interface XSpreadsheetDocument
170                 XSpreadsheetDocument xspreadsheetdocument =
171                     ( XSpreadsheetDocument ) UnoRuntime.queryInterface(
172                         XSpreadsheetDocument.class, aInstance );
173 
174                 // Querying for the interface XIndexAccess
175                 XIndexAccess xindexaccess = ( XIndexAccess )
176                     UnoRuntime.queryInterface( XIndexAccess.class,
177                                                xspreadsheetdocument.getSheets() );
178 
179                 // Getting the first XSpreadsheet
180                 XSpreadsheet xspreadsheet = (XSpreadsheet)UnoRuntime.queryInterface(
181                     XSpreadsheet.class, xindexaccess.getByIndex( 0 ));
182 
183                 // Querying for the interface XCellRange on the XSpeadsheet
184                 XCellRange xcellrange = ( XCellRange )
185                 UnoRuntime.queryInterface( XCellRange.class, xspreadsheet );
186 
187                 /* Getting the Gregorian calendar with the date on which to start
188                    the calculation */
189                 GregorianCalendar gregCalAbsoluteStartDate =
190                     this.getGregorianCalendarFromString(this.getStringFromCell(
191                                                             xcellrange, 5, 2 ) );
192                 gregCalAbsoluteStartDate.add( Calendar.DATE, -1 );
193 
194                 // Set the start date with the absolute start date
195                 GregorianCalendar gregCalStartDate =
196                 (GregorianCalendar) gregCalAbsoluteStartDate.clone();
197 
198                 /* Creating the service FunctionAccess, which allows generic
199                    access to all spreadsheet functions */
200                 Object objectFunctionAccess =
201                     m_xMCF.createInstanceWithContext(
202                         "com.sun.star.sheet.FunctionAccess", m_cmpCtx );
203 
204                 // Querying for the interface XFunctionAccess on service
205                 // FunctionAccess
206                 XFunctionAccess xfunctionaccess = (XFunctionAccess)
207                     UnoRuntime.queryInterface(XFunctionAccess.class,
208                                               objectFunctionAccess );
209 
210                 // Creating vector for holidays
211                 Vector vectorHolidays = new Vector();
212 
213                 // Get the Official Holidays
214                 this.getOfficialHolidays( vectorHolidays, xcellrange,
215                                           xfunctionaccess,
216                                           gregCalStartDate.get(
217                                               Calendar.YEAR ) );
218 
219                 // Get the private holidays
220                 this.getPrivateHolidays(vectorHolidays, xcellrange,
221                                         xfunctionaccess);
222 
223                 // Getting the object array of holidays
224                 Object[] objectSortedHolidays = vectorHolidays.toArray();
225 
226                 // Sorting the holidays
227                 Arrays.sort( objectSortedHolidays );
228 
229                 // Collect the Official Holidays and the private holidays
230                 Object [][]objectHolidays =
231                 new Object[][] { objectSortedHolidays };
232 
233                 // Row index
234                 int intRowTo = this.INT_ROW_FROM - 1;
235 
236                 // Getting the feature of the first cell
237                 String sFeature = this.getStringFromCell(xcellrange,
238                                                          intRowTo + 1,
239                                                          this.INT_COLUMN_FEATURE);
240 
241                 // Determine the last row with an entry in the first column
242                 while ( ( sFeature != null ) &&
243                         ( !sFeature.equals( "" ) ) ) {
244                     intRowTo++;
245                     sFeature = this.getStringFromCell( xcellrange,
246                     intRowTo + 1, this.INT_COLUMN_FEATURE );
247                 }
248 
249                 // Setting the last row to be calculated
250                 final int INT_ROW_TO = intRowTo + 1;
251 
252                 // Deleting cells which will be recalculated
253                 for ( int intRow = this.INT_ROW_FROM; intRow < INT_ROW_TO + 5;
254                       intRow++ ) {
255                     for ( int intColumn = this.INT_COLUMN_STARTDATE;
256                           intColumn <= this.INT_COLUMN_END_DAY_OF_WEEK;
257                           intColumn++ ) {
258                         this.setStringToCell(xcellrange, intRow, intColumn, "");
259                     }
260                 }
261 
262                 /* Clearing the background color of the due date cells and setting
263                    the hyperlink to the bugtracker */
264                 for (int intRow = this.INT_ROW_FROM; intRow < INT_ROW_TO; intRow++)
265                 {
266                     // Querying for the interface XPropertySet for the cell
267                     // providing the due date
268                     XPropertySet xpropertyset = ( XPropertySet )
269                         UnoRuntime.queryInterface(XPropertySet.class,
270                                                   xcellrange.getCellByPosition(
271                                                       this.INT_COLUMN_DUEDATE,
272                                                       intRow ));
273 
274                     // Changing the background color of the cell to white
275                     xpropertyset.setPropertyValue( "CellBackColor",
276                     new Integer( 16777215 ) );
277 
278                     // Getting the cell of the bug id
279                     XCell xcell = xcellrange.getCellByPosition(
280                     this.INT_COLUMN_FEATURE, intRow );
281 
282                     // Querying for the interface XSimpleText
283                     XSimpleText xsimpletext = ( XSimpleText )
284                     UnoRuntime.queryInterface( XSimpleText.class, xcell );
285 
286                     // Getting the text cursor
287                     XTextCursor xtextcursor = xsimpletext.createTextCursor();
288 
289                     // Querying for the interface XTextRange
290                     XTextRange xtextrange = ( XTextRange )
291                     UnoRuntime.queryInterface( XTextRange.class, xtextcursor );
292 
293                     // Getting the bug ID from the cell
294                     String sBugID = xtextrange.getString();
295                     if ( !sBugID.startsWith(
296                              "http://www.openoffice.org/issues/show_bug.cgi?id=") ) {
297                         String sBugIDLink =
298                             "http://www.openoffice.org/issues/show_bug.cgi?id=" + sBugID;
299 
300                         // Querying for the interface XMultiServiceFactory
301                         XMultiServiceFactory xMSFTextField =
302                             (XMultiServiceFactory)UnoRuntime.queryInterface(
303                                 XMultiServiceFactory.class, aInstance );
304 
305                         // Creating an instance of the text field URL
306                         Object objectTextField =
307                             xMSFTextField.createInstance(
308                                 "com.sun.star.text.TextField.URL" );
309 
310                         // Querying for the interface XTextField
311                         XTextField xtextfield = ( XTextField )
312                             UnoRuntime.queryInterface( XTextField.class,
313                                                        objectTextField );
314 
315                         // Querying for the interface XPropertySet
316                         XPropertySet xpropertysetTextField = ( XPropertySet )
317                             UnoRuntime.queryInterface( XPropertySet.class,
318                                                        xtextfield );
319 
320                         // Setting the URL
321                         xpropertysetTextField.setPropertyValue( "URL",
322                                                                 sBugIDLink );
323 
324                         // Setting the representation of the URL
325                         xpropertysetTextField.setPropertyValue( "Representation",
326                                                                 sBugID );
327 
328                         // Querying for the interface XText
329                         XText xtext = ( XText )UnoRuntime.queryInterface(
330                             XText.class, xcell );
331 
332                         // Delete cell content
333                         xtextrange.setString( "" );
334 
335                         // Inserting the text field URL to the cell
336                         xtext.insertTextContent( xtextrange, xtextfield, false );
337                     }
338                 }
339 
340                 // Processing all features/bugs in the table
341                 for (int intRow = this.INT_ROW_FROM; intRow < INT_ROW_TO; intRow++)
342                 {
343                     // Getting the cell of the column "Needed Days" in the
344                     // current row
345                     XCell xcell = xcellrange.getCellByPosition(
346                         INT_COLUMN_NEEDEDDAYS, intRow );
347 
348                     // Getting the number of needed days to perform the feature
349                     int intNeededDays = (int) Math.round( xcell.getValue() );
350 
351                     // Getting the content of a specified cell
352                     String sStatus = this.getStringFromCell( xcellrange,
353                     intRow, this.INT_COLUMN_STATUS );
354 
355                     /* Testing if the number of needed days is greater than
356                        zero and if
357                        the status is not "done" */
358                     if ( ( intNeededDays > 0 )
359                          && !( sStatus.toLowerCase().trim().equals("done")) ) {
360                         // Getting the start date after a specified number of
361                         // workdays
362                         gregCalStartDate = this.getWorkday(
363                             gregCalStartDate, 1, objectHolidays,
364                             xfunctionaccess );
365 
366                         // Getting a string with the date format jjjj-mm-dd from
367                         // the Gregorian calendar
368                         String sDate = this.getStringFromGregorianCalendar(
369                             gregCalStartDate );
370 
371                         // Set the start date in the specified cell of the table
372                         this.setStringToCell(xcellrange, intRow,
373                                              this.INT_COLUMN_STARTDATE, sDate);
374 
375                         // For the start day set the day of week in the specified
376                         // cell of the table
377                         this.setDayOfWeek( gregCalStartDate,
378                                            xcellrange, intRow,
379                                            this.INT_COLUMN_START_DAY_OF_WEEK );
380 
381                         // Getting the end date after a specified number of workdays
382                         GregorianCalendar gregCalEndDate =
383                             this.getWorkday( gregCalStartDate,
384                                              intNeededDays - 1,
385                                              objectHolidays, xfunctionaccess );
386 
387                         // Creating a string with the date format jjjj-mm-dd
388                         sDate = this.getStringFromGregorianCalendar(
389                             gregCalEndDate );
390 
391                         // Set the end date in the specified cell of the table
392                         this.setStringToCell( xcellrange, intRow,
393                                               this.INT_COLUMN_ENDDATE, sDate );
394 
395                         // For the end day set the day of week in the specified
396                         // cell of the table
397                         this.setDayOfWeek(gregCalEndDate, xcellrange,
398                                           intRow, this.INT_COLUMN_END_DAY_OF_WEEK);
399 
400                         // Set the initial date for the next loop
401                         gregCalStartDate = ( GregorianCalendar )
402                             gregCalEndDate.clone();
403 
404                         // Get the due date from the table
405                         String sDueDate = this.getStringFromCell(
406                             xcellrange, intRow, this.INT_COLUMN_DUEDATE );
407 
408                         // Testing if the due date is not empty
409                         if ( !sDueDate.equals( "" ) ) {
410                             GregorianCalendar gregCalDueDate =
411                                 this.getGregorianCalendarFromString(sDueDate);
412 
413                             // Testing if the due date is before the calculated
414                             // end date
415                             if ( gregCalDueDate.before(
416                                      gregCalEndDate ) ) {
417                                 /* Getting the date when the processing of the
418                                    feature/bug should
419                                    be started at the latest */
420                                 GregorianCalendar gregCalLatestDateToStart =
421                                     this.getWorkday(gregCalDueDate,
422                                                     -( intNeededDays - 1 ),
423                                                     objectHolidays,
424                                                     xfunctionaccess);
425 
426                                 // Begin with the current row
427                                 int intRowToInsert = intRow;
428 
429                                 // Get the start date for the feature/bug in the
430                                 // current row
431                                 GregorianCalendar gregCalPreviousStartDate =
432                                     this.getGregorianCalendarFromString(
433                                         this.getStringFromCell(
434                                             xcellrange, intRowToInsert,
435                                             this.INT_COLUMN_STARTDATE ) );
436 
437                                 // Testing if we have to search for an earlier date
438                                 // to begin
439                                 while ((gregCalLatestDateToStart.before(
440                                             gregCalPreviousStartDate)) &&
441                                         (INT_ROW_FROM != intRowToInsert)) {
442                                     // Decrease the row
443                                     intRowToInsert--;
444 
445                                     // Get the start date for the feature/bug in
446                                     // the current row
447                                     String sStartDate = this.getStringFromCell(
448                                         xcellrange, intRowToInsert,
449                                         this.INT_COLUMN_STARTDATE );
450 
451                                     // Search until a valid start date is found
452                                     while ( sStartDate.equals( "" ) ) {
453                                         // Decrease the row
454                                         intRowToInsert--;
455 
456                                         // Get the start date for the feature/bug
457                                         // in the current row
458                                         sStartDate = this.getStringFromCell(
459                                             xcellrange, intRowToInsert,
460                                             this.INT_COLUMN_STARTDATE );
461                                     }
462 
463                                     // Get the GregorianCalender format for the
464                                     // start date
465                                     gregCalPreviousStartDate =
466                                         this.getGregorianCalendarFromString(
467                                             sStartDate );
468                                 }
469 
470                                 // Getting the cell of the column "Needed Days"
471                                 // in the row where to insert
472                                 XCell xcellNeededDaysWhereToInsert =
473                                     xcellrange.getCellByPosition(
474                                         INT_COLUMN_NEEDEDDAYS, intRowToInsert );
475                                 // Getting the number of needed days to perform
476                                 // the feature
477                                 int intNeededDaysWhereToInsert = (int)
478                                     Math.round(
479                                         xcellNeededDaysWhereToInsert.getValue());
480 
481                                 GregorianCalendar gregCalPreviousNewEndDate =
482                                     this.getWorkday(gregCalPreviousStartDate,
483                                                     intNeededDays - 1 +
484                                                     intNeededDaysWhereToInsert,
485                                                     objectHolidays,
486                                                     xfunctionaccess);
487                                 String sPreviousDueDate = this.getStringFromCell(
488                                     xcellrange, intRowToInsert,
489                                     this.INT_COLUMN_DUEDATE );
490 
491                                 GregorianCalendar gregCalPreviousDueDate = null;
492 
493                                 if ( !sPreviousDueDate.equals( "" ) ) {
494                                     gregCalPreviousDueDate =
495                                         this.getGregorianCalendarFromString(
496                                             sPreviousDueDate );
497                                 }
498 
499                                 if ( ( intRowToInsert == intRow ) ||
500                                      ( gregCalPreviousNewEndDate.after(
501                                          gregCalPreviousDueDate ) ) ) {
502                                     // Querying for the interface XPropertySet for
503                                     // the cell providing the due date
504                                     XPropertySet xpropertyset = ( XPropertySet )
505                                         UnoRuntime.queryInterface(
506                                             XPropertySet.class,
507                                             xcellrange.getCellByPosition(
508                                                 this.INT_COLUMN_DUEDATE,
509                                                 intRow ) );
510 
511                                     // Changing the background color of the cell
512                                     // to red
513                                     xpropertyset.setPropertyValue(
514                                         "CellBackColor", new Integer( 16711680 ) );
515                                 } else {
516                                     // Querying for the interface XColumnRowRange
517                                     // on the XCellRange
518                                     XColumnRowRange xcolumnrowrange =
519                                         ( XColumnRowRange)UnoRuntime.queryInterface(
520                                             XColumnRowRange.class, xcellrange );
521                                     // Inserting one row to the table
522                                     XTableRows xTableRows =
523                                         xcolumnrowrange.getRows();
524                                     xTableRows.insertByIndex( intRowToInsert, 1 );
525 
526                                     // Querying for the interface
527                                     // XCellRangeMovement on XCellRange
528                                     XCellRangeMovement xcellrangemovement =
529                                       (XCellRangeMovement)UnoRuntime.queryInterface(
530                                           XCellRangeMovement.class, xcellrange );
531 
532                                     // Creating the cell address of the destination
533                                     CellAddress celladdress = new CellAddress();
534                                     celladdress.Sheet = 0;
535                                     celladdress.Column = 0;
536                                     celladdress.Row = intRowToInsert;
537 
538                                     // Creating the cell range of the source
539                                     CellRangeAddress cellrangeaddress =
540                                     new CellRangeAddress();
541                                     cellrangeaddress.Sheet = 0;
542                                     cellrangeaddress.StartColumn = 0;
543                                     cellrangeaddress.StartRow = intRow + 1;
544                                     cellrangeaddress.EndColumn = 8;
545                                     cellrangeaddress.EndRow = intRow + 1;
546 
547                                     // Moves the cell range to another position in
548                                     // the document
549                                     xcellrangemovement.moveRange(celladdress,
550                                                                  cellrangeaddress);
551 
552                                     // Removing the row not needed anymore
553                                     xcolumnrowrange.getRows().removeByIndex(intRow
554                                                                             + 1, 1);
555 
556                                     // Set the current row, because we want to
557                                     // recalculate all rows below
558                                     intRow = intRowToInsert - 1;
559 
560                                     // Tests at which line we want to insert
561                                     if ( intRow >= this.INT_ROW_FROM ) {
562                                         // Get the start date
563                                         gregCalStartDate =
564                                             this.getGregorianCalendarFromString(
565                                                 this.getStringFromCell( xcellrange,
566                                                    intRow,this.INT_COLUMN_ENDDATE));
567                                     }
568                                     else {
569                                         // Set the start date with the absolute s
570                                         // tart date
571                                         gregCalStartDate = (GregorianCalendar)
572                                             gregCalAbsoluteStartDate.clone();
573                                     }
574                                 }
575                             }
576                         }
577                     }
578                 }
579             }
580             catch( Exception exception ) {
581                 showExceptionMessage( exception );
582             }
583         }
584 
585         /** Getting a string from a Gregorian calendar.
586          * @param gregCal Date to be converted.
587          * @return string (converted Gregorian calendar).
588          */
getStringFromGregorianCalendar( GregorianCalendar gregCal )589         public String getStringFromGregorianCalendar( GregorianCalendar gregCal ) {
590             String sDate = ( gregCal.get( Calendar.MONTH ) + 1 )
591                 + STRING_SEPARATOR + gregCal.get( Calendar.DATE )
592 //                + STRING_SEPARATOR + ( gregCal.get( Calendar.MONTH ) + 1 )
593                 + STRING_SEPARATOR + gregCal.get( Calendar.YEAR );
594 
595             return sDate;
596         }
597 
598         /** Getting a GregorianCalendar from a string.
599          * @param sDate String to be converted.
600          * @return The result of the converting of the string.
601          */
getGregorianCalendarFromString( String sDate )602         public GregorianCalendar getGregorianCalendarFromString( String sDate ) {
603             int []intDateValue = this.getDateValuesFromString( sDate );
604 
605             return( new GregorianCalendar( intDateValue[ 2 ], intDateValue[ 0 ],
606                                            intDateValue[ 1 ] ) );
607         }
608 
609         /** Getting the day, month and year from a string.
610          * @param sDate String to be parsed.
611          * @return Returns an array of integer variables.
612          */
getDateValuesFromString( String sDate)613         public int[] getDateValuesFromString( String sDate) {
614             int[] intDateValues = new int[ 3 ];
615 
616             int intPositionFirstTag = sDate.indexOf( STRING_SEPARATOR );
617             int intPositionSecondTag = sDate.indexOf(STRING_SEPARATOR,
618                                                      intPositionFirstTag + 1);
619 
620             // Getting the value of the month
621             intDateValues[ 0 ] = Integer.parseInt(
622                 sDate.substring(0, intPositionFirstTag)) - 1;
623             // Getting the value of the day
624             intDateValues[ 1 ] = Integer.parseInt(
625                 sDate.substring(intPositionFirstTag + 1, intPositionSecondTag));
626             // Getting the value of the year
627             intDateValues[ 2 ] = Integer.parseInt(
628                 sDate.substring(intPositionSecondTag + 1, sDate.length()));
629 
630             return intDateValues;
631         }
632 
633         /** Getting a content from a specified cell.
634          * @param xcellrange Providing access to cells.
635          * @param intRow Number of row.
636          * @param intColumn Number of column.
637          * @return String from the specified cell.
638          */
getStringFromCell( XCellRange xcellrange, int intRow, int intColumn )639         public String getStringFromCell( XCellRange xcellrange, int intRow,
640                                          int intColumn ) {
641             XTextRange xtextrangeStartDate = null;
642 
643             try {
644                 // Getting the cell holding the information about the start date
645                 XCell xcellStartDate = xcellrange.getCellByPosition(intColumn,
646                                                                     intRow);
647                 // Querying for the interface XTextRange on the XCell
648                 xtextrangeStartDate = (XTextRange)
649                     UnoRuntime.queryInterface(XTextRange.class, xcellStartDate);
650             }
651             catch( Exception exception ) {
652                 this.showExceptionMessage( exception );
653             }
654 
655             // Getting the start date
656             return xtextrangeStartDate.getString().trim();
657         }
658 
659         /** Writing a specified string to a specified cell.
660          * @param xcellrange Providing access to the cells.
661          * @param intRow Number of row.
662          * @param intColumn Number of column.
663          * @param sDate Date to write to the cell.
664          */
setStringToCell( XCellRange xcellrange, int intRow, int intColumn, String sDate )665         public void setStringToCell( XCellRange xcellrange, int intRow,
666                                      int intColumn, String sDate ) {
667             try {
668                 // Getting the cell holding the information on the day to start
669                 XCell xcellStartDate = xcellrange.getCellByPosition(intColumn,
670                                                                     intRow);
671                 // Querying for the interface XTextRange on the XCell
672                 XTextRange xtextrange = (XTextRange)
673                     UnoRuntime.queryInterface(XTextRange.class, xcellStartDate);
674                 // Setting the new start date
675                 xtextrange.setString( sDate );
676             }
677             catch( Exception exception ) {
678                 this.showExceptionMessage( exception );
679             }
680         }
681 
682         /** Calculates the week of day and calls the method "setStringToCell".
683          * @param gregCal Day to be written to the cell.
684          * @param xcellrange Providing access to the cells.
685          * @param intRow Number of row.
686          * @param intColumn Number of column.
687          */
setDayOfWeek( GregorianCalendar gregCal, XCellRange xcellrange, int intRow, int intColumn)688         public void setDayOfWeek( GregorianCalendar gregCal,
689                                   XCellRange xcellrange, int intRow,
690                                   int intColumn) {
691             int intDayOfWeek = gregCal.get( Calendar.DAY_OF_WEEK );
692             String sDayOfWeek = "";
693             if ( intDayOfWeek == Calendar.MONDAY ) {
694                 sDayOfWeek = "MON";
695             } else if ( intDayOfWeek == Calendar.TUESDAY ) {
696                 sDayOfWeek = "TUE";
697             } else if ( intDayOfWeek == Calendar.WEDNESDAY ) {
698                 sDayOfWeek = "WED";
699             } else if ( intDayOfWeek == Calendar.THURSDAY ) {
700                 sDayOfWeek = "THU";
701             } else if ( intDayOfWeek == Calendar.FRIDAY ) {
702                 sDayOfWeek = "FRI";
703             }
704 
705             this.setStringToCell( xcellrange, intRow, intColumn,
706             sDayOfWeek );
707         }
708 
709         /** Calculates the dates of the official holidays with help of Calc
710          * functions.
711          * @param vectorHolidays Holding all holidays.
712          * @param xcellrange Providing the cells.
713          * @param xfunctionaccess Provides access to functions of the Calc.
714          * @param intYear Year to calculate the official holidays.
715          */
getOfficialHolidays( Vector vectorHolidays, XCellRange xcellrange, XFunctionAccess xfunctionaccess, int intYear )716         public void getOfficialHolidays(
717         Vector vectorHolidays,
718         XCellRange xcellrange,
719         XFunctionAccess xfunctionaccess,
720         int intYear ) {
721             try {
722                 // Official Holidays for how many years?
723                 final int intHowManyYears = 2;
724 
725                 // Get the Official Holiday for two years
726                 for ( int intNumberOfYear = 0;
727                       intNumberOfYear <= ( intHowManyYears - 1 );
728                       intNumberOfYear++ ) {
729                     intYear += intNumberOfYear;
730 
731                     // Getting the Easter Sunday
732                     Double dEasterSunday = ( Double )
733                         xfunctionaccess.callFunction(
734                             "EASTERSUNDAY", new Object[] { new Integer(intYear) });
735 
736                     int intEasterSunday = (int)Math.round(
737                         dEasterSunday.doubleValue());
738 
739                     // New-year
740                     vectorHolidays.addElement( xfunctionaccess.callFunction(
741                                                    "DATE",
742                                                    new Object[] {
743                                                        new Integer( intYear ),
744                                                        new Integer( 1 ),
745                                                        new Integer( 1 ) } ));
746 
747                     // Good Friday
748                     vectorHolidays.addElement(
749                     new Double( intEasterSunday - 2 ) );
750 
751                     // Easter Monday
752                     vectorHolidays.addElement(
753                     new Double( intEasterSunday + 1 ) );
754 
755                     // Labour Day
756                     vectorHolidays.addElement( xfunctionaccess.callFunction(
757                                                    "DATE",
758                                                    new Object[] {
759                                                        new Integer( intYear ),
760                                                        new Integer( 5 ),
761                                                        new Integer( 1 ) } ));
762 
763                     // Ascension Day
764                     vectorHolidays.addElement(new Double(intEasterSunday + 39 ));
765 
766                     // Pentecost Monday
767                     vectorHolidays.addElement(new Double(intEasterSunday + 50 ));
768 
769                     // German Unification
770                     vectorHolidays.addElement( xfunctionaccess.callFunction(
771                                                    "DATE",
772                                                    new Object[] {
773                                                        new Integer( intYear ),
774                                                        new Integer( 10 ),
775                                                        new Integer( 3 ) } ));
776 
777                     // Christmas Day First
778                     vectorHolidays.addElement( xfunctionaccess.callFunction(
779                                                    "DATE",
780                                                    new Object[] {
781                                                        new Integer( intYear ),
782                                                        new Integer( 12 ),
783                                                        new Integer( 25 ) } ));
784 
785                     // Christmas Day Second
786                     vectorHolidays.addElement( xfunctionaccess.callFunction(
787                                                    "DATE",
788                                                    new Object[] {
789                                                        new Integer( intYear ),
790                                                        new Integer( 12 ),
791                                                        new Integer( 26 ) } ));
792                 }
793             }
794             catch( Exception exception ) {
795                 this.showExceptionMessage( exception );
796             }
797         }
798 
799         /** Returns the serial number of the date before or after a specified
800          * number of workdays.
801          * @param gregCalStartDate Date to start with the calculation.
802          * @param intDays Number of workdays (e.g. 5 or -3).
803          * @param objectHolidays Private and public holidays to take into account.
804          * @param xfunctionaccess Allows to call functions from the Calc.
805          * @return The gregorian date before or after a specified number of
806          *         workdays.
807          */
getWorkday( GregorianCalendar gregCalStartDate, int intDays, Object[][] objectHolidays, XFunctionAccess xfunctionaccess )808         public GregorianCalendar getWorkday(
809             GregorianCalendar gregCalStartDate,
810             int intDays, Object[][] objectHolidays,
811             XFunctionAccess xfunctionaccess ) {
812             GregorianCalendar gregCalWorkday = null;
813 
814             try {
815                 // Getting the value of the start date
816                 Double dDate = ( Double ) xfunctionaccess.callFunction(
817                     "DATE",
818                     new Object[] {
819                         new Integer( gregCalStartDate.get( Calendar.YEAR ) ),
820                         new Integer( gregCalStartDate.get( Calendar.MONTH ) + 1 ),
821                         new Integer( gregCalStartDate.get( Calendar.DATE ) )
822                     } );
823 
824                 Double dWorkday = ( Double ) xfunctionaccess.callFunction(
825                 "com.sun.star.sheet.addin.Analysis.getWorkday",
826                 new Object[] { dDate, new Integer( intDays ), objectHolidays } );
827 
828                 Double dYear = ( Double ) xfunctionaccess.callFunction(
829                     "YEAR", new Object[] { dWorkday } );
830                 Double dMonth = ( Double ) xfunctionaccess.callFunction(
831                     "MONTH", new Object[] { dWorkday } );
832                 Double dDay = ( Double ) xfunctionaccess.callFunction(
833                     "DAY", new Object[] { dWorkday } );
834 
835                 gregCalWorkday = new GregorianCalendar(
836                 dYear.intValue(),
837                 dMonth.intValue() - 1,
838                 dDay.intValue() );
839             }
840             catch( Exception exception ) {
841                 this.showExceptionMessage( exception );
842             }
843 
844             return gregCalWorkday;
845         }
846 
847         /** Getting the holidays from the spreadsheet.
848          * @param vectorHolidays Holding all holidays.
849          * @param xcellrange Providing the cells.
850          * @param xfunctionaccess Provides the access to functions of the Calc.
851          */
getPrivateHolidays( Vector vectorHolidays, XCellRange xcellrange, XFunctionAccess xfunctionaccess )852         public void getPrivateHolidays( Vector vectorHolidays,
853                                         XCellRange xcellrange,
854                                         XFunctionAccess xfunctionaccess ) {
855             try {
856                 int intRow = this.INT_ROW_HOLIDAYS_START;
857                 int intColumn = this.INT_COLUMN_HOLIDAYS_START;
858 
859                 double dHolidayStart = xcellrange.getCellByPosition(
860                     intColumn, intRow ).getValue();
861 
862                 double dHolidayEnd = xcellrange.getCellByPosition(
863                     intColumn + 1, intRow ).getValue();
864 
865                 while ( dHolidayStart != 0 ) {
866                     if ( dHolidayEnd == 0 ) {
867                         vectorHolidays.addElement(
868                             new Integer( (int) Math.round(
869                                              dHolidayStart ) ) );
870                     }
871                     else {
872                         for ( int intHoliday = (int) Math.round(
873                                   dHolidayStart );
874                               intHoliday <= (int) Math.round( dHolidayEnd );
875                               intHoliday++ ) {
876                             vectorHolidays.addElement( new Double( intHoliday ) );
877                         }
878                     }
879 
880                     intRow++;
881                     dHolidayStart = xcellrange.getCellByPosition(
882                         intColumn, intRow).getValue();
883                     dHolidayEnd = xcellrange.getCellByPosition(
884                         intColumn + 1, intRow).getValue();
885                 }
886             }
887             catch( Exception exception ) {
888                 this.showExceptionMessage( exception );
889             }
890         }
891 
892         /** Showing the stack trace in a JOptionPane.
893          * @param sMessage The message to show.
894          */
showMessage( String sMessage )895         public void showMessage( String sMessage ) {
896             javax.swing.JFrame jframe = new javax.swing.JFrame();
897             jframe.setLocation(100, 100);
898             jframe.setSize(300, 200);
899             jframe.setVisible(true);
900             javax.swing.JOptionPane.showMessageDialog(
901                 jframe, sMessage, "Debugging information",
902                 javax.swing.JOptionPane.INFORMATION_MESSAGE);
903             jframe.dispose();
904         }
905 
906         /** Writing the stack trace from an exception to a string and calling
907          * the method showMessage() with this string.
908          * @param exception The occurred exception.
909          * @see showMessage
910          */
showExceptionMessage( Exception exception )911         public void showExceptionMessage( Exception exception ) {
912             java.io.StringWriter swriter = new java.io.StringWriter();
913             java.io.PrintWriter printwriter =
914                 new java.io.PrintWriter( swriter );
915             exception.printStackTrace( printwriter);
916             System.err.println( exception );
917             this.showMessage( swriter.getBuffer().substring(0) );
918         }
919     }
920 
921     /**
922      * Gives a factory for creating the service.
923      * This method is called by the <code>JavaLoader</code>
924      * <p>
925      * @return  returns a <code>XSingleComponentFactory</code> for creating
926      *          the component
927      * @param   sImplName the name of the implementation for which a
928      *          service is desired
929      * @see     com.sun.star.comp.loader.JavaLoader
930      */
__getComponentFactory(String sImplName)931     public static XSingleComponentFactory __getComponentFactory(String sImplName) {
932         XSingleComponentFactory xFactory = null;
933 
934         if ( sImplName.equals( ToDoImpl.class.getName() ) )
935             xFactory = Factory.createComponentFactory(ToDoImpl.class,
936                                                       ToDoImpl.getServiceNames());
937 
938         return xFactory;
939     }
940 
941     /**
942      * Writes the service information into the given registry key.
943      * This method is called by the <code>JavaLoader</code>
944      * <p>
945      * @return  returns true if the operation succeeded
946      * @param   regKey the registryKey
947      * @see     com.sun.star.comp.loader.JavaLoader
948      */
949     // This method not longer necessary since OOo 3.4 where the component registration
950     // was changed to passive component registration. For more details see
951     // https://wiki.openoffice.org/wiki/Passive_Component_Registration
952 
953 //     public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) {
954 //         return Factory.writeRegistryServiceInfo(ToDoImpl.class.getName(),
955 //                                                 ToDoImpl.getServiceNames(), regKey);
956 //     }
957 }
958 
959