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