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 package integration.forms; 24 25 import com.sun.star.awt.XImageProducer; 26 import com.sun.star.beans.PropertyValue; 27 import com.sun.star.beans.XPropertySet; 28 import com.sun.star.container.XNameAccess; 29 import com.sun.star.form.runtime.XFormController; 30 import com.sun.star.form.XImageProducerSupplier; 31 import com.sun.star.frame.XDispatch; 32 import com.sun.star.lang.EventObject; 33 import com.sun.star.lang.XMultiServiceFactory; 34 import com.sun.star.sdb.CommandType; 35 import com.sun.star.sdb.SQLErrorEvent; 36 import com.sun.star.sdb.XSQLErrorBroadcaster; 37 import com.sun.star.sdb.XSQLErrorListener; 38 import com.sun.star.sdbc.XConnection; 39 import com.sun.star.sdbc.XDataSource; 40 import com.sun.star.sdbc.XResultSet; 41 import com.sun.star.sdbc.XResultSetUpdate; 42 import com.sun.star.uno.UnoRuntime; 43 import com.sun.star.uno.XNamingService; 44 import com.sun.star.util.URL; 45 import com.sun.star.util.XCloseable; 46 import com.sun.star.util.XURLTransformer; 47 import connectivity.tools.HsqlDatabase; 48 import connectivity.tools.sdb.Connection; 49 import java.io.FileOutputStream; 50 51 import org.junit.After; 52 import org.junit.AfterClass; 53 import org.junit.Before; 54 import org.junit.BeforeClass; 55 import org.junit.Test; 56 import static org.junit.Assert.*; 57 import org.openoffice.test.OfficeConnection; 58 59 60 public class FormControlTest implements XSQLErrorListener 61 { 62 private static final OfficeConnection officeConnection = new OfficeConnection(); 63 private static String s_tableName = "CTC_form_controls"; 64 65 private HsqlDatabase m_databaseDocument; 66 private XDataSource m_dataSource; 67 private XPropertySet m_dataSourceProps; 68 private XMultiServiceFactory m_orb; 69 private DocumentHelper m_document; 70 private FormLayer m_formLayer; 71 private XPropertySet m_masterForm; 72 private XFormController m_masterFormController; 73 private String m_sImageURL; 74 private SQLErrorEvent m_mostRecentErrorEvent; 75 76 private final String m_dataSourceName = "integration.forms.FormControlTest"; 77 78 /* ------------------------------------------------------------------ */ 79 80 @BeforeClass beforeClass()81 public static void beforeClass() throws Exception 82 { 83 officeConnection.setUp(); 84 } 85 86 @AfterClass afterClass()87 public static void afterClass() throws Exception 88 { 89 officeConnection.tearDown(); 90 } 91 92 /* ------------------------------------------------------------------ */ 93 /// pre-test initialization 94 @Before before()95 public void before() throws com.sun.star.uno.Exception, java.lang.Exception 96 { 97 // ensure that we have a data source to work with, and the required tables 98 if ( !ensureDataSource() || !ensureTables() ) 99 { 100 fail( "could not access the required data source or table therein." ); 101 return; 102 } 103 104 // create the document which we work on 105 createSampleDocument(); 106 107 createImageFile(); 108 } 109 110 /* ------------------------------------------------------------------ */ 111 @Test checkFirstRow()112 public void checkFirstRow() throws com.sun.star.uno.Exception, java.lang.Exception 113 { 114 moveToFirst(); 115 116 // and check the content of the various controls 117 if ( !checkRadios( (short)1, (short)0, (short)0 ) 118 || !checkDoubleValue( 1, "ID", "Value" ) 119 || !checkDoubleValue( 42, "f_integer", "EffectiveValue" ) 120 || !checkStringValue( "the answer", "f_text", "Text" ) 121 || !checkDoubleValue( 0.12, "f_decimal", "Value" ) 122 || !checkIntValue ( 20030922, "f_date", "Date" ) 123 || !checkIntValue ( 15000000, "f_time", "Time" ) 124 || !checkIntValue ( 20030923, "f_timestamp_date", "Date" ) 125 || !checkIntValue ( 17152300, "f_timestamp_time", "Time" ) 126 || !checkShortValue ( (short)1, "f_tinyint", "State" ) 127 ) 128 { 129 fail( "checking the content of one or more controls on the first row failed (see the log for details)" ); 130 return; 131 } 132 } 133 134 /* ------------------------------------------------------------------ */ 135 @Test checkInsertRow()136 public void checkInsertRow() throws com.sun.star.uno.Exception, java.lang.Exception 137 { 138 // move the cursor to the insert row 139 moveToInsertRow(); 140 141 // and check the content of the various controls 142 if ( !verifyCleanInsertRow() ) 143 { 144 fail( "checking the content of one or more controls on the insert row failed (see the log for details)" ); 145 return; 146 } 147 } 148 149 /* ------------------------------------------------------------------ */ 150 /// some tests with the image control 151 @Test checkImageControl()152 public void checkImageControl() throws com.sun.star.uno.Exception, java.lang.Exception 153 { 154 // since we did not yet insert any image, the control should not display one ... 155 moveToFirst(); 156 if ( !verifyReferenceImage( new byte[0] ) ) 157 { 158 fail( "image control failed to display empty image" ); 159 return; 160 } 161 162 // check if the image control is able to insert our sample image into the database 163 // insert an 164 XPropertySet xImageModel = getControlModel( "f_blob" ); 165 xImageModel.setPropertyValue( "ImageURL", m_sImageURL ); 166 167 if ( !verifyReferenceImage( getSamplePictureBytes() ) ) 168 { 169 fail( "image control does not display the sample image as required" ); 170 return; 171 } 172 173 // save the record 174 saveRecordByUI(); 175 176 // still needs to be the sample image 177 if ( !verifyReferenceImage( getSamplePictureBytes() ) ) 178 { 179 fail( "image control does not, after saving the record, display the sample image as required" ); 180 return; 181 } 182 183 // on the next record, the image should be empty 184 moveToNext(); 185 if ( !verifyReferenceImage( new byte[0] ) ) 186 { 187 fail( "image control failed to display empty image, after coming from a non-empty image" ); 188 return; 189 } 190 191 // back to the record where we just inserted the image, it should be our sample image 192 moveToFirst(); 193 if ( !verifyReferenceImage( getSamplePictureBytes() ) ) 194 { 195 fail( "image control does not, after coming back to the record, display the sample image as required" ); 196 return; 197 } 198 199 // okay, now remove the image 200 xImageModel.setPropertyValue( "ImageURL", new String() ); 201 if ( !verifyReferenceImage( new byte[0] ) ) 202 { 203 fail( "image control failed to remove the image" ); 204 return; 205 } 206 nextRecordByUI(); 207 previousRecordByUI(); 208 if ( !verifyReferenceImage( new byte[0] ) ) 209 { 210 fail( "image still there after coming back, though we just removed it" ); 211 return; 212 } 213 } 214 215 /* ------------------------------------------------------------------ */ 216 /** This is both a test for controls which are bound to the same column (they must reflect 217 * each others updates), and for the immediate updates which need to happen for both check 218 * boxes and radio buttons: They must commit their content to the underlying column as soon 219 * as the change is made, *not* only upon explicit commit 220 */ 221 @Test checkCrossUpdates_checkBox()222 public void checkCrossUpdates_checkBox() throws com.sun.star.uno.Exception, java.lang.Exception 223 { 224 // move to the first record 225 moveToFirst(); 226 if ( !checkShortValue ( (short)1, "f_tinyint", "State" ) 227 || !checkDoubleValue( 1, "f_tinyint_format", "EffectiveValue" ) 228 ) 229 { 230 fail( "huh? inconsistence in the test!" ); 231 // we created the sample data in a way that the f_tinyint field should contain a "1" at the first 232 // record. We already asserted the proper function of the check box in checkFirstRow, so if this 233 // fails here, the script became inconsistent 234 return; 235 } 236 237 XPropertySet checkModel = getControlModel( "f_tinyint" ); 238 checkModel.setPropertyValue( "State", new Short( (short)0 ) ); 239 240 // setting the state of the check box needs to be reflected in the formatted field immediately 241 if ( !checkDoubleValue( 0, "f_tinyint_format", "EffectiveValue" ) ) 242 { 243 fail( "cross-update failed: updating the check box should result in updating the same-bound formatted field (1)!" ); 244 return; 245 } 246 247 // same for the "indetermined" state of the check box 248 checkModel.setPropertyValue( "State", new Short( (short)2 ) ); 249 if ( !checkNullValue( "f_tinyint_format", "EffectiveValue" ) ) 250 { 251 fail( "cross-update failed: updating the check box should result in updating the same-bound formatted field (2)!" ); 252 return; 253 } 254 255 // undo the changes done so far 256 undoRecordByUI(); 257 // and see if this is properly reflected in the controls 258 if ( !checkShortValue ( (short)1, "f_tinyint", "State" ) 259 || !checkDoubleValue( 1, "f_tinyint_format", "EffectiveValue" ) 260 ) 261 { 262 fail( "either the check box or the formatted field failed to recognize the UNDO!" ); 263 return; 264 } 265 266 // the other way round - when changing the formatted field - the change should *not* 267 // be reflected to the check box, since the formatted field needs an explicit commit 268 XPropertySet tinyFormattedModel = getControlModel( "f_tinyint_format" ); 269 m_document.getCurrentView().grabControlFocus( tinyFormattedModel ); 270 m_formLayer.userTextInput( tinyFormattedModel, "0" ); 271 if ( !checkShortValue ( (short)1, "f_tinyint", "State" ) 272 ) 273 { 274 fail( "the check box should not be updated here! (did the formatted model commit immediately?)" ); 275 return; 276 } 277 278 // set the focus to *any* other control (since we just have it at hand, we use the check box control) 279 // this should result in the formatted control being committed, and thus in the check box updating 280 m_document.getCurrentView().grabControlFocus( checkModel ); 281 if ( !checkShortValue ( (short)0, "f_tinyint", "State" ) 282 ) 283 { 284 fail( "formatted field did not commit (or check box did not update)" ); 285 return; 286 } 287 288 // undo the changes done so far, so we leave the document in a clean state for the next test 289 undoRecordByUI(); 290 } 291 292 /* ------------------------------------------------------------------ */ 293 /** very similar to checkCrossUpdates_checkBox - does nearly the same for the radio buttons. See there for more 294 * explanations. 295 */ 296 @Test checkCrossUpdates_radioButton()297 public void checkCrossUpdates_radioButton() throws com.sun.star.uno.Exception, java.lang.Exception 298 { 299 // move to the first record 300 moveToFirst(); 301 if ( !checkRadios( (short)1, (short)0, (short)0 ) 302 || !checkStringValue( "none", "f_text_enum_text", "Text" ) 303 ) 304 { 305 fail( "huh? inconsistence in the test!" ); 306 return; 307 } 308 309 XPropertySet radioModel = getRadioModel( "radio_group", "normal" ); 310 radioModel.setPropertyValue( "State", new Short( (short)1 ) ); 311 312 // setting the state of the radio button needs to be reflected in the formatted field immediately 313 if ( !checkStringValue( "normal", "f_text_enum_text", "Text" ) ) 314 { 315 fail( "cross-update failed: updating the radio button should result in updating the same-bound text field (1)!" ); 316 return; 317 } 318 319 // same for the "indetermined" state of the check box 320 getRadioModel( "radio_group", "important" ).setPropertyValue( "State", new Short( (short)1 ) ); 321 if ( !checkStringValue( "important", "f_text_enum_text", "Text" ) ) 322 { 323 fail( "cross-update failed: updating the radio button should result in updating the same-bound text field (2)!" ); 324 return; 325 } 326 327 // undo the changes done so far 328 undoRecordByUI(); 329 // and see if this is properly reflected in the controls 330 if ( !checkRadios( (short)1, (short)0, (short)0 ) 331 || !checkStringValue( "none", "f_text_enum_text", "Text" ) 332 ) 333 { 334 fail( "either the radio button or the text field failed to recognize the UNDO!" ); 335 return; 336 } 337 338 // the other way round - when changing the formatted field - the change should *not* 339 // be reflected to the check box, since the formatted field needs an explicit commit 340 XPropertySet textModel = getControlModel( "f_text_enum_text" ); 341 m_document.getCurrentView().grabControlFocus( textModel ); 342 m_formLayer.userTextInput( textModel, "normal" ); 343 if ( !checkRadios( (short)1, (short)0, (short)0 ) 344 ) 345 { 346 fail( "the radio buttons should not be updated here! (did the formatted model commit immediately?)" ); 347 return; 348 } 349 350 // set the focus to *any* other control (since we just have it at hand, we use the check box control) 351 // this should result in the formatted control being committed, and thus in the check box updating 352 m_document.getCurrentView().grabControlFocus( radioModel ); 353 if ( !checkRadios( (short)0, (short)1, (short)0 ) 354 ) 355 { 356 fail( "text field did not commit (or radio button did not update)" ); 357 return; 358 } 359 360 // undo the changes done so far, so we leave the document in a clean state for the next test 361 undoRecordByUI(); 362 } 363 364 /* ------------------------------------------------------------------ */ 365 /** some tests with updating the table via our controls 366 */ 367 @Test checkRowUpdates()368 public void checkRowUpdates() throws com.sun.star.uno.Exception, java.lang.Exception 369 { 370 // start with inserting a new record 371 moveToInsertRow(); 372 assertTrue( "insert row not in expected clean state", verifyCleanInsertRow() ); 373 374 userTextInput( "ID", "3", true ); 375 userTextInput( "f_integer", "729", true ); 376 userTextInput( "f_text", "test", true ); 377 userTextInput( "f_decimal", "152343", true ); 378 userTextInput( "f_date", "31.12.1999", true ); 379 userTextInput( "f_time", "23:59:59", true ); 380 381 // move to the next row, this should automatically commit the changes we made 382 nextRecordByUI(); 383 // and back to the row we just inserted 384 previousRecordByUI(); 385 386 if ( !checkDoubleValue( 3, "ID", "Value" ) 387 || !checkDoubleValue( 729, "f_integer", "EffectiveValue" ) 388 || !checkStringValue( "test", "f_text", "Text" ) 389 || !checkDoubleValue( 152343, "f_decimal", "Value" ) 390 || !checkIntValue ( 19991231, "f_date", "Date" ) 391 || !checkIntValue ( 23595900, "f_time", "Time" ) 392 ) 393 { 394 fail( "the changes we made on the insert row have not been committed" ); 395 return; 396 } 397 398 // now change the data, to see if regular updates work, too 399 userTextInput( "ID", "4", true ); 400 userTextInput( "f_integer", "618", true ); 401 userTextInput( "f_text", "yet another stupid, meaningless text", true ); 402 userTextInput( "f_required_text", "this must not be NULL", true ); 403 userTextInput( "f_decimal", "4562", true ); 404 userTextInput( "f_date", "26.03.2004", true ); 405 userTextInput( "f_time", "17:05:00", true ); 406 407 // move to the next row, this should automatically commit the changes we made 408 nextRecordByUI(); 409 // and back to the row we just inserted 410 previousRecordByUI(); 411 412 if ( !checkDoubleValue( 4, "ID", "Value" ) 413 || !checkDoubleValue( 618, "f_integer", "EffectiveValue" ) 414 || !checkStringValue( "yet another stupid, meaningless text", "f_text", "Text" ) 415 || !checkDoubleValue( 4562, "f_decimal", "Value" ) 416 || !checkIntValue ( 20040326, "f_date", "Date" ) 417 || !checkIntValue ( 17050000, "f_time", "Time" ) 418 ) 419 { 420 fail( "the changes we made on the insert row have not been committed" ); 421 return; 422 } 423 424 m_document.getCurrentView().grabControlFocus( getControlModel( "ID" ) ); 425 } 426 427 /* ------------------------------------------------------------------ */ 428 /** checks the "ConvertEmptyToNull" property behavior of an edit control 429 * 430 */ 431 @Test checkEmptyIsNull()432 public void checkEmptyIsNull() throws com.sun.star.uno.Exception, java.lang.Exception 433 { 434 // start with inserting a new record 435 moveToInsertRow(); 436 assertTrue( "insert row not in expected clean state", verifyCleanInsertRow() ); 437 438 // make an input in any field, but leave the edit control which is bound to a required field 439 // empty 440 userTextInput( "ID", "5", true ); 441 userTextInput( "f_text", "more text", true ); 442 443 // this should *not* fail. Even if we did not input anything into the control bound to the 444 // f_required_text column, this control's reset (done when moving to the insertion row) is 445 // expected to write an empty string into its bound column, since its EmptyIsNULL property 446 // is set to FALSE 447 // (#i92471#) 448 m_mostRecentErrorEvent = null; 449 nextRecordByUI(); 450 assertTrue( "updating an incomplete record did not work as expected", m_mostRecentErrorEvent == null ); 451 } 452 453 /* ------------------------------------------------------------------ */ verifyCleanInsertRow( )454 private boolean verifyCleanInsertRow( ) throws com.sun.star.uno.Exception, java.lang.Exception 455 { 456 // and check the content of the various controls 457 return ( checkRadios( (short)0, (short)0, (short)0 ) 458 && checkShortValue( (short)2, "f_tinyint", "State" ) 459 && checkStringValue( "", "f_text", "Text" ) 460 && checkNullValue( "ID", "Value" ) 461 && checkNullValue( "f_integer", "EffectiveValue" ) 462 && checkNullValue( "f_decimal", "Value" ) 463 ); 464 } 465 466 /* ------------------------------------------------------------------ */ 467 /// post-test cleanup 468 @After after()469 public void after() throws com.sun.star.uno.Exception, java.lang.Exception 470 { 471 // close our document 472 if ( m_document != null ) 473 { 474 XCloseable closeDoc = (XCloseable)UnoRuntime.queryInterface( XCloseable.class, 475 m_document.getDocument() ); 476 closeDoc.close( true ); 477 } 478 } 479 480 //========================================================================= 481 /* ------------------------------------------------------------------ */ ensureDataSource()482 private boolean ensureDataSource() throws Exception 483 { 484 m_orb = UnoRuntime.queryInterface(XMultiServiceFactory.class, officeConnection.getComponentContext().getServiceManager()); 485 486 XNameAccess databaseContext = (XNameAccess)UnoRuntime.queryInterface( XNameAccess.class, 487 m_orb.createInstance( "com.sun.star.sdb.DatabaseContext" ) ); 488 XNamingService namingService = (XNamingService)UnoRuntime.queryInterface( XNamingService.class, 489 databaseContext ); 490 491 // revoke the data source, if it previously existed 492 if ( databaseContext.hasByName( m_dataSourceName ) ) 493 namingService.revokeObject( m_dataSourceName ); 494 495 // // create a new ODB file, and register it with its URL 496 m_databaseDocument = new HsqlDatabase( m_orb ); 497 String documentURL = m_databaseDocument.getDocumentURL(); 498 namingService.registerObject( m_dataSourceName, databaseContext.getByName( documentURL ) ); 499 500 m_dataSource = (XDataSource)UnoRuntime.queryInterface( XDataSource.class, 501 databaseContext.getByName( m_dataSourceName ) ); 502 m_dataSourceProps = dbfTools.queryPropertySet( m_dataSource ); 503 504 XPropertySet dataSourceSettings = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, 505 m_dataSourceProps.getPropertyValue( "Settings" ) ); 506 dataSourceSettings.setPropertyValue( "FormsCheckRequiredFields", new Boolean( false ) ); 507 508 return m_dataSource != null; 509 } 510 511 /* ------------------------------------------------------------------ */ 512 /** retrieves the control model with the given name 513 */ getControlModel( String name )514 private XPropertySet getControlModel( String name ) throws com.sun.star.uno.Exception, java.lang.Exception 515 { 516 XNameAccess nameAccess = (XNameAccess)UnoRuntime.queryInterface( XNameAccess.class, 517 m_masterForm ); 518 return (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, 519 nameAccess.getByName( name ) ); 520 } 521 522 /* ------------------------------------------------------------------ */ createSampleDocument()523 private void createSampleDocument() throws com.sun.star.uno.Exception, java.lang.Exception 524 { 525 526 m_document = DocumentHelper.blankTextDocument( m_orb ); 527 m_formLayer = new FormLayer( m_document ); 528 529 // insert some controls 530 XPropertySet xIDField = m_formLayer.insertControlLine( "DatabaseNumericField", "ID", "", 3 ); 531 m_formLayer.insertControlLine( "DatabaseFormattedField","f_integer", "", 11 ); 532 m_formLayer.insertControlLine( "DatabaseTextField", "f_text", "", 19 ); 533 XPropertySet xReqField = m_formLayer.insertControlLine( "DatabaseTextField", "f_required_text", "", 27 ); 534 m_formLayer.insertControlLine( "DatabaseNumericField", "f_decimal", "", 35 ); 535 m_formLayer.insertControlLine( "DatabaseDateField", "f_date", "", 43 ); 536 XPropertySet xTimeField = m_formLayer.insertControlLine( "DatabaseTimeField", "f_time", "", 51 ); 537 m_formLayer.insertControlLine( "DatabaseDateField", "f_timestamp", "_date", 59 ); 538 m_formLayer.insertControlLine( "DatabaseTimeField", "f_timestamp", "_time", 67 ); 539 XPropertySet xImageField = m_formLayer.insertControlLine( "DatabaseImageControl", "f_blob", "", 2, 75, 40 ); 540 m_formLayer.insertControlLine( "DatabaseTextField", "f_text_enum", "_text", 80, 25, 6 ); 541 XPropertySet xCheckBox = m_formLayer.insertControlLine( "DatabaseCheckBox", "f_tinyint", "", 80, 33, 6 ); 542 m_formLayer.insertControlLine( "DatabaseFormattedField","f_tinyint", "_format",80, 41, 6 ); 543 m_formLayer.insertControlLine( "DatabaseTextField", "dummy", "", 150 ); 544 545 xIDField.setPropertyValue( "DecimalAccuracy", new Short( (short)0 ) ); 546 xImageField.setPropertyValue( "ScaleImage", new Boolean( true) ); 547 xImageField.setPropertyValue( "Tabstop", new Boolean( true ) ); 548 xCheckBox.setPropertyValue( "TriState", new Boolean( true ) ); 549 xCheckBox.setPropertyValue( "DefaultState", new Short( (short)2 ) ); 550 xTimeField.setPropertyValue( "TimeFormat", new Short( (short)1 ) ); 551 xTimeField.setPropertyValue( "TimeMax", new Integer( 23595999 ) ); 552 xReqField.setPropertyValue( "ConvertEmptyToNull", new Boolean( false ) ); 553 554 // the logical form 555 m_masterForm = (XPropertySet)dbfTools.getParent( xIDField, XPropertySet.class ); 556 m_masterForm.setPropertyValue( "DataSourceName", m_dataSourceProps.getPropertyValue( "Name" ) ); 557 m_masterForm.setPropertyValue( "CommandType", new Integer( CommandType.TABLE ) ); 558 m_masterForm.setPropertyValue( "Command", s_tableName ); 559 560 insertRadio( 3, "none", "none" ); 561 insertRadio( 10, "normal", "normal" ); 562 insertRadio( 17, "important", "important" ); 563 564 // switch the forms into data entry mode 565 m_document.getCurrentView( ).toggleFormDesignMode( ); 566 567 m_masterFormController = m_document.getCurrentView().getFormController( m_masterForm ); 568 XSQLErrorBroadcaster errorBroadcaster = (XSQLErrorBroadcaster)UnoRuntime.queryInterface( XSQLErrorBroadcaster.class, 569 m_masterFormController ); 570 errorBroadcaster.addSQLErrorListener( this ); 571 572 // set the focus to the ID control 573 m_document.getCurrentView().grabControlFocus( xIDField ); 574 } 575 576 /* ------------------------------------------------------------------ */ insertRadio( int nYPos, String label, String refValue )577 private void insertRadio( int nYPos, String label, String refValue ) throws com.sun.star.uno.Exception, java.lang.Exception 578 { 579 XPropertySet xRadio = m_formLayer.createControlAndShape( "DatabaseRadioButton", 106, nYPos, 25, 6 ); 580 xRadio.setPropertyValue( "Label", label ); 581 xRadio.setPropertyValue( "RefValue", refValue ); 582 xRadio.setPropertyValue( "Name", new String( "radio_group" ) ); 583 xRadio.setPropertyValue( "DataField", new String( "f_text_enum" ) ); 584 } 585 586 /* ------------------------------------------------------------------ */ getCreateTableStatement( )587 private String getCreateTableStatement( ) 588 { 589 String sCreateTableStatement = "CREATE TABLE \"" + s_tableName + "\" ("; 590 sCreateTableStatement += "\"ID\" INTEGER NOT NULL PRIMARY KEY,"; 591 sCreateTableStatement += "\"f_integer\" INTEGER default NULL,"; 592 sCreateTableStatement += "\"f_text\" VARCHAR(50) default NULL,"; 593 sCreateTableStatement += "\"f_required_text\" VARCHAR(50) NOT NULL,"; 594 sCreateTableStatement += "\"f_decimal\" DECIMAL(10,2) default NULL,"; 595 sCreateTableStatement += "\"f_date\" DATE default NULL,"; 596 sCreateTableStatement += "\"f_time\" TIME default NULL,"; 597 sCreateTableStatement += "\"f_timestamp\" DATETIME default NULL,"; 598 sCreateTableStatement += "\"f_blob\" VARBINARY,"; 599 sCreateTableStatement += "\"f_text_enum\" VARCHAR(50) default NULL,"; 600 sCreateTableStatement += "\"f_tinyint\" TINYINT default NULL"; 601 sCreateTableStatement += ");"; 602 return sCreateTableStatement; 603 } 604 605 /* ------------------------------------------------------------------ */ getSampleDataValueString( )606 private String[] getSampleDataValueString( ) throws java.lang.Exception 607 { 608 String[] aValues = new String[] { 609 "1,42,'the answer','foo',0.12,'2003-09-22','15:00:00','2003-09-23 17:15:23',NULL,'none',1", 610 "2,13,'the question','bar',12.43,'2003-09-24','16:18:00','2003-09-24 08:45:12',NULL,'none',0" 611 }; 612 return aValues; 613 } 614 615 /* ------------------------------------------------------------------ */ ensureTables()616 private boolean ensureTables() throws com.sun.star.uno.Exception, java.lang.Exception 617 { 618 Connection connection = new Connection( m_dataSource.getConnection( "", "" ) ); 619 assertTrue( "could not connect to the data source", connection != null ); 620 621 // drop the table, if it already exists 622 if ( !implExecuteStatement( "DROP TABLE \"" + s_tableName + "\" IF EXISTS" ) 623 || !implExecuteStatement( getCreateTableStatement() ) 624 ) 625 { 626 fail( "could not create the required sample table!" ); 627 return false; 628 } 629 630 String sInsertionPrefix = "INSERT INTO \"" + s_tableName + "\" VALUES ("; 631 String[] aValues = getSampleDataValueString(); 632 for ( int i=0; i<aValues.length; ++i ) 633 if ( !implExecuteStatement( sInsertionPrefix + aValues[ i ] + ")" ) ) 634 { 635 fail( "could not create the required sample data" ); 636 return false; 637 } 638 639 connection.refreshTables(); 640 641 // do not need the connection anymore 642 connection.close(); 643 644 return true; 645 } 646 647 /* ------------------------------------------------------------------ */ 648 /// checks the 3 radio buttons for the given states checkRadios( short stateNone, short stateNormal, short stateImportant )649 private boolean checkRadios( short stateNone, short stateNormal, short stateImportant ) throws com.sun.star.uno.Exception, java.lang.Exception 650 { 651 if ( ((Short)getRadioModel( "radio_group", "none" ).getPropertyValue( "State" )).shortValue() != stateNone ) 652 { 653 fail( "wrong value of the 'none' radio button!" ); 654 } 655 else if ( ((Short)getRadioModel( "radio_group", "normal" ).getPropertyValue( "State" )).shortValue() != stateNormal ) 656 { 657 fail( "wrong value of the 'normal' radio button!" ); 658 } 659 else if ( ((Short)getRadioModel( "radio_group", "important" ).getPropertyValue( "State" )).shortValue() != stateImportant ) 660 { 661 fail( "wrong value of the 'important' radio button!" ); 662 } 663 else 664 return true; 665 666 return false; 667 } 668 669 /* ------------------------------------------------------------------ */ checkNullValue( String fieldName, String propertyName )670 private boolean checkNullValue( String fieldName, String propertyName ) throws com.sun.star.uno.Exception, java.lang.Exception 671 { 672 Object value = getControlModel( fieldName ).getPropertyValue( propertyName ); 673 if ( !util.utils.isVoid( value ) ) 674 { 675 System.out.println( "wrong value of the " + fieldName + " field!" ); 676 System.out.println( " expected: <null/>" ); 677 System.out.println( " found : " + value.toString() ); 678 } 679 else 680 return true; 681 682 return false; 683 } 684 685 /* ------------------------------------------------------------------ */ checkIntValue( int requiredValue, String fieldName, String propertyName )686 private boolean checkIntValue( int requiredValue, String fieldName, String propertyName ) throws com.sun.star.uno.Exception, java.lang.Exception 687 { 688 try 689 { 690 if ( fieldName.equals( "f_time" ) ) 691 // http://bugs.mysql.com/bug.php?id=5681 692 return true; 693 694 int currentValue = ((Integer)getControlModel( fieldName ).getPropertyValue( propertyName )).intValue(); 695 if ( currentValue != requiredValue ) 696 { 697 System.out.println( "wrong value of the " + fieldName + " field!" ); 698 System.out.println( " expected: " + String.valueOf( requiredValue ) ); 699 System.out.println( " found : " + String.valueOf( currentValue ) ); 700 } 701 else 702 return true; 703 } 704 catch( com.sun.star.uno.Exception e ) 705 { 706 System.err.println( "caught an exception while retrieving property value '" + propertyName + "' of control model '" + fieldName + "'" ); 707 throw e; 708 } 709 710 return false; 711 } 712 713 /* ------------------------------------------------------------------ */ checkShortValue( short requiredValue, String fieldName, String propertyName )714 private boolean checkShortValue( short requiredValue, String fieldName, String propertyName ) throws com.sun.star.uno.Exception, java.lang.Exception 715 { 716 try 717 { 718 short currentValue = ((Short)getControlModel( fieldName ).getPropertyValue( propertyName )).shortValue(); 719 if ( currentValue != requiredValue ) 720 { 721 System.out.println( "wrong value of the " + fieldName + " field!" ); 722 System.out.println( " expected: " + String.valueOf( requiredValue ) ); 723 System.out.println( " found : " + String.valueOf( currentValue ) ); 724 } 725 else 726 return true; 727 } 728 catch( com.sun.star.uno.Exception e ) 729 { 730 System.err.println( "caught an exception while retrieving property value '" + propertyName + "' of control model '" + fieldName + "'" ); 731 throw e; 732 } 733 734 return false; 735 } 736 737 /* ------------------------------------------------------------------ */ checkDoubleValue( double requiredValue, String fieldName, String propertyName )738 private boolean checkDoubleValue( double requiredValue, String fieldName, String propertyName ) throws com.sun.star.uno.Exception, java.lang.Exception 739 { 740 double currentValue = ((Double)getControlModel( fieldName ).getPropertyValue( propertyName )).doubleValue(); 741 if ( currentValue != requiredValue ) 742 { 743 System.out.println( "wrong value of the " + fieldName + " field!" ); 744 System.out.println( " expected: " + String.valueOf( requiredValue ) ); 745 System.out.println( " found : " + String.valueOf( currentValue ) ); 746 } 747 else 748 return true; 749 750 return false; 751 } 752 753 /* ------------------------------------------------------------------ */ checkStringValue( String requiredValue, String fieldName, String propertyName )754 private boolean checkStringValue( String requiredValue, String fieldName, String propertyName ) throws com.sun.star.uno.Exception, java.lang.Exception 755 { 756 String currentValue = (String)getControlModel( fieldName ).getPropertyValue( propertyName ); 757 if ( !currentValue.equals( requiredValue ) ) 758 { 759 System.out.println( "wrong value of the " + fieldName + " field!" ); 760 System.out.println( " expected: " + requiredValue ); 761 System.out.println( " found : " + currentValue ); 762 } 763 else 764 return true; 765 766 return false; 767 } 768 769 /* ------------------------------------------------------------------ */ getRadioModel( String name, String refValue )770 private XPropertySet getRadioModel( String name, String refValue ) throws com.sun.star.uno.Exception, java.lang.Exception 771 { 772 return m_formLayer.getRadioModelByRefValue( m_masterForm, name, refValue ); 773 } 774 775 /* ------------------------------------------------------------------ */ 776 /** executes the given statement on the given connection 777 */ implExecuteStatement( String sStatement )778 protected boolean implExecuteStatement( String sStatement ) throws java.lang.Exception 779 { 780 try 781 { 782 m_databaseDocument.executeSQL( sStatement ); 783 } 784 catch(com.sun.star.sdbc.SQLException e) 785 { 786 System.err.println( e ); 787 return false; 788 } 789 790 return true; 791 } 792 793 /* ------------------------------------------------------------------ */ 794 /** simulates a user's text input into a control given by model name 795 */ userTextInput( String modelName, String text, boolean withCommit )796 private void userTextInput( String modelName, String text, boolean withCommit ) throws com.sun.star.uno.Exception, java.lang.Exception 797 { 798 XPropertySet controlModel = getControlModel( modelName ); 799 // the form runtime environment (namely the form controller) rely on focus events for recognizing 800 // control content changes ... 801 if ( withCommit ) 802 m_document.getCurrentView().grabControlFocus( controlModel ); 803 804 m_formLayer.userTextInput( controlModel, text ); 805 806 // focus back to a dummy control model so the content of the model we just changed will 807 // be committed to the underlying database column 808 if ( withCommit ) 809 m_document.getCurrentView().grabControlFocus( getControlModel( "dummy" ) ); 810 } 811 812 /* ------------------------------------------------------------------ */ moveToInsertRow()813 private void moveToInsertRow() throws com.sun.star.uno.Exception, java.lang.Exception 814 { 815 XResultSetUpdate xResultSet = (XResultSetUpdate)UnoRuntime.queryInterface( XResultSetUpdate.class, m_masterForm ); 816 xResultSet.moveToInsertRow( ); 817 } 818 819 /* ------------------------------------------------------------------ */ moveToFirst()820 private void moveToFirst() throws com.sun.star.uno.Exception, java.lang.Exception 821 { 822 XResultSet xResultSet = (XResultSet)UnoRuntime.queryInterface( XResultSet.class, m_masterForm ); 823 xResultSet.first( ); 824 } 825 826 /* ------------------------------------------------------------------ */ moveToNext()827 private void moveToNext() throws com.sun.star.uno.Exception, java.lang.Exception 828 { 829 XResultSet xResultSet = (XResultSet)UnoRuntime.queryInterface( XResultSet.class, m_masterForm ); 830 xResultSet.next( ); 831 } 832 833 /* ------------------------------------------------------------------ */ 834 /** simulates pressing a toolbox button with the given URL 835 */ executeSlot( String slotURL )836 private void executeSlot( String slotURL ) throws java.lang.Exception 837 { 838 XDispatch xDispatch = m_document.getCurrentView().getDispatcher( slotURL ); 839 840 URL[] url = new URL[] { new URL() }; 841 url[0].Complete = slotURL; 842 XURLTransformer xTransformer = (XURLTransformer)UnoRuntime.queryInterface( 843 XURLTransformer.class, m_orb.createInstance( "com.sun.star.util.URLTransformer" ) ); 844 xTransformer.parseStrict( url ); 845 846 PropertyValue[] aArgs = new PropertyValue[0]; 847 xDispatch.dispatch( url[0], aArgs ); 848 } 849 850 /* ------------------------------------------------------------------ */ 851 /** undos the changes on the current record, by simulating pressing of the respective toolbox button 852 */ undoRecordByUI()853 private void undoRecordByUI() throws java.lang.Exception 854 { 855 executeSlot( ".uno:RecUndo" ); 856 } 857 858 /* ------------------------------------------------------------------ */ 859 /** saves the current record, by simulating pressing of the respective toolbox button 860 */ saveRecordByUI()861 private void saveRecordByUI() throws java.lang.Exception 862 { 863 executeSlot( ".uno:RecSave" ); 864 } 865 866 /* ------------------------------------------------------------------ */ 867 /** moves to the next record, by simulating pressing of the respective toolbox button 868 */ nextRecordByUI()869 private void nextRecordByUI() throws java.lang.Exception 870 { 871 executeSlot( ".uno:NextRecord" ); 872 } 873 /* ------------------------------------------------------------------ */ 874 /** moves to the previous record, by simulating pressing of the respective toolbox button 875 */ previousRecordByUI()876 private void previousRecordByUI() throws java.lang.Exception 877 { 878 executeSlot( ".uno:PrevRecord" ); 879 } 880 881 /* ------------------------------------------------------------------ */ createImageFile()882 private void createImageFile() throws java.io.IOException 883 { 884 m_sImageURL = util.utils.getOfficeTempDir( m_orb ) + "image.gif"; 885 886 FileOutputStream aFile = new FileOutputStream( m_sImageURL ); 887 aFile.write( getSamplePicture() ); 888 aFile.close(); 889 System.out.println( "created temporary image file: " + m_sImageURL ); 890 891 // for later setting the url at the imaghe control, we need a real URL, no system path 892 m_sImageURL = util.utils.getOfficeTemp( m_orb ) + "image.gif"; 893 } 894 895 /* ------------------------------------------------------------------ */ getSamplePicture()896 private byte[] getSamplePicture() 897 { 898 byte[] aBytes = new byte[] { 899 (byte)0x47, (byte)0x49, (byte)0x46, (byte)0x38, (byte)0x39, (byte)0x61, (byte)0x0A, (byte)0x00, (byte)0x0A, (byte)0x00, (byte)0xB3, (byte)0x00, (byte)0x00, (byte)0xFF, (byte)0x00, (byte)0x00, 900 (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0x00, (byte)0x00, (byte)0xFF, (byte)0xFF, (byte)0x00, (byte)0xFF, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xFF, (byte)0xFF, 901 (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, 902 (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0x2C, (byte)0x00, (byte)0x00, 903 (byte)0x00, (byte)0x00, (byte)0x0A, (byte)0x00, (byte)0x0A, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x20, (byte)0x10, (byte)0xC8, (byte)0x49, (byte)0x41, (byte)0xB9, (byte)0xF8, (byte)0xCA, 904 (byte)0x12, (byte)0xBA, (byte)0x2F, (byte)0x5B, (byte)0x30, (byte)0x8C, (byte)0x43, (byte)0x00, (byte)0x5A, (byte)0x22, (byte)0x41, (byte)0x94, (byte)0x27, (byte)0x37, (byte)0xA8, (byte)0x6C, 905 (byte)0x48, (byte)0xC6, (byte)0xA8, (byte)0xD7, (byte)0xB5, (byte)0x19, (byte)0x56, (byte)0xED, (byte)0x11, (byte)0x00, (byte)0x3B 906 }; 907 908 return aBytes; 909 } 910 911 /* ------------------------------------------------------------------ */ getSamplePictureBytes()912 private byte[] getSamplePictureBytes() 913 { 914 byte[] aBytes = new byte[] { 915 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, 916 (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, 917 (byte)0x01, (byte)0x03, (byte)0x03, (byte)0x03, (byte)0x03, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x01, (byte)0x03, (byte)0x04, (byte)0x04, (byte)0x03, (byte)0x01, 918 (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x01, (byte)0x03, (byte)0x04, (byte)0x04, (byte)0x03, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x01, (byte)0x03, 919 (byte)0x03, (byte)0x03, (byte)0x03, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05, (byte)0x00, 920 (byte)0x00, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 921 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 922 }; 923 return aBytes; 924 } 925 926 /* ------------------------------------------------------------------ */ verifyReferenceImage( byte[] referenceBytes )927 private boolean verifyReferenceImage( byte[] referenceBytes ) throws com.sun.star.uno.Exception, java.lang.Exception 928 { 929 XPropertySet xImageModel = getControlModel( "f_blob" ); 930 931 // check if the image control properly says that there currently is no image on the first record 932 XImageProducerSupplier xSuppProducer = (XImageProducerSupplier)UnoRuntime.queryInterface( XImageProducerSupplier.class, 933 xImageModel ); 934 XImageProducer xProducer = xSuppProducer.getImageProducer(); 935 936 ImageComparison compareImages = new ImageComparison( referenceBytes, this ); 937 synchronized( this ) 938 { 939 xProducer.addConsumer( compareImages ); 940 xProducer.startProduction(); 941 // wait(); 942 } 943 xProducer.removeConsumer( compareImages ); 944 945 return compareImages.imagesEqual( ); 946 } 947 948 /* ------------------------------------------------------------------ */ errorOccured( SQLErrorEvent _event )949 public void errorOccured( SQLErrorEvent _event ) 950 { 951 // just remember for the moment 952 m_mostRecentErrorEvent = _event; 953 } 954 955 /* ------------------------------------------------------------------ */ disposing( EventObject _event )956 public void disposing( EventObject _event ) 957 { 958 // not interested in 959 } 960 } 961