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
24import java.beans.BeanInfo;
25import java.beans.BeanProperty;
26import java.beans.IntrospectionException;
27import java.beans.Introspector;
28import java.beans.PropertyChangeListener;
29import java.beans.PropertyDescriptor;
30
31import java.util.Arrays;
32
33
34/**
35 * @test
36 * @bug 8132565 8155013
37 * @summary Some inheritance check for BeanProperty annotation
38 * @author a.stepanov
39 * @run main InheritanceBeanPropertyTest
40 */
41
42
43public class InheritanceBeanPropertyTest {
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
53    private final static double X = java.lang.Math.PI;
54
55    private final static String
56        V_NAME  = "java.lang.Math.PI",
57        V_SHORT = "PI",
58        V = Double.toString(X);
59
60    private final static String DESCRIPTION_2 = "XYZ";
61
62
63    // ---------- test cases ----------
64
65    public static class BaseGet {
66
67        private final static String TESTCASE = "base getter";
68
69        public double getX() { return X; }
70    }
71
72    public static class OverloadGet extends BaseGet {
73
74        private final static String TESTCASE = "overload getter";
75
76        private final double x[] = {X, X, X};
77
78        @BeanProperty(
79            description  = DESCRIPTION,
80            bound        = BOUND,
81            expert       = EXPERT,
82            hidden       = HIDDEN,
83            preferred    = PREFERRED,
84            required     = REQUIRED,
85            visualUpdate = UPDATE,
86            enumerationValues = {V_NAME})
87        public double getX(int i) { return x[i]; } // indexed
88
89        public void addPropertyChangeListener(PropertyChangeListener l)    {}
90        public void removePropertyChangeListener(PropertyChangeListener l) {}
91    }
92
93    // ----------
94
95    public static class BaseSet {
96
97        private final static String TESTCASE = "base setter";
98
99        double u;
100        public void setX(double v) { u = v; }
101    }
102
103    public static class OverloadSet extends BaseSet {
104
105        private final static String TESTCASE = "overload setter";
106
107        private final double x[] = {X, X, X};
108
109        @BeanProperty(
110            description  = DESCRIPTION,
111            bound        = BOUND,
112            expert       = EXPERT,
113            hidden       = HIDDEN,
114            preferred    = PREFERRED,
115            required     = REQUIRED,
116            visualUpdate = UPDATE,
117            enumerationValues = {V_NAME})
118        public void setX(int i, double v) { x[i] = v; } // indexed
119
120        public void addPropertyChangeListener(PropertyChangeListener l)    {}
121        public void removePropertyChangeListener(PropertyChangeListener l) {}
122    }
123
124    // ----------
125
126    public static class BaseIGet {
127
128        protected final double x[] = {X, X, X};
129        public double[] getX() { return x; }
130    }
131
132    public static class OverloadIGet extends BaseIGet {
133
134        private final static String TESTCASE = "overload indexed getter";
135
136        @BeanProperty(
137            description  = DESCRIPTION,
138            bound        = BOUND,
139            expert       = EXPERT,
140            hidden       = HIDDEN,
141            preferred    = PREFERRED,
142            required     = REQUIRED,
143            visualUpdate = UPDATE,
144            enumerationValues = {V_NAME})
145        public double getX(int i) { return x[i]; }
146
147        public void addPropertyChangeListener(PropertyChangeListener l)    {}
148        public void removePropertyChangeListener(PropertyChangeListener l) {}
149    }
150
151    // ----------
152
153    public static class BaseISet {
154
155        protected double x[] = {X, X, X};
156        public void setX(double a[]) { x = Arrays.copyOf(a, a.length); }
157    }
158
159    public static class OverloadISet extends BaseISet {
160
161        private final static String TESTCASE = "overload indexed setter";
162
163        @BeanProperty(
164            description  = DESCRIPTION,
165            bound        = BOUND,
166            expert       = EXPERT,
167            hidden       = HIDDEN,
168            preferred    = PREFERRED,
169            required     = REQUIRED,
170            visualUpdate = UPDATE,
171            enumerationValues = {V_NAME})
172        public void setX(int i, double v) { x[i] = v; }
173
174        public void addPropertyChangeListener(PropertyChangeListener l)    {}
175        public void removePropertyChangeListener(PropertyChangeListener l) {}
176    }
177
178    // ----------
179
180    public static class BoolGet {
181
182        @BeanProperty(
183            description  = DESCRIPTION_2,
184            bound        = !BOUND,
185            expert       = !EXPERT,
186            hidden       = !HIDDEN,
187            preferred    = !PREFERRED,
188            required     = !REQUIRED,
189            visualUpdate = !UPDATE)
190        public boolean getX() { return false; }
191    }
192
193    public static class BoolGetIs extends BoolGet {
194
195        private final static String TESTCASE = "base boolean getter + is";
196
197        @BeanProperty(
198            description  = DESCRIPTION,
199            bound        = BOUND,
200            expert       = EXPERT,
201            hidden       = HIDDEN,
202            preferred    = PREFERRED,
203            required     = REQUIRED,
204            visualUpdate = UPDATE)
205        public boolean isX() { return false; }
206
207        public void addPropertyChangeListener(PropertyChangeListener l)    {}
208        public void removePropertyChangeListener(PropertyChangeListener l) {}
209    }
210    // ----------
211
212    public static class BoolIs {
213
214        @BeanProperty(
215            description  = DESCRIPTION_2,
216            bound        = !BOUND,
217            expert       = !EXPERT,
218            hidden       = !HIDDEN,
219            preferred    = !PREFERRED,
220            required     = !REQUIRED,
221            visualUpdate = !UPDATE)
222        public boolean isX() { return false; }
223    }
224
225    public static class BoolIsGet extends BoolIs {
226
227        private final static String TESTCASE = "base is + boolean getter";
228
229        @BeanProperty(
230            description  = DESCRIPTION,
231            bound        = BOUND,
232            expert       = EXPERT,
233            hidden       = HIDDEN,
234            preferred    = PREFERRED,
235            required     = REQUIRED,
236            visualUpdate = UPDATE)
237        public boolean getX() { return false; }
238
239        public void addPropertyChangeListener(PropertyChangeListener l)    {}
240        public void removePropertyChangeListener(PropertyChangeListener l) {}
241    }
242
243    // ----------
244
245    public static class AnnotatedGet {
246
247        private final static String TESTCASE = "annotated super getter";
248
249        @BeanProperty(
250            description  = DESCRIPTION,
251            bound        = BOUND,
252            expert       = EXPERT,
253            hidden       = HIDDEN,
254            preferred    = PREFERRED,
255            required     = REQUIRED,
256            visualUpdate = UPDATE,
257            enumerationValues = {V_NAME})
258        public double getX() { return 0.; }
259
260        public void addPropertyChangeListener(PropertyChangeListener l)    {}
261        public void removePropertyChangeListener(PropertyChangeListener l) {}
262    }
263
264    public static class OverrideAnnotatedGet extends AnnotatedGet {
265
266        private final static String TESTCASE = "override annotated getter";
267
268        @Override
269        public double getX() { return X; }
270    }
271
272    // ----------
273
274    public static class AnnotatedIs {
275
276        private final static String TESTCASE = "annotated super is";
277
278        @BeanProperty(
279            description  = DESCRIPTION,
280            bound        = BOUND,
281            expert       = EXPERT,
282            hidden       = HIDDEN,
283            preferred    = PREFERRED,
284            required     = REQUIRED,
285            visualUpdate = UPDATE,
286            enumerationValues = {V_NAME})
287        public boolean isX() { return false; }
288
289        public void addPropertyChangeListener(PropertyChangeListener l)    {}
290        public void removePropertyChangeListener(PropertyChangeListener l) {}
291    }
292
293    public static class OverrideAnnotatedIs extends AnnotatedIs {
294
295        private final static String TESTCASE = "override annotated is";
296
297        @Override
298        public boolean isX() { return false; }
299    }
300
301    // ----------
302
303    public static class AnnotatedSet {
304
305        private final static String TESTCASE = "annotated super set";
306
307        protected double x;
308
309        @BeanProperty(
310            description  = DESCRIPTION,
311            bound        = BOUND,
312            expert       = EXPERT,
313            hidden       = HIDDEN,
314            preferred    = PREFERRED,
315            required     = REQUIRED,
316            visualUpdate = UPDATE,
317            enumerationValues = {V_NAME})
318        public void setX(double v) { x = -v; }
319
320        public void addPropertyChangeListener(PropertyChangeListener l)    {}
321        public void removePropertyChangeListener(PropertyChangeListener l) {}
322    }
323
324    public static class OverrideAnnotatedSet extends AnnotatedSet {
325
326        private final static String TESTCASE = "override annotated setter";
327
328        @Override
329        public void setX(double v) { x = v; }
330    }
331
332    // ----------
333
334    public static class AnnotatedGet2 {
335
336        protected double x;
337
338        @BeanProperty(
339            description  = DESCRIPTION_2,
340            bound        = !BOUND,
341            expert       = !EXPERT,
342            hidden       = !HIDDEN,
343            preferred    = !PREFERRED,
344            required     = !REQUIRED,
345            visualUpdate = !UPDATE)
346        public double getX() { return 0.; }
347    }
348
349    public static class OverrideAnnotatedGet2 extends AnnotatedGet2 {
350
351        private final static String TESTCASE = "override annotated getter - 2";
352
353        @BeanProperty(
354            description  = DESCRIPTION,
355            bound        = BOUND,
356            expert       = EXPERT,
357            hidden       = HIDDEN,
358            preferred    = PREFERRED,
359            required     = REQUIRED,
360            visualUpdate = UPDATE,
361            enumerationValues = {V_NAME})
362        @Override
363        public double getX() { return X; }
364
365        public void addPropertyChangeListener(PropertyChangeListener l)    {}
366        public void removePropertyChangeListener(PropertyChangeListener l) {}
367    }
368
369    public static class AnnotatedGet2Ext extends AnnotatedGet2 {
370
371        private final static String TESTCASE = "extend annotated getter - 2";
372
373        @BeanProperty(
374            description  = DESCRIPTION,
375            bound        = BOUND,
376            expert       = EXPERT,
377            hidden       = HIDDEN,
378            preferred    = PREFERRED,
379            required     = REQUIRED,
380            visualUpdate = UPDATE,
381            enumerationValues = {V_NAME})
382        public void setX(double v) { x = v; }
383
384        public void addPropertyChangeListener(PropertyChangeListener l)    {}
385        public void removePropertyChangeListener(PropertyChangeListener l) {}
386    }
387
388    // ----------
389
390    public static class AnnotatedIs2 {
391
392        protected boolean b = false;
393
394        @BeanProperty(
395            description  = DESCRIPTION_2,
396            bound        = !BOUND,
397            expert       = !EXPERT,
398            hidden       = !HIDDEN,
399            preferred    = !PREFERRED,
400            required     = !REQUIRED,
401            visualUpdate = !UPDATE)
402        public boolean isX() { return false; }
403    }
404
405    public static class OverrideAnnotatedIs2 extends AnnotatedIs2 {
406
407        private final static String TESTCASE = "override annotated is - 2";
408
409        @BeanProperty(
410            description  = DESCRIPTION,
411            bound        = BOUND,
412            expert       = EXPERT,
413            hidden       = HIDDEN,
414            preferred    = PREFERRED,
415            required     = REQUIRED,
416            visualUpdate = UPDATE)
417        @Override
418        public boolean isX() { return b; }
419
420        public void addPropertyChangeListener(PropertyChangeListener l)    {}
421        public void removePropertyChangeListener(PropertyChangeListener l) {}
422    }
423
424    public static class AnnotatedIs2Ext extends AnnotatedIs2 {
425
426        private final static String TESTCASE = "extend annotated is - 2";
427
428        @BeanProperty(
429            description  = DESCRIPTION,
430            bound        = BOUND,
431            expert       = EXPERT,
432            hidden       = HIDDEN,
433            preferred    = PREFERRED,
434            required     = REQUIRED,
435            visualUpdate = UPDATE)
436        public void setX(boolean v) { b = v; }
437
438        public void addPropertyChangeListener(PropertyChangeListener l)    {}
439        public void removePropertyChangeListener(PropertyChangeListener l) {}
440    }
441
442    // ----------
443
444    public static class AnnotatedSet2 {
445
446        protected double x;
447
448        @BeanProperty(
449            description  = DESCRIPTION_2,
450            bound        = !BOUND,
451            expert       = !EXPERT,
452            hidden       = !HIDDEN,
453            preferred    = !PREFERRED,
454            required     = !REQUIRED,
455            visualUpdate = !UPDATE)
456        public void setX(double v) { x = -v; }
457    }
458
459    public static class OverrideAnnotatedSet2 extends AnnotatedSet2 {
460
461        private final static String TESTCASE = "override annotated setter - 2";
462
463        @BeanProperty(
464            description  = DESCRIPTION,
465            bound        = BOUND,
466            expert       = EXPERT,
467            hidden       = HIDDEN,
468            preferred    = PREFERRED,
469            required     = REQUIRED,
470            visualUpdate = UPDATE,
471            enumerationValues = {V_NAME})
472        @Override
473        public void setX(double v) { x = v; }
474
475        public void addPropertyChangeListener(PropertyChangeListener l)    {}
476        public void removePropertyChangeListener(PropertyChangeListener l) {}
477    }
478
479    public static class AnnotatedSet2Ext extends AnnotatedSet2 {
480
481        private final static String TESTCASE = "extend annotated setter - 2";
482
483        @BeanProperty(
484            description  = DESCRIPTION,
485            bound        = BOUND,
486            expert       = EXPERT,
487            hidden       = HIDDEN,
488            preferred    = PREFERRED,
489            required     = REQUIRED,
490            visualUpdate = UPDATE,
491            enumerationValues = {V_NAME})
492        public double getX() { return x; }
493
494        public void addPropertyChangeListener(PropertyChangeListener l)    {}
495        public void removePropertyChangeListener(PropertyChangeListener l) {}
496    }
497
498    // ----------
499
500    public abstract static class AbstractGet {
501
502        @BeanProperty(
503            description  = DESCRIPTION_2,
504            bound        = !BOUND,
505            expert       = !EXPERT,
506            hidden       = !HIDDEN,
507            preferred    = !PREFERRED,
508            required     = !REQUIRED,
509            visualUpdate = !UPDATE)
510        public abstract double getX();
511    }
512
513    public static class OverrideAbstractGet extends AbstractGet {
514
515        private final static String TESTCASE =
516            "override abstract annotated getter";
517
518        @Override
519        public double getX() { return X; }
520    }
521
522    public static class OverrideAbstractGet2 extends AbstractGet {
523
524        private final static String TESTCASE =
525            "override abstract annotated getter - 2";
526
527        @BeanProperty(
528            description  = DESCRIPTION,
529            bound        = BOUND,
530            expert       = EXPERT,
531            hidden       = HIDDEN,
532            preferred    = PREFERRED,
533            required     = REQUIRED,
534            visualUpdate = UPDATE,
535            enumerationValues = {V_NAME})
536        @Override
537        public double getX() { return X; }
538
539        public void addPropertyChangeListener(PropertyChangeListener l)    {}
540        public void removePropertyChangeListener(PropertyChangeListener l) {}
541    }
542
543    public abstract static class AbstractGetExt extends AbstractGet {
544
545        private final static String TESTCASE =
546            "extend abstract annotated getter";
547
548        @BeanProperty(
549            description  = DESCRIPTION,
550            bound        = BOUND,
551            expert       = EXPERT,
552            hidden       = HIDDEN,
553            preferred    = PREFERRED,
554            required     = REQUIRED,
555            visualUpdate = UPDATE,
556            enumerationValues = {V_NAME})
557        public abstract void setX(double v);
558
559        public void addPropertyChangeListener(PropertyChangeListener l)    {}
560        public void removePropertyChangeListener(PropertyChangeListener l) {}
561    }
562
563    // ----------
564
565    public abstract static class AbstractIs {
566
567        @BeanProperty(
568            description  = DESCRIPTION_2,
569            bound        = !BOUND,
570            expert       = !EXPERT,
571            hidden       = !HIDDEN,
572            preferred    = !PREFERRED,
573            required     = !REQUIRED,
574            visualUpdate = !UPDATE)
575        public abstract boolean isX();
576    }
577
578    public static class OverrideAbstractIs extends AbstractIs {
579
580        private final static String TESTCASE =
581            "override abstract annotated is";
582
583        @Override
584        public boolean isX() { return true; }
585    }
586
587    public static class OverrideAbstractIs2 extends AbstractIs {
588
589        private final static String TESTCASE =
590            "override abstract annotated is - 2";
591
592        @BeanProperty(
593            description  = DESCRIPTION,
594            bound        = BOUND,
595            expert       = EXPERT,
596            hidden       = HIDDEN,
597            preferred    = PREFERRED,
598            required     = REQUIRED,
599            visualUpdate = UPDATE)
600        @Override
601        public boolean isX() { return true; }
602
603        public void addPropertyChangeListener(PropertyChangeListener l)    {}
604        public void removePropertyChangeListener(PropertyChangeListener l) {}
605    }
606
607
608    public abstract static class AbstractIsExt extends AbstractIs {
609
610        private final static String TESTCASE =
611            "extend abstract annotated is";
612
613        @BeanProperty(
614            description  = DESCRIPTION,
615            bound        = BOUND,
616            expert       = EXPERT,
617            hidden       = HIDDEN,
618            preferred    = PREFERRED,
619            required     = REQUIRED,
620            visualUpdate = UPDATE)
621        public abstract boolean getX();
622
623        public void addPropertyChangeListener(PropertyChangeListener l)    {}
624        public void removePropertyChangeListener(PropertyChangeListener l) {}
625    }
626
627    // ----------
628
629    public abstract static class AbstractSet {
630
631        @BeanProperty(
632            description  = DESCRIPTION_2,
633            bound        = !BOUND,
634            expert       = !EXPERT,
635            hidden       = !HIDDEN,
636            preferred    = !PREFERRED,
637            required     = !REQUIRED,
638            visualUpdate = !UPDATE)
639        public abstract void setX(double v);
640    }
641
642    public static class OverrideAbstractSet extends AbstractSet {
643
644        private final static String TESTCASE =
645            "override abstract annotated setter";
646
647        private double x;
648
649        @Override
650        public void setX(double v) { x = v; }
651    }
652
653    public static class OverrideAbstractSet2 extends AbstractSet {
654
655        private final static String TESTCASE =
656            "override abstract annotated setter - 2";
657
658        private double x;
659
660        @BeanProperty(
661            description  = DESCRIPTION,
662            bound        = BOUND,
663            expert       = EXPERT,
664            hidden       = HIDDEN,
665            preferred    = PREFERRED,
666            required     = REQUIRED,
667            visualUpdate = UPDATE,
668            enumerationValues = {V_NAME})
669        @Override
670        public void setX(double v) { x = v; }
671
672        public void addPropertyChangeListener(PropertyChangeListener l)    {}
673        public void removePropertyChangeListener(PropertyChangeListener l) {}
674    }
675
676    public abstract static class AbstractSetExt extends AbstractSet {
677
678        private final static String TESTCASE =
679            "extend abstract annotated setter";
680
681        @BeanProperty(
682            description  = DESCRIPTION,
683            bound        = BOUND,
684            expert       = EXPERT,
685            hidden       = HIDDEN,
686            preferred    = PREFERRED,
687            required     = REQUIRED,
688            visualUpdate = UPDATE,
689            enumerationValues = {V_NAME})
690        public abstract void setX(double v[]);
691
692        public void addPropertyChangeListener(PropertyChangeListener l)    {}
693        public void removePropertyChangeListener(PropertyChangeListener l) {}
694    }
695
696    // ----------
697
698    public static abstract class AbstractGet2 {
699
700        private final static String TESTCASE = "abstract super getter";
701
702        @BeanProperty(
703            description  = DESCRIPTION,
704            bound        = BOUND,
705            expert       = EXPERT,
706            hidden       = HIDDEN,
707            preferred    = PREFERRED,
708            required     = REQUIRED,
709            visualUpdate = UPDATE,
710            enumerationValues = {V_NAME})
711        public abstract double getX();
712
713        public void addPropertyChangeListener(PropertyChangeListener l)    {}
714        public void removePropertyChangeListener(PropertyChangeListener l) {}
715    }
716
717    public static abstract class AbstractGet2Ext extends AbstractGet2 {
718
719        @BeanProperty(
720            description  = DESCRIPTION_2,
721            bound        = !BOUND,
722            expert       = !EXPERT,
723            hidden       = !HIDDEN,
724            preferred    = !PREFERRED,
725            required     = !REQUIRED,
726            visualUpdate = !UPDATE)
727        public abstract void setX(double a[]);
728    }
729
730    // ----------
731
732    public static interface IGet {
733
734        @BeanProperty(
735            description  = DESCRIPTION_2,
736            bound        = !BOUND,
737            expert       = !EXPERT,
738            hidden       = !HIDDEN,
739            preferred    = !PREFERRED,
740            required     = !REQUIRED,
741            visualUpdate = !UPDATE)
742        double getX();
743    }
744
745    public static class IGetImpl implements IGet {
746
747        private final static String TESTCASE = "implement getter interface";
748
749        @Override
750        public double getX() { return X; }
751    }
752
753    public static class IGetImpl2 implements IGet {
754
755        private final static String TESTCASE = "implement getter interface - 2";
756
757        @BeanProperty(
758            description  = DESCRIPTION,
759            bound        = BOUND,
760            expert       = EXPERT,
761            hidden       = HIDDEN,
762            preferred    = PREFERRED,
763            required     = REQUIRED,
764            visualUpdate = UPDATE,
765            enumerationValues = {V_NAME})
766        @Override
767        public double getX() { return X; }
768
769        public void addPropertyChangeListener(PropertyChangeListener l)    {}
770        public void removePropertyChangeListener(PropertyChangeListener l) {}
771    }
772
773    public abstract static class IGetImpl3 implements IGet {
774
775        private final static String TESTCASE = "implement getter interface - 3";
776
777        @BeanProperty(
778            description  = DESCRIPTION,
779            bound        = BOUND,
780            expert       = EXPERT,
781            hidden       = HIDDEN,
782            preferred    = PREFERRED,
783            required     = REQUIRED,
784            visualUpdate = UPDATE,
785            enumerationValues = {V_NAME})
786        public abstract void setX(double v);
787
788        public void addPropertyChangeListener(PropertyChangeListener l)    {}
789        public void removePropertyChangeListener(PropertyChangeListener l) {}
790    }
791
792    // ----------
793
794    public static interface IIs {
795
796        @BeanProperty(
797            description  = DESCRIPTION_2,
798            bound        = !BOUND,
799            expert       = !EXPERT,
800            hidden       = !HIDDEN,
801            preferred    = !PREFERRED,
802            required     = !REQUIRED,
803            visualUpdate = !UPDATE)
804        public boolean isX();
805    }
806
807    public static class IIsImpl implements IIs {
808
809        private final static String TESTCASE = "implement is interface";
810
811        @Override
812        public boolean isX() { return true; }
813    }
814
815    public static class IIsImpl2 implements IIs {
816
817        private final static String TESTCASE = "implement is interface - 2";
818
819        @BeanProperty(
820            description  = DESCRIPTION,
821            bound        = BOUND,
822            expert       = EXPERT,
823            hidden       = HIDDEN,
824            preferred    = PREFERRED,
825            required     = REQUIRED,
826            visualUpdate = UPDATE)
827        @Override
828        public boolean isX() { return true; }
829
830        public void addPropertyChangeListener(PropertyChangeListener l)    {}
831        public void removePropertyChangeListener(PropertyChangeListener l) {}
832    }
833
834    public abstract static class IIsImpl3 implements IIs {
835
836        private final static String TESTCASE = "implement is interface - 3";
837
838        @BeanProperty(
839            description  = DESCRIPTION,
840            bound        = BOUND,
841            expert       = EXPERT,
842            hidden       = HIDDEN,
843            preferred    = PREFERRED,
844            required     = REQUIRED,
845            visualUpdate = UPDATE)
846        public abstract void setX(boolean v);
847
848        public void addPropertyChangeListener(PropertyChangeListener l)    {}
849        public void removePropertyChangeListener(PropertyChangeListener l) {}
850    }
851
852    // ----------
853
854    public static interface ISet {
855
856        @BeanProperty(
857            description  = DESCRIPTION_2,
858            bound        = !BOUND,
859            expert       = !EXPERT,
860            hidden       = !HIDDEN,
861            preferred    = !PREFERRED,
862            required     = !REQUIRED,
863            visualUpdate = !UPDATE)
864        public void setX(double v);
865    }
866
867    public static class ISetImpl implements ISet {
868
869        private final static String TESTCASE = "implement getter interface";
870
871        private double x;
872
873        @Override
874        public void setX(double v) { x = v; }
875    }
876
877    public static class ISetImpl2 implements ISet {
878
879        private final static String TESTCASE = "implement getter interface - 2";
880
881        private double x;
882
883        @BeanProperty(
884            description  = DESCRIPTION,
885            bound        = BOUND,
886            expert       = EXPERT,
887            hidden       = HIDDEN,
888            preferred    = PREFERRED,
889            required     = REQUIRED,
890            visualUpdate = UPDATE,
891            enumerationValues = {V_NAME})
892        @Override
893        public void setX(double v) { x = v; }
894
895        public void addPropertyChangeListener(PropertyChangeListener l)    {}
896        public void removePropertyChangeListener(PropertyChangeListener l) {}
897    }
898
899    public abstract static class ISetImpl3 implements ISet {
900
901        private final static String TESTCASE = "implement getter interface - 3";
902
903        @BeanProperty(
904            description  = DESCRIPTION,
905            bound        = BOUND,
906            expert       = EXPERT,
907            hidden       = HIDDEN,
908            preferred    = PREFERRED,
909            required     = REQUIRED,
910            visualUpdate = UPDATE,
911            enumerationValues = {V_NAME})
912        public abstract double getX();
913
914        public void addPropertyChangeListener(PropertyChangeListener l)    {}
915        public void removePropertyChangeListener(PropertyChangeListener l) {}
916    }
917
918    // ----------
919
920    public static interface ISet2 {
921
922        final static String TESTCASE = "super interface - setter";
923
924        @BeanProperty(
925            description  = DESCRIPTION,
926            bound        = BOUND,
927            expert       = EXPERT,
928            hidden       = HIDDEN,
929            preferred    = PREFERRED,
930            required     = REQUIRED,
931            visualUpdate = UPDATE,
932            enumerationValues = {V_NAME})
933        public void setX(double v);
934
935        public void addPropertyChangeListener(PropertyChangeListener l);
936        public void removePropertyChangeListener(PropertyChangeListener l);
937    }
938
939    public static class ISet2Impl implements ISet2 {
940
941        private double x;
942
943        @BeanProperty(
944            description  = DESCRIPTION_2,
945            bound        = !BOUND,
946            expert       = !EXPERT,
947            hidden       = !HIDDEN,
948            preferred    = !PREFERRED,
949            required     = !REQUIRED,
950            visualUpdate = !UPDATE)
951        @Override
952        public void setX(double v) { x = v; }
953
954        @Override
955        public void addPropertyChangeListener(PropertyChangeListener l) {}
956        @Override
957        public void removePropertyChangeListener(PropertyChangeListener l) {}
958    }
959
960    // ----------
961
962    public static interface IGet2 {
963
964        final static String TESTCASE = "super interface - indexed getter";
965
966        @BeanProperty(
967            description  = DESCRIPTION,
968            bound        = BOUND,
969            expert       = EXPERT,
970            hidden       = HIDDEN,
971            preferred    = PREFERRED,
972            required     = REQUIRED,
973            visualUpdate = UPDATE,
974            enumerationValues = {V_NAME})
975        public double[] getX();
976
977        public void addPropertyChangeListener(PropertyChangeListener l);
978        public void removePropertyChangeListener(PropertyChangeListener l);
979    }
980
981    public static class IGet2Impl implements IGet2 {
982
983        @BeanProperty(
984            description  = DESCRIPTION_2,
985            bound        = !BOUND,
986            expert       = !EXPERT,
987            hidden       = !HIDDEN,
988            preferred    = !PREFERRED,
989            required     = !REQUIRED,
990            visualUpdate = !UPDATE)
991        @Override
992        public double[] getX() { return new double[]{X, X}; }
993
994        @Override
995        public void addPropertyChangeListener(PropertyChangeListener l) {}
996        @Override
997        public void removePropertyChangeListener(PropertyChangeListener l) {}
998    }
999
1000    // ----------
1001
1002    public static class ProtectedGet {
1003
1004        @BeanProperty(
1005            description  = DESCRIPTION_2,
1006            bound        = !BOUND,
1007            expert       = !EXPERT,
1008            hidden       = !HIDDEN,
1009            preferred    = !PREFERRED,
1010            required     = !REQUIRED,
1011            visualUpdate = !UPDATE)
1012        protected double getX() { return 0.; }
1013    }
1014
1015    public static class OverrideProtectedGet extends ProtectedGet {
1016
1017        final static String TESTCASE = "override protected getter";
1018
1019        @BeanProperty(
1020            description  = DESCRIPTION,
1021            bound        = BOUND,
1022            expert       = EXPERT,
1023            hidden       = HIDDEN,
1024            preferred    = PREFERRED,
1025            required     = REQUIRED,
1026            visualUpdate = UPDATE,
1027            enumerationValues = {V_NAME})
1028        @Override
1029        public double getX() { return X; }
1030
1031        public void addPropertyChangeListener(PropertyChangeListener l) {}
1032        public void removePropertyChangeListener(PropertyChangeListener l) {}
1033    }
1034
1035    // ----------
1036
1037    // static getter - see also JDK-8154938
1038    public static class StaticGet {
1039
1040        @BeanProperty(
1041            description  = DESCRIPTION_2,
1042            bound        = !BOUND,
1043            expert       = !EXPERT,
1044            hidden       = !HIDDEN,
1045            preferred    = !PREFERRED,
1046            required     = !REQUIRED,
1047            visualUpdate = !UPDATE)
1048        public static double getProp() { return 0.; }
1049    }
1050
1051    public static class HideStaticGet extends StaticGet {
1052
1053        final static String TESTCASE = "hide static getter";
1054
1055        public double getX() { return X; } // add to get the "default" info
1056        public static double getProp() { return X; }
1057    }
1058
1059    // TODO: if 8154938 is considered to be a real issue,
1060    // create one more test case "HideStaticGet2 extends StaticGet" with an
1061    // annotated getter and check the correctness of the corresponding bean info
1062
1063    // ---------- checks ----------
1064
1065    private static boolean check(String what, boolean v, boolean ref) {
1066
1067        boolean ok = (v == ref);
1068        if (!ok) { System.out.println(
1069            "invalid " + what + ": " + v + ", expected: " + ref); }
1070        return ok;
1071    }
1072
1073    private static boolean checkInfo(BeanInfo i, boolean ignoreValsCheck) {
1074
1075        System.out.println("checking info...");
1076
1077        PropertyDescriptor descriptors[] = i.getPropertyDescriptors();
1078        int nd = descriptors.length;
1079        if (nd != 1) {
1080            System.out.println("invalid number of descriptors: " + nd);
1081            return false;
1082        }
1083
1084        PropertyDescriptor d = descriptors[0];
1085
1086        String descr = d.getShortDescription();
1087        boolean ok = descr.equals(DESCRIPTION);
1088        if (!ok) { System.out.println("invalid description: " + descr +
1089                ", expected: " + DESCRIPTION); }
1090
1091        ok &= check("isBound",  d.isBound(),  BOUND);
1092        ok &= check("isExpert", d.isExpert(), EXPERT);
1093        ok &= check("isHidden", d.isHidden(), HIDDEN);
1094        ok &= check("isPreferred", d.isPreferred(), PREFERRED);
1095        ok &= check("required", (boolean) d.getValue("required"), REQUIRED);
1096        ok &= check("visualUpdate",
1097            (boolean) d.getValue("visualUpdate"), UPDATE);
1098
1099        if (ignoreValsCheck) { return ok; }
1100
1101        Object vals[] = (Object[]) d.getValue("enumerationValues");
1102        if (vals == null) {
1103            System.out.println("null enumerationValues");
1104            return false;
1105        }
1106
1107        boolean okVals = (
1108            (vals.length == 3) &&
1109             vals[0].toString().equals(V_SHORT) &&
1110             vals[1].toString().equals(V)       &&
1111             vals[2].toString().equals(V_NAME));
1112
1113        if (!okVals) { System.out.println("invalid enumerationValues"); }
1114
1115        return (ok && okVals);
1116    }
1117
1118    private static boolean checkDefault(BeanInfo i) {
1119
1120        System.out.println("checking default info...");
1121
1122        PropertyDescriptor descriptors[] = i.getPropertyDescriptors();
1123        int nd = descriptors.length;
1124        if (nd != 1) {
1125            System.out.println("invalid number of descriptors: " + nd);
1126            return false;
1127        }
1128
1129        PropertyDescriptor d = descriptors[0];
1130
1131        String descr = d.getShortDescription();
1132        boolean ok = descr.equals("x");
1133        if (!ok) { System.out.println("invalid description: " + descr +
1134                ", expected: x"); }
1135
1136        ok &= check("isBound",  d.isBound(),  false);
1137        ok &= check("isExpert", d.isExpert(), false);
1138        ok &= check("isHidden", d.isHidden(), false);
1139        ok &= check("isPreferred", d.isPreferred(), false);
1140        ok &= check("required", (boolean) d.getValue("required"), false);
1141        ok &= check("visualUpdate",
1142            (boolean) d.getValue("visualUpdate"), false);
1143
1144        Object vals[] = (Object[]) d.getValue("enumerationValues");
1145        if (vals != null && vals.length > 0) {
1146            System.out.println("non-empty enumerationValues");
1147            ok = false;
1148        }
1149
1150        return ok;
1151    }
1152
1153    // do not check enumerationValues for these classes
1154    private static boolean ignoreVals(Class<?> c) {
1155        return (
1156            c.equals(BoolGetIs.class)            ||
1157            c.equals(BoolIsGet.class)            ||
1158            c.equals(AnnotatedIs.class)          ||
1159            c.equals(OverrideAnnotatedIs2.class) ||
1160            c.equals(AnnotatedIs2Ext.class)      ||
1161            c.equals(OverrideAbstractIs.class)   ||
1162            c.equals(OverrideAbstractIs2.class)  ||
1163            c.equals(AbstractIsExt.class)        ||
1164            c.equals(OverrideAbstractIs.class)   ||
1165            c.equals(IIsImpl.class)              ||
1166            c.equals(IIsImpl2.class)             ||
1167            c.equals(IIsImpl3.class)
1168        );
1169    }
1170
1171    // default property descriptor data are expected for these classes
1172    private static boolean isDefault(Class<?> c) {
1173        return (
1174            c.equals(OverrideAnnotatedGet.class) ||
1175            c.equals(OverrideAnnotatedIs.class ) ||
1176            c.equals(OverrideAnnotatedSet.class) ||
1177            c.equals(OverrideAbstractGet.class)  ||
1178            c.equals(OverrideAbstractIs.class)   ||
1179            c.equals(OverrideAbstractSet.class)  ||
1180            c.equals(IGetImpl.class)             ||
1181            c.equals(IIsImpl.class)              ||
1182            c.equals(ISetImpl.class)             ||
1183            c.equals(BaseGet.class)              ||
1184            c.equals(BaseSet.class)              ||
1185            c.equals(HideStaticGet.class)
1186        );
1187    }
1188
1189
1190    // ---------- run test ----------
1191
1192    public static void main(String[] args) throws Exception {
1193
1194        Class<?>
1195            ic1 = ISet2Impl.class.getInterfaces()[0],
1196            ic2 = IGet2Impl.class.getInterfaces()[0];
1197
1198        Class<?> cases[] = {
1199
1200            OverloadGet.class,
1201            OverloadGet.class.getSuperclass(),
1202            OverloadSet.class,
1203            OverloadSet.class.getSuperclass(),
1204            OverloadIGet.class,
1205            OverloadISet.class,
1206
1207            // TODO: uncomment/update after 8132565 fix
1208            //BoolGetIs.class,
1209            //BoolIsGet.class,
1210            //OverrideAnnotatedGet.class,
1211            //OverrideAnnotatedIs.class,
1212            //OverrideAnnotatedSet.class,
1213            //OverrideAnnotatedGet2.class,
1214            //AnnotatedGet2Ext.class,
1215            //OverrideAnnotatedIs2.class
1216            //AnnotatedIs2Ext.class,
1217            //OverrideAnnotatedSet2.class,
1218            //AnnotatedSet2Ext.class,
1219
1220            OverrideAnnotatedGet.class.getSuperclass(),
1221            OverrideAnnotatedIs.class.getSuperclass(),
1222            OverrideAnnotatedSet.class.getSuperclass(),
1223
1224            // TODO: uncomment/update after 8132565 fix
1225            //OverrideAbstractGet.class,
1226            //OverrideAbstractGet2.class,
1227            //AbstractGetExt.class,
1228            //OverrideAbstractIs.class,
1229            //OverrideAbstractIs2.class,
1230            //AbstractIsExt.class
1231            //OverrideAbstractSet.class,
1232            //OverrideAbstractSet2.class,
1233            //AbstractSetExt.class,
1234
1235            AbstractGet2Ext.class.getSuperclass(),
1236            IGetImpl.class,
1237            IGetImpl2.class,
1238            IGetImpl3.class,
1239            IIsImpl.class,
1240            IIsImpl2.class,
1241            IIsImpl3.class,
1242            ISetImpl.class,
1243            ISetImpl2.class,
1244            ISetImpl3.class,
1245            ic1,
1246            // ic2,  // TODO: uncomment/update after 8155013 fix
1247            OverrideProtectedGet.class,
1248            HideStaticGet.class
1249        };
1250
1251        boolean passed = true;
1252
1253        for (Class<?> c: cases) {
1254
1255            java.lang.reflect.Field f = c.getDeclaredField("TESTCASE");
1256            f.setAccessible(true);
1257            String descr = f.get(c).toString();
1258
1259            System.out.println("\n" + c.getSimpleName() + " (" + descr + "):");
1260            BeanInfo i;
1261            try {
1262                i = Introspector.getBeanInfo(c,
1263                    (c.equals(ic1) || c.equals(ic2)) ? null : Object.class);
1264            }
1265            catch (IntrospectionException e) { throw new RuntimeException(e); }
1266
1267            boolean ok;
1268
1269            if (isDefault(c)) {
1270                ok = checkDefault(i);
1271            } else {
1272                ok = checkInfo(i, ignoreVals(c));
1273            }
1274            System.out.println(ok ? "OK" : "NOK");
1275            passed = passed && ok;
1276        }
1277
1278        if (!passed) { throw new RuntimeException("test failed"); }
1279        System.out.println("\ntest passed");
1280    }
1281}
1282