| 1 | |
package com.thoughtworks.qdox.model; |
| 2 | |
|
| 3 | |
import java.util.ArrayList; |
| 4 | |
import java.util.HashMap; |
| 5 | |
import java.util.Iterator; |
| 6 | |
import java.util.LinkedList; |
| 7 | |
import java.util.List; |
| 8 | |
import java.util.Map; |
| 9 | |
import java.util.Set; |
| 10 | |
|
| 11 | |
import com.thoughtworks.qdox.parser.Builder; |
| 12 | |
import com.thoughtworks.qdox.parser.structs.AnnoDef; |
| 13 | |
import com.thoughtworks.qdox.parser.structs.ClassDef; |
| 14 | |
import com.thoughtworks.qdox.parser.structs.FieldDef; |
| 15 | |
import com.thoughtworks.qdox.parser.structs.MethodDef; |
| 16 | |
import com.thoughtworks.qdox.parser.structs.TagDef; |
| 17 | |
|
| 18 | |
|
| 19 | |
|
| 20 | |
|
| 21 | |
public class ModelBuilder implements Builder { |
| 22 | |
|
| 23 | |
private final ClassLibrary classLibrary; |
| 24 | |
private final JavaSource source; |
| 25 | |
private JavaClassParent currentParent; |
| 26 | |
private JavaClass currentClass; |
| 27 | |
private List currentAnnoDefs; |
| 28 | |
private String lastComment; |
| 29 | |
private List lastTagSet; |
| 30 | |
private DocletTagFactory docletTagFactory; |
| 31 | |
|
| 32 | |
public ModelBuilder() { |
| 33 | 46 | this(new ClassLibrary(null), new DefaultDocletTagFactory()); |
| 34 | 46 | } |
| 35 | |
|
| 36 | 314 | public ModelBuilder(ClassLibrary classLibrary, DocletTagFactory docletTagFactory) { |
| 37 | 314 | this.classLibrary = classLibrary; |
| 38 | 314 | this.docletTagFactory = docletTagFactory; |
| 39 | 314 | source = new JavaSource(); |
| 40 | 314 | source.setClassLibrary(classLibrary); |
| 41 | 314 | currentParent = source; |
| 42 | 314 | currentAnnoDefs = new ArrayList(); |
| 43 | 314 | } |
| 44 | |
|
| 45 | |
public void addPackage(String packageName) { |
| 46 | 206 | source.setPackage(packageName); |
| 47 | 206 | } |
| 48 | |
|
| 49 | |
public void addImport(String importName) { |
| 50 | 207 | source.addImport(importName); |
| 51 | 207 | } |
| 52 | |
|
| 53 | |
public void addJavaDoc(String text) { |
| 54 | 117 | lastComment = text; |
| 55 | 117 | lastTagSet = new LinkedList(); |
| 56 | 117 | } |
| 57 | |
|
| 58 | |
public void addJavaDocTag(TagDef tagDef) { |
| 59 | 121 | lastTagSet.add(tagDef); |
| 60 | 121 | } |
| 61 | |
|
| 62 | |
public void beginClass(ClassDef def) { |
| 63 | 337 | currentClass = new JavaClass(); |
| 64 | 337 | currentClass.setParent(currentParent); |
| 65 | 337 | currentClass.setLineNumber(def.lineNumber); |
| 66 | |
|
| 67 | |
|
| 68 | 337 | currentClass.setName(def.name); |
| 69 | 337 | currentClass.setInterface(ClassDef.INTERFACE.equals(def.type)); |
| 70 | 337 | currentClass.setEnum(ClassDef.ENUM.equals(def.type)); |
| 71 | 337 | currentClass.setAnnotation(ClassDef.ANNOTATION_TYPE.equals(def.type)); |
| 72 | |
|
| 73 | |
|
| 74 | |
|
| 75 | 337 | if (currentClass.isInterface()) { |
| 76 | 53 | currentClass.setSuperClass(null); |
| 77 | 53 | } else if (!currentClass.isEnum()) { |
| 78 | 275 | currentClass.setSuperClass(def.extendz.size() > 0 ? createType((String) def.extendz.toArray()[0], 0) : null); |
| 79 | |
} |
| 80 | |
|
| 81 | |
|
| 82 | |
{ |
| 83 | 337 | Set implementSet = currentClass.isInterface() ? def.extendz : def.implementz; |
| 84 | 337 | Iterator implementIt = implementSet.iterator(); |
| 85 | 337 | Type[] implementz = new Type[implementSet.size()]; |
| 86 | 418 | for (int i = 0; i < implementz.length && implementIt.hasNext(); i++) { |
| 87 | 81 | implementz[i] = createType((String) implementIt.next(), 0); |
| 88 | |
} |
| 89 | 337 | currentClass.setImplementz(implementz); |
| 90 | |
} |
| 91 | |
|
| 92 | |
|
| 93 | |
{ |
| 94 | 337 | String[] modifiers = new String[def.modifiers.size()]; |
| 95 | 337 | def.modifiers.toArray(modifiers); |
| 96 | 337 | currentClass.setModifiers(modifiers); |
| 97 | |
} |
| 98 | |
|
| 99 | |
|
| 100 | 337 | addJavaDoc(currentClass); |
| 101 | |
|
| 102 | |
|
| 103 | |
|
| 104 | |
|
| 105 | |
|
| 106 | |
|
| 107 | |
|
| 108 | |
|
| 109 | 337 | setAnnotations( currentClass ); |
| 110 | |
|
| 111 | 337 | currentParent.addClass(currentClass); |
| 112 | 337 | currentParent = currentClass; |
| 113 | 337 | classLibrary.add(currentClass.getFullyQualifiedName()); |
| 114 | 337 | } |
| 115 | |
|
| 116 | |
public void endClass() { |
| 117 | 337 | currentParent = currentClass.getParent(); |
| 118 | 337 | if (currentParent instanceof JavaClass) { |
| 119 | 12 | currentClass = (JavaClass) currentParent; |
| 120 | 12 | } else { |
| 121 | 325 | currentClass = null; |
| 122 | |
} |
| 123 | 337 | } |
| 124 | |
|
| 125 | |
private Type createType(String typeName, int dimensions) { |
| 126 | 3341 | if (typeName == null || typeName.equals("")) return null; |
| 127 | 3170 | return Type.createUnresolved(typeName, dimensions, currentClass); |
| 128 | |
} |
| 129 | |
|
| 130 | |
private void addJavaDoc(AbstractJavaEntity entity) { |
| 131 | 2242 | if (lastComment == null) return; |
| 132 | |
|
| 133 | 117 | entity.setComment(lastComment); |
| 134 | |
|
| 135 | 117 | Iterator tagDefIterator = lastTagSet.iterator(); |
| 136 | 117 | List tagList = new ArrayList(); |
| 137 | 238 | while (tagDefIterator.hasNext()) { |
| 138 | 121 | TagDef tagDef = (TagDef) tagDefIterator.next(); |
| 139 | 121 | tagList.add( |
| 140 | |
docletTagFactory.createDocletTag( |
| 141 | |
tagDef.name, tagDef.text, |
| 142 | |
entity, tagDef.lineNumber |
| 143 | |
) |
| 144 | |
); |
| 145 | 121 | } |
| 146 | 117 | entity.setTags(tagList); |
| 147 | |
|
| 148 | 117 | lastComment = null; |
| 149 | 117 | } |
| 150 | |
|
| 151 | |
public void addMethod(MethodDef def) { |
| 152 | 1727 | JavaMethod currentMethod = new JavaMethod(); |
| 153 | 1727 | currentMethod.setParentClass(currentClass); |
| 154 | 1727 | currentMethod.setLineNumber(def.lineNumber); |
| 155 | |
|
| 156 | |
|
| 157 | 1727 | currentMethod.setName(def.name); |
| 158 | 1727 | currentMethod.setReturns(createType(def.returns, def.dimensions)); |
| 159 | 1727 | currentMethod.setConstructor(def.constructor); |
| 160 | |
|
| 161 | |
|
| 162 | |
{ |
| 163 | 1727 | JavaParameter[] params = new JavaParameter[def.params.size()]; |
| 164 | 1727 | int i = 0; |
| 165 | 1727 | for (Iterator iterator = def.params.iterator(); iterator.hasNext();) { |
| 166 | 1007 | FieldDef fieldDef = (FieldDef) iterator.next(); |
| 167 | 1007 | params[i++] = new JavaParameter(createType(fieldDef.type, fieldDef.dimensions), fieldDef.name, fieldDef.isVarArgs); |
| 168 | 1007 | } |
| 169 | 1727 | currentMethod.setParameters(params); |
| 170 | |
} |
| 171 | |
|
| 172 | |
|
| 173 | |
{ |
| 174 | 1727 | Type[] exceptions = new Type[def.exceptions.size()]; |
| 175 | 1727 | int index = 0; |
| 176 | 1727 | for (Iterator iter = def.exceptions.iterator(); iter.hasNext();) { |
| 177 | 282 | exceptions[index++] = createType((String) iter.next(), 0); |
| 178 | 282 | } |
| 179 | 1727 | currentMethod.setExceptions(exceptions); |
| 180 | |
} |
| 181 | |
|
| 182 | |
|
| 183 | |
{ |
| 184 | 1727 | String[] modifiers = new String[def.modifiers.size()]; |
| 185 | 1727 | def.modifiers.toArray(modifiers); |
| 186 | 1727 | currentMethod.setModifiers(modifiers); |
| 187 | |
} |
| 188 | |
|
| 189 | 1727 | currentMethod.setSourceCode(def.body); |
| 190 | |
|
| 191 | |
|
| 192 | 1727 | addJavaDoc(currentMethod); |
| 193 | |
|
| 194 | |
|
| 195 | 1727 | setAnnotations( currentMethod ); |
| 196 | |
|
| 197 | 1727 | currentClass.addMethod(currentMethod); |
| 198 | 1727 | } |
| 199 | |
|
| 200 | |
public void addField(FieldDef def) { |
| 201 | 178 | JavaField currentField = new JavaField(); |
| 202 | 178 | currentField.setParent(currentClass); |
| 203 | 178 | currentField.setLineNumber(def.lineNumber); |
| 204 | |
|
| 205 | 178 | currentField.setName(def.name); |
| 206 | 178 | currentField.setType(createType(def.type, def.dimensions)); |
| 207 | |
|
| 208 | |
|
| 209 | |
{ |
| 210 | 178 | String[] modifiers = new String[def.modifiers.size()]; |
| 211 | 178 | def.modifiers.toArray(modifiers); |
| 212 | 178 | currentField.setModifiers(modifiers); |
| 213 | |
} |
| 214 | |
|
| 215 | |
|
| 216 | 178 | currentField.setInitializationExpression(def.body); |
| 217 | |
|
| 218 | |
|
| 219 | 178 | addJavaDoc(currentField); |
| 220 | |
|
| 221 | |
|
| 222 | 178 | setAnnotations( currentField ); |
| 223 | |
|
| 224 | 178 | currentClass.addField(currentField); |
| 225 | 178 | } |
| 226 | |
|
| 227 | |
private void setAnnotations( AbstractJavaEntity entity ) { |
| 228 | 2242 | if( !currentAnnoDefs.isEmpty() ) { |
| 229 | 17 | Annotation[] annotations = new Annotation[currentAnnoDefs.size()]; |
| 230 | 17 | int index = 0; |
| 231 | 17 | for (Iterator iter = currentAnnoDefs.iterator(); iter.hasNext();) { |
| 232 | 21 | AnnoDef def = (AnnoDef)iter.next(); |
| 233 | 21 | annotations[index++] = buildAnnotation( def, entity ); |
| 234 | 21 | } |
| 235 | |
|
| 236 | 17 | entity.setAnnotations( annotations ); |
| 237 | 17 | currentAnnoDefs.clear(); |
| 238 | |
} |
| 239 | 2242 | } |
| 240 | |
|
| 241 | |
private Annotation buildAnnotation( AnnoDef def, AbstractJavaEntity entity ) { |
| 242 | 24 | Type annoType = createType(def.name, 0); |
| 243 | |
|
| 244 | 24 | Map args = new HashMap(); |
| 245 | 24 | for (Iterator iter = def.args.entrySet().iterator(); iter.hasNext();) { |
| 246 | 21 | Map.Entry entry = (Map.Entry)iter.next(); |
| 247 | 21 | Object value = entry.getValue(); |
| 248 | |
|
| 249 | 21 | if( value instanceof AnnoDef ) { |
| 250 | 3 | args.put( entry.getKey(), buildAnnotation( (AnnoDef)value, entity ) ); |
| 251 | 3 | } |
| 252 | 18 | else if( value instanceof List ) { |
| 253 | 18 | List values = (List)value; |
| 254 | 18 | if( values.size() == 1 ) { |
| 255 | |
|
| 256 | 14 | args.put( entry.getKey(), values.get( 0 ) ); |
| 257 | 14 | } |
| 258 | |
else { |
| 259 | 4 | args.put( entry.getKey(), values ); |
| 260 | |
} |
| 261 | |
} |
| 262 | 21 | } |
| 263 | |
|
| 264 | 24 | Annotation anno = new Annotation( annoType, entity, args, def.lineNumber ); |
| 265 | 24 | return anno; |
| 266 | |
} |
| 267 | |
|
| 268 | |
|
| 269 | |
|
| 270 | |
public void addAnnotation( AnnoDef def ) { |
| 271 | 22 | currentAnnoDefs.add( def ); |
| 272 | 22 | } |
| 273 | |
|
| 274 | |
public JavaSource getSource() { |
| 275 | 313 | return source; |
| 276 | |
} |
| 277 | |
|
| 278 | |
} |