cid#1607171 Data race condition
[LibreOffice.git] / odk / examples / java / ToDo / ToDo.java
blob36d0d7eece6a7b1ac83393333b2739a7a3ac9001
1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * The Contents of this file are made available subject to the terms of
5 * the BSD license.
7 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of Sun Microsystems, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
29 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
31 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
32 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *************************************************************************/
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.Calendar;
39 import java.util.GregorianCalendar;
41 import com.sun.star.beans.XPropertySet;
42 import com.sun.star.container.XIndexAccess;
43 import com.sun.star.lang.XMultiComponentFactory;
44 import com.sun.star.lang.XMultiServiceFactory;
45 import com.sun.star.lang.XServiceInfo;
46 import com.sun.star.lang.XSingleComponentFactory;
47 import com.sun.star.lib.uno.helper.Factory;
48 import com.sun.star.lib.uno.helper.WeakBase;
49 import com.sun.star.sheet.XCellRangeMovement;
50 import com.sun.star.sheet.XFunctionAccess;
51 import com.sun.star.sheet.XSpreadsheet;
52 import com.sun.star.sheet.XSpreadsheetDocument;
53 import com.sun.star.table.CellAddress;
54 import com.sun.star.table.CellRangeAddress;
55 import com.sun.star.table.XCell;
56 import com.sun.star.table.XCellRange;
57 import com.sun.star.table.XColumnRowRange;
58 import com.sun.star.table.XTableRows;
59 import com.sun.star.text.XSimpleText;
60 import com.sun.star.text.XText;
61 import com.sun.star.text.XTextCursor;
62 import com.sun.star.text.XTextField;
63 import com.sun.star.text.XTextRange;
64 import com.sun.star.uno.UnoRuntime;
65 import com.sun.star.uno.XComponentContext;
66 import org.openoffice.XToDo;
68 /** This class capsulates the class, that implements the minimal component, a
69 * factory for creating the service (<CODE>__getServiceFactory</CODE>) and a
70 * method, that writes the information into the given registry key
71 * (<CODE>__writeRegistryServiceInfo</CODE>).
73 public class ToDo {
75 /** This class implements the component. At least the interfaces
76 * XInterface, XTypeProvider, and XWeak implemented by the helper class
77 * WeakBase and XServiceInfo should be provided by the service.
79 public static class ToDoImpl extends WeakBase implements XServiceInfo, XToDo {
81 /** The service name, that must be used to get an instance of this service.
83 private static final String __serviceName = "org.openoffice.ToDo";
85 /** The initial component contextr, that gives access to
86 * the service manager, supported singletons, ...
87 * It's often later used
89 private XComponentContext m_cmpCtx;
91 /** The service manager, that gives access to all registered services.
92 * It's often later used
94 private XMultiComponentFactory m_xMCF;
96 // Implementation helper variables
97 private static final int INT_COLUMN_FEATURE = 0;
98 private static final int INT_COLUMN_NEEDEDDAYS = 2;
99 private static final int INT_COLUMN_STARTDATE = 3;
100 private static final int INT_COLUMN_START_DAY_OF_WEEK = 4;
101 private static final int INT_COLUMN_ENDDATE = 5;
102 private static final int INT_COLUMN_END_DAY_OF_WEEK = 6;
103 private static final int INT_COLUMN_DUEDATE = 7;
104 private static final int INT_COLUMN_STATUS = 8;
106 private static final int INT_ROW_FROM = 14; // 8
108 private static final int INT_ROW_HOLIDAYS_START = 4;
109 private static final int INT_COLUMN_HOLIDAYS_START = 7; // 10
111 private static final String STRING_SEPARATOR = "/";
114 /** The constructor of the inner class has a XComponenContext parameter.
115 * @param xCompContext the initial component context
117 public ToDoImpl(XComponentContext xCompContext) {
118 try {
119 m_cmpCtx = xCompContext;
120 m_xMCF = m_cmpCtx.getServiceManager();
122 catch( Exception e ) {
123 e.printStackTrace(System.err);
127 /** This method returns an array of all supported service names.
128 * @return Array of supported service names.
130 public String[] getSupportedServiceNames() {
131 return getServiceNames();
134 private static String[] getServiceNames() {
135 String[] sSupportedServiceNames = { __serviceName };
136 return sSupportedServiceNames;
139 /** This method returns true, if the given service will be
140 * supported by the component.
141 * @return True, if the given service name will be supported.
143 public boolean supportsService(String sServiceName) {
144 return sServiceName.equals( __serviceName );
147 /** Return the class name of the component.
148 * @return Class name of the component.
150 public String getImplementationName() {
151 return ToDoImpl.class.getName();
154 /** For every bug/feature listed in a spreadsheet document this method
155 * calculates the start date, day of week of the start date, the end date
156 * and the day of week of the end date. All calculations are dependent
157 * on the values of "Needed Days", "Due Date" and "Status". The columns
158 * "Needed Days" and "Status" are mandatory. The first feature/bug should
159 * be placed in row nine. The date to start the calculation should be
160 * placed in cell C6. The private holidays should be placed in cell K4/K5
161 * and below. All rows will be calculated up to the first empty cell in
162 * the first column. If a cell in the column "Due Date" will be colored
163 * red, you should take a look at your entries.
164 * @param aInstance Spreadsheet document.
165 * @throws com.sun.star.uno.RuntimeException This exception could occur
166 * at every interface method.
168 public void recalc( java.lang.Object aInstance )
169 throws com.sun.star.uno.RuntimeException {
170 try {
171 // Querying for the interface XSpreadsheetDocument
172 XSpreadsheetDocument xspreadsheetdocument =
173 UnoRuntime.queryInterface(
174 XSpreadsheetDocument.class, aInstance );
176 // Querying for the interface XIndexAccess
177 XIndexAccess xindexaccess = UnoRuntime.queryInterface( XIndexAccess.class,
178 xspreadsheetdocument.getSheets() );
180 // Getting the first XSpreadsheet
181 XSpreadsheet xspreadsheet = UnoRuntime.queryInterface(
182 XSpreadsheet.class, xindexaccess.getByIndex( 0 ));
184 // Querying for the interface XCellRange on the XSpreadsheet
185 XCellRange xcellrange = UnoRuntime.queryInterface( XCellRange.class, xspreadsheet );
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 );
194 // Set the start date with the absolute start date
195 GregorianCalendar gregCalStartDate =
196 (GregorianCalendar) gregCalAbsoluteStartDate.clone();
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 );
204 // Querying for the interface XFunctionAccess on service
205 // FunctionAccess
206 XFunctionAccess xfunctionaccess = UnoRuntime.queryInterface(XFunctionAccess.class,
207 objectFunctionAccess );
209 // Creating vector for holidays
210 ArrayList<Object> vectorHolidays = new ArrayList<Object>();
212 // Get the Official Holidays
213 this.getOfficialHolidays( vectorHolidays, xcellrange,
214 xfunctionaccess,
215 gregCalStartDate.get(
216 Calendar.YEAR ) );
218 // Get the private holidays
219 this.getPrivateHolidays(vectorHolidays, xcellrange,
220 xfunctionaccess);
222 // Getting the object array of holidays
223 Object[] objectSortedHolidays = vectorHolidays.toArray();
225 // Sorting the holidays
226 Arrays.sort( objectSortedHolidays );
228 // Collect the Official Holidays and the private holidays
229 Object [][]objectHolidays =
230 new Object[][] { objectSortedHolidays };
232 // Row index
233 int intRowTo = ToDoImpl.INT_ROW_FROM - 1;
235 // Getting the feature of the first cell
236 String sFeature = this.getStringFromCell(xcellrange,
237 intRowTo + 1,
238 ToDoImpl.INT_COLUMN_FEATURE);
240 // Determine the last row with an entry in the first column
241 while ( ( sFeature != null ) &&
242 ( !sFeature.equals( "" ) ) ) {
243 intRowTo++;
244 sFeature = this.getStringFromCell( xcellrange,
245 intRowTo + 1, ToDoImpl.INT_COLUMN_FEATURE );
248 // Setting the last row to be calculated
249 final int INT_ROW_TO = intRowTo + 1;
251 // Deleting cells which will be recalculated
252 for ( int intRow = ToDoImpl.INT_ROW_FROM; intRow < INT_ROW_TO + 5;
253 intRow++ ) {
254 for ( int intColumn = ToDoImpl.INT_COLUMN_STARTDATE;
255 intColumn <= ToDoImpl.INT_COLUMN_END_DAY_OF_WEEK;
256 intColumn++ ) {
257 this.setStringToCell(xcellrange, intRow, intColumn, "");
261 /* Clearing the background color of the due date cells and setting
262 the hyperlink to the bugtracker */
263 for (int intRow = ToDoImpl.INT_ROW_FROM; intRow < INT_ROW_TO; intRow++)
265 // Querying for the interface XPropertySet for the cell
266 // providing the due date
267 XPropertySet xpropertyset = UnoRuntime.queryInterface(XPropertySet.class,
268 xcellrange.getCellByPosition(
269 ToDoImpl.INT_COLUMN_DUEDATE,
270 intRow ));
272 // Changing the background color of the cell to white
273 xpropertyset.setPropertyValue( "CellBackColor",
274 Integer.valueOf( 16777215 ) );
276 // Getting the cell of the bug id
277 XCell xcell = xcellrange.getCellByPosition(
278 ToDoImpl.INT_COLUMN_FEATURE, intRow );
280 // Querying for the interface XSimpleText
281 XSimpleText xsimpletext = UnoRuntime.queryInterface( XSimpleText.class, xcell );
283 // Getting the text cursor
284 XTextCursor xtextcursor = xsimpletext.createTextCursor();
286 // Querying for the interface XTextRange
287 XTextRange xtextrange = UnoRuntime.queryInterface( XTextRange.class, xtextcursor );
289 // Getting the bug ID from the cell
290 String sBugID = xtextrange.getString();
291 if ( !sBugID.startsWith(
292 "http://www.openoffice.org/issues/show_bug.cgi?id=") ) {
293 String sBugIDLink =
294 "http://www.openoffice.org/issues/show_bug.cgi?id=" + sBugID;
296 // Querying for the interface XMultiServiceFactory
297 XMultiServiceFactory xMSFTextField =
298 UnoRuntime.queryInterface(
299 XMultiServiceFactory.class, aInstance );
301 // Creating an instance of the text field URL
302 Object objectTextField =
303 xMSFTextField.createInstance(
304 "com.sun.star.text.TextField.URL" );
306 // Querying for the interface XTextField
307 XTextField xtextfield = UnoRuntime.queryInterface( XTextField.class,
308 objectTextField );
310 // Querying for the interface XPropertySet
311 XPropertySet xpropertysetTextField = UnoRuntime.queryInterface( XPropertySet.class,
312 xtextfield );
314 // Setting the URL
315 xpropertysetTextField.setPropertyValue( "URL",
316 sBugIDLink );
318 // Setting the representation of the URL
319 xpropertysetTextField.setPropertyValue( "Representation",
320 sBugID );
322 // Querying for the interface XText
323 XText xtext = UnoRuntime.queryInterface(
324 XText.class, xcell );
326 // Delete cell content
327 xtextrange.setString( "" );
329 // Inserting the text field URL to the cell
330 xtext.insertTextContent( xtextrange, xtextfield, false );
334 // Processing all features/bugs in the table
335 for (int intRow = ToDoImpl.INT_ROW_FROM; intRow < INT_ROW_TO; intRow++)
337 // Getting the cell of the column "Needed Days" in the
338 // current row
339 XCell xcell = xcellrange.getCellByPosition(
340 INT_COLUMN_NEEDEDDAYS, intRow );
342 // Getting the number of needed days to perform the feature
343 int intNeededDays = (int) Math.round( xcell.getValue() );
345 // Getting the content of a specified cell
346 String sStatus = this.getStringFromCell( xcellrange,
347 intRow, ToDoImpl.INT_COLUMN_STATUS );
349 /* Testing if the number of needed days is greater than
350 zero and if
351 the status is not "done" */
352 if ( ( intNeededDays > 0 )
353 && !( sStatus.toLowerCase().trim().equals("done")) ) {
354 // Getting the start date after a specified number of
355 // workdays
356 gregCalStartDate = this.getWorkday(
357 gregCalStartDate, 1, objectHolidays,
358 xfunctionaccess );
360 // Getting a string with the date format jjjj-mm-dd from
361 // the gregorian calendar
362 String sDate = this.getStringFromGregorianCalendar(
363 gregCalStartDate );
365 // Set the start date in the specified cell of the table
366 this.setStringToCell(xcellrange, intRow,
367 ToDoImpl.INT_COLUMN_STARTDATE, sDate);
369 // For the start day set the day of week in the specified
370 // cell of the table
371 this.setDayOfWeek( gregCalStartDate,
372 xcellrange, intRow,
373 ToDoImpl.INT_COLUMN_START_DAY_OF_WEEK );
375 // Getting the end date after a specified number of workdays
376 GregorianCalendar gregCalEndDate =
377 this.getWorkday( gregCalStartDate,
378 intNeededDays - 1,
379 objectHolidays, xfunctionaccess );
381 // Creating a string with the date format jjjj-mm-dd
382 sDate = this.getStringFromGregorianCalendar(
383 gregCalEndDate );
385 // Set the end date in the specified cell of the table
386 this.setStringToCell( xcellrange, intRow,
387 ToDoImpl.INT_COLUMN_ENDDATE, sDate );
389 // For the end day set the day of week in the specified
390 // cell of the table
391 this.setDayOfWeek(gregCalEndDate, xcellrange,
392 intRow, ToDoImpl.INT_COLUMN_END_DAY_OF_WEEK);
394 // Set the initial date for the next loop
395 gregCalStartDate = ( GregorianCalendar )
396 gregCalEndDate.clone();
398 // Get the due date from the table
399 String sDueDate = this.getStringFromCell(
400 xcellrange, intRow, ToDoImpl.INT_COLUMN_DUEDATE );
402 // Testing if the due date is not empty
403 if ( !sDueDate.equals( "" ) ) {
404 GregorianCalendar gregCalDueDate =
405 this.getGregorianCalendarFromString(sDueDate);
407 // Testing if the due date is before the calculated
408 // end date
409 if ( gregCalDueDate.before(
410 gregCalEndDate ) ) {
411 /* Getting the date when the processing of the
412 feature/bug should
413 be started at the latest */
414 GregorianCalendar gregCalLatestDateToStart =
415 this.getWorkday(gregCalDueDate,
416 -( intNeededDays - 1 ),
417 objectHolidays,
418 xfunctionaccess);
420 // Begin with the current row
421 int intRowToInsert = intRow;
423 // Get the start date for the feature/bug in the
424 // current row
425 GregorianCalendar gregCalPreviousStartDate =
426 this.getGregorianCalendarFromString(
427 this.getStringFromCell(
428 xcellrange, intRowToInsert,
429 ToDoImpl.INT_COLUMN_STARTDATE ) );
431 // Testing if we have to search for an earlier date
432 // to begin
433 while ((gregCalLatestDateToStart.before(
434 gregCalPreviousStartDate)) &&
435 (INT_ROW_FROM != intRowToInsert)) {
436 // Decrease the row
437 intRowToInsert--;
439 // Get the start date for the feature/bug in
440 // the current row
441 String sStartDate = this.getStringFromCell(
442 xcellrange, intRowToInsert,
443 ToDoImpl.INT_COLUMN_STARTDATE );
445 // Search until a valid start date is found
446 while ( sStartDate.equals( "" ) ) {
447 // Decrease the row
448 intRowToInsert--;
450 // Get the start date for the feature/bug
451 // in the current row
452 sStartDate = this.getStringFromCell(
453 xcellrange, intRowToInsert,
454 ToDoImpl.INT_COLUMN_STARTDATE );
457 // Get the GregorianCalendar format for the
458 // start date
459 gregCalPreviousStartDate =
460 this.getGregorianCalendarFromString(
461 sStartDate );
464 // Getting the cell of the column "Needed Days"
465 // in the row where to insert
466 XCell xcellNeededDaysWhereToInsert =
467 xcellrange.getCellByPosition(
468 INT_COLUMN_NEEDEDDAYS, intRowToInsert );
469 // Getting the number of needed days to perform
470 // the feature
471 int intNeededDaysWhereToInsert = (int)
472 Math.round(
473 xcellNeededDaysWhereToInsert.getValue());
475 GregorianCalendar gregCalPreviousNewEndDate =
476 this.getWorkday(gregCalPreviousStartDate,
477 intNeededDays - 1 +
478 intNeededDaysWhereToInsert,
479 objectHolidays,
480 xfunctionaccess);
481 String sPreviousDueDate = this.getStringFromCell(
482 xcellrange, intRowToInsert,
483 ToDoImpl.INT_COLUMN_DUEDATE );
485 GregorianCalendar gregCalPreviousDueDate = null;
487 if ( !sPreviousDueDate.equals( "" ) ) {
488 gregCalPreviousDueDate =
489 this.getGregorianCalendarFromString(
490 sPreviousDueDate );
493 if ( ( intRowToInsert == intRow ) ||
494 ( gregCalPreviousNewEndDate.after(
495 gregCalPreviousDueDate ) ) ) {
496 // Querying for the interface XPropertySet for
497 // the cell providing the due date
498 XPropertySet xpropertyset = UnoRuntime.queryInterface(
499 XPropertySet.class,
500 xcellrange.getCellByPosition(
501 ToDoImpl.INT_COLUMN_DUEDATE,
502 intRow ) );
504 // Changing the background color of the cell
505 // to red
506 xpropertyset.setPropertyValue(
507 "CellBackColor", Integer.valueOf( 16711680 ) );
508 } else {
509 // Querying for the interface XColumnRowRange
510 // on the XCellRange
511 XColumnRowRange xcolumnrowrange =
512 UnoRuntime.queryInterface(
513 XColumnRowRange.class, xcellrange );
514 // Inserting one row to the table
515 XTableRows xTableRows =
516 xcolumnrowrange.getRows();
517 xTableRows.insertByIndex( intRowToInsert, 1 );
519 // Querying for the interface
520 // XCellRangeMovement on XCellRange
521 XCellRangeMovement xcellrangemovement =
522 UnoRuntime.queryInterface(
523 XCellRangeMovement.class, xcellrange );
525 // Creating the cell address of the destination
526 CellAddress celladdress = new CellAddress();
527 celladdress.Sheet = 0;
528 celladdress.Column = 0;
529 celladdress.Row = intRowToInsert;
531 // Creating the cell range of the source
532 CellRangeAddress cellrangeaddress =
533 new CellRangeAddress();
534 cellrangeaddress.Sheet = 0;
535 cellrangeaddress.StartColumn = 0;
536 cellrangeaddress.StartRow = intRow + 1;
537 cellrangeaddress.EndColumn = 8;
538 cellrangeaddress.EndRow = intRow + 1;
540 // Moves the cell range to another position in
541 // the document
542 xcellrangemovement.moveRange(celladdress,
543 cellrangeaddress);
545 // Removing the row not needed anymore
546 xcolumnrowrange.getRows().removeByIndex(intRow
547 + 1, 1);
549 // Set the current row, because we want to
550 // recalculate all rows below
551 intRow = intRowToInsert - 1;
553 // Tests at which line we want to insert
554 if ( intRow >= ToDoImpl.INT_ROW_FROM ) {
555 // Get the start date
556 gregCalStartDate =
557 this.getGregorianCalendarFromString(
558 this.getStringFromCell( xcellrange,
559 intRow,ToDoImpl.INT_COLUMN_ENDDATE));
561 else {
562 // Set the start date with the absolute s
563 // tart date
564 gregCalStartDate = (GregorianCalendar)
565 gregCalAbsoluteStartDate.clone();
573 catch( Exception exception ) {
574 showExceptionMessage( exception );
578 /** Getting a string from a gregorian calendar.
579 * @param gregCal Date to be converted.
580 * @return string (converted gregorian calendar).
582 private String getStringFromGregorianCalendar( GregorianCalendar gregCal ) {
583 String sDate = ( gregCal.get( Calendar.MONTH ) + 1 )
584 + STRING_SEPARATOR + gregCal.get( Calendar.DATE )
585 + STRING_SEPARATOR + gregCal.get( Calendar.YEAR );
587 return sDate;
590 /** Getting a GregorianCalendar from a string.
591 * @param sDate String to be converted.
592 * @return The result of the converting of the string.
594 private GregorianCalendar getGregorianCalendarFromString( String sDate ) {
595 int []intDateValue = this.getDateValuesFromString( sDate );
597 return( new GregorianCalendar( intDateValue[ 2 ], intDateValue[ 0 ],
598 intDateValue[ 1 ] ) );
601 /** Getting the day, month and year from a string.
602 * @param sDate String to be parsed.
603 * @return Returns an array of integer variables.
605 private int[] getDateValuesFromString( String sDate) {
606 int[] intDateValues = new int[ 3 ];
608 int intPositionFirstTag = sDate.indexOf( STRING_SEPARATOR );
609 int intPositionSecondTag = sDate.indexOf(STRING_SEPARATOR,
610 intPositionFirstTag + 1);
612 // Getting the value of the month
613 intDateValues[ 0 ] = Integer.parseInt(
614 sDate.substring(0, intPositionFirstTag)) - 1;
615 // Getting the value of the day
616 intDateValues[ 1 ] = Integer.parseInt(
617 sDate.substring(intPositionFirstTag + 1, intPositionSecondTag));
618 // Getting the value of the year
619 intDateValues[ 2 ] = Integer.parseInt(
620 sDate.substring(intPositionSecondTag + 1, sDate.length()));
622 return intDateValues;
625 /** Getting a content from a specified cell.
626 * @param xcellrange Providing access to cells.
627 * @param intRow Number of row.
628 * @param intColumn Number of column.
629 * @return String from the specified cell.
631 private String getStringFromCell( XCellRange xcellrange, int intRow,
632 int intColumn ) {
633 XTextRange xtextrangeStartDate = null;
635 try {
636 // Getting the cell holding the information about the start date
637 XCell xcellStartDate = xcellrange.getCellByPosition(intColumn,
638 intRow);
639 // Querying for the interface XTextRange on the XCell
640 xtextrangeStartDate = UnoRuntime.queryInterface(XTextRange.class, xcellStartDate);
642 catch( Exception exception ) {
643 this.showExceptionMessage( exception );
646 // Getting the start date
647 return xtextrangeStartDate.getString().trim();
650 /** Writing a specified string to a specified cell.
651 * @param xcellrange Providing access to the cells.
652 * @param intRow Number of row.
653 * @param intColumn Number of column.
654 * @param sDate Date to write to the cell.
656 private void setStringToCell( XCellRange xcellrange, int intRow,
657 int intColumn, String sDate ) {
658 try {
659 // Getting the cell holding the information on the day to start
660 XCell xcellStartDate = xcellrange.getCellByPosition(intColumn,
661 intRow);
662 // Querying for the interface XTextRange on the XCell
663 XTextRange xtextrange = UnoRuntime.queryInterface(XTextRange.class, xcellStartDate);
664 // Setting the new start date
665 xtextrange.setString( sDate );
667 catch( Exception exception ) {
668 this.showExceptionMessage( exception );
672 /** Calculates the week of day and calls the method "setStringToCell".
673 * @param gregCal Day to be written to the cell.
674 * @param xcellrange Providing access to the cells.
675 * @param intRow Number of row.
676 * @param intColumn Number of column.
678 private void setDayOfWeek( GregorianCalendar gregCal,
679 XCellRange xcellrange, int intRow,
680 int intColumn) {
681 int intDayOfWeek = gregCal.get( Calendar.DAY_OF_WEEK );
682 String sDayOfWeek = "";
683 if ( intDayOfWeek == Calendar.MONDAY ) {
684 sDayOfWeek = "MON";
685 } else if ( intDayOfWeek == Calendar.TUESDAY ) {
686 sDayOfWeek = "TUE";
687 } else if ( intDayOfWeek == Calendar.WEDNESDAY ) {
688 sDayOfWeek = "WED";
689 } else if ( intDayOfWeek == Calendar.THURSDAY ) {
690 sDayOfWeek = "THU";
691 } else if ( intDayOfWeek == Calendar.FRIDAY ) {
692 sDayOfWeek = "FRI";
695 this.setStringToCell( xcellrange, intRow, intColumn,
696 sDayOfWeek );
699 /** Calculates the dates of the official holidays with help of Calc
700 * functions.
701 * @param vectorHolidays Holding all holidays.
702 * @param xcellrange Providing the cells.
703 * @param xfunctionaccess Provides access to functions of the Calc.
704 * @param intYear Year to calculate the official holidays.
706 private void getOfficialHolidays(
707 ArrayList<Object> vectorHolidays,
708 XCellRange xcellrange,
709 XFunctionAccess xfunctionaccess,
710 int intYear ) {
711 try {
712 // Official Holidays for how many years?
713 final int intHowManyYears = 2;
715 // Get the Official Holiday for two years
716 for ( int intNumberOfYear = 0;
717 intNumberOfYear <= ( intHowManyYears - 1 );
718 intNumberOfYear++ ) {
719 intYear += intNumberOfYear;
721 // Getting the Easter sunday
722 Double dEasterSunday = ( Double )
723 xfunctionaccess.callFunction(
724 "EASTERSUNDAY", new Object[] { Integer.valueOf(intYear) });
726 int intEasterSunday = (int)Math.round(
727 dEasterSunday.doubleValue());
729 // New-year
730 vectorHolidays.add( xfunctionaccess.callFunction(
731 "DATE",
732 new Object[] {
733 Integer.valueOf( intYear ),
734 Integer.valueOf( 1 ),
735 Integer.valueOf( 1 ) } ));
737 // Good Friday
738 vectorHolidays.add(
739 Double.valueOf( intEasterSunday - 2 ) );
741 // Easter monday
742 vectorHolidays.add(
743 Double.valueOf( intEasterSunday + 1 ) );
745 // Labour Day
746 vectorHolidays.add( xfunctionaccess.callFunction(
747 "DATE",
748 new Object[] {
749 Integer.valueOf( intYear ),
750 Integer.valueOf( 5 ),
751 Integer.valueOf( 1 ) } ));
753 // Ascension Day
754 vectorHolidays.add(Double.valueOf(intEasterSunday + 39 ));
756 // Pentecost monday
757 vectorHolidays.add(Double.valueOf(intEasterSunday + 50 ));
759 // German Unification
760 vectorHolidays.add( xfunctionaccess.callFunction(
761 "DATE",
762 new Object[] {
763 Integer.valueOf( intYear ),
764 Integer.valueOf( 10 ),
765 Integer.valueOf( 3 ) } ));
767 // Christmas Day First
768 vectorHolidays.add( xfunctionaccess.callFunction(
769 "DATE",
770 new Object[] {
771 Integer.valueOf( intYear ),
772 Integer.valueOf( 12 ),
773 Integer.valueOf( 25 ) } ));
775 // Christmas Day Second
776 vectorHolidays.add( xfunctionaccess.callFunction(
777 "DATE",
778 new Object[] {
779 Integer.valueOf( intYear ),
780 Integer.valueOf( 12 ),
781 Integer.valueOf( 26 ) } ));
784 catch( Exception exception ) {
785 this.showExceptionMessage( exception );
789 /** Returns the serial number of the date before or after a specified
790 * number of workdays.
791 * @param gregCalStartDate Date to start with the calculation.
792 * @param intDays Number of workdays (e.g. 5 or -3).
793 * @param objectHolidays Private and public holidays to take into account.
794 * @param xfunctionaccess Allows to call functions from the Calc.
795 * @return The gregorian date before or after a specified number of
796 * workdays.
798 private GregorianCalendar getWorkday(
799 GregorianCalendar gregCalStartDate,
800 int intDays, Object[][] objectHolidays,
801 XFunctionAccess xfunctionaccess ) {
802 GregorianCalendar gregCalWorkday = null;
804 try {
805 // Getting the value of the start date
806 Double dDate = ( Double ) xfunctionaccess.callFunction(
807 "DATE",
808 new Object[] {
809 Integer.valueOf( gregCalStartDate.get( Calendar.YEAR ) ),
810 Integer.valueOf( gregCalStartDate.get( Calendar.MONTH ) + 1 ),
811 Integer.valueOf( gregCalStartDate.get( Calendar.DATE ) )
812 } );
814 Double dWorkday = ( Double ) xfunctionaccess.callFunction(
815 "com.sun.star.sheet.addin.Analysis.getWorkday",
816 new Object[] { dDate, Integer.valueOf( intDays ), objectHolidays } );
818 Double dYear = ( Double ) xfunctionaccess.callFunction(
819 "YEAR", new Object[] { dWorkday } );
820 Double dMonth = ( Double ) xfunctionaccess.callFunction(
821 "MONTH", new Object[] { dWorkday } );
822 Double dDay = ( Double ) xfunctionaccess.callFunction(
823 "DAY", new Object[] { dWorkday } );
825 gregCalWorkday = new GregorianCalendar(
826 dYear.intValue(),
827 dMonth.intValue() - 1,
828 dDay.intValue() );
830 catch( Exception exception ) {
831 this.showExceptionMessage( exception );
834 return gregCalWorkday;
837 /** Getting the holidays from the spreadsheet.
838 * @param vectorHolidays Holding all holidays.
839 * @param xcellrange Providing the cells.
840 * @param xfunctionaccess Provides the access to functions of the Calc.
842 private void getPrivateHolidays( ArrayList<Object> vectorHolidays,
843 XCellRange xcellrange,
844 XFunctionAccess xfunctionaccess ) {
845 try {
846 int intRow = ToDoImpl.INT_ROW_HOLIDAYS_START;
847 int intColumn = ToDoImpl.INT_COLUMN_HOLIDAYS_START;
849 double dHolidayStart = xcellrange.getCellByPosition(
850 intColumn, intRow ).getValue();
852 double dHolidayEnd = xcellrange.getCellByPosition(
853 intColumn + 1, intRow ).getValue();
855 while ( dHolidayStart != 0 ) {
856 if ( dHolidayEnd == 0 ) {
857 vectorHolidays.add(
858 Integer.valueOf( (int) Math.round(
859 dHolidayStart ) ) );
861 else {
862 for ( int intHoliday = (int) Math.round(
863 dHolidayStart );
864 intHoliday <= (int) Math.round( dHolidayEnd );
865 intHoliday++ ) {
866 vectorHolidays.add( Double.valueOf( intHoliday ) );
870 intRow++;
871 dHolidayStart = xcellrange.getCellByPosition(
872 intColumn, intRow).getValue();
873 dHolidayEnd = xcellrange.getCellByPosition(
874 intColumn + 1, intRow).getValue();
877 catch( Exception exception ) {
878 this.showExceptionMessage( exception );
882 /** Showing the stack trace in a JOptionPane.
883 * @param sMessage The message to show.
885 private void showMessage( String sMessage ) {
886 javax.swing.JFrame jframe = new javax.swing.JFrame();
887 jframe.setLocation(100, 100);
888 jframe.setSize(300, 200);
889 jframe.setVisible(true);
890 javax.swing.JOptionPane.showMessageDialog(
891 jframe, sMessage, "Debugging information",
892 javax.swing.JOptionPane.INFORMATION_MESSAGE);
893 jframe.dispose();
896 /** Writing the stack trace from an exception to a string and calling
897 * the method showMessage() with this string.
898 * @param exception The occurred exception.
899 * @see #showMessage(String)
901 private void showExceptionMessage( Exception exception ) {
902 java.io.StringWriter swriter = new java.io.StringWriter();
903 java.io.PrintWriter printwriter =
904 new java.io.PrintWriter( swriter );
905 exception.printStackTrace( printwriter);
906 System.err.println( exception );
907 this.showMessage( swriter.getBuffer().substring(0) );
912 * Gives a factory for creating the service.
913 * This method is called by the <code>JavaLoader</code>
914 * <p>
915 * @return returns a <code>XSingleComponentFactory</code> for creating
916 * the component
917 * @param sImplName the name of the implementation for which a
918 * service is desired
919 * @see com.sun.star.comp.loader.JavaLoader
921 public static XSingleComponentFactory __getComponentFactory(String sImplName) {
922 XSingleComponentFactory xFactory = null;
924 if ( sImplName.equals( ToDoImpl.class.getName() ) )
925 xFactory = Factory.createComponentFactory(ToDoImpl.class,
926 ToDoImpl.getServiceNames());
928 return xFactory;
932 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */