1 /* 2 * This file is part of the LibreOffice project. 3 * 4 * This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 * 8 * This file incorporates work covered by the following license notice: 9 * 10 * Licensed to the Apache Software Foundation (ASF) under one or more 11 * contributor license agreements. See the NOTICE file distributed 12 * with this work for additional information regarding copyright 13 * ownership. The ASF licenses this file to you under the Apache 14 * License, Version 2.0 (the "License"); you may not use this file 15 * except in compliance with the License. You may obtain a copy of 16 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 17 */ 18 package mod._forms; 19 import com.sun.star.beans.NamedValue; 20 import com.sun.star.beans.PropertyValue; 21 import com.sun.star.container.XIndexAccess; 22 import java.io.PrintWriter; 23 24 import lib.StatusException; 25 import lib.TestCase; 26 import lib.TestEnvironment; 27 import lib.TestParameters; 28 import util.DBTools; 29 import util.FormTools; 30 import util.WriterTools; 31 32 import com.sun.star.beans.XPropertySet; 33 import com.sun.star.drawing.XControlShape; 34 import com.sun.star.form.XBoundComponent; 35 import com.sun.star.form.XForm; 36 import com.sun.star.form.XLoadable; 37 import com.sun.star.lang.XMultiServiceFactory; 38 import com.sun.star.lang.XComponent; 39 import com.sun.star.sdbc.XConnection; 40 import com.sun.star.sdbc.XResultSetUpdate; 41 import com.sun.star.sdb.XDocumentDataSource; 42 import com.sun.star.text.XTextDocument; 43 import com.sun.star.uno.AnyConverter; 44 import com.sun.star.uno.Type; 45 import com.sun.star.uno.UnoRuntime; 46 import com.sun.star.uno.XInterface; 47 import com.sun.star.util.XCloseable; 48 import java.util.ArrayList; 49 import lib.Status; 50 import util.utils; 51 52 53 /** 54 * Test for object which is represented by service 55 * <code>com.sun.star.form.component.DateField</code>. <p> 56 * Object implements the following interfaces : 57 * <ul> 58 * <li> <code>com::sun::star::io::XPersistObject</code></li> 59 * <li> <code>com::sun::star::awt::UnoControlDateFieldModel</code></li> 60 * <li> <code>com::sun::star::form::XReset</code></li> 61 * <li> <code>com::sun::star::form::XBoundComponent</code></li> 62 * <li> <code>com::sun::star::form::FormComponent</code></li> 63 * <li> <code>com::sun::star::form::component::DateField</code></li> 64 * <li> <code>com::sun::star::beans::XFastPropertySet</code></li> 65 * <li> <code>com::sun::star::beans::XMultiPropertySet</code></li> 66 * <li> <code>com::sun::star::form::XUpdateBroadcaster</code></li> 67 * <li> <code>com::sun::star::form::DataAwareControlModel</code></li> 68 * <li> <code>com::sun::star::beans::XPropertyState</code></li> 69 * <li> <code>com::sun::star::form::FormControlModel</code></li> 70 * <li> <code>com::sun::star::container::XNamed</code></li> 71 * <li> <code>com::sun::star::lang::XComponent</code></li> 72 * <li> <code>com::sun::star::lang::XEventListener</code></li> 73 * <li> <code>com::sun::star::beans::XPropertyAccess</code></li> 74 * <li> <code>com::sun::star::beans::XPropertyContainer</code></li> 75 * <li> <code>com::sun::star::beans::XPropertySet</code></li> 76 * <li> <code>com::sun::star::form::XLoadListener</code></li> 77 * <li> <code>com::sun::star::container::XChild</code></li> 78 * </ul> 79 * The following files used by this test : 80 * <ul> 81 * <li><b> TestDB </b> (directory) : directory with test database </li> 82 * <li><b> TestDB/TestDB.dbf </b> : table file. See 83 * {@link util.DBTools DBTools} class for more information.</li> 84 * </ul> <p> 85 * This object test <b> is NOT </b> designed to be run in several 86 * threads concurrently. 87 * @see com.sun.star.io.XPersistObject 88 * @see com.sun.star.awt.UnoControlDateFieldModel 89 * @see com.sun.star.form.XReset 90 * @see com.sun.star.form.XBoundComponent 91 * @see com.sun.star.form.FormComponent 92 * @see com.sun.star.form.component.DateField 93 * @see com.sun.star.beans.XFastPropertySet 94 * @see com.sun.star.beans.XMultiPropertySet 95 * @see com.sun.star.form.XUpdateBroadcaster 96 * @see com.sun.star.form.DataAwareControlModel 97 * @see com.sun.star.beans.XPropertyState 98 * @see com.sun.star.form 99 * @see com.sun.star.container.XNamed 100 * @see com.sun.star.lang.XComponent 101 * @see com.sun.star.lang.XEventListener 102 * @see com.sun.star.beans.XPropertyAccess 103 * @see com.sun.star.beans.XPropertyContainer 104 * @see com.sun.star.beans.XPropertySet 105 * @see com.sun.star.form.XLoadListener 106 * @see com.sun.star.container.XChild 107 * @see ifc.io._XPersistObject 108 * @see ifc.awt._UnoControlDateFieldModel 109 * @see ifc.form._XReset 110 * @see ifc.form._XBoundComponent 111 * @see ifc.form._FormComponent 112 * @see ifc.form.component._DateField 113 * @see ifc.beans._XFastPropertySet 114 * @see ifc.beans._XMultiPropertySet 115 * @see ifc.form._XUpdateBroadcaster 116 * @see ifc.form._DataAwareControlModel 117 * @see ifc.beans._XPropertyState 118 * @see ifc.form._FormControlModel 119 * @see ifc.container._XNamed 120 * @see ifc.lang._XComponent 121 * @see ifc.lang._XEventListener 122 * @see ifc.beans._XPropertySet 123 * @see ifc.form._XLoadListener 124 * @see ifc.container._XChild 125 */ 126 public class GenericModelTest extends TestCase { 127 private XTextDocument m_xTextDoc; 128 private Object m_dbSrc = null; 129 /** 130 * This is the name of the Data Base which the test uses: "APITestDatabase" 131 */ 132 private static final String m_dbSourceName = "APITestDatabase"; 133 private static final String m_TestDB = "TestDB"; 134 private DBTools m_dbTools = null; 135 136 private boolean m_ConnectionClosed = false; 137 138 /** 139 * describes the kind of the shape which should be created. 140 * Example: m_kindOfshape=DateFilled 141 */ 142 protected String m_kindOfControl = null; 143 144 /** 145 * If your object needs some special property values you can specify them with this 146 * <CODE>ArrayList</CODE>. You have to add a <CODE>NamedValue</CODE> to this list. 147 * Example: 148 * NamedValue myProp = new NamedValue(); 149 * myProp.Name = "Test"; 150 * myProp.Value = "My special Value"; 151 * m_propertiesToSet.add(myProp); 152 */ 153 protected ArrayList<NamedValue> m_propertiesToSet = new ArrayList<NamedValue>(); 154 155 /** 156 * This variable contains the name of the property which should be changed while 157 * interface <CODE>com::sun::star::form::XUpdateBroadcaster</CODE> is tested. The 158 * interface test needs the <CODE>ObjectRelation</CODE> 159 * "XUpdateBroadcaster.Checker" which is a <CODE>ifc.form._XUpdateBroadcaster.UpdateChecker</CODE>. 160 * @see ifc.form._XUpdateBroadcaster.UpdateChecker 161 * @see ifc.form._XUpdateBroadcaster 162 */ 163 protected String m_ChangePropertyName = null; 164 /** 165 * This variable contains the value the property should be set while 166 * interface <CODE>com::sun::star::form::XUpdateBroadcaster</CODE> is tested. 167 * The interface test needs the <CODE>ObjectRelation</CODE> 168 * "XUpdateBroadcaster.Checker" which is a <CODE>ifc.form._XUpdateBroadcaster.UpdateChecker</CODE>. 169 * Normally the <CODE>Checker</CODE> uses <CODE>util.ValueChanger</CODE> to change 170 * the value of the property. If the current of this property is NULL the 171 * <CODE>ValueChanger</CODE> is unable to change the value. In this case the value 172 * of this variable was used. 173 */ 174 protected Object m_ChangePropertyValue = null; 175 176 /** 177 * This variable contains the implementation name of the object. 178 */ 179 protected String m_ObjectName = null; 180 181 /** 182 * For local implementations of <CODE>Checker</CODE> this variable contains the 183 * <CODE>FormLoader</CODE> 184 */ 185 protected XLoadable m_XFormLoader = null; 186 /** 187 * For local implementations of <CODE>Checker</CODE> this variable contains the 188 * <CODE>XPropertySet</CODE> 189 */ 190 protected XPropertySet m_XPS = null; 191 /** 192 * For local implementations of <CODE>Checker</CODE> this variable contains the 193 * <CODE>Control</CODE> 194 */ 195 protected XInterface m_XCtrl = null; 196 /** 197 * The interface test of <CODE>ifc.form._DataWareControlModel</CODE> expects an 198 * object relation <CODE>'LC'</CODE>. This is a <CODE>XControlModel</CODE> of a shape. 199 * This variable contains the kind of shape to create for the interface test, 200 * f.e. "FixedText" 201 * @see ifc.form._DataAwareControlModel 202 */ 203 protected String m_LCShape_Type = null; 204 205 /** 206 * If this variable is true some more debug info was logged. It was set by the parameter variable 207 * <code>debug_is_active</code> 208 */ 209 private boolean debug = false; 210 211 /** 212 * Creates Writer document where controls are placed. 213 * @param tParam the test parameter 214 * @param log the log writer 215 */ 216 @Override initialize(TestParameters tParam, PrintWriter log)217 protected void initialize(TestParameters tParam, PrintWriter log) throws Exception { 218 log.println("creating a textdocument"); 219 m_xTextDoc = WriterTools.createTextDoc(tParam.getMSF()); 220 m_ConnectionClosed = false; 221 debug = tParam.getBool(util.PropertyName.DEBUG_IS_ACTIVE); 222 m_propertiesToSet.clear(); 223 } 224 225 /** 226 * close the connection 227 * close the data source 228 * close the document 229 * revoke the data source 230 * @param tParam the test parameter 231 * @param log the log writer 232 */ 233 @Override cleanup(TestParameters tParam, PrintWriter log)234 protected void cleanup(TestParameters tParam, PrintWriter log) { 235 log.println("closing connection..."); 236 237 // some interface tests call cleanup to reset the environment. If such 238 // a test is the last one cleanup was called twice. The second call 239 // causes then nasty exceptions... 240 if (m_ConnectionClosed) return; 241 242 try { 243 XIndexAccess forms = UnoRuntime.queryInterface( XIndexAccess.class, 244 FormTools.getForms( WriterTools.getDrawPage( m_xTextDoc ) ) ); 245 XForm myForm = (XForm) AnyConverter.toObject(new Type(XForm.class), 246 forms.getByIndex(0)); 247 248 if (debug){ 249 if (myForm == null){ 250 log.println("ERROR: could not get 'Standard' from drawpage!"); 251 } 252 log.println("the draw page contains following elements:"); 253 String[] elements = FormTools.getForms(WriterTools.getDrawPage(m_xTextDoc)).getElementNames(); 254 for (int i = 0; i< elements.length; i++){ 255 log.println("Element[" + i + "] :" + elements[i]); 256 } 257 258 } 259 260 XPropertySet xSetProp = UnoRuntime.queryInterface( XPropertySet.class, myForm ); 261 XConnection connection = UnoRuntime.queryInterface( XConnection.class, xSetProp.getPropertyValue( "ActiveConnection" ) ); 262 if ( connection == null ) 263 { 264 if ( debug ) 265 log.println("ERROR: could not get property 'ActiveConnection' from the XForm"); 266 } 267 else 268 { 269 connection.close(); 270 } 271 } catch (Exception e) { 272 log.println("ERROR: Can't close the connection: " + e.toString()); 273 e.printStackTrace( log ); 274 } 275 276 log.println("closing data source..."); 277 try { 278 XCloseable closer = UnoRuntime.queryInterface( 279 XCloseable.class, m_dbSrc); 280 if ( closer == null ) 281 { 282 XDocumentDataSource dataSource = UnoRuntime.queryInterface( 283 XDocumentDataSource.class, m_dbSrc); 284 if ( dataSource != null ) 285 closer = UnoRuntime.queryInterface( 286 XCloseable.class, dataSource.getDatabaseDocument() ); 287 } 288 if (debug && closer==null){ 289 log.println("ERROR: couldn't get 'XCloseable' from DataSource"); 290 } 291 closer.close(true); 292 } catch (com.sun.star.util.CloseVetoException e) { 293 log.println("ERROR: couldn't close data source: " + e.toString()); 294 } catch (com.sun.star.lang.DisposedException e) { 295 log.println("ERROR: couldn't close data source: " + e.toString()); 296 } catch (Exception e) { 297 log.println("ERROR: couldn't close data source: " + e.toString()); 298 } 299 300 log.println("disposing data source..."); 301 try { 302 XComponent dataSourceComp = UnoRuntime.queryInterface( 303 XComponent.class, m_dbSrc); 304 dataSourceComp.dispose(); 305 } 306 catch (Exception e) { 307 log.println("couldn't dispose the data source"); 308 } 309 310 log.println("closing document..."); 311 312 try { 313 XCloseable closer = UnoRuntime.queryInterface( 314 XCloseable.class, m_xTextDoc); 315 closer.close(true); 316 } catch (com.sun.star.util.CloseVetoException e) { 317 log.println("ERROR: couldn't close document: " + e.toString()); 318 } catch (com.sun.star.lang.DisposedException e) { 319 log.println("ERROR: couldn't close document: " + e.toString()); 320 } catch (Exception e) { 321 log.println("ERROR: couldn't close document: " + e.toString()); 322 } 323 324 log.println("revoking data source..."); 325 try { 326 m_dbTools.revokeDB(m_dbSourceName); 327 } catch (com.sun.star.container.NoSuchElementException e){ 328 } catch (com.sun.star.uno.Exception e) { 329 log.println("ERROR: Error while object test cleaning up: " + e.toString()); 330 } 331 332 m_ConnectionClosed = true; 333 } 334 335 /** 336 * Creating a TestEnvironment for the interfaces to be tested. 337 * First <code>TestDB</code> database is registered. 338 * Creates DateField in the Form, then binds it to TestDB 339 * database and returns Field's control. <p> 340 * Object relations created : 341 * <ul> 342 * <li> <code>'OBJNAME'</code> for 343 * {@link ifc.io._XPersistObject} : name of service which is 344 * represented by this object. </li> 345 * <li> <code>'LC'</code> for {@link ifc.form._DataAwareControlModel}. 346 * Specifies the value for LabelControl property. It is 347 * <code>FixedText</code> component added to the document.</li> 348 * <li> <code>'FL'</code> for 349 * {@link ifc.form._DataAwareControlModel} interface. 350 * Specifies XLoadable implementation which connects form to 351 * the data source.</li> 352 * <li> <code>'XUpdateBroadcaster.Checker'</code> : <code> 353 * _XUpdateBroadcaster.UpdateChecker</code> interface implementation 354 * which can update, commit data and check if the data was successfully 355 * committed.</li> 356 * <li> <code>'DataAwareControlModel.NewFieldName'</code> : for 357 * <code>com.sun.star.form.DataAwareControlModel</code> service 358 * which contains new name of the field ('_DATE') to bind control to. 359 * </li> 360 * <li> <code>'XFastPropertySet.ExcludeProps'</code> : for 361 * <code>com.sun.star.beans.XFastPropertySet</code> interface 362 * the property FormatKey can have only restricted set of values. 363 * </li> 364 * </ul> 365 * @see ifc.form._XUpdateBroadcaster 366 * @param Param the test parameter 367 * @param log the log writer 368 * @return a test environment 369 */ 370 @Override createTestEnvironment(TestParameters Param, PrintWriter log)371 protected TestEnvironment createTestEnvironment(TestParameters Param, 372 PrintWriter log) throws Exception { 373 XInterface oObj = null; 374 XControlShape aShape = null; 375 XMultiServiceFactory xMSF = Param.getMSF(); 376 377 log.println("adding control shape '" + m_kindOfControl + "'"); 378 aShape = FormTools.createControlShape(m_xTextDoc, 3000, 379 4500, 15000, 10000, 380 m_kindOfControl); 381 382 WriterTools.getDrawPage(m_xTextDoc).add(aShape); 383 oObj = aShape.getControl(); 384 385 log.println("Implementation name: " + util.utils.getImplName(oObj)); 386 387 String sourceTestDB = utils.getFullURL(utils.getFullTestDocName("TestDB/testDB.dbf")); 388 String destTestDB = utils.getOfficeTemp(xMSF); 389 destTestDB = utils.getFullURL(destTestDB + "testDB.dbf"); 390 391 log.println("copy '"+sourceTestDB + "' -> '" + destTestDB + "'"); 392 utils.copyFile(xMSF, sourceTestDB, destTestDB); 393 394 m_dbTools = new DBTools( xMSF ); 395 String tmpDir = utils.getOfficeTemp(xMSF); 396 397 DBTools.DataSourceInfo srcInf = m_dbTools.newDataSourceInfo(); 398 srcInf.URL = "sdbc:dbase:" + DBTools.dirToUrl(tmpDir); 399 log.println("data source: " + srcInf.URL); 400 401 m_dbSrc = srcInf.getDataSourceService(); 402 m_dbTools.reRegisterDB(m_dbSourceName, m_dbSrc); 403 404 m_XFormLoader = FormTools.bindForm(m_xTextDoc, m_dbSourceName, 405 m_TestDB); 406 407 log.println("creating a new environment for object"); 408 409 TestEnvironment tEnv = new TestEnvironment(oObj); 410 411 tEnv.addObjRelation("OBJNAME", m_ObjectName); 412 413 log.println("adding shape '" + m_LCShape_Type +"' for DataAwareControlModel test"); 414 aShape = FormTools.createControlShape(m_xTextDoc, 6000, 4500, 15000, 415 10000, m_LCShape_Type); 416 WriterTools.getDrawPage(m_xTextDoc).add(aShape); 417 418 m_XPS = UnoRuntime.queryInterface( 419 XPropertySet.class, oObj); 420 421 int i = 0; 422 NamedValue prop = null; 423 for (i = 0; i < m_propertiesToSet.size(); i++){ 424 prop = m_propertiesToSet.get(i); 425 426 log.println("setting property: '"+prop.Name+"' to value '"+prop.Value.toString()+"'"); 427 428 m_XPS.setPropertyValue(prop.Name, prop.Value); 429 } 430 431 // added LabelControl for 'DataAwareControlModel' 432 tEnv.addObjRelation("LC", aShape.getControl()); 433 434 // added FormLoader for 'DataAwareControlModel' 435 tEnv.addObjRelation("FL", m_XFormLoader); 436 437 // adding relation for XUpdateBroadcaster 438 m_XCtrl = oObj; 439 440 tEnv.addObjRelation("XUpdateBroadcaster.Checker", 441 new Checker(m_XFormLoader, m_XPS, m_XCtrl, m_ChangePropertyName, m_ChangePropertyValue)); 442 443 // adding relation for DataAwareControlModel service 444 tEnv.addObjRelation("DataAwareControlModel.NewFieldName", 445 DBTools.TST_DATE_F); 446 447 //adding ObjRelation for XPersistObject 448 tEnv.addObjRelation("PSEUDOPERSISTENT", Boolean.TRUE); 449 450 // adding relation for XFastPropertySet 451 java.util.HashSet<String> exclude = new java.util.HashSet<String>(); 452 exclude.add("FormatKey"); 453 tEnv.addObjRelation("XFastPropertySet.ExcludeProps", exclude); 454 455 PropertyValue propVal = new PropertyValue(); 456 propVal.Name = "HelpText"; 457 propVal.Value = "Text since XPropertyAccess"; 458 tEnv.addObjRelation("XPropertyAccess.propertyToChange", propVal); 459 tEnv.addObjRelation("XPropertyContainer.propertyNotRemovable", "HelpText"); 460 461 462 return tEnv; 463 } // finish method getTestEnvironment 464 465 466 private static class Checker implements ifc.form._XUpdateBroadcaster.UpdateChecker { 467 private Object lastValue = null; 468 private XLoadable formLoaderF = null; 469 private XPropertySet ps = null; 470 private XInterface ctrl = null; 471 private String ChangePropertyName = null; 472 Object ChangePropertyValue = null; 473 Checker(XLoadable xl, XPropertySet ps, XInterface ctrl, String ChangePropertyName, Object ChangePropertyValue)474 public Checker(XLoadable xl, XPropertySet ps, XInterface ctrl, String ChangePropertyName, Object ChangePropertyValue) { 475 formLoaderF = xl; 476 this.ps = ps; 477 this.ctrl = ctrl; 478 this.ChangePropertyName=ChangePropertyName; 479 this.ChangePropertyValue=ChangePropertyValue; 480 } 481 update()482 public void update() throws com.sun.star.uno.Exception { 483 if (!formLoaderF.isLoaded()) { 484 formLoaderF.load(); 485 } 486 487 lastValue = util.ValueChanger.changePValue(ps.getPropertyValue(ChangePropertyName)); 488 489 if (lastValue == null){ 490 491 if (ChangePropertyValue != null){ 492 493 lastValue = ChangePropertyValue; 494 495 } else { 496 497 String msg = "The initial value of the property '" + ChangePropertyName + "' is NULL\n"; 498 msg += "The member variable 'm_ChangePropertyValue' is NULL\n"; 499 msg += "Could not change Property."; 500 501 throw new StatusException(Status.failed(msg)); 502 } 503 } 504 ps.setPropertyValue(ChangePropertyName, lastValue); 505 } 506 commit()507 public void commit() throws com.sun.star.sdbc.SQLException { 508 XBoundComponent bound = UnoRuntime.queryInterface( 509 XBoundComponent.class, ctrl); 510 XResultSetUpdate update = UnoRuntime.queryInterface( 511 XResultSetUpdate.class, 512 formLoaderF); 513 514 bound.commit(); 515 update.updateRow(); 516 } 517 wasCommited()518 public boolean wasCommited() throws com.sun.star.uno.Exception { 519 formLoaderF.reload(); 520 521 Object newValue = ps.getPropertyValue(ChangePropertyName); 522 523 return (newValue != null) && (util.ValueComparer.equalValue(lastValue, newValue)); 524 } 525 } 526 } // finish class GenericModelTest 527