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