1 /*
2 * Copyright 2001-2013 Stephen Colebourne
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.joda.beans.gen;
17
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.HashSet;
21 import java.util.List;
22 import java.util.Set;
23
24 import org.joda.beans.PropertyReadWrite;
25
26 /**
27 * A bean that can be generated.
28 *
29 * @author Stephen Colebourne
30 */
31 class GeneratableProperty {
32
33 /** Collection types. */
34 private static final Set<String> COLLECTIONS = new HashSet<String>(
35 Arrays.asList(
36 "Collection", "Set", "SortedSet", "NavigableSet", "List",
37 "ArrayList", "LinkedList",
38 "HashSet", "LinkedHashSet", "TreeSet", "ConcurrentSkipListSet"));
39 /** Map types. */
40 private static final Set<String> MAPS = new HashSet<String>(
41 Arrays.asList(
42 "Map", "SortedMap", "NavigableMap", "ConcurrentMap", "ConcurrentNavigableMap",
43 "HashMap", "LinkedHashMap", "TreeMap", "ConcurrentHashMap", "ConcurrentSkipListMap"));
44
45 /** Owning bean. */
46 private final GeneratableBean bean;
47 /** Property name. */
48 private String propertyName;
49 /** Field name. */
50 private String fieldName;
51 /** Upper property name. */
52 private String upperName;
53 /** Property type. */
54 private String type;
55 /** Whether the field is declared final. */
56 private boolean isFinal;
57 /** The getter style. */
58 private String getStyle;
59 /** The setter style. */
60 private String setStyle;
61 /** The validation string. */
62 private String validation;
63 /** Deprecated flag. */
64 private boolean deprecated;
65 /** First comment about the property. */
66 private String firstComment;
67 /** Other comments about the property. */
68 private final List<String> comments = new ArrayList<String>();
69
70 /**
71 * Constructor.
72 */
73 GeneratableProperty(GeneratableBean bean) {
74 this.bean = bean;
75 }
76
77 //-----------------------------------------------------------------------
78 /**
79 * Gets the bean.
80 * @return the bean, not null
81 */
82 public GeneratableBean getBean() {
83 return bean;
84 }
85
86 /**
87 * Gets the property name.
88 * @return the property name
89 */
90 public String getPropertyName() {
91 return propertyName;
92 }
93
94 /**
95 * Sets the property name.
96 * @param propertyName the property name to set
97 */
98 public void setPropertyName(String propertyName) {
99 this.propertyName = propertyName;
100 }
101
102 /**
103 * Gets the field name.
104 * @return the field name
105 */
106 public String getFieldName() {
107 return fieldName;
108 }
109
110 /**
111 * Sets the field name.
112 * @param fieldName the field name to set
113 */
114 public void setFieldName(String fieldName) {
115 this.fieldName = fieldName;
116 }
117
118 /**
119 * Gets the upper property name.
120 * @return the upper name
121 */
122 public String getUpperName() {
123 return upperName;
124 }
125
126 /**
127 * Sets the upper property name.
128 * @param upperName the upper name to set
129 */
130 public void setUpperName(String upperName) {
131 this.upperName = upperName;
132 }
133
134 /**
135 * Gets the type.
136 * @return the type
137 */
138 public String getType() {
139 return type;
140 }
141
142 /**
143 * Sets the type.
144 * @param type the type to set
145 */
146 public void setType(String type) {
147 this.type = type;
148 }
149
150 /**
151 * Gets whether the field is declared final.
152 * @return the type
153 */
154 public boolean isFinal() {
155 return isFinal;
156 }
157
158 /**
159 * Sets whether the field is declared final.
160 * @param type the field is final flag
161 */
162 public void setFinal(boolean isFinal) {
163 this.isFinal = isFinal;
164 }
165
166 /**
167 * Gets the getter style.
168 * @return the getter style
169 */
170 public String getGetStyle() {
171 return getStyle;
172 }
173
174 /**
175 * Sets the getter style.
176 * @param getStyle the getter style to set
177 */
178 public void setGetStyle(String getStyle) {
179 this.getStyle = getStyle;
180 }
181
182 /**
183 * Gets the setter style.
184 * @return the setter style
185 */
186 public String getSetStyle() {
187 return setStyle;
188 }
189
190 /**
191 * Sets the setter style.
192 * @param setStyle the setter style to set
193 */
194 public void setSetStyle(String setStyle) {
195 this.setStyle = setStyle;
196 }
197
198 /**
199 * Gets the validation.
200 * @return the validation
201 */
202 public String getValidation() {
203 return validation;
204 }
205
206 /**
207 * Sets the validation.
208 * @param validation the validation to set
209 */
210 public void setValidation(String validation) {
211 this.validation = validation;
212 }
213
214 /**
215 * Checks if the property is deprecated.
216 * @return the deprecated flag
217 */
218 public boolean isDeprecated() {
219 return deprecated;
220 }
221
222 /**
223 * Sets if the property is deprecated.
224 * @param deprecated the deprecated to set
225 */
226 public void setDeprecated(boolean deprecated) {
227 this.deprecated = deprecated;
228 }
229
230 /**
231 * Gets the first comment line.
232 * @return the first comment
233 */
234 public String getFirstComment() {
235 return firstComment;
236 }
237
238 /**
239 * Sets the first comment line.
240 * @param firstComment the first comment to set
241 */
242 public void setFirstComment(String firstComment) {
243 this.firstComment = firstComment;
244 }
245
246 /**
247 * Gets the remaining comments.
248 * @return the remaining comments, not null
249 */
250 public List<String> getComments() {
251 return comments;
252 }
253
254 //-----------------------------------------------------------------------
255 /**
256 * Checks if the property is parameterised with generics.
257 * @return true if generified
258 */
259 public boolean isGenericParamType() {
260 return type.indexOf("<") >= 0;
261 }
262
263 /**
264 * Checks if the property is parameterised with generics.
265 * @return true if generified
266 */
267 public boolean isGenericWildcardParamType() {
268 return type.endsWith("<?>");
269 }
270
271 /**
272 * Gets the parameterisation of the property.
273 * @return the generic type, or a blank string if not generic, not null
274 */
275 public String getGenericParamType() {
276 int pos = type.indexOf("<");
277 if (pos < 0) {
278 return "";
279 }
280 return type.substring(pos + 1, type.length() - 1);
281 }
282
283 /**
284 * Gets the raw type of the property without generics.
285 * @return the raw type, not null
286 */
287 public String getRawType() {
288 int pos = type.indexOf("<");
289 return (pos < 0 ? type : type.substring(0, pos));
290 }
291
292 /**
293 * Checks if the type is the generic type of the bean.
294 * For example, if the property is of type T in a bean of Foo[T].
295 * @return true if matches
296 */
297 public boolean isBeanGenericType() {
298 return type.equals(bean.getTypeGenericName(false));
299 }
300
301 /**
302 * Checks if the property is generic in some way.
303 * @return true if generic
304 */
305 public boolean isGeneric() {
306 return isGenericParamType() || isBeanGenericType();
307 }
308
309 /**
310 * Checks if the property is derived.
311 * @return true if derived
312 */
313 public boolean isDerived() {
314 return fieldName == null;
315 }
316
317 //-----------------------------------------------------------------------
318 /**
319 * Checks if this property is a known collection type.
320 *
321 * @return true if it is a known collection type
322 */
323 public boolean isCollectionType() {
324 return isGeneric() && COLLECTIONS.contains(getRawType());
325 }
326
327 /**
328 * Checks if this property is a known map type.
329 *
330 * @return true if it is a known map type
331 */
332 public boolean isMapType() {
333 return "FlexiBean".equals(getType()) || (isGeneric() && MAPS.contains(getRawType()));
334 }
335
336 /**
337 * Gets the read-write flag.
338 *
339 * @return the read write
340 */
341 public PropertyReadWrite getReadWrite() {
342 SetterGen generator = SetterGen.of(this);
343 if (getGetStyle().length() > 0 && getSetStyle().length() > 0 && (generator.isSetterGenerated(this) || getSetStyle().equals("manual"))) {
344 return PropertyReadWrite.READ_WRITE;
345 }
346 if (getGetStyle().length() > 0) {
347 return PropertyReadWrite.READ_ONLY;
348 }
349 if (getSetStyle().length() > 0) {
350 return PropertyReadWrite.WRITE_ONLY;
351 }
352 throw new RuntimeException("Property must have a getter or setter: " + propertyName);
353 }
354
355 //-----------------------------------------------------------------------
356 /**
357 * Checks if the validation is non-null.
358 * @return true if non-null
359 */
360 public boolean isValidated() {
361 return getValidation() != null && getValidation().length() > 0;
362 }
363
364 /**
365 * Checks if the validation is non-null.
366 * @return true if non-null
367 */
368 public boolean isNotNull() {
369 return getValidation().equals("notNull") || getValidation().equals("notEmpty");
370 }
371
372 /**
373 * Gets the validation method name.
374 * @return the method name
375 */
376 public String getValidationMethodName() {
377 if (isValidated() == false) {
378 throw new IllegalStateException();
379 }
380 if (getValidation().equals("notNull") || getValidation().equals("notEmpty")) {
381 return "JodaBeanUtils." + getValidation();
382 }
383 return getValidation(); // method in bean or static
384 }
385
386 }