1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.jxpath;
19
20 import java.beans.BeanInfo;
21 import java.beans.IntrospectionException;
22 import java.beans.Introspector;
23 import java.beans.PropertyDescriptor;
24 import java.util.Arrays;
25 import java.util.Comparator;
26 import java.util.HashMap;
27
28
29
30
31
32
33
34
35 public class JXPathBasicBeanInfo implements JXPathBeanInfo {
36
37 private static final long serialVersionUID = -3863803443111484155L;
38 private static final Comparator<PropertyDescriptor> PROPERTY_DESCRIPTOR_COMPARATOR = Comparator.comparing(PropertyDescriptor::getName);
39
40
41
42 private boolean atomic;
43
44
45
46
47 private final Class clazz;
48
49
50
51
52 private Class dynamicPropertyHandlerClass;
53
54
55
56
57 private transient PropertyDescriptor[] propertyDescriptors;
58
59
60
61
62 private transient HashMap<String, PropertyDescriptor> propertyDescriptorMap;
63
64
65
66
67
68
69 public JXPathBasicBeanInfo(final Class clazz) {
70 this.clazz = clazz;
71 }
72
73
74
75
76
77
78
79 public JXPathBasicBeanInfo(final Class clazz, final boolean atomic) {
80 this.clazz = clazz;
81 this.atomic = atomic;
82 }
83
84
85
86
87
88
89
90 public JXPathBasicBeanInfo(final Class clazz, final Class dynamicPropertyHandlerClass) {
91 this.clazz = clazz;
92 this.atomic = false;
93 this.dynamicPropertyHandlerClass = dynamicPropertyHandlerClass;
94 }
95
96
97
98
99
100
101 @Override
102 public Class getDynamicPropertyHandlerClass() {
103 return dynamicPropertyHandlerClass;
104 }
105
106 @Override
107 public synchronized PropertyDescriptor getPropertyDescriptor(final String propertyName) {
108 if (propertyDescriptorMap == null) {
109 propertyDescriptorMap = new HashMap<>();
110 final PropertyDescriptor[] pds = getPropertyDescriptors();
111 for (final PropertyDescriptor pd : pds) {
112 propertyDescriptorMap.put(pd.getName(), pd);
113 }
114 }
115 return propertyDescriptorMap.get(propertyName);
116 }
117
118 @Override
119 public synchronized PropertyDescriptor[] getPropertyDescriptors() {
120 if (propertyDescriptors == null) {
121 if (clazz == Object.class) {
122 propertyDescriptors = new PropertyDescriptor[0];
123 } else {
124 try {
125 BeanInfo bi;
126 if (clazz.isInterface()) {
127 bi = Introspector.getBeanInfo(clazz);
128 } else {
129 bi = Introspector.getBeanInfo(clazz, Object.class);
130 }
131 final PropertyDescriptor[] pds = bi.getPropertyDescriptors();
132 final PropertyDescriptor[] descriptors = new PropertyDescriptor[pds.length];
133 System.arraycopy(pds, 0, descriptors, 0, pds.length);
134 Arrays.sort(descriptors, PROPERTY_DESCRIPTOR_COMPARATOR);
135 propertyDescriptors = descriptors;
136 } catch (final IntrospectionException ex) {
137 ex.printStackTrace();
138 return new PropertyDescriptor[0];
139 }
140 }
141 }
142 if (propertyDescriptors.length == 0) {
143 return propertyDescriptors;
144 }
145 final PropertyDescriptor[] result = new PropertyDescriptor[propertyDescriptors.length];
146 System.arraycopy(propertyDescriptors, 0, result, 0, propertyDescriptors.length);
147 return result;
148 }
149
150
151
152
153
154
155 @Override
156 public boolean isAtomic() {
157 return atomic;
158 }
159
160
161
162
163
164
165 @Override
166 public boolean isDynamic() {
167 return dynamicPropertyHandlerClass != null;
168 }
169
170 @Override
171 public String toString() {
172 final StringBuilder buffer = new StringBuilder();
173 buffer.append("BeanInfo [class = ");
174 buffer.append(clazz.getName());
175 if (isDynamic()) {
176 buffer.append(", dynamic");
177 }
178 if (isAtomic()) {
179 buffer.append(", atomic");
180 }
181 buffer.append(", properties = ");
182 final PropertyDescriptor[] jpds = getPropertyDescriptors();
183 for (final PropertyDescriptor jpd : jpds) {
184 buffer.append("\n ");
185 buffer.append(jpd.getPropertyType());
186 buffer.append(": ");
187 buffer.append(jpd.getName());
188 }
189 buffer.append("]");
190 return buffer.toString();
191 }
192 }