1 /* 2 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package test.com.sun.javafx.test; 27 28 import javafx.beans.property.ReadOnlyProperty; 29 import javafx.beans.InvalidationListener; 30 import javafx.beans.Observable; 31 import javafx.beans.value.ObservableValue; 32 33 import org.junit.Assert; 34 import org.junit.Test; 35 36 public abstract class PropertiesTestBase { 37 38 private final Configuration configuration; 39 40 public PropertiesTestBase(final Configuration configuration) { 41 this.configuration = configuration; 42 } 43 44 @Test 45 public void testGetBean() { 46 configuration.getBeanTest(); 47 } 48 49 @Test 50 public void testGetName() { 51 configuration.getNameTest(); 52 } 53 54 @Test 55 public void testBasicAccess() { 56 configuration.basicAccessTest(); 57 } 58 59 @Test 60 public void testBinding() { 61 configuration.bindingTest(); 62 } 63 64 /** 65 * Single bean, single property configuration. 66 */ 67 public static Object[] config(final Object bean, 68 final String propertyName, 69 final Object propertyValue1, 70 final Object propertyValue2) { 71 return config(new Configuration(bean, 72 propertyName, 73 propertyValue1, 74 propertyValue2)); 75 } 76 77 /** 78 * Single bean, single property configuration with custom value comparator. 79 */ 80 public static Object[] config(final Object bean, 81 final String propertyName, 82 final Object propertyValue1, 83 final Object propertyValue2, 84 final ValueComparator comparator) { 85 return config(new Configuration(bean, 86 propertyName, 87 propertyValue1, 88 propertyValue2, 89 comparator)); 90 } 91 92 /** 93 * Single bean, propertyA (source) and propertyB (dependent) property 94 * configuration. 95 */ 96 public static Object[] config(final Object beanA, 97 final String propertyAName, 98 final Object propertyAValue1, 99 final Object propertyAValue2, 100 final String propertyBName, 101 final Object propertyBValue1, 102 final Object propertyBValue2) { 103 return config(new Configuration(beanA, 104 propertyAName, 105 propertyAValue1, 106 propertyAValue2, 107 propertyBName, 108 propertyBValue1, 109 propertyBValue2)); 110 } 111 112 /** 113 * BeanA with propertyA (source) and BeanB with propertyB (dependent) 114 * configuration. 115 */ 116 public static Object[] config(final Object beanA, 117 final String propertyAName, 118 final Object propertyAValue1, 119 final Object propertyAValue2, 120 final Object beanB, 121 final String propertyBName, 122 final Object propertyBValue1, 123 final Object propertyBValue2) { 124 return config(new Configuration(beanA, 125 propertyAName, 126 propertyAValue1, 127 propertyAValue2, 128 beanB, 129 propertyBName, 130 propertyBValue1, 131 propertyBValue2)); 132 } 133 134 /** 135 * BeanA with propertyA (source) and BeanB with propertyB (dependent) 136 * with custom value comparator configuration. 137 */ 138 public static Object[] config(final Object beanA, 139 final String propertyAName, 140 final Object propertyAValue1, 141 final Object propertyAValue2, 142 final Object beanB, 143 final String propertyBName, 144 final Object propertyBValue1, 145 final Object propertyBValue2, 146 final ValueComparator propertyBComparator) { 147 return config(new Configuration(beanA, 148 propertyAName, 149 propertyAValue1, 150 propertyAValue2, 151 beanB, 152 propertyBName, 153 propertyBValue1, 154 propertyBValue2, 155 propertyBComparator)); 156 } 157 158 public static Object[] config(final Configuration configuration) { 159 return new Object[] { configuration }; 160 } 161 162 public static class Configuration { 163 private final Object beanA; 164 165 private final PropertyReference propertyAReference; 166 167 private final Object propertyAValue1; 168 169 private final Object propertyAValue2; 170 171 private final Object beanB; 172 173 private final PropertyReference propertyBReference; 174 175 private final Object propertyBValue1; 176 177 private final Object propertyBValue2; 178 179 private final ValueComparator propertyBComparator; 180 181 private boolean allowMultipleNotifications; 182 183 public Configuration(final Object bean, 184 final String propertyName, 185 final Object propertyValue1, 186 final Object propertyValue2) { 187 this(bean, propertyName, propertyValue1, propertyValue2, 188 bean, propertyName, propertyValue1, propertyValue2, 189 ValueComparator.DEFAULT); 190 } 191 192 public Configuration(final Object bean, 193 final String propertyName, 194 final Object propertyValue1, 195 final Object propertyValue2, 196 final ValueComparator valueComparator) { 197 this(bean, propertyName, propertyValue1, propertyValue2, 198 bean, propertyName, propertyValue1, propertyValue2, 199 valueComparator); 200 } 201 202 public Configuration(final Object bean, 203 final String propertyAName, 204 final Object propertyAValue1, 205 final Object propertyAValue2, 206 final String propertyBName, 207 final Object propertyBValue1, 208 final Object propertyBValue2) { 209 this(bean, propertyAName, propertyAValue1, propertyAValue2, 210 bean, propertyBName, propertyBValue1, propertyBValue2, 211 ValueComparator.DEFAULT); 212 } 213 214 public Configuration(final Object beanA, 215 final String propertyAName, 216 final Object propertyAValue1, 217 final Object propertyAValue2, 218 final Object beanB, 219 final String propertyBName, 220 final Object propertyBValue1, 221 final Object propertyBValue2) { 222 this(beanA, propertyAName, propertyAValue1, propertyAValue2, 223 beanB, propertyBName, propertyBValue1, propertyBValue2, 224 ValueComparator.DEFAULT); 225 } 226 227 public Configuration(final Object beanA, 228 final String propertyAName, 229 final Object propertyAValue1, 230 final Object propertyAValue2, 231 final Object beanB, 232 final String propertyBName, 233 final Object propertyBValue1, 234 final Object propertyBValue2, 235 final ValueComparator propertyBComparator) { 236 this.beanA = beanA; 237 this.propertyAReference = PropertyReference.createForBean( 238 beanA.getClass(), 239 propertyAName); 240 this.propertyAValue1 = propertyAValue1; 241 this.propertyAValue2 = propertyAValue2; 242 this.beanB = beanB; 243 this.propertyBReference = PropertyReference.createForBean( 244 beanB.getClass(), 245 propertyBName); 246 this.propertyBValue1 = propertyBValue1; 247 this.propertyBValue2 = propertyBValue2; 248 this.propertyBComparator = propertyBComparator; 249 } 250 251 public void setAllowMultipleNotifications( 252 final boolean allowMultipleNotifications) { 253 this.allowMultipleNotifications = allowMultipleNotifications; 254 } 255 256 public void getBeanTest() { 257 final ReadOnlyProperty<?> propertyA = 258 (ReadOnlyProperty<?>) BindingHelper.getPropertyModel( 259 beanA, propertyAReference); 260 final ReadOnlyProperty<?> propertyB = 261 (ReadOnlyProperty<?>) BindingHelper.getPropertyModel( 262 beanB, propertyBReference); 263 264 Assert.assertSame(beanA, propertyA.getBean()); 265 Assert.assertSame(beanB, propertyB.getBean()); 266 } 267 268 public void getNameTest() { 269 final ReadOnlyProperty<?> propertyA = 270 (ReadOnlyProperty<?>) BindingHelper.getPropertyModel( 271 beanA, propertyAReference); 272 final ReadOnlyProperty<?> propertyB = 273 (ReadOnlyProperty<?>) BindingHelper.getPropertyModel( 274 beanB, propertyBReference); 275 276 Assert.assertEquals(propertyAReference.getPropertyName(), 277 propertyA.getName()); 278 Assert.assertEquals(propertyBReference.getPropertyName(), 279 propertyB.getName()); 280 } 281 282 public void basicAccessTest() { 283 // set to first value and verify dependet value 284 propertyAReference.setValue(beanA, propertyAValue1); 285 propertyBComparator.assertEquals( 286 propertyBValue1, 287 propertyBReference.getValue(beanB)); 288 289 final ValueInvalidationListener valueInvalidationListener = 290 new ValueInvalidationListener(allowMultipleNotifications); 291 final ObservableValue observableValueB = 292 (ObservableValue) BindingHelper.getPropertyModel( 293 beanB, propertyBReference); 294 295 // register listener 296 observableValueB.addListener(valueInvalidationListener); 297 298 // set to second value 299 propertyAReference.setValue(beanA, propertyAValue2); 300 301 // verify that the listener has been called 302 valueInvalidationListener.assertCalled(); 303 valueInvalidationListener.reset(); 304 305 // test whether the second dependent value is set 306 propertyBComparator.assertEquals( 307 propertyBValue2, 308 propertyBReference.getValue(beanB)); 309 310 // set to the second value again 311 propertyAReference.setValue(beanA, propertyAValue2); 312 313 // verify that the listener has not been called 314 valueInvalidationListener.assertNotCalled(); 315 316 // unregister listener 317 observableValueB.removeListener(valueInvalidationListener); 318 319 // set to the first value again and test 320 propertyAReference.setValue(beanA, propertyAValue1); 321 propertyBComparator.assertEquals( 322 propertyBValue1, 323 propertyBReference.getValue(beanB)); 324 325 // verify that the listener has not been called 326 valueInvalidationListener.assertNotCalled(); 327 } 328 329 public void bindingTest() { 330 // set to the first value 331 propertyAReference.setValue(beanA, propertyAValue1); 332 333 // bind to a variable set to second value 334 final Object firstVariable = 335 BindingHelper.createVariable(propertyAValue2); 336 BindingHelper.bind(beanA, propertyAReference, firstVariable); 337 338 // test what we get 339 propertyBComparator.assertEquals( 340 propertyBValue2, 341 propertyBReference.getValue(beanB)); 342 343 final ValueInvalidationListener valueInvalidationListener = 344 new ValueInvalidationListener(allowMultipleNotifications); 345 final ObservableValue observableValue = 346 (ObservableValue) BindingHelper.getPropertyModel( 347 beanB, propertyBReference); 348 349 // register listener 350 observableValue.addListener(valueInvalidationListener); 351 352 // change the value of the bound variable 353 BindingHelper.setWritableValue(propertyAReference.getValueType(), 354 firstVariable, propertyAValue1); 355 356 // verify that the listener has been called 357 valueInvalidationListener.assertCalled(); 358 valueInvalidationListener.reset(); 359 360 // check the value 361 propertyBComparator.assertEquals( 362 propertyBValue1, 363 propertyBReference.getValue(beanB)); 364 365 // change binding 366 final Object secondVariable = 367 BindingHelper.createVariable(propertyAValue2); 368 BindingHelper.bind(beanA, propertyAReference, secondVariable); 369 370 // verify that the listener has been called 371 valueInvalidationListener.assertCalled(); 372 valueInvalidationListener.reset(); 373 374 // check the value 375 propertyBComparator.assertEquals( 376 propertyBValue2, 377 propertyBReference.getValue(beanB)); 378 379 // unbind 380 BindingHelper.unbind(beanA, propertyAReference); 381 382 // verify that the listener has not been called 383 valueInvalidationListener.assertNotCalled(); 384 385 // change the value of the last bound variable 386 BindingHelper.setWritableValue(propertyAReference.getValueType(), 387 secondVariable, propertyAValue1); 388 389 // verify that the listener has not been called 390 valueInvalidationListener.assertNotCalled(); 391 392 // check that the current property value equals to the last 393 // value set by binding 394 propertyBComparator.assertEquals( 395 propertyBValue2, 396 propertyBReference.getValue(beanB)); 397 398 // set to the first value again 399 propertyAReference.setValue(beanA, propertyAValue1); 400 401 // verify that the listener has been called 402 valueInvalidationListener.assertCalled(); 403 valueInvalidationListener.reset(); 404 405 // check the value 406 propertyBComparator.assertEquals( 407 propertyBValue1, 408 propertyBReference.getValue(beanB)); 409 410 // unregister listener 411 observableValue.removeListener(valueInvalidationListener); 412 } 413 } 414 415 private static final class ValueInvalidationListener 416 implements InvalidationListener { 417 private final boolean allowMultipleNotifications; 418 419 private int counter; 420 421 public ValueInvalidationListener( 422 final boolean allowMultipleNotifications) { 423 this.allowMultipleNotifications = allowMultipleNotifications; 424 } 425 426 public void reset() { 427 counter = 0; 428 } 429 430 public void assertCalled() { 431 if (counter == 0) { 432 Assert.fail("Listener has not been called!"); 433 return; 434 } 435 436 if (!allowMultipleNotifications && (counter > 1)) { 437 Assert.fail("Listener called multiple times!"); 438 } 439 } 440 441 public void assertNotCalled() { 442 if (counter != 0) { 443 Assert.fail("Listener has been called!"); 444 return; 445 } 446 } 447 448 @Override 449 public void invalidated(final Observable valueModel) { 450 ++counter; 451 } 452 } 453 }