518 lines
No EOL
21 KiB
Java
518 lines
No EOL
21 KiB
Java
/*************************************************************************
|
|
*
|
|
* $RCSfile: MultiPropertyTest.java,v $
|
|
*
|
|
* $Revision: 1.2 $
|
|
*
|
|
* last change:$Date: 2003-02-10 13:32:13 $
|
|
*
|
|
* The Contents of this file are made available subject to the terms of
|
|
* either of the following licenses
|
|
*
|
|
* - GNU Lesser General Public License Version 2.1
|
|
* - Sun Industry Standards Source License Version 1.1
|
|
*
|
|
* Sun Microsystems Inc., October, 2000
|
|
*
|
|
* GNU Lesser General Public License Version 2.1
|
|
* =============================================
|
|
* Copyright 2000 by Sun Microsystems, Inc.
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License version 2.1, as published by the Free Software Foundation.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307 USA
|
|
*
|
|
*
|
|
* Sun Industry Standards Source License Version 1.1
|
|
* =================================================
|
|
* The contents of this file are subject to the Sun Industry Standards
|
|
* Source License Version 1.1 (the "License"); You may not use this file
|
|
* except in compliance with the License. You may obtain a copy of the
|
|
* License at http://www.openoffice.org/license.html.
|
|
*
|
|
* Software provided under this License is provided on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
|
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
|
|
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
|
|
* See the License for the specific provisions governing your rights and
|
|
* obligations concerning the Software.
|
|
*
|
|
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
|
|
*
|
|
* Copyright: 2000 by Sun Microsystems, Inc.
|
|
*
|
|
* All Rights Reserved.
|
|
*
|
|
* Contributor(s): _______________________________________
|
|
*
|
|
*
|
|
************************************************************************/
|
|
|
|
package lib;
|
|
|
|
import com.sun.star.beans.Property;
|
|
import com.sun.star.beans.PropertyAttribute;
|
|
import com.sun.star.beans.PropertyVetoException;
|
|
import com.sun.star.beans.XPropertySet;
|
|
import com.sun.star.beans.XPropertySetInfo;
|
|
import com.sun.star.beans.UnknownPropertyException;
|
|
import com.sun.star.lang.XServiceInfo;
|
|
import com.sun.star.lang.IllegalArgumentException;
|
|
import com.sun.star.lang.WrappedTargetException;
|
|
import com.sun.star.uno.UnoRuntime;
|
|
|
|
import java.lang.reflect.Method;
|
|
|
|
import util.ValueChanger;
|
|
import util.ValueComparer;
|
|
|
|
import com.sun.star.uno.Any;
|
|
import com.sun.star.uno.AnyConverter;
|
|
import com.sun.star.uno.Type;
|
|
|
|
/**
|
|
* MultiPropertyTest extends the functionality of MultiMethodTest to support
|
|
* services testing. Since, in most cases, service tests has one method testing
|
|
* most of its properties, the MultiPropertyTest provides unified version of
|
|
* the method: testProperty().
|
|
*
|
|
* <p>The testProperty() is called, when the MultiMethodTest's testing method
|
|
* is not found in the subclass. So, by defining such methods for properties
|
|
* the standard testing behavioutr can be changed.
|
|
*
|
|
* <p>The testing behaviour also can be changed by overriding compare(),
|
|
* getNewVAlue() or toString(Object) methods, or by extending PropertyTester
|
|
* class.
|
|
*
|
|
* @see MultiMethodTest
|
|
* @see #testProperty(String)
|
|
* @see #testProperty(String, Propertytester)
|
|
* @see #getNewValue
|
|
* @see #compare
|
|
* @see #toString(Object)
|
|
*/
|
|
public class MultiPropertyTest extends MultiMethodTest {
|
|
/**
|
|
* Contains a XPropertySet interface of the tested object. Is initialized
|
|
* in MultiMethodTest code.
|
|
*/
|
|
public XPropertySet oObj;
|
|
protected boolean optionalService = false;
|
|
|
|
/**
|
|
* Overrides super.before() to check the service is supported by the object.
|
|
*/
|
|
protected void before() {
|
|
XServiceInfo xInfo = (XServiceInfo)UnoRuntime.queryInterface(
|
|
XServiceInfo.class, oObj);
|
|
|
|
optionalService = entry.isOptional;
|
|
|
|
String theService = getTestedClassName();
|
|
if (xInfo != null && !xInfo.supportsService(theService)) {
|
|
log.println("Service "+theService+" not available");
|
|
if (optionalService) {
|
|
log.println("This is OK since it is optional");
|
|
} else {
|
|
Status.failed(theService + " is not supported");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Overrides MultiMethodTest.invokeTestMethod(). If the test for the
|
|
* <code>meth</code> is not available (<code>meth</code> == <tt>null</tt>)
|
|
* calls testProperty method for the method. Otherwise calls
|
|
* super.invokeTestMethod().
|
|
*
|
|
* @see #MultiMethodTest.invokeTestMethod()
|
|
*/
|
|
protected void invokeTestMethod(Method meth, String methName) {
|
|
if (meth != null) {
|
|
super.invokeTestMethod(meth, methName);
|
|
} else {
|
|
testProperty(methName);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* PropertyTester class defines how to test a property and defined
|
|
* to allow subclasses of MultiPropertyTest to change the testing
|
|
* behaviour more flexible, since the behaviour can be customized for
|
|
* each property separately, by providing subclass of PropertyTester
|
|
* and passing it to testProperty(String, PropertyTester method).
|
|
*/
|
|
public class PropertyTester {
|
|
/**
|
|
* The method defines the whole process of testing propName
|
|
* property.
|
|
*
|
|
* <p>First, it checks if the property exists(it maybe optional).
|
|
* Then, a value to set the property with is calculated with
|
|
* getNewValue method. Normally, the new value is calculated
|
|
* based on old value, but subclasses can override the behaviour
|
|
* (for example, if old value is null) and specify their own value.
|
|
* Then the property is set with that new value and the result(
|
|
* it maybe an exception too, for example a PropertyVetoException)
|
|
* is checked with checkResult method.
|
|
*
|
|
* @param propName - the property to test.
|
|
* @result - adds the result of testing propName property to
|
|
* MultiMethodTest.tRes.
|
|
*/
|
|
protected void testProperty(String propName) {
|
|
XPropertySetInfo info = oObj.getPropertySetInfo();
|
|
|
|
if (!info.hasPropertyByName(propName)) {
|
|
if (isOptional(propName) || optionalService) {
|
|
// skipping optional property test
|
|
log.println("Property '" + propName
|
|
+ "' is optional and not supported");
|
|
tRes.tested(propName,true);
|
|
return;
|
|
} else {
|
|
// cannot test the property
|
|
log.println("Tested XPropertySet does not contain'"
|
|
+ propName + "' property");
|
|
tRes.tested(propName, false);
|
|
return;
|
|
}
|
|
}
|
|
|
|
try {
|
|
Object oldValue = oObj.getPropertyValue(propName);
|
|
|
|
Object newValue;
|
|
|
|
// trying to create new value
|
|
try {
|
|
newValue = getNewValue(propName, oldValue);
|
|
} catch (java.lang.IllegalArgumentException e) {
|
|
// skipping test since new value is not available
|
|
Status.failed("Cannot create new value for '"
|
|
+ propName + " : " + e.getMessage());
|
|
return;
|
|
}
|
|
|
|
// for an exception thrown during setting new value
|
|
// to pass it to checkResult method
|
|
Exception exception = null;
|
|
|
|
try {
|
|
oObj.setPropertyValue(propName, newValue);
|
|
} catch(IllegalArgumentException e) {
|
|
exception = e;
|
|
} catch(PropertyVetoException e) {
|
|
exception = e;
|
|
} catch(WrappedTargetException e) {
|
|
exception = e;
|
|
} catch(UnknownPropertyException e) {
|
|
exception = e;
|
|
} catch(RuntimeException e) {
|
|
exception = e;
|
|
}
|
|
|
|
// getting result value
|
|
Object resValue = oObj.getPropertyValue(propName);
|
|
|
|
// checking results
|
|
checkResult(propName, oldValue, newValue, resValue, exception);
|
|
} catch (Exception e) {
|
|
log.println("Exception occured while testing property '" + propName + "'");
|
|
e.printStackTrace(log);
|
|
tRes.tested(propName, false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The method checks result of setting a new value to the
|
|
* property based o the following arguments:
|
|
* @propName - the property to test
|
|
* @oldValue - the old value of the property, before changing it.
|
|
* @newValue - the new value the property has been set with
|
|
* @resValue - the value of the property after having changed it
|
|
* @exception - if not null - the exception thrown by
|
|
* XPropertySet.setPropertyValue, else indicates
|
|
* normal method completion.
|
|
*
|
|
* <p>If the property is READ_ONLY, than either PropertyVetoException
|
|
* should be thrown or the value of property should not have changed
|
|
* (resValue is compared with oldValue with compare method).
|
|
*
|
|
* <p>If the property is not READ_ONLY, checks that the new value has
|
|
* been successfully set(resValue is compared with newValue with
|
|
* compare method).
|
|
*
|
|
* <p>If the exception is not null then(except the case of read-only
|
|
* property and PropertyVetoException above) it is rethrown to allow
|
|
* further catching it if needed.
|
|
*
|
|
* <p>Subclasses can override to change this behaviour.
|
|
*/
|
|
protected void checkResult(String propName, Object oldValue,
|
|
Object newValue, Object resValue, Exception exception)
|
|
throws Exception {
|
|
XPropertySetInfo info = oObj.getPropertySetInfo();
|
|
Property prop = info.getPropertyByName(propName);
|
|
|
|
short attr = prop.Attributes;
|
|
boolean readOnly = (prop.Attributes
|
|
& PropertyAttribute.READONLY) != 0;
|
|
boolean maybeVoid = (prop.Attributes
|
|
& PropertyAttribute.MAYBEVOID) != 0;
|
|
//check get-set methods
|
|
if (maybeVoid) log.println("Property "+propName+" is void");
|
|
if (readOnly) log.println("Property "+propName+" is readOnly");
|
|
if (util.utils.isVoid(oldValue) && !maybeVoid) {
|
|
log.println(propName
|
|
+ " is void, but it's not MAYBEVOID");
|
|
tRes.tested(propName, false);
|
|
} else if (oldValue == null ) {
|
|
log.println(propName
|
|
+ " has null value, and therefore can't be changed");
|
|
tRes.tested(propName, true);
|
|
} else if (readOnly) {
|
|
// check if exception was thrown
|
|
if (exception != null) {
|
|
if (exception instanceof PropertyVetoException) {
|
|
// the change of read only prohibited - OK
|
|
log.println("Property is ReadOnly and wasn't changed");
|
|
log.println("Property '" + propName + "' OK");
|
|
tRes.tested(propName, true);
|
|
} else if (exception instanceof IllegalArgumentException) {
|
|
// the change of read only prohibited - OK
|
|
log.println("Property is ReadOnly and wasn't changed");
|
|
log.println("Property '" + propName + "' OK");
|
|
tRes.tested(propName, true);
|
|
} else if (exception instanceof UnknownPropertyException) {
|
|
// the change of read only prohibited - OK
|
|
log.println("Property is ReadOnly and wasn't changed");
|
|
log.println("Property '" + propName + "' OK");
|
|
tRes.tested(propName, true);
|
|
}else if (exception instanceof RuntimeException) {
|
|
// the change of read only prohibited - OK
|
|
log.println("Property is ReadOnly and wasn't changed");
|
|
log.println("Property '" + propName + "' OK");
|
|
tRes.tested(propName, true);
|
|
} else {
|
|
throw exception;
|
|
}
|
|
} else {
|
|
// if no exception - check that value
|
|
// has not changed
|
|
if (!compare(resValue, oldValue)) {
|
|
log.println("Read only property '"
|
|
+ propName + "' has changed");
|
|
try {
|
|
if (!util.utils.isVoid(oldValue)
|
|
&& oldValue instanceof Any) {
|
|
oldValue = AnyConverter.toObject
|
|
(new Type(((Any)oldValue).getClass()),oldValue);
|
|
}
|
|
log.println("old = " + toString(oldValue));
|
|
log.println("new = " + toString(newValue));
|
|
log.println("result = " + toString(resValue));
|
|
log.println("expected = " + toString(oldValue));
|
|
} catch(com.sun.star.lang.IllegalArgumentException iae) {
|
|
}
|
|
|
|
tRes.tested(propName, false);
|
|
} else {
|
|
log.println("Read only property '"
|
|
+ propName + "' hasn't changed");
|
|
log.println("Property '" + propName + "' OK");
|
|
tRes.tested(propName, true);
|
|
}
|
|
}
|
|
} else {
|
|
if (exception == null) {
|
|
// if no exception thrown
|
|
// check that the new value is set
|
|
if ((!compare(resValue, newValue)) || (compare(resValue, oldValue))) {
|
|
log.println("Value for '" + propName
|
|
+ "' hasn't changed as expected");
|
|
try {
|
|
if (!util.utils.isVoid(oldValue)
|
|
&& oldValue instanceof Any) {
|
|
oldValue = AnyConverter.toObject
|
|
(new Type(((Any)oldValue).getClass()),oldValue);
|
|
}
|
|
log.println("old = " + toString(oldValue));
|
|
log.println("new = " + toString(newValue));
|
|
log.println("result = " + toString(resValue));
|
|
log.println("expected = " + toString(oldValue));
|
|
} catch(com.sun.star.lang.IllegalArgumentException iae) {
|
|
}
|
|
if (resValue != null ) {
|
|
if ( (!compare(resValue, oldValue)) || (!resValue.equals(oldValue))) {
|
|
log.println("But it has changed.");
|
|
tRes.tested(propName, true);
|
|
} else {
|
|
tRes.tested(propName, false);
|
|
}
|
|
}
|
|
else {
|
|
tRes.tested(propName, false);
|
|
}
|
|
//tRes.tested(propName, false);
|
|
} else {
|
|
log.println("Property '" + propName + "' OK");
|
|
try {
|
|
if (!util.utils.isVoid(oldValue)
|
|
&& oldValue instanceof Any) {
|
|
oldValue = AnyConverter.toObject
|
|
(new Type(((Any)oldValue).getClass()),oldValue);
|
|
}
|
|
log.println("old = " + toString(oldValue));
|
|
log.println("new = " + toString(newValue));
|
|
log.println("result = " + toString(resValue));
|
|
log.println("expected = " + toString(oldValue));
|
|
} catch(com.sun.star.lang.IllegalArgumentException iae) {
|
|
}
|
|
tRes.tested(propName, true);
|
|
}
|
|
} else {
|
|
throw exception;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The method produces new value of the property from the oldValue.
|
|
* It returns the result of ValueChanger.changePValue method.
|
|
* Subclasses can override the method to return their own value,
|
|
* when the changePValue beahviour is not enough, for example,
|
|
* when oldValue is null.
|
|
*/
|
|
protected Object getNewValue(String propName, Object oldValue)
|
|
throws java.lang.IllegalArgumentException {
|
|
return ValueChanger.changePValue(oldValue);
|
|
}
|
|
|
|
/**
|
|
* The method compares obj1 and obj2. It calls
|
|
* MultiPropertyTest.compare, but subclasses can override to change
|
|
* the behaviour, since normally compare calls Object.equals method
|
|
* which is not apropriate in some cases(e.g., structs with equals
|
|
* not overridden).
|
|
*/
|
|
protected boolean compare(Object obj1, Object obj2) {
|
|
return callCompare(obj1, obj2);
|
|
}
|
|
|
|
/**
|
|
* The method returns a String representation of the obj. It calls
|
|
* MultipropertyTest.toString(Object), but subclasses can override
|
|
* to change the behaviour.
|
|
*/
|
|
protected String toString(Object obj) {
|
|
return callToString(obj);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Extension for <code>PropertyTester</code> which switches two
|
|
* different values. <code>getNewValue()</code> method of this
|
|
* class returns one of these two values depending on the
|
|
* old value, so new value is not equal to old value.
|
|
*/
|
|
public class PropertyValueSwitcher extends PropertyTester {
|
|
Object val1 = null ;
|
|
Object val2 = null ;
|
|
|
|
/**
|
|
* Constructs a property tester with two different values
|
|
* specified as parameters.
|
|
*
|
|
* @param val1 Not <code>null</code> value for the property
|
|
* tested.
|
|
* @param val1 Not <code>null</code> value for the property
|
|
* tested which differs from the first value.
|
|
*/
|
|
public PropertyValueSwitcher(Object val1, Object val2) {
|
|
this.val1 = val1 ;
|
|
this.val2 = val2 ;
|
|
}
|
|
|
|
/**
|
|
* Overriden method of <code>PropertyTester</code> which
|
|
* retruns new value from two values specified.
|
|
*
|
|
* @return The second value if old value is equal to the first
|
|
* one, the first value otherwise.
|
|
*/
|
|
protected Object getNewValue(String propName, Object old) {
|
|
if (ValueComparer.equalValue(val1, old))
|
|
return val2 ;
|
|
else
|
|
return val1 ;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The method performs testing of propName property using propTester.
|
|
*/
|
|
protected void testProperty(String propName, PropertyTester propTester) {
|
|
propTester.testProperty(propName);
|
|
}
|
|
|
|
/**
|
|
* The method performs testing of propName property. It uses PropertyTester
|
|
* instance for testing.
|
|
*/
|
|
protected void testProperty(String propName) {
|
|
testProperty(propName, new PropertyTester());
|
|
}
|
|
|
|
/**
|
|
* Tests the property using <code>PropertyValueSwitcher</code>
|
|
* tester and two values for this property.
|
|
*
|
|
* @see #PropertyValueSwitcher
|
|
*/
|
|
protected void testProperty(String propName, Object val1, Object val2) {
|
|
testProperty(propName, new PropertyValueSwitcher(val1, val2));
|
|
}
|
|
|
|
/**
|
|
* The method just calls compare. This is a workaround to CodeWarrior's
|
|
* compiler bug.
|
|
*/
|
|
private boolean callCompare(Object obj1, Object obj2) {
|
|
return compare(obj1, obj2);
|
|
}
|
|
|
|
/**
|
|
* Compares two object. In the implementation calls obj1.equals(obj2).
|
|
*/
|
|
protected boolean compare(Object obj1, Object obj2) {
|
|
return ValueComparer.equalValue(obj1, obj2);
|
|
}
|
|
|
|
/**
|
|
* The method just calls toString. This is a workaround to
|
|
* CodeWarrior's compiler bug.
|
|
*/
|
|
private String callToString(Object obj) {
|
|
return toString(obj);
|
|
}
|
|
|
|
/**
|
|
* Gets string representation of the obj. In the implementation
|
|
* returns obj.toString().
|
|
*/
|
|
protected String toString(Object obj) {
|
|
return obj == null ? "null" : obj.toString();
|
|
}
|
|
} |