1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sf.jameleon.bean;
20
21 import com.thoughtworks.qdox.JavaDocBuilder;
22 import com.thoughtworks.qdox.model.*;
23 import net.sf.jameleon.exception.JameleonException;
24 import net.sf.jameleon.util.InstanceSerializer;
25
26 import java.io.File;
27 import java.io.FileNotFoundException;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.util.*;
31
32 public class Javadoc2Bean {
33
34 protected File sourceDir;
35 protected String isA = "net.sf.jameleon.function.FunctionTag";
36 protected JavaDocBuilder docBuilder;
37 protected Map serializedFiles = new HashMap();
38
39 /***
40 * Default constructor only used to initialize variables
41 */
42 public Javadoc2Bean() {
43 docBuilder = new JavaDocBuilder();
44 docBuilder.getClassLibrary().addClassLoader(getClass().getClassLoader());
45 }
46
47 public String getClassNameFromSource(String sourceFileName) throws MissingResourceException{
48 if (sourceFileName.startsWith(sourceDir.getPath())) {
49 sourceFileName = sourceFileName.substring(sourceDir.getPath().length() + 1);
50 }
51 String className = sourceFileName.substring(0, sourceFileName.lastIndexOf(".java"));
52 className = className.replace(File.separatorChar, '.');
53 return className;
54 }
55
56 public File getSourceFile(String className){
57 String sourceName = convertClassNameToSourceName(className,true);
58 sourceName = sourceDir.getPath() + File.separator + sourceName;
59 return new File(sourceName);
60 }
61
62 public String convertClassNameToSourceName(String className, boolean appendJava){
63 int index = className.indexOf(".class");
64 String sourceName = className;
65 if (index > -1) {
66 sourceName = sourceName.substring(0,index);
67 }
68 sourceName = sourceName.replace('.',File.separatorChar);
69 if (appendJava) {
70 sourceName += ".java";
71 }
72 return sourceName;
73 }
74
75 public File getSourceDir(){
76 return this.sourceDir;
77 }
78
79 public void setSourceDir(File sourceDir){
80 this.sourceDir = sourceDir;
81 }
82
83 public String getIsA(){
84 return isA;
85 }
86
87 public void setIsA(String isA){
88 this.isA = isA;
89 }
90
91 public FunctionalPoint getFunctionalPointWithClass(String className) throws FileNotFoundException{
92 return getFunctionalPoint(getJavaClassWithClass(className));
93 }
94
95 public FunctionalPoint getFunctionalPointWithSource(File sourceFile) throws FileNotFoundException{
96 return getFunctionalPoint(getJavaClassWithSource(sourceFile));
97 }
98
99 public FunctionalPoint getFunctionalPoint(JavaClass clss){
100 FunctionalPoint fp = null;
101 if ( clss != null && clss.isA(isA)) {
102 fp = new FunctionalPoint();
103 fp.setClassName(clss.getFullyQualifiedName());
104 addClassDocs(fp, clss);
105 addApplications(fp, clss);
106 addSteps(fp, clss);
107 addFields(fp, clss);
108 addMethods(fp, clss);
109 addDocsFromSerializedFP(fp,clss);
110 }
111 return fp;
112 }
113
114 protected FunctionalPoint getFunctionalPointFromSerializedFile(JavaClass clss){
115 String qName = clss.getFullyQualifiedName();
116 FunctionalPoint fp = null;
117 if (serializedFiles.containsKey(qName)) {
118 fp = (FunctionalPoint)serializedFiles.get(qName);
119 } else {
120 String fileName = qName.replace('.', '/')+".dat";
121 InputStream in = getClass().getClassLoader().getResourceAsStream(fileName);
122 if (in != null) {
123 try {
124 fp = (FunctionalPoint) InstanceSerializer.deserialize(in);
125 serializedFiles.put(qName,fp);
126 } catch (IOException ioe) {
127
128 } catch (ClassNotFoundException cnfe) {
129 throw new JameleonException("Can not find FunctionalPoint! "+cnfe);
130 }
131 }
132 }
133 return fp;
134 }
135
136 protected void addDocsFromSerializedFP(FunctionalPoint fp, JavaClass clss){
137 FunctionalPoint serFp;
138 for (JavaClass superClass = clss; superClass != null && superClass.isA(isA); superClass = superClass.getSuperJavaClass()) {
139 serFp = getFunctionalPointFromSerializedFile(superClass);
140 if (serFp != null) {
141 String key;
142 for (Iterator it = serFp.getAttributes().keySet().iterator(); it.hasNext();) {
143 key = (String)it.next();
144 if ( !fp.getAttributes().containsKey(key) ) {
145 fp.addAttribute((Attribute)serFp.getAttributes().get(key));
146 }
147 }
148 }
149 }
150 }
151
152 protected void addClassDocs(FunctionalPoint fp, JavaClass clss) {
153 String comment = clss.getComment();
154 fp.setDescription(comment);
155 fp.setShortDescription(getShortDescription(comment));
156 DocletTag[] tagNames = clss.getTagsByName("jameleon.function");
157 for (int i = 0; i < tagNames.length; i++) {
158 fp.addTagName(convertNullToString(tagNames[i].getNamedParameter("name")));
159 fp.setType(convertNullToString(tagNames[i].getNamedParameter("type")));
160 }
161 DocletTag tag = clss.getTagByName("author");
162 if (tag != null) {
163 fp.setAuthor(convertNullToString(tag.getValue()));
164 }
165 }
166
167 protected String getShortDescription(String description){
168 String desc = description;
169 if (desc != null && desc.trim().length() > 0){
170 desc = description.replaceAll("(?s)^(.+?)[.//n//r]+.*", "$1")+".";
171 }
172 return desc;
173 }
174
175 protected void addApplications(FunctionalPoint fp, JavaClass clss) {
176 DocletTag[] applicationTags = clss.getTagsByName("jameleon.application");
177 for (int i = 0; i < applicationTags.length; i++) {
178 fp.addApplication(convertNullToString(applicationTags[i].getValue()));
179 }
180 }
181
182 protected void addSteps(FunctionalPoint fp, JavaClass clss) {
183 DocletTag[] tags = clss.getTagsByName("jameleon.step");
184 for (int i = 0; i < tags.length; i++) {
185 fp.addStep(convertNullToString(tags[i].getValue()));
186 }
187 }
188
189 protected void addMethods(FunctionalPoint fp, JavaClass clss) {
190 String name, type;
191 JavaMethod[] methods = clss.getMethods(true);
192 Attribute attr;
193 for (int i = 0; i < methods.length; i++) {
194 if (methods[i].isPropertyMutator() && methods[i].getTagByName("jameleon.attribute") != null) {
195 type = getFirstParameterTypeFromJavaMethod(methods[i]);
196 name = methods[i].getPropertyName();
197 if (fp.getAttributes().containsKey(name)) {
198 attr = (Attribute)fp.getAttributes().get(name);
199 fp.addAttribute(createAttributeFromTag(methods[i], name, attr.getType(), attr.getContextName(), false));
200 } else {
201 fp.addAttribute(createAttributeFromTag(methods[i], name, type, "",false));
202 }
203 }
204 }
205 }
206
207 protected void addFields(FunctionalPoint fp, JavaClass clss) {
208 JavaField[] fields = getFields(clss);
209 processAttributes(fields, fp);
210 }
211
212 protected JavaField[] getFields(JavaClass clss) {
213 Set signatures = new HashSet();
214 List fields = new ArrayList();
215 addFieldsFromSuperclassAndInterfaces(signatures, fields, clss);
216 return (JavaField[]) fields.toArray(new JavaField[fields.size()]);
217 }
218
219 protected void addFieldsFromSuperclassAndInterfaces(Set signatures, List fieldList, JavaClass clazz) {
220 JavaField[] fields = clazz.getFields();
221
222 addNewFields(signatures, fieldList, fields);
223
224 JavaClass superclass = clazz.getSuperJavaClass();
225
226
227 if ((superclass != null) && (superclass != clazz)) {
228 addFieldsFromSuperclassAndInterfaces(signatures, fieldList, superclass);
229 }
230
231 JavaClass[] implementz = clazz.getImplementedInterfaces();
232
233 for (int i = 0; i < implementz.length; i++) {
234 if (implementz[i] != null) {
235 addFieldsFromSuperclassAndInterfaces(signatures, fieldList, implementz[i]);
236 }
237 }
238 }
239
240 private void addNewFields(Set signatures, List fieldList, JavaField[] fields) {
241 for (int i = 0; i < fields.length; i++) {
242 String signature = fields[i].getName();
243 if (!signatures.contains(signature)) {
244 fieldList.add(fields[i]);
245 signatures.add(signature);
246 }
247 }
248 }
249
250 private void processAttributes(JavaField[] attributes, FunctionalPoint fp){
251 String name, contextName, type;
252 for (int i = 0; i < attributes.length; i++){
253 if (attributes[i].getTagByName("jameleon.attribute") != null) {
254 contextName = attributes[i].getNamedParameter("jameleon.attribute","contextName");
255 type = attributes[i].getType().getValue();
256 name = attributes[i].getName();
257 fp.addAttribute(createAttributeFromTag(attributes[i], name, type, contextName,true));
258 }
259 }
260 }
261
262 protected Attribute createAttributeFromTag(AbstractJavaEntity aje, String name, String type, String contextName, boolean instanceVariable) {
263 Attribute attr = new Attribute();
264 attr.setName(convertNullToString(name));
265 attr.setContextName(contextName);
266 attr.setType(convertNullToString(type));
267 attr.setDescription(convertNullToString(aje.getComment()));
268 attr.setRequired(Boolean.valueOf(aje.getNamedParameter("jameleon.attribute", "required")).booleanValue());
269
270 attr.setDefaultValue(aje.getNamedParameter("jameleon.attribute","default"));
271 attr.setInstanceVariable(instanceVariable);
272 return attr;
273 }
274
275 public JavaDocBuilder getJavaDocBuilder(){
276 return setUpSourceSet();
277 }
278
279 protected JavaDocBuilder setUpSourceSet(){
280 if (docBuilder == null) {
281 docBuilder = new JavaDocBuilder();
282 docBuilder.getClassLibrary().addClassLoader(getClass().getClassLoader());
283 docBuilder.addSourceTree(sourceDir);
284 }
285 return docBuilder;
286 }
287
288 protected JavaClass getJavaClassWithClass(String className) throws FileNotFoundException{
289 return getJavaClass(className, className);
290 }
291
292 private JavaClass getJavaClass(String className, String resource) throws FileNotFoundException{
293 try {
294 getSourceFile(className);
295 } catch (MissingResourceException mre) {
296 throw new FileNotFoundException("File corresponding to "+resource +" not found");
297 }
298 return getJavaDocBuilder().getClassByName(className);
299 }
300
301 protected JavaClass getJavaClassWithSource(File sourceFile) throws FileNotFoundException{
302 if (!sourceFile.exists()) {
303 throw new FileNotFoundException("File \""+sourceFile.getPath() +"\" not found");
304 }
305 return getJavaDocBuilder().getClassByName(getClassNameFromSource(sourceFile.getPath()));
306 }
307
308 protected String convertNullToString(String str){
309 String rtrStr = "";
310 if (str != null && str.length() > 0) {
311 rtrStr = str;
312 }
313 return rtrStr;
314 }
315
316 /***
317 * XJavadoc only gets the unqualified type of the instance variable, e.g. String not java.lang.String
318 * But on method params, XJavadoc gets the fully qualified name
319 * Since we use both, we want to make it consistent
320 * @param method - the method that represents the attribute
321 * @return the first parameter type as a String, fully qualified.
322 */
323 protected String getFirstParameterTypeFromJavaMethod(JavaMethod method) {
324 String type = "";
325 JavaParameter[] params = method.getParameters();
326 if (params.length > 0) {
327 JavaParameter param = params[0];
328 type = param.getType().getValue();
329 int index = type.indexOf(" ");
330 if (index > -1) {
331 type = type.substring(0, index);
332 }
333 }
334 return type;
335 }
336
337 }
338
339
340