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 javafx.beans.property;
  27 
  28 
  29 import static org.junit.Assert.assertEquals;
  30 import static org.junit.Assert.assertFalse;
  31 import static org.junit.Assert.assertTrue;
  32 
  33 import javafx.beans.InvalidationListenerMock;
  34 import javafx.beans.value.ChangeListenerMock;
  35 import javafx.beans.value.ObservableObjectValueStub;
  36 
  37 import org.junit.Before;
  38 import org.junit.Test;
  39 
  40 public class ReadOnlyObjectWrapperTest {
  41 
  42     private static final Object UNDEFINED = null;
  43     private static final Object DEFAULT = null;
  44     private static final Object VALUE_1 = new Object();
  45     private static final Object VALUE_2 = new Object();
  46     
  47     private ReadOnlyObjectWrapperMock property;
  48     private ReadOnlyObjectProperty<Object> readOnlyProperty;
  49     private InvalidationListenerMock internalInvalidationListener;
  50     private InvalidationListenerMock publicInvalidationListener;
  51     private ChangeListenerMock<Object> internalChangeListener;
  52     private ChangeListenerMock<Object> publicChangeListener;
  53     
  54     @Before
  55     public void setUp() throws Exception {
  56         property = new ReadOnlyObjectWrapperMock();
  57         readOnlyProperty = property.getReadOnlyProperty();
  58         internalInvalidationListener = new InvalidationListenerMock();
  59         publicInvalidationListener = new InvalidationListenerMock();
  60         internalChangeListener = new ChangeListenerMock<Object>(UNDEFINED);
  61         publicChangeListener = new ChangeListenerMock<Object>(UNDEFINED);
  62     }
  63     
  64     private void attachInvalidationListeners() {
  65         property.addListener(internalInvalidationListener);
  66         readOnlyProperty.addListener(publicInvalidationListener);
  67         property.get();
  68         readOnlyProperty.get();
  69         internalInvalidationListener.reset();
  70         publicInvalidationListener.reset();
  71     }
  72 
  73     private void attachInternalChangeListener() {
  74         property.addListener(internalChangeListener);
  75         property.get();
  76         internalChangeListener.reset();
  77     }
  78 
  79     private void attachPublicChangeListener() {
  80         readOnlyProperty.addListener(publicChangeListener);
  81         readOnlyProperty.get();
  82         publicChangeListener.reset();
  83     }
  84 
  85     @Test
  86     public void testConstructor_NoArguments() {
  87         final ReadOnlyObjectWrapper<Object> p1 = new ReadOnlyObjectWrapper<Object>();
  88         assertEquals(DEFAULT, p1.get());
  89         assertEquals((Object)DEFAULT, p1.getValue());
  90         assertFalse(property.isBound());
  91         assertEquals(null, p1.getBean());
  92         assertEquals("", p1.getName());
  93         final ReadOnlyObjectProperty<Object> r1 = p1.getReadOnlyProperty();
  94         assertEquals(DEFAULT, r1.get());
  95         assertEquals((Object)DEFAULT, r1.getValue());
  96         assertEquals(null, r1.getBean());
  97         assertEquals("", r1.getName());
  98     }
  99     
 100     @Test
 101     public void testConstructor_InitialValue() {
 102         final ReadOnlyObjectWrapper<Object> p1 = new ReadOnlyObjectWrapper<Object>(VALUE_1);
 103         assertEquals(VALUE_1, p1.get());
 104         assertEquals((Object)VALUE_1, p1.getValue());
 105         assertFalse(property.isBound());
 106         assertEquals(null, p1.getBean());
 107         assertEquals("", p1.getName());
 108         final ReadOnlyObjectProperty<Object> r1 = p1.getReadOnlyProperty();
 109         assertEquals(VALUE_1, r1.get());
 110         assertEquals((Object)VALUE_1, r1.getValue());
 111         assertEquals(null, r1.getBean());
 112         assertEquals("", r1.getName());
 113     }
 114     
 115     @Test
 116     public void testConstructor_Bean_Name() {
 117         final Object bean = new Object();
 118         final String name = "My name";
 119         final ReadOnlyObjectWrapper<Object> p1 = new ReadOnlyObjectWrapper<Object>(bean, name);
 120         assertEquals(DEFAULT, p1.get());
 121         assertEquals((Object)DEFAULT, p1.getValue());
 122         assertFalse(property.isBound());
 123         assertEquals(bean, p1.getBean());
 124         assertEquals(name, p1.getName());
 125         final ReadOnlyObjectProperty<Object> r1 = p1.getReadOnlyProperty();
 126         assertEquals(DEFAULT, r1.get());
 127         assertEquals((Object)DEFAULT, r1.getValue());
 128         assertEquals(bean, r1.getBean());
 129         assertEquals(name, r1.getName());
 130     }
 131     
 132     @Test
 133     public void testConstructor_Bean_Name_InitialValue() {
 134         final Object bean = new Object();
 135         final String name = "My name";
 136         final ReadOnlyObjectWrapper<Object> p1 = new ReadOnlyObjectWrapper<Object>(bean, name, VALUE_1);
 137         assertEquals(VALUE_1, p1.get());
 138         assertEquals((Object)VALUE_1, p1.getValue());
 139         assertFalse(property.isBound());
 140         assertEquals(bean, p1.getBean());
 141         assertEquals(name, p1.getName());
 142         final ReadOnlyObjectProperty<Object> r1 = p1.getReadOnlyProperty();
 143         assertEquals(VALUE_1, r1.get());
 144         assertEquals((Object)VALUE_1, r1.getValue());
 145         assertEquals(bean, r1.getBean());
 146         assertEquals(name, r1.getName());
 147     }
 148 
 149     @Test
 150     public void testLazySet() {
 151         attachInvalidationListeners();
 152         
 153         // set value once
 154         property.set(VALUE_1);
 155         assertEquals(VALUE_1, property.get());
 156         property.check(1);
 157         internalInvalidationListener.check(readOnlyProperty, 1);
 158         assertEquals(VALUE_1, readOnlyProperty.get());
 159         publicInvalidationListener.check(readOnlyProperty, 1);
 160         
 161         // set same value again
 162         property.set(VALUE_1);
 163         assertEquals(VALUE_1, property.get());
 164         property.check(0);
 165         internalInvalidationListener.check(null, 0);
 166         assertEquals(VALUE_1, readOnlyProperty.get());
 167         publicInvalidationListener.check(null, 0);
 168         
 169         // set value twice without reading
 170         property.set(VALUE_2);
 171         property.set(VALUE_1);
 172         assertEquals(VALUE_1, property.get());
 173         property.check(1);
 174         internalInvalidationListener.check(readOnlyProperty, 1);
 175         assertEquals(VALUE_1, readOnlyProperty.get());
 176         publicInvalidationListener.check(readOnlyProperty, 1);
 177     }
 178     
 179     @Test
 180     public void testInternalEagerSet() {
 181         attachInternalChangeListener();
 182         
 183         // set value once
 184         property.set(VALUE_1);
 185         assertEquals(VALUE_1, property.get());
 186         property.check(1);
 187         internalChangeListener.check(readOnlyProperty, DEFAULT, VALUE_1, 1);
 188         assertEquals(VALUE_1, readOnlyProperty.get());
 189         
 190         // set same value again
 191         property.set(VALUE_1);
 192         assertEquals(VALUE_1, property.get());
 193         property.check(0);
 194         internalChangeListener.check(null, UNDEFINED, UNDEFINED, 0);
 195         assertEquals(VALUE_1, readOnlyProperty.get());
 196         
 197         // set value twice without reading
 198         property.set(VALUE_2);
 199         property.set(VALUE_1);
 200         assertEquals(VALUE_1, property.get());
 201         property.check(2);
 202         internalChangeListener.check(readOnlyProperty, VALUE_2, VALUE_1, 2);
 203         assertEquals(VALUE_1, readOnlyProperty.get());
 204     }
 205     
 206     @Test
 207     public void testPublicEagerSet() {
 208         attachPublicChangeListener();
 209         
 210         // set value once
 211         property.set(VALUE_1);
 212         assertEquals(VALUE_1, property.get());
 213         property.check(1);
 214         assertEquals(VALUE_1, readOnlyProperty.get());
 215         publicChangeListener.check(readOnlyProperty, DEFAULT, VALUE_1, 1);
 216         
 217         // set same value again
 218         property.set(VALUE_1);
 219         assertEquals(VALUE_1, property.get());
 220         property.check(0);
 221         assertEquals(VALUE_1, readOnlyProperty.get());
 222         publicChangeListener.check(null, UNDEFINED, UNDEFINED, 0);
 223         
 224         // set value twice without reading
 225         property.set(VALUE_2);
 226         property.set(VALUE_1);
 227         assertEquals(VALUE_1, property.get());
 228         property.check(2);
 229         assertEquals(VALUE_1, readOnlyProperty.get());
 230         publicChangeListener.check(readOnlyProperty, VALUE_2, VALUE_1, 2);
 231     }
 232 
 233     @Test
 234     public void testLazySetValue() {
 235         attachInvalidationListeners();
 236         
 237         // set value once
 238         property.setValue(VALUE_1);
 239         assertEquals(VALUE_1, property.get());
 240         property.check(1);
 241         internalInvalidationListener.check(readOnlyProperty, 1);
 242         assertEquals(VALUE_1, readOnlyProperty.get());
 243         publicInvalidationListener.check(readOnlyProperty, 1);
 244         
 245         // set same value again
 246         property.setValue(VALUE_1);
 247         assertEquals(VALUE_1, property.get());
 248         property.check(0);
 249         internalInvalidationListener.check(null, 0);
 250         assertEquals(VALUE_1, readOnlyProperty.get());
 251         publicInvalidationListener.check(null, 0);
 252         
 253         // set value twice without reading
 254         property.setValue(VALUE_2);
 255         property.setValue(VALUE_1);
 256         assertEquals(VALUE_1, property.get());
 257         property.check(1);
 258         internalInvalidationListener.check(readOnlyProperty, 1);
 259         assertEquals(VALUE_1, readOnlyProperty.get());
 260         publicInvalidationListener.check(readOnlyProperty, 1);
 261     }
 262     
 263     @Test
 264     public void testInternalEagerSetValue() {
 265         attachInternalChangeListener();
 266         
 267         // set value once
 268         property.setValue(VALUE_1);
 269         assertEquals(VALUE_1, property.get());
 270         property.check(1);
 271         internalChangeListener.check(readOnlyProperty, DEFAULT, VALUE_1, 1);
 272         assertEquals(VALUE_1, readOnlyProperty.get());
 273         
 274         // set same value again
 275         property.setValue(VALUE_1);
 276         assertEquals(VALUE_1, property.get());
 277         property.check(0);
 278         internalChangeListener.check(null, UNDEFINED, UNDEFINED, 0);
 279         assertEquals(VALUE_1, readOnlyProperty.get());
 280         
 281         // set value twice without reading
 282         property.setValue(VALUE_2);
 283         property.setValue(VALUE_1);
 284         assertEquals(VALUE_1, property.get());
 285         property.check(2);
 286         internalChangeListener.check(readOnlyProperty, VALUE_2, VALUE_1, 2);
 287         assertEquals(VALUE_1, readOnlyProperty.get());
 288     }
 289     
 290     @Test
 291     public void testPublicEagerSetValue() {
 292         attachPublicChangeListener();
 293         
 294         // set value once
 295         property.setValue(VALUE_1);
 296         assertEquals(VALUE_1, property.get());
 297         property.check(1);
 298         assertEquals(VALUE_1, readOnlyProperty.get());
 299         publicChangeListener.check(readOnlyProperty, DEFAULT, VALUE_1, 1);
 300         
 301         // set same value again
 302         property.setValue(VALUE_1);
 303         assertEquals(VALUE_1, property.get());
 304         property.check(0);
 305         assertEquals(VALUE_1, readOnlyProperty.get());
 306         publicChangeListener.check(null, UNDEFINED, UNDEFINED, 0);
 307         
 308         // set value twice without reading
 309         property.setValue(VALUE_2);
 310         property.setValue(VALUE_1);
 311         assertEquals(VALUE_1, property.get());
 312         property.check(2);
 313         assertEquals(VALUE_1, readOnlyProperty.get());
 314         publicChangeListener.check(readOnlyProperty, VALUE_2, VALUE_1, 2);
 315     }
 316     
 317     @Test(expected=RuntimeException.class)
 318     public void testSetBoundValue() {
 319         final ObjectProperty<Object> v = new SimpleObjectProperty<Object>(VALUE_1);
 320         property.bind(v);
 321         property.set(VALUE_1);
 322     }
 323 
 324     @Test
 325     public void testLazyBind_primitive() {
 326         attachInvalidationListeners();
 327         final ObservableObjectValueStub<Object> v = new ObservableObjectValueStub<Object>(VALUE_1);
 328 
 329         property.bind(v);
 330         assertEquals(VALUE_1, property.get());
 331         assertTrue(property.isBound());
 332         property.check(1);
 333         internalInvalidationListener.check(readOnlyProperty, 1);
 334         assertEquals(VALUE_1, readOnlyProperty.get());
 335         publicInvalidationListener.check(readOnlyProperty, 1);
 336 
 337         // change binding once
 338         v.set(VALUE_2);
 339         assertEquals(VALUE_2, property.get());
 340         property.check(1);
 341         internalInvalidationListener.check(readOnlyProperty, 1);
 342         assertEquals(VALUE_2, readOnlyProperty.get());
 343         publicInvalidationListener.check(readOnlyProperty, 1);
 344 
 345         // change binding twice without reading
 346         v.set(VALUE_1);
 347         v.set(VALUE_2);
 348         assertEquals(VALUE_2, property.get());
 349         property.check(1);
 350         internalInvalidationListener.check(readOnlyProperty, 1);
 351         assertEquals(VALUE_2, readOnlyProperty.get());
 352         publicInvalidationListener.check(readOnlyProperty, 1);
 353 
 354         // change binding twice to same value
 355         v.set(VALUE_1);
 356         v.set(VALUE_1);
 357         assertEquals(VALUE_1, property.get());
 358         property.check(1);
 359         internalInvalidationListener.check(readOnlyProperty, 1);
 360         assertEquals(VALUE_1, readOnlyProperty.get());
 361         publicInvalidationListener.check(readOnlyProperty, 1);
 362     }
 363 
 364     @Test
 365     public void testInternalEagerBind_primitive() {
 366         attachInternalChangeListener();
 367         final ObservableObjectValueStub<Object> v = new ObservableObjectValueStub<Object>(VALUE_1);
 368 
 369         property.bind(v);
 370         assertEquals(VALUE_1, property.get());
 371         assertTrue(property.isBound());
 372         property.check(1);
 373         internalChangeListener.check(readOnlyProperty, DEFAULT, VALUE_1, 1);
 374         assertEquals(VALUE_1, readOnlyProperty.get());
 375 
 376         // change binding once
 377         v.set(VALUE_2);
 378         assertEquals(VALUE_2, property.get());
 379         property.check(1);
 380         internalChangeListener.check(readOnlyProperty, VALUE_1, VALUE_2, 1);
 381         assertEquals(VALUE_2, readOnlyProperty.get());
 382 
 383         // change binding twice without reading
 384         v.set(VALUE_1);
 385         v.set(VALUE_2);
 386         assertEquals(VALUE_2, property.get());
 387         property.check(2);
 388         internalChangeListener.check(readOnlyProperty, VALUE_1, VALUE_2, 2);
 389         assertEquals(VALUE_2, readOnlyProperty.get());
 390 
 391         // change binding twice to same value
 392         v.set(VALUE_1);
 393         v.set(VALUE_1);
 394         assertEquals(VALUE_1, property.get());
 395         property.check(2);
 396         internalChangeListener.check(readOnlyProperty, VALUE_2, VALUE_1, 1);
 397         assertEquals(VALUE_1, readOnlyProperty.get());
 398     }
 399     
 400     @Test
 401     public void testPublicEagerBind_primitive() {
 402         attachPublicChangeListener();
 403         final ObservableObjectValueStub<Object> v = new ObservableObjectValueStub<Object>(VALUE_1);
 404 
 405         property.bind(v);
 406         assertEquals(VALUE_1, property.get());
 407         assertTrue(property.isBound());
 408         property.check(1);
 409         assertEquals(VALUE_1, readOnlyProperty.get());
 410         publicChangeListener.check(readOnlyProperty, DEFAULT, VALUE_1, 1);
 411 
 412         // change binding once
 413         v.set(VALUE_2);
 414         assertEquals(VALUE_2, property.get());
 415         property.check(1);
 416         assertEquals(VALUE_2, readOnlyProperty.get());
 417         publicChangeListener.check(readOnlyProperty, VALUE_1, VALUE_2, 1);
 418 
 419         // change binding twice without reading
 420         v.set(VALUE_1);
 421         v.set(VALUE_2);
 422         assertEquals(VALUE_2, property.get());
 423         property.check(2);
 424         assertEquals(VALUE_2, readOnlyProperty.get());
 425         publicChangeListener.check(readOnlyProperty, VALUE_1, VALUE_2, 2);
 426 
 427         // change binding twice to same value
 428         v.set(VALUE_1);
 429         v.set(VALUE_1);
 430         assertEquals(VALUE_1, property.get());
 431         property.check(2);
 432         assertEquals(VALUE_1, readOnlyProperty.get());
 433         publicChangeListener.check(readOnlyProperty, VALUE_2, VALUE_1, 1);
 434     }
 435     
 436     @Test
 437     public void testLazyBind_generic() {
 438         attachInvalidationListeners();
 439         final ObservableObjectValueStub<Object> v = new ObservableObjectValueStub<Object>(VALUE_1);
 440 
 441         property.bind(v);
 442         assertEquals(VALUE_1, property.get());
 443         assertTrue(property.isBound());
 444         property.check(1);
 445         internalInvalidationListener.check(readOnlyProperty, 1);
 446         assertEquals(VALUE_1, readOnlyProperty.get());
 447         publicInvalidationListener.check(readOnlyProperty, 1);
 448 
 449         // change binding once
 450         v.set(VALUE_2);
 451         assertEquals(VALUE_2, property.get());
 452         property.check(1);
 453         internalInvalidationListener.check(readOnlyProperty, 1);
 454         assertEquals(VALUE_2, readOnlyProperty.get());
 455         publicInvalidationListener.check(readOnlyProperty, 1);
 456 
 457         // change binding twice without reading
 458         v.set(VALUE_1);
 459         v.set(VALUE_2);
 460         assertEquals(VALUE_2, property.get());
 461         property.check(1);
 462         internalInvalidationListener.check(readOnlyProperty, 1);
 463         assertEquals(VALUE_2, readOnlyProperty.get());
 464         publicInvalidationListener.check(readOnlyProperty, 1);
 465 
 466         // change binding twice to same value
 467         v.set(VALUE_1);
 468         v.set(VALUE_1);
 469         assertEquals(VALUE_1, property.get());
 470         property.check(1);
 471         internalInvalidationListener.check(readOnlyProperty, 1);
 472         assertEquals(VALUE_1, readOnlyProperty.get());
 473         publicInvalidationListener.check(readOnlyProperty, 1);
 474     }
 475 
 476     @Test
 477     public void testInternalEagerBind_generic() {
 478         attachInternalChangeListener();
 479         final ObservableObjectValueStub<Object> v = new ObservableObjectValueStub<Object>(VALUE_1);
 480 
 481         property.bind(v);
 482         assertEquals(VALUE_1, property.get());
 483         assertTrue(property.isBound());
 484         property.check(1);
 485         internalChangeListener.check(readOnlyProperty, DEFAULT, VALUE_1, 1);
 486         assertEquals(VALUE_1, readOnlyProperty.get());
 487 
 488         // change binding once
 489         v.set(VALUE_2);
 490         assertEquals(VALUE_2, property.get());
 491         property.check(1);
 492         internalChangeListener.check(readOnlyProperty, VALUE_1, VALUE_2, 1);
 493         assertEquals(VALUE_2, readOnlyProperty.get());
 494 
 495         // change binding twice without reading
 496         v.set(VALUE_1);
 497         v.set(VALUE_2);
 498         assertEquals(VALUE_2, property.get());
 499         property.check(2);
 500         internalChangeListener.check(readOnlyProperty, VALUE_1, VALUE_2, 2);
 501         assertEquals(VALUE_2, readOnlyProperty.get());
 502 
 503         // change binding twice to same value
 504         v.set(VALUE_1);
 505         v.set(VALUE_1);
 506         assertEquals(VALUE_1, property.get());
 507         property.check(2);
 508         internalChangeListener.check(readOnlyProperty, VALUE_2, VALUE_1, 1);
 509         assertEquals(VALUE_1, readOnlyProperty.get());
 510     }
 511 
 512     @Test
 513     public void testPublicEagerBind_generic() {
 514         attachPublicChangeListener();
 515         final ObservableObjectValueStub<Object> v = new ObservableObjectValueStub<Object>(VALUE_1);
 516 
 517         property.bind(v);
 518         assertEquals(VALUE_1, property.get());
 519         assertTrue(property.isBound());
 520         property.check(1);
 521         assertEquals(VALUE_1, readOnlyProperty.get());
 522         publicChangeListener.check(readOnlyProperty, DEFAULT, VALUE_1, 1);
 523 
 524         // change binding once
 525         v.set(VALUE_2);
 526         assertEquals(VALUE_2, property.get());
 527         property.check(1);
 528         assertEquals(VALUE_2, readOnlyProperty.get());
 529         publicChangeListener.check(readOnlyProperty, VALUE_1, VALUE_2, 1);
 530 
 531         // change binding twice without reading
 532         v.set(VALUE_1);
 533         v.set(VALUE_2);
 534         assertEquals(VALUE_2, property.get());
 535         property.check(2);
 536         assertEquals(VALUE_2, readOnlyProperty.get());
 537         publicChangeListener.check(readOnlyProperty, VALUE_1, VALUE_2, 2);
 538 
 539         // change binding twice to same value
 540         v.set(VALUE_1);
 541         v.set(VALUE_1);
 542         assertEquals(VALUE_1, property.get());
 543         property.check(2);
 544         assertEquals(VALUE_1, readOnlyProperty.get());
 545         publicChangeListener.check(readOnlyProperty, VALUE_2, VALUE_1, 1);
 546     }
 547     
 548     @Test(expected=NullPointerException.class)
 549     public void testBindToNull() {
 550         property.bind(null);
 551     }
 552 
 553     @Test
 554     public void testRebind() {
 555         attachInvalidationListeners();
 556         final ObjectProperty<Object> v1 = new SimpleObjectProperty<Object>(VALUE_1);
 557         final ObjectProperty<Object> v2 = new SimpleObjectProperty<Object>(VALUE_2);
 558         property.bind(v1);
 559         property.get();
 560         readOnlyProperty.get();
 561         property.reset();
 562         internalInvalidationListener.reset();
 563         publicInvalidationListener.reset();
 564         
 565         // rebind causes invalidation event
 566         property.bind(v2);
 567         assertEquals(VALUE_2, property.get());
 568         assertTrue(property.isBound());
 569         property.check(1);
 570         internalInvalidationListener.check(readOnlyProperty, 1);
 571         assertEquals(VALUE_2, readOnlyProperty.get());
 572         publicInvalidationListener.check(readOnlyProperty, 1);
 573         
 574         // change new binding
 575         v2.set(VALUE_1);
 576         assertEquals(VALUE_1, property.get());
 577         property.check(1);
 578         internalInvalidationListener.check(readOnlyProperty, 1);
 579         assertEquals(VALUE_1, readOnlyProperty.get());
 580         publicInvalidationListener.check(readOnlyProperty, 1);
 581         
 582         // change old binding
 583         v1.set(VALUE_2);
 584         assertEquals(VALUE_1, property.get());
 585         property.check(0);
 586         internalInvalidationListener.check(null, 0);
 587         assertEquals(VALUE_1, readOnlyProperty.get());
 588         publicInvalidationListener.check(null, 0);
 589         
 590         // rebind to same observable should have no effect
 591         property.bind(v2);
 592         assertEquals(VALUE_1, property.get());
 593         assertTrue(property.isBound());
 594         property.check(0);
 595         internalInvalidationListener.check(null, 0);
 596         assertEquals(VALUE_1, readOnlyProperty.get());
 597         publicInvalidationListener.check(null, 0);
 598     }
 599 
 600     @Test
 601     public void testUnbind() {
 602         attachInvalidationListeners();
 603         final ObjectProperty<Object> v = new SimpleObjectProperty<Object>(VALUE_1);
 604         property.bind(v);
 605         property.unbind();
 606         assertEquals(VALUE_1, property.get());
 607         assertFalse(property.isBound());
 608         assertEquals(VALUE_1, readOnlyProperty.get());
 609         property.reset();
 610         internalInvalidationListener.reset();
 611         publicInvalidationListener.reset();
 612         
 613         // change binding
 614         v.set(VALUE_2);
 615         assertEquals(VALUE_1, property.get());
 616         property.check(0);
 617         internalInvalidationListener.check(null, 0);
 618         assertEquals(VALUE_1, readOnlyProperty.get());
 619         publicInvalidationListener.check(null, 0);
 620         
 621         // set value
 622         property.set(VALUE_2);
 623         assertEquals(VALUE_2, property.get());
 624         property.check(1);
 625         internalInvalidationListener.check(readOnlyProperty, 1);
 626         assertEquals(VALUE_2, readOnlyProperty.get());
 627         publicInvalidationListener.check(readOnlyProperty, 1);
 628     }
 629     
 630     @Test
 631     public void testAddingListenerWillAlwaysReceiveInvalidationEvent() {
 632         final ObjectProperty<Object> v = new SimpleObjectProperty<Object>(VALUE_1);
 633         final InvalidationListenerMock internalListener2 = new InvalidationListenerMock();
 634         final InvalidationListenerMock internalListener3 = new InvalidationListenerMock();
 635         final InvalidationListenerMock publicListener2 = new InvalidationListenerMock();
 636         final InvalidationListenerMock publicListener3 = new InvalidationListenerMock();
 637 
 638         // setting the property,checking internal
 639         property.set(VALUE_1);
 640         property.addListener(internalListener2);
 641         internalListener2.reset();
 642         property.set(VALUE_2);
 643         internalListener2.check(readOnlyProperty, 1);
 644         
 645         // setting the property, checking public
 646         property.set(VALUE_1);
 647         readOnlyProperty.addListener(publicListener2);
 648         publicListener2.reset();
 649         property.set(VALUE_2);
 650         publicListener2.check(readOnlyProperty, 1);
 651         
 652         // binding the property, checking internal
 653         property.bind(v);
 654         v.set(VALUE_2);
 655         property.addListener(internalListener3);
 656         v.get();
 657         internalListener3.reset();
 658         v.set(VALUE_1);
 659         internalListener3.check(readOnlyProperty, 1);
 660         
 661         // binding the property, checking public
 662         property.bind(v);
 663         v.set(VALUE_2);
 664         readOnlyProperty.addListener(publicListener3);
 665         v.get();
 666         publicListener3.reset();
 667         v.set(VALUE_1);
 668         publicListener3.check(readOnlyProperty, 1);
 669     }
 670     
 671     @Test
 672     public void testRemoveListeners() {
 673         attachInvalidationListeners();
 674         attachInternalChangeListener();
 675         property.removeListener(internalInvalidationListener);
 676         property.removeListener(internalChangeListener);
 677         property.get();
 678         internalInvalidationListener.reset();
 679         internalChangeListener.reset();
 680         
 681         property.set(VALUE_1);
 682         internalInvalidationListener.check(null, 0);
 683         internalChangeListener.check(null, UNDEFINED, UNDEFINED, 0);
 684         
 685         // no read only property created => no-op
 686         final ReadOnlyObjectWrapper<Object> v1 = new ReadOnlyObjectWrapper<Object>();
 687         v1.removeListener(internalInvalidationListener);
 688         v1.removeListener(internalChangeListener);
 689     }
 690     
 691     @Test
 692     public void testNoReadOnlyPropertyCreated() {
 693         final ObjectProperty<Object> v1 = new SimpleObjectProperty<Object>(VALUE_1);
 694         final ReadOnlyObjectWrapper<Object> p1 = new ReadOnlyObjectWrapper<Object>();
 695         
 696         p1.set(VALUE_1);
 697         p1.bind(v1);
 698         assertEquals(VALUE_1, p1.get());
 699         v1.set(VALUE_2);
 700         assertEquals(VALUE_2, p1.get());
 701     }
 702     
 703     @Test
 704     public void testToString() {
 705         final ObjectProperty<Object> v1 = new SimpleObjectProperty<Object>(VALUE_1);
 706         
 707         property.set(VALUE_1);
 708         assertEquals("ObjectProperty [value: " + VALUE_1 + "]", property.toString());
 709         assertEquals("ReadOnlyObjectProperty [value: " + VALUE_1 + "]", readOnlyProperty.toString());
 710         
 711         property.bind(v1);
 712         assertEquals("ObjectProperty [bound, invalid]", property.toString());
 713         assertEquals("ReadOnlyObjectProperty [value: " + VALUE_1 + "]", readOnlyProperty.toString());
 714         property.get();
 715         assertEquals("ObjectProperty [bound, value: " + VALUE_1 + "]", property.toString());
 716         assertEquals("ReadOnlyObjectProperty [value: " + VALUE_1 + "]", readOnlyProperty.toString());
 717         v1.set(VALUE_2);
 718         assertEquals("ObjectProperty [bound, invalid]", property.toString());
 719         assertEquals("ReadOnlyObjectProperty [value: " + VALUE_2 + "]", readOnlyProperty.toString());
 720         property.get();
 721         assertEquals("ObjectProperty [bound, value: " + VALUE_2 + "]", property.toString());
 722         assertEquals("ReadOnlyObjectProperty [value: " + VALUE_2 + "]", readOnlyProperty.toString());
 723         
 724         final Object bean = new Object();
 725         final String name = "My name";
 726         final ReadOnlyObjectWrapper<Object> v2 = new ReadOnlyObjectWrapper<Object>(bean, name);
 727         assertEquals("ObjectProperty [bean: " + bean.toString() + ", name: My name, value: " + DEFAULT + "]", v2.toString());
 728         assertEquals("ReadOnlyObjectProperty [bean: " + bean.toString() + ", name: My name, value: " + DEFAULT + "]", v2.getReadOnlyProperty().toString());
 729         
 730         final ReadOnlyObjectWrapper<Object> v3 = new ReadOnlyObjectWrapper<Object>(bean, "");
 731         assertEquals("ObjectProperty [bean: " + bean.toString() + ", value: " + DEFAULT + "]", v3.toString());
 732         assertEquals("ReadOnlyObjectProperty [bean: " + bean.toString() + ", value: " + DEFAULT + "]", v3.getReadOnlyProperty().toString());
 733 
 734         final ReadOnlyObjectWrapper<Object> v4 = new ReadOnlyObjectWrapper<Object>(null, name);
 735         assertEquals("ObjectProperty [name: My name, value: " + DEFAULT + "]", v4.toString());
 736         assertEquals("ReadOnlyObjectProperty [name: My name, value: " + DEFAULT + "]", v4.getReadOnlyProperty().toString());
 737     }
 738     
 739     private static class ReadOnlyObjectWrapperMock extends ReadOnlyObjectWrapper<Object> {
 740         
 741         private int counter;
 742         
 743         @Override
 744         protected void invalidated() {
 745             counter++;
 746         }
 747         
 748         private void check(int expected) {
 749             assertEquals(expected, counter);
 750             reset();
 751         }
 752         
 753         private void reset() {
 754             counter = 0;
 755         }
 756     }
 757 }