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