1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.joda.beans.impl.reflection;
17
18 import java.lang.reflect.Field;
19 import java.lang.reflect.Modifier;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.Map;
23 import java.util.NoSuchElementException;
24
25 import org.joda.beans.Bean;
26 import org.joda.beans.BeanBuilder;
27 import org.joda.beans.MetaBean;
28 import org.joda.beans.MetaProperty;
29 import org.joda.beans.PropertyMap;
30 import org.joda.beans.impl.BasicBeanBuilder;
31 import org.joda.beans.impl.BasicPropertyMap;
32
33
34
35
36
37
38
39
40
41 public final class ReflectiveMetaBean implements MetaBean {
42
43
44 private final Class<? extends Bean> beanType;
45
46 private final Map<String, MetaProperty<?>> metaPropertyMap;
47
48
49
50
51
52
53
54
55 public static <B extends Bean> ReflectiveMetaBean of(Class<B> beanClass) {
56 return new ReflectiveMetaBean(beanClass);
57 }
58
59
60
61
62
63
64 @SuppressWarnings("unchecked")
65 private ReflectiveMetaBean(Class<? extends Bean> beanType) {
66 if (beanType == null) {
67 throw new NullPointerException("Bean class must not be null");
68 }
69 this.beanType = beanType;
70 Map<String, MetaProperty<?>> map = new HashMap<String, MetaProperty<?>>();
71 Field[] fields = beanType.getDeclaredFields();
72 for (Field field : fields) {
73 if (MetaProperty.class.isAssignableFrom(field.getType()) && Modifier.isStatic(field.getModifiers())) {
74 field.setAccessible(true);
75 MetaProperty<Object> mp;
76 try {
77 mp = (MetaProperty<Object>) field.get(null);
78 if (mp instanceof ReflectiveMetaProperty) {
79 ((ReflectiveMetaProperty<Object>) mp).setMetaBean(this);
80 }
81 } catch (IllegalArgumentException ex) {
82 throw new UnsupportedOperationException("MetaProperty cannot be created: " + field.getName(), ex);
83 } catch (IllegalAccessException ex) {
84 throw new UnsupportedOperationException("MetaProperty cannot be created: " + field.getName(), ex);
85 }
86 if (mp == null) {
87 throw new UnsupportedOperationException("MetaProperty cannot be created: " + field.getName() + ": Value must not be null");
88 }
89 map.put(mp.name(), mp);
90 }
91 }
92
93 this.metaPropertyMap = Collections.unmodifiableMap(map);
94 }
95
96
97 @Override
98 public BeanBuilder<Bean> builder() {
99 try {
100 Bean bean = beanType.newInstance();
101 return new BasicBeanBuilder<Bean>(bean);
102 } catch (InstantiationException ex) {
103 throw new UnsupportedOperationException("Bean cannot be created: " + beanName(), ex);
104 } catch (IllegalAccessException ex) {
105 throw new UnsupportedOperationException("Bean cannot be created: " + beanName(), ex);
106 }
107 }
108
109 @Override
110 public PropertyMap createPropertyMap(Bean bean) {
111 return BasicPropertyMap.of(bean);
112 }
113
114
115 @Override
116 public String beanName() {
117 return beanType.getName();
118 }
119
120 @Override
121 public Class<? extends Bean> beanType() {
122 return beanType;
123 }
124
125
126 @Override
127 public int metaPropertyCount() {
128 return metaPropertyMap.size();
129 }
130
131 @Override
132 public boolean metaPropertyExists(String propertyName) {
133 return metaPropertyMap.containsKey(propertyName);
134 }
135
136 @SuppressWarnings("unchecked")
137 @Override
138 public <R> MetaProperty<R> metaProperty(String propertyName) {
139 MetaProperty<?> metaProperty = metaPropertyMap.get(propertyName);
140 if (metaProperty == null) {
141 throw new NoSuchElementException("Property not found: " + propertyName);
142 }
143 return (MetaProperty<R>) metaProperty;
144 }
145
146 @Override
147 public Iterable<MetaProperty<?>> metaPropertyIterable() {
148 return metaPropertyMap.values();
149 }
150
151 @Override
152 public Map<String, MetaProperty<?>> metaPropertyMap() {
153 return metaPropertyMap;
154 }
155
156
157 @Override
158 public boolean equals(Object obj) {
159 if (obj instanceof ReflectiveMetaBean) {
160 ReflectiveMetaBean other = (ReflectiveMetaBean) obj;
161 return this.beanType.equals(other.beanType);
162 }
163 return false;
164 }
165
166 @Override
167 public int hashCode() {
168 return beanType.hashCode() + 3;
169 }
170
171
172
173
174
175
176 @Override
177 public String toString() {
178 return "MetaBean:" + beanName();
179 }
180
181 }