1 /*
   2  * Copyright (c) 2016, 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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.beans.BeanInfo;
  25 import java.beans.BeanProperty;
  26 import java.beans.IntrospectionException;
  27 import java.beans.Introspector;
  28 import java.beans.PropertyChangeListener;
  29 import java.beans.PropertyDescriptor;
  30 
  31 import java.util.Arrays;
  32 
  33 
  34 /**
  35  * @test
  36  * @bug 8132703 8132163 8132732 8132973 8154756 8132888
  37  * @summary Some check for BeanProperty annotation
  38  * @author a.stepanov
  39  * @run main BeanPropertyTest
  40  */
  41 
  42 
  43 public class BeanPropertyTest {
  44 
  45     private final static String  DESCRIPTION = "TEST";
  46     private final static boolean BOUND       = true;
  47     private final static boolean EXPERT      = false;
  48     private final static boolean HIDDEN      = true;
  49     private final static boolean PREFERRED   = false;
  50     private final static boolean REQUIRED    = true;
  51     private final static boolean UPDATE      = false;
  52     private final static String
  53         V_NAME  = "javax.swing.SwingConstants.TOP",
  54         V_SHORT = "TOP",
  55         V = Integer.toString(javax.swing.SwingConstants.TOP);
  56     private final static int X = javax.swing.SwingConstants.TOP;
  57 
  58     private final static String DESCRIPTION_2 = "XYZ";
  59 
  60 
  61     // ---------- test cases ----------
  62 
  63     public static class G01 {
  64 
  65         private final static String TESTCASE = "arbitrary getter name";
  66 
  67         private final int x = X;
  68 
  69         @BeanProperty(
  70             description  = DESCRIPTION,
  71             bound        = BOUND,
  72             expert       = EXPERT,
  73             hidden       = HIDDEN,
  74             preferred    = PREFERRED,
  75             required     = REQUIRED,
  76             visualUpdate = UPDATE,
  77             enumerationValues = {V_NAME})
  78         public int get1() { return x; }
  79 
  80         public void addPropertyChangeListener(PropertyChangeListener l)    {}
  81         public void removePropertyChangeListener(PropertyChangeListener l) {}
  82     }
  83 
  84     public static class S01 {
  85 
  86         private final static String TESTCASE = "arbitrary setter name";
  87 
  88         private int x;
  89 
  90         @BeanProperty(
  91             description  = DESCRIPTION,
  92             bound        = BOUND,
  93             expert       = EXPERT,
  94             hidden       = HIDDEN,
  95             preferred    = PREFERRED,
  96             required     = REQUIRED,
  97             visualUpdate = UPDATE,
  98             enumerationValues = {V_NAME})
  99         public void setXXXXX(int v) { x = v; }
 100 
 101         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 102         public void removePropertyChangeListener(PropertyChangeListener l) {}
 103     }
 104 
 105     // JDK-8132703
 106     public static class G02 {
 107 
 108         private final static String TESTCASE = "arbitrary getter name";
 109 
 110         private final int x = X;
 111 
 112         @BeanProperty(
 113             description  = DESCRIPTION,
 114             bound        = BOUND,
 115             expert       = EXPERT,
 116             hidden       = HIDDEN,
 117             preferred    = PREFERRED,
 118             required     = REQUIRED,
 119             visualUpdate = UPDATE,
 120             enumerationValues = {V_NAME})
 121         public int get() { return x; }
 122 
 123         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 124         public void removePropertyChangeListener(PropertyChangeListener l) {}
 125     }
 126 
 127     // JDK-8132703
 128     public static class S02 {
 129 
 130         private final static String TESTCASE = "arbitrary setter name";
 131 
 132         private int x;
 133 
 134         @BeanProperty(
 135             description  = DESCRIPTION,
 136             bound        = BOUND,
 137             expert       = EXPERT,
 138             hidden       = HIDDEN,
 139             preferred    = PREFERRED,
 140             required     = REQUIRED,
 141             visualUpdate = UPDATE,
 142             enumerationValues = {V_NAME})
 143         public void set(int v) { x = v; }
 144 
 145         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 146         public void removePropertyChangeListener(PropertyChangeListener l) {}
 147     }
 148 
 149     // JDK-8132703
 150     public static class G03 {
 151 
 152         private final static String TESTCASE = "arbitrary getter name";
 153 
 154         private final int x = X;
 155 
 156         @BeanProperty(
 157             description  = DESCRIPTION,
 158             bound        = BOUND,
 159             expert       = EXPERT,
 160             hidden       = HIDDEN,
 161             preferred    = PREFERRED,
 162             required     = REQUIRED,
 163             visualUpdate = UPDATE,
 164             enumerationValues = {V_NAME})
 165         public int GetX() { return x; }
 166 
 167         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 168         public void removePropertyChangeListener(PropertyChangeListener l) {}
 169     }
 170 
 171     // JDK-8132703
 172     public static class S03 {
 173 
 174         private final static String TESTCASE = "arbitrary setter name";
 175 
 176         private int x;
 177 
 178         @BeanProperty(
 179             description  = DESCRIPTION,
 180             bound        = BOUND,
 181             expert       = EXPERT,
 182             hidden       = HIDDEN,
 183             preferred    = PREFERRED,
 184             required     = REQUIRED,
 185             visualUpdate = UPDATE,
 186             enumerationValues = {V_NAME})
 187         public void SetX(int v) { x = v; }
 188 
 189         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 190         public void removePropertyChangeListener(PropertyChangeListener l) {}
 191     }
 192 
 193     // JDK-8132163
 194     public static class G04 {
 195 
 196         private final static String TESTCASE = "arbitrary getter return type";
 197 
 198         private final int x = X;
 199 
 200         @BeanProperty(
 201             description  = DESCRIPTION,
 202             bound        = BOUND,
 203             expert       = EXPERT,
 204             hidden       = HIDDEN,
 205             preferred    = PREFERRED,
 206             required     = REQUIRED,
 207             visualUpdate = UPDATE,
 208             enumerationValues = {V_NAME})
 209         public Object getX() { return x; }
 210 
 211         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 212         public void removePropertyChangeListener(PropertyChangeListener l) {}
 213     }
 214 
 215     // JDK-8132163
 216     public static class S04 {
 217 
 218         private final static String TESTCASE = "arbitrary setter argument type";
 219 
 220         private int x;
 221 
 222         @BeanProperty(
 223             description  = DESCRIPTION,
 224             bound        = BOUND,
 225             expert       = EXPERT,
 226             hidden       = HIDDEN,
 227             preferred    = PREFERRED,
 228             required     = REQUIRED,
 229             visualUpdate = UPDATE,
 230             enumerationValues = {V_NAME})
 231         public void setX(short v) { x = v; }
 232 
 233         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 234         public void removePropertyChangeListener(PropertyChangeListener l) {}
 235     }
 236 
 237     public static class G05 {
 238 
 239         private final static String TESTCASE =
 240             "annotated getter + arbitrary setter argument type";
 241 
 242         private int x;
 243 
 244         @BeanProperty(
 245             description  = DESCRIPTION,
 246             bound        = BOUND,
 247             expert       = EXPERT,
 248             hidden       = HIDDEN,
 249             preferred    = PREFERRED,
 250             required     = REQUIRED,
 251             visualUpdate = UPDATE,
 252             enumerationValues = {V_NAME})
 253         public int getX() { return x; }
 254         public void setX(short v) { x = v; }
 255 
 256 
 257         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 258         public void removePropertyChangeListener(PropertyChangeListener l) {}
 259     }
 260 
 261     // JDK-8132163
 262     public static class S05 {
 263 
 264         private final static String TESTCASE =
 265             "annotated setter + arbitrary getter return type";
 266 
 267         private int x;
 268 
 269         @BeanProperty(
 270             description  = DESCRIPTION,
 271             bound        = BOUND,
 272             expert       = EXPERT,
 273             hidden       = HIDDEN,
 274             preferred    = PREFERRED,
 275             required     = REQUIRED,
 276             visualUpdate = UPDATE,
 277             enumerationValues = {V_NAME})
 278         public void setX(int v) { x = v; }
 279         public Object getX() { return x; }
 280 
 281         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 282         public void removePropertyChangeListener(PropertyChangeListener l) {}
 283     }
 284 
 285     public static class G06 {
 286 
 287         private final static String TESTCASE = "indexed getter";
 288 
 289         private final int x[] = {X, X, X};
 290 
 291         @BeanProperty(
 292             description  = DESCRIPTION,
 293             bound        = BOUND,
 294             expert       = EXPERT,
 295             hidden       = HIDDEN,
 296             preferred    = PREFERRED,
 297             required     = REQUIRED,
 298             visualUpdate = UPDATE,
 299             enumerationValues = {V_NAME})
 300         public int getX(int i) { return x[i]; }
 301 
 302         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 303         public void removePropertyChangeListener(PropertyChangeListener l) {}
 304     }
 305 
 306     public static class S06 {
 307 
 308         private final static String TESTCASE = "indexed setter";
 309 
 310         private final int x[] = {X, X, X};
 311 
 312         @BeanProperty(
 313             description  = DESCRIPTION,
 314             bound        = BOUND,
 315             expert       = EXPERT,
 316             hidden       = HIDDEN,
 317             preferred    = PREFERRED,
 318             required     = REQUIRED,
 319             visualUpdate = UPDATE,
 320             enumerationValues = {V_NAME})
 321         public void setX(int i, int v) { x[i] = v; }
 322 
 323         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 324         public void removePropertyChangeListener(PropertyChangeListener l) {}
 325     }
 326 
 327     public static class G07 {
 328 
 329         private final static String TESTCASE =
 330             "indexed (annotated) + non-indexed getters";
 331 
 332         private final int x[] = {X, X, X};
 333 
 334         @BeanProperty(
 335             description  = DESCRIPTION,
 336             bound        = BOUND,
 337             expert       = EXPERT,
 338             hidden       = HIDDEN,
 339             preferred    = PREFERRED,
 340             required     = REQUIRED,
 341             visualUpdate = UPDATE,
 342             enumerationValues = {V_NAME})
 343         public int getX(int i) { return x[i]; }
 344 
 345         public int[] getX() { return x; }
 346 
 347         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 348         public void removePropertyChangeListener(PropertyChangeListener l) {}
 349     }
 350 
 351     public static class S07 {
 352 
 353         private final static String TESTCASE =
 354             "indexed (annotated) + non-indexed setters";
 355 
 356         private int x[] = new int[3];
 357 
 358         @BeanProperty(
 359             description  = DESCRIPTION,
 360             bound        = BOUND,
 361             expert       = EXPERT,
 362             hidden       = HIDDEN,
 363             preferred    = PREFERRED,
 364             required     = REQUIRED,
 365             visualUpdate = UPDATE,
 366             enumerationValues = {V_NAME})
 367         public void setX(int i, int v) { x[i] = v; }
 368 
 369         public void setX(int a[]) { x = Arrays.copyOf(a, a.length); }
 370 
 371         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 372         public void removePropertyChangeListener(PropertyChangeListener l) {}
 373     }
 374 
 375     // JDK-8132732
 376     public static class G08 {
 377 
 378         private final static String TESTCASE =
 379             "non-indexed (annotated) + indexed getters";
 380 
 381         private final int x[] = {X, X, X};
 382 
 383         @BeanProperty(
 384             description  = DESCRIPTION,
 385             bound        = BOUND,
 386             expert       = EXPERT,
 387             hidden       = HIDDEN,
 388             preferred    = PREFERRED,
 389             required     = REQUIRED,
 390             visualUpdate = UPDATE,
 391             enumerationValues = {V_NAME})
 392         public int[] getX() { return x; }
 393 
 394         public int getX(int i) { return x[i]; }
 395 
 396         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 397         public void removePropertyChangeListener(PropertyChangeListener l) {}
 398     }
 399 
 400     // JDK-8132732
 401     public static class S08 {
 402 
 403         private final static String TESTCASE =
 404             "non-indexed (annotated) + indexed setters";
 405 
 406         private int x[] = new int[3];
 407 
 408         @BeanProperty(
 409             description  = DESCRIPTION,
 410             bound        = BOUND,
 411             expert       = EXPERT,
 412             hidden       = HIDDEN,
 413             preferred    = PREFERRED,
 414             required     = REQUIRED,
 415             visualUpdate = UPDATE,
 416             enumerationValues = {V_NAME})
 417         public void setX(int a[]) { x = Arrays.copyOf(a, a.length); }
 418 
 419         public void setX(int i, int v) { x[i] = v; }
 420 
 421         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 422         public void removePropertyChangeListener(PropertyChangeListener l) {}
 423     }
 424 
 425     // JDK-8132732
 426     public static class G09 {
 427 
 428         private final static String TESTCASE = "two annotated getters";
 429 
 430         private final int x[] = {X, X, X};
 431 
 432         @BeanProperty(
 433             description  = DESCRIPTION,
 434             bound        = BOUND,
 435             expert       = EXPERT,
 436             hidden       = HIDDEN,
 437             preferred    = PREFERRED,
 438             required     = REQUIRED,
 439             visualUpdate = UPDATE,
 440             enumerationValues = {V_NAME})
 441         public int[] getX() { return x; }
 442 
 443         @BeanProperty(
 444             description  = DESCRIPTION_2,
 445             bound        = !BOUND,
 446             expert       = !EXPERT,
 447             hidden       = !HIDDEN,
 448             preferred    = !PREFERRED,
 449             required     = !REQUIRED,
 450             visualUpdate = !UPDATE)
 451         public int getX(int i) { return x[i]; }
 452 
 453         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 454         public void removePropertyChangeListener(PropertyChangeListener l) {}
 455     }
 456 
 457     // JDK-8132732
 458     public static class S09 {
 459 
 460         private final static String TESTCASE = "two annotated setters";
 461 
 462         private int x[] = new int[3];
 463 
 464         @BeanProperty(
 465             description  = DESCRIPTION,
 466             bound        = BOUND,
 467             expert       = EXPERT,
 468             hidden       = HIDDEN,
 469             preferred    = PREFERRED,
 470             required     = REQUIRED,
 471             visualUpdate = UPDATE,
 472             enumerationValues = {V_NAME})
 473         public void setX(int a[]) { x = Arrays.copyOf(a, a.length); }
 474 
 475         @BeanProperty(
 476             description  = DESCRIPTION_2,
 477             bound        = !BOUND,
 478             expert       = !EXPERT,
 479             hidden       = !HIDDEN,
 480             preferred    = !PREFERRED,
 481             required     = !REQUIRED,
 482             visualUpdate = !UPDATE)
 483         public void setX(int i, int v) { x[i] = v; }
 484 
 485 
 486         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 487         public void removePropertyChangeListener(PropertyChangeListener l) {}
 488     }
 489 
 490     public static class G10 {
 491 
 492         private final static String TESTCASE =
 493             "getter + similarly named field";
 494 
 495         public int prop, Prop, setProp, getProp;
 496 
 497         @BeanProperty(
 498             description  = DESCRIPTION,
 499             bound        = BOUND,
 500             expert       = EXPERT,
 501             hidden       = HIDDEN,
 502             preferred    = PREFERRED,
 503             required     = REQUIRED,
 504             visualUpdate = UPDATE,
 505             enumerationValues = {V_NAME})
 506         public int getProp() { return X; }
 507         public void setProp(int v) { prop = Prop = setProp = getProp = v; }
 508 
 509         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 510         public void removePropertyChangeListener(PropertyChangeListener l) {}
 511     }
 512 
 513     public static class S10 {
 514 
 515         private final static String TESTCASE =
 516             "setter + similarly named field";
 517 
 518         public int prop, Prop, setProp, getProp;
 519 
 520         private int x;
 521 
 522         @BeanProperty(
 523             description  = DESCRIPTION,
 524             bound        = BOUND,
 525             expert       = EXPERT,
 526             hidden       = HIDDEN,
 527             preferred    = PREFERRED,
 528             required     = REQUIRED,
 529             visualUpdate = UPDATE,
 530             enumerationValues = {V_NAME})
 531         public int getProp() { return x; }
 532         public void setProp(int v) { x = v; }
 533 
 534         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 535         public void removePropertyChangeListener(PropertyChangeListener l) {}
 536     }
 537 
 538     public static class G11 {
 539 
 540         private final static String TESTCASE =
 541             "getter + similarly named field of other type";
 542 
 543         public Object prop, Prop, setProp, getProp;
 544 
 545         @BeanProperty(
 546             description  = DESCRIPTION,
 547             bound        = BOUND,
 548             expert       = EXPERT,
 549             hidden       = HIDDEN,
 550             preferred    = PREFERRED,
 551             required     = REQUIRED,
 552             visualUpdate = UPDATE,
 553             enumerationValues = {V_NAME})
 554         public int getProp() { return X; }
 555         public void setProp(int v) { prop = Prop = setProp = getProp = v; }
 556 
 557         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 558         public void removePropertyChangeListener(PropertyChangeListener l) {}
 559     }
 560 
 561     public static class S11 {
 562 
 563         private final static String TESTCASE =
 564             "setter + similarly named field of other type";
 565 
 566         public String prop, Prop, setProp, getProp;
 567 
 568         private int x;
 569 
 570         @BeanProperty(
 571             description  = DESCRIPTION,
 572             bound        = BOUND,
 573             expert       = EXPERT,
 574             hidden       = HIDDEN,
 575             preferred    = PREFERRED,
 576             required     = REQUIRED,
 577             visualUpdate = UPDATE,
 578             enumerationValues = {V_NAME})
 579         public int getProp() { return x; }
 580         public void setProp(int v) { x = v; }
 581 
 582         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 583         public void removePropertyChangeListener(PropertyChangeListener l) {}
 584     }
 585 
 586     // JDK-8132163
 587     public static class G12 {
 588 
 589         private final static String TESTCASE =
 590             "getter having wrapper class return type";
 591 
 592         private final int x = X;
 593 
 594         @BeanProperty(
 595             description  = DESCRIPTION,
 596             bound        = BOUND,
 597             expert       = EXPERT,
 598             hidden       = HIDDEN,
 599             preferred    = PREFERRED,
 600             required     = REQUIRED,
 601             visualUpdate = UPDATE,
 602             enumerationValues = {V_NAME})
 603         public Integer getProp() { return x; }
 604 
 605         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 606         public void removePropertyChangeListener(PropertyChangeListener l) {}
 607     }
 608 
 609     // JDK-8132163
 610     public static class S12 {
 611 
 612         private final static String TESTCASE =
 613             "setter with wrapper class argument type";
 614 
 615         private int x;
 616 
 617         @BeanProperty(
 618             description  = DESCRIPTION,
 619             bound        = BOUND,
 620             expert       = EXPERT,
 621             hidden       = HIDDEN,
 622             preferred    = PREFERRED,
 623             required     = REQUIRED,
 624             visualUpdate = UPDATE,
 625             enumerationValues = {V_NAME})
 626         public void setX(Integer v) { x = v; }
 627 
 628         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 629         public void removePropertyChangeListener(PropertyChangeListener l) {}
 630     }
 631 
 632     public static class G13 {
 633 
 634         private final static String TESTCASE =
 635             "getter + overloading methods";
 636 
 637         private final int x = X;
 638 
 639         @BeanProperty(
 640             description  = DESCRIPTION,
 641             bound        = BOUND,
 642             expert       = EXPERT,
 643             hidden       = HIDDEN,
 644             preferred    = PREFERRED,
 645             required     = REQUIRED,
 646             visualUpdate = UPDATE,
 647             enumerationValues = {V_NAME})
 648         public int getX() { return x; }
 649         public int getX(boolean arg) { return (arg ? x : 0); }
 650         public int getX(int ... dummy) { return 0; }
 651 
 652         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 653         public void removePropertyChangeListener(PropertyChangeListener l) {}
 654     }
 655 
 656     // JDK-8154756
 657     public static class S13 {
 658 
 659         private final static String TESTCASE =
 660             "setter + overloading methods";
 661 
 662         private int x;
 663 
 664         @BeanProperty(
 665             description  = DESCRIPTION,
 666             bound        = BOUND,
 667             expert       = EXPERT,
 668             hidden       = HIDDEN,
 669             preferred    = PREFERRED,
 670             required     = REQUIRED,
 671             visualUpdate = UPDATE,
 672             enumerationValues = {V_NAME})
 673         public void setX(int v) { x = v; }
 674         public int  setX() { return (x = X); }
 675         public void setX(int ... dummy) {}
 676         private void setX(Object ... dummy) {}
 677 
 678 
 679         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 680         public void removePropertyChangeListener(PropertyChangeListener l) {}
 681     }
 682 
 683 
 684     // JDK-8132888
 685     public static class G14 {
 686 
 687         private final static String TESTCASE = "non-public getter";
 688 
 689         private final int x = X;
 690 
 691         @BeanProperty(
 692             description  = DESCRIPTION,
 693             bound        = BOUND,
 694             expert       = EXPERT,
 695             hidden       = HIDDEN,
 696             preferred    = PREFERRED,
 697             required     = REQUIRED,
 698             visualUpdate = UPDATE,
 699             enumerationValues = {V_NAME})
 700         int getX() { return x; } // getter is not public
 701 
 702         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 703         public void removePropertyChangeListener(PropertyChangeListener l) {}
 704     }
 705 
 706     // JDK-8132888
 707     public static class S14 {
 708 
 709         private final static String TESTCASE = "non-public setter";
 710 
 711         private int x;
 712 
 713         @BeanProperty(
 714             description  = DESCRIPTION,
 715             bound        = BOUND,
 716             expert       = EXPERT,
 717             hidden       = HIDDEN,
 718             preferred    = PREFERRED,
 719             required     = REQUIRED,
 720             visualUpdate = UPDATE,
 721             enumerationValues = {V_NAME})
 722         void setX(int v) { x = v; } // setter is not public
 723 
 724         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 725         public void removePropertyChangeListener(PropertyChangeListener l) {}
 726     }
 727 
 728     public static class getX {
 729 
 730         private final static String TESTCASE =
 731             "class name coincides with getter name";
 732 
 733         private int x;
 734 
 735         @BeanProperty(
 736             description  = DESCRIPTION,
 737             bound        = BOUND,
 738             expert       = EXPERT,
 739             hidden       = HIDDEN,
 740             preferred    = PREFERRED,
 741             required     = REQUIRED,
 742             visualUpdate = UPDATE,
 743             enumerationValues = {V_NAME})
 744         public int  getX() { return x; }
 745         public void setX(int v) { x = v; }
 746 
 747         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 748         public void removePropertyChangeListener(PropertyChangeListener l) {}
 749     }
 750 
 751     public static class setX {
 752 
 753         private final static String TESTCASE =
 754             "class name coincides with setter name";
 755 
 756         private int x;
 757 
 758         @BeanProperty(
 759             description  = DESCRIPTION,
 760             bound        = BOUND,
 761             expert       = EXPERT,
 762             hidden       = HIDDEN,
 763             preferred    = PREFERRED,
 764             required     = REQUIRED,
 765             visualUpdate = UPDATE,
 766             enumerationValues = {V_NAME})
 767         public void setX(int v) { x = v; }
 768         public int  getX() { return x; }
 769 
 770         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 771         public void removePropertyChangeListener(PropertyChangeListener l) {}
 772     }
 773 
 774     // JDK-8132973
 775     public static class GS {
 776 
 777         private final static String TESTCASE =
 778             "both getter and setter are annotated";
 779 
 780         private int x;
 781 
 782         @BeanProperty(
 783             description  = DESCRIPTION,
 784             bound        = BOUND,
 785             expert       = EXPERT,
 786             hidden       = HIDDEN,
 787             preferred    = PREFERRED,
 788             required     = REQUIRED,
 789             visualUpdate = UPDATE,
 790             enumerationValues = {V_NAME})
 791         public int getX() { return x; }
 792 
 793         @BeanProperty(
 794             description  = DESCRIPTION_2,
 795             bound        = !BOUND,
 796             expert       = !EXPERT,
 797             hidden       = !HIDDEN,
 798             preferred    = !PREFERRED,
 799             required     = !REQUIRED,
 800             visualUpdate = !UPDATE)
 801         public void setX(int v) { x = v; }
 802 
 803 
 804         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 805         public void removePropertyChangeListener(PropertyChangeListener l) {}
 806     }
 807 
 808     public static class Self {
 809 
 810         private final static String TESTCASE = "trivial singleton";
 811 
 812         private static Self instance = null;
 813         private Self() {}
 814 
 815         @BeanProperty(
 816             description  = DESCRIPTION,
 817             bound        = BOUND,
 818             expert       = EXPERT,
 819             hidden       = HIDDEN,
 820             preferred    = PREFERRED,
 821             required     = REQUIRED,
 822             visualUpdate = UPDATE)
 823         public Self getSelf() {
 824             if (instance == null) { instance = new Self(); }
 825             return instance;
 826         }
 827 
 828         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 829         public void removePropertyChangeListener(PropertyChangeListener l) {}
 830     }
 831 
 832     public static class SelfArr {
 833 
 834         private final static String TESTCASE = "trivial singleton + array";
 835 
 836         private static SelfArr arr[] = null;
 837         private SelfArr() {}
 838 
 839         @BeanProperty(
 840             description  = DESCRIPTION,
 841             bound        = BOUND,
 842             expert       = EXPERT,
 843             hidden       = HIDDEN,
 844             preferred    = PREFERRED,
 845             required     = REQUIRED,
 846             visualUpdate = UPDATE)
 847         public SelfArr[] getSelfArr() {
 848             if (arr == null) { arr = new SelfArr[]{new SelfArr(), new SelfArr()}; }
 849             return arr;
 850         }
 851 
 852         public void addPropertyChangeListener(PropertyChangeListener l)    {}
 853         public void removePropertyChangeListener(PropertyChangeListener l) {}
 854     }
 855 
 856 
 857     // ---------- checks ----------
 858 
 859     private static boolean check(String what, boolean v, boolean ref) {
 860 
 861         boolean ok = (v == ref);
 862         if (!ok) { System.out.println(
 863             "invalid " + what + ": " + v + ", expected: " + ref); }
 864         return ok;
 865     }
 866 
 867     private static boolean checkInfo(BeanInfo i, boolean checkVals) {
 868 
 869         System.out.println("checking info...");
 870 
 871         PropertyDescriptor descriptors[] = i.getPropertyDescriptors();
 872         int nd = descriptors.length;
 873         if (nd != 1) {
 874             System.out.println("invalid number of descriptors: " + nd);
 875             return false;
 876         }
 877 
 878         PropertyDescriptor d = descriptors[0];
 879 
 880         String descr = d.getShortDescription();
 881         boolean ok = descr.equals(DESCRIPTION);
 882         if (!ok) { System.out.println("invalid description: " + descr +
 883                 ", expected: " + DESCRIPTION); }
 884 
 885         ok &= check("isBound",  d.isBound(),  BOUND);
 886         ok &= check("isExpert", d.isExpert(), EXPERT);
 887         ok &= check("isHidden", d.isHidden(), HIDDEN);
 888         ok &= check("isPreferred", d.isPreferred(), PREFERRED);
 889         ok &= check("required", (boolean) d.getValue("required"), REQUIRED);
 890         ok &= check("visualUpdate",
 891             (boolean) d.getValue("visualUpdate"), UPDATE);
 892 
 893         if (!checkVals) { return ok; }
 894 
 895         Object vals[] = (Object[]) d.getValue("enumerationValues");
 896         if (vals == null) {
 897             System.out.println("null enumerationValues");
 898             return false;
 899         }
 900 
 901         boolean okVals = (
 902             (vals.length == 3) &&
 903              vals[0].toString().equals(V_SHORT) &&
 904              vals[1].toString().equals(V)       &&
 905              vals[2].toString().equals(V_NAME));
 906 
 907         if (!okVals) { System.out.println("invalid enumerationValues"); }
 908 
 909         return (ok && okVals);
 910     }
 911 
 912     private static boolean checkAlternativeInfo(BeanInfo i) {
 913 
 914         System.out.println("checking alternative info...");
 915 
 916         PropertyDescriptor descriptors[] = i.getPropertyDescriptors();
 917         int nd = descriptors.length;
 918         if (nd != 1) {
 919             System.out.println("invalid number of descriptors: " + nd);
 920             return false;
 921         }
 922 
 923         PropertyDescriptor d = descriptors[0];
 924 
 925         String descr = d.getShortDescription();
 926         boolean ok = descr.equals(DESCRIPTION_2);
 927         if (!ok) { System.out.println("invalid alternative description: " +
 928             descr + ", expected: " + DESCRIPTION_2); }
 929 
 930         ok &= check("isBound",  d.isBound(),  !BOUND);
 931         ok &= check("isExpert", d.isExpert(), !EXPERT);
 932         ok &= check("isHidden", d.isHidden(), !HIDDEN);
 933         ok &= check("isPreferred", d.isPreferred(), !PREFERRED);
 934         ok &= check("required", (boolean) d.getValue("required"), !REQUIRED);
 935         ok &= check("visualUpdate",
 936             (boolean) d.getValue("visualUpdate"), !UPDATE);
 937 
 938         Object vals[] = (Object[]) d.getValue("enumerationValues");
 939         if (vals != null || vals.length > 0) {
 940             System.out.println("non-null enumerationValues");
 941             return false;
 942         }
 943 
 944         return ok;
 945     }
 946 
 947 
 948     private static boolean checkAlternative(Class<?> c) {
 949         return (
 950             c.equals(G09.class) ||
 951             c.equals(S09.class) ||
 952             c.equals(GS.class));
 953     }
 954 
 955     private static boolean ignoreVals(Class<?> c) {
 956         return (c.equals(Self.class) || c.equals(SelfArr.class));
 957     }
 958 
 959 
 960     // ---------- run test ----------
 961 
 962     public static void main(String[] args) throws Exception {
 963 
 964         Class<?> cases[] = {
 965 
 966             G01.class, S01.class,
 967             // G02.class, S02.class, // TODO: please update after 8132703 fix
 968             // G03.class, S03.class, // TODO: please update after 8132703 fix
 969             // G04.class, S04.class, // TODO: please update after 8132163 fix
 970             G05.class, // S05.class, // TODO: please update after 8132163 fix
 971             G06.class, S06.class,
 972             G07.class, S07.class,
 973             // G08.class, S08.class, // TODO: please update after 8132732 fix
 974             // G09.class, S09.class, // TODO: please update after 8132732 fix
 975             G10.class, S10.class,
 976             G11.class, S11.class,
 977             // G12.class, S12.class, // TODO: please update after 8132163 fix
 978             G13.class, // S13.class, // TODO: please update after 8154756 fix
 979             // G14.class, S14.class, // TODO: please update after 8132888 fix or
 980                                      // remove these cases if it is not an issue
 981             // GS.class, // TODO: please update after 8132973 fix
 982             getX.class, setX.class,
 983             Self.class, SelfArr.class
 984         };
 985 
 986         boolean passed = true;
 987 
 988         for (Class<?> c: cases) {
 989 
 990             java.lang.reflect.Field f = c.getDeclaredField("TESTCASE");
 991             f.setAccessible(true);
 992             String descr = f.get(c).toString();
 993 
 994             System.out.println("\n" + c.getSimpleName() + " (" + descr + "):");
 995             BeanInfo i;
 996             try { i = Introspector.getBeanInfo(c, Object.class); }
 997             catch (IntrospectionException e) { throw new RuntimeException(e); }
 998             boolean ok = checkInfo(i, !ignoreVals(c));
 999             if (checkAlternative(c)) {
1000                 ok |= checkAlternativeInfo(i);
1001             }
1002             System.out.println(ok ? "OK" : "NOK");
1003             passed = passed && ok;
1004         }
1005 
1006         if (!passed) { throw new RuntimeException("test failed"); }
1007         System.out.println("\ntest passed");
1008     }
1009 }