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