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