1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package net.sf.commonclipse;
18
19 import java.util.HashMap;
20 import java.util.Iterator;
21 import java.util.Map;
22
23 import org.eclipse.jdt.core.Flags;
24 import org.eclipse.jdt.core.IField;
25 import org.eclipse.jdt.core.IMethod;
26 import org.eclipse.jdt.core.IType;
27 import org.eclipse.jdt.core.ITypeHierarchy;
28 import org.eclipse.jdt.core.JavaModelException;
29
30
31 /***
32 * Generator for toString() methods.
33 * @author fgiust
34 * @version $Revision: 1.7 $ ($Author: fgiust $)
35 */
36 public final class ToStringGenerator extends Generator
37 {
38
39 /***
40 * Class name for the ToString buider.
41 */
42 private static final String BUILDER_CLASS = "org.apache.commons.lang.builder.ToStringBuilder";
43
44 /***
45 * Singleton for ToStringGenerator.
46 */
47 private static Generator instance = new ToStringGenerator();
48
49 /***
50 * Use getInstance() to obtain an instance of ToStringGenerator.
51 */
52 private ToStringGenerator()
53 {
54 }
55
56 /***
57 * Returns the ToStringGenerator instance.
58 * @return instance of ToStringGenerator
59 */
60 public static Generator getInstance()
61 {
62 return instance;
63 }
64
65 /***
66 * @see net.sf.commonclipse.Generator#getMethodName()
67 */
68 protected String getMethodName()
69 {
70 return "toString";
71 }
72
73 /***
74 * @see net.sf.commonclipse.Generator#addImports(org.eclipse.jdt.core.IType)
75 */
76 protected void addImports(IType type) throws JavaModelException
77 {
78 type.getCompilationUnit().createImport(BUILDER_CLASS, null, null);
79
80 if (CCPluginPreferences.getPreferences().useCustomToStringStyle())
81 {
82 type.getCompilationUnit().createImport(
83 CCPluginPreferences.getPreferences().getToStringStyleQualifiedClass(),
84 null,
85 null);
86 }
87 }
88
89 /***
90 * @see net.sf.commonclipse.Generator#createMethod(org.eclipse.jdt.core.IType)
91 */
92 protected String createMethod(IType type) throws JavaModelException
93 {
94
95 StringBuffer buffer = new StringBuffer();
96
97 buffer.append(getJavadoc());
98
99 buffer.append(" public String toString()\n {\n return new ToStringBuilder(this");
100
101 if (CCPluginPreferences.getPreferences().useCustomToStringStyle())
102 {
103 buffer.append(", ");
104 buffer.append(CCPluginPreferences.getPreferences().getToStringStyleClassAndConstant());
105 }
106
107 buffer.append(")\n");
108
109 if (CCPluginPreferences.getPreferences().appendSuperToToString())
110 {
111 buffer.append(".appendSuper(super.toString())\n");
112 }
113
114 if (CCPluginPreferences.getPreferences().useJavabeanToString())
115 {
116 buffer.append(buildAppenderListFromBean(type));
117 }
118 else
119 {
120 buffer.append(buildAppenderList(type));
121 }
122
123 buffer.append(".toString();\n}");
124
125 return buffer.toString();
126 }
127
128 /***
129 * Iterates on javabean properties and calls getFieldAppender for all of them.
130 * @param type IType
131 * @return String
132 * @throws JavaModelException exception in analyzing properties
133 */
134 private String buildAppenderListFromBean(IType type) throws JavaModelException
135 {
136
137 Map getterMethods = buildMethodsMap(type);
138
139
140 Map fields = buildFieldMap(type);
141
142
143 Iterator iterator = getterMethods.entrySet().iterator();
144
145 StringBuffer buffer = new StringBuffer();
146
147 while (iterator.hasNext())
148 {
149 IMethod method = (IMethod) ((Map.Entry) iterator.next()).getValue();
150 String methodName = method.getElementName();
151 String propertyName = getJavabeanProperyName(methodName);
152
153
154 if (!isExcluded(propertyName))
155 {
156
157 IField matchingField = (IField) fields.get(propertyName);
158
159 if (matchingField != null)
160 {
161 if (propertyName.equals(matchingField.getElementName()))
162 {
163
164
165 buffer.append(getFieldAppender(propertyName, propertyName));
166 continue;
167 }
168 }
169
170
171 buffer.append(getFieldAppender(propertyName, methodName + "()"));
172 }
173 }
174 return buffer.toString();
175 }
176
177 /***
178 * Returns a Map containing all the javabean getter methods in this type and its supertypes.
179 * @param type IType
180 * @return Map containg method names - IMethod objects
181 * @throws JavaModelException exception in analyzing type
182 */
183 private Map buildMethodsMap(IType type) throws JavaModelException
184 {
185 Map getterMethods = new HashMap();
186
187
188 ITypeHierarchy hierarchy = type.newSupertypeHierarchy(null);
189 IType[] types = hierarchy.getAllClasses();
190
191 for (int j = 0; j < types.length; j++)
192 {
193 IMethod[] superMethods = types[j].getMethods();
194
195 for (int x = 0; x < superMethods.length; x++)
196 {
197 IMethod method = superMethods[x];
198
199 if (isJavabeanGetter(method))
200 {
201 getterMethods.put(method.getElementName(), method);
202 }
203 }
204 }
205
206 return getterMethods;
207 }
208
209 /***
210 * Returns the javabean property name from the getter method name.
211 * @param methodName getter method name
212 * @return javabean property name (ex. "test" for "getTest()")
213 */
214 private String getJavabeanProperyName(String methodName)
215 {
216
217 String propertyName;
218 if (methodName.startsWith("get"))
219 {
220 propertyName = methodName.substring(3, methodName.length());
221 }
222 else
223 {
224
225 propertyName = methodName.substring(2, methodName.length());
226 }
227
228 if (propertyName.length() > 1 && Character.isLowerCase(propertyName.charAt(1)))
229 {
230 propertyName = Character.toLowerCase(propertyName.charAt(0))
231 + propertyName.substring(1, propertyName.length());
232 }
233 else if (propertyName.length() == 1)
234 {
235 propertyName = propertyName.toLowerCase();
236 }
237 return propertyName;
238 }
239
240 /***
241 * Checks if the given method is a javabean getter (start with get or is for boolean properties, no param).
242 * @param method IMethod
243 * @return <code>true</code> if the method is a javabean property accessor
244 * @throws JavaModelException exception thrown in analyzing method
245 */
246 private boolean isJavabeanGetter(IMethod method) throws JavaModelException
247 {
248
249 if (method.getNumberOfParameters() == 0 && Flags.isPublic(method.getFlags()))
250 {
251 String methodName = method.getElementName();
252
253 if (methodName.length() > 3 && methodName.startsWith("get"))
254 {
255 return true;
256 }
257 else if (methodName.length() > 2 && methodName.startsWith("is")
258 && ("Z".equals(method.getReturnType())
259 || "QBoolean;".equals(method.getReturnType())))
260 {
261 return true;
262 }
263 }
264 return false;
265 }
266
267 /***
268 * Generates the method javadoc.
269 * @return String javadoc
270 */
271 private String getJavadoc()
272 {
273 return "/**\n * @see java.lang.Object#toString()\n */\n";
274 }
275
276 /***
277 * @see net.sf.commonclipse.Generator#getExistingMethod(org.eclipse.jdt.core.IType)
278 */
279 protected IMethod getExistingMethod(IType type)
280 {
281 return type.getMethod(getMethodName(), new String[0]);
282 }
283
284 /***
285 * @see net.sf.commonclipse.Generator#getFieldAppender(java.lang.String, java.lang.String)
286 */
287 protected String getFieldAppender(String fieldName, String accessor)
288 {
289 return ".append(\"" + fieldName + "\", this." + accessor + ")\n";
290 }
291
292 }