| 1 package org.ashkelon; 2 7 8 import java.io.Serializable ; 9 import java.sql.Connection ; 10 import java.sql.PreparedStatement ; 11 import java.sql.ResultSet ; 12 import java.sql.SQLException ; 13 import java.util.ArrayList ; 14 import java.util.Comparator ; 15 import java.util.HashMap ; 16 import java.util.Iterator ; 17 import java.util.LinkedList ; 18 import java.util.List ; 19 import java.util.Map ; 20 21 import org.ashkelon.db.DBMgr; 22 import org.ashkelon.db.DBUtils; 23 import org.ashkelon.db.PKManager; 24 import org.ashkelon.util.JDocUtil; 25 import org.ashkelon.util.Logger; 26 import org.ashkelon.util.StringUtils; 27 import org.ashkelon.util.TreeNode; 28 29 import com.sun.javadoc.ClassDoc; 30 import com.sun.javadoc.ConstructorDoc; 31 import com.sun.javadoc.FieldDoc; 32 import com.sun.javadoc.MethodDoc; 33 34 41 public class ClassType implements Comparator , JDoc, Serializable  42 { 43 private int classType; 44 private String qualifiedName; 45 private String name; 46 private JPackage jPackage; 47 private ClassType superClass; 48 private String superClassName; 49 private boolean isAbstract; 50 private String version; 51 private DocInfo doc; 52 53 private boolean isStatic; 54 private boolean isFinal; 55 private int accessibility; 56 private String modifiers; 57 58 private List authors; 59 private List interfaces; 60 61 private List fields; 62 private List constructors; 63 private List methods; 64 65 private String containingClassName; 66 private ClassType containingClass; 67 private List innerClasses; 68 private API api; 69 70 private int id; 71 private boolean idSet = false; 72 73 private boolean storePackage = false; 74 75 private int level; 78 private static String SEQUENCE = "CLASSTYPE_SEQ"; 79 private static String TABLENAME = "CLASSTYPE"; 80 81 82 public static final int ORDINARY_CLASS = 1; 83 84 public static final int INTERFACE = 2; 85 86 public static final int EXCEPTION_CLASS = 3; 87 88 public static final int ERROR_CLASS = 4; 89 90 public static final String [] CLASSTYPES = {"ordinaryClass", "interface", "exception", "errorClass"}; 91 92 private transient Logger log; 93 94 public ClassType(String qualifiedName) 95 { 96 setQualifiedName(qualifiedName); 97 setName(JDocUtil.unqualify(qualifiedName)); 98 99 setAuthors(new ArrayList ()); 100 setInterfaces(new ArrayList ()); 101 102 setFields(new ArrayList ()); 103 setConstructors(new ArrayList ()); 104 setMethods(new ArrayList ()); 105 106 setSuperClassName(""); 107 108 setContainingClassName(""); 109 setInnerClasses(new ArrayList ()); 110 111 Logger.getInstance().debug("qualified name: "+qualifiedName); 112 113 if (qualifiedName.indexOf(".") > -1) 118 setPackage(new JPackage(qualifiedName.substring(0, qualifiedName.lastIndexOf(".")))); 119 120 setDoc(new DocInfo()); 121 122 log = Logger.getInstance(); 123 } 124 125 public ClassType(ClassDoc classdoc, API api) 126 { 127 this.api = api; 128 setName(classdoc.name()); 129 setQualifiedName(classdoc.qualifiedTypeName()); 130 131 setDoc(new DocInfo(classdoc)); 132 133 ClassDoc superClass = classdoc.superclass(); 134 if (superClass == null) 135 setSuperClassName(""); 136 else 137 setSuperClassName(superClass.qualifiedName()); 138 139 ClassDoc containingClass = classdoc.containingClass(); 140 if (containingClass == null) 141 setContainingClassName(""); 142 else 143 setContainingClassName(containingClass.qualifiedName()); 144 145 146 setAbstract(classdoc.isAbstract()); 147 String version = JDocUtil.getTagText(classdoc.tags("@version")); 148 if (version == null) 149 version = ""; 150 setVersion(version); 151 setClassType(getClassType(classdoc)); 152 153 setStatic(classdoc.isStatic()); 154 setFinal(classdoc.isFinal()); 155 setAccessibility(JDocUtil.getAccessibility(classdoc)); 156 String modifiers = classdoc.modifiers(); 157 if (modifiers.endsWith(" interface")) 158 { 159 modifiers = modifiers.substring(0, modifiers.indexOf(" interface")); 160 } 161 setModifiers(modifiers); 162 163 authors = new ArrayList (); 164 addAuthors(classdoc); 165 166 interfaces = new ArrayList (); 167 addInterfaces(classdoc.interfaces()); 168 169 fields = new ArrayList (); 170 addFields(classdoc.fields()); 171 172 constructors = new ArrayList (); 173 addConstructors(classdoc.constructors()); 174 175 methods = new ArrayList (); 176 addMethods(classdoc.methods()); 177 178 innerClasses = new ArrayList (); 179 addInnerClasses(classdoc.innerClasses()); 180 } 181 182 public ClassType(ClassDoc classdoc, JPackage jp, API api) 183 { 184 this(classdoc, api); 185 if (jp == null) 186 { 187 jp = new JPackage(classdoc.containingPackage(), false, api); 188 storePackage = true; 189 } 190 setPackage(jp); 191 } 192 193 public int getId(Connection conn) throws SQLException  194 { 195 if (!idSet) 196 { 197 id = PKManager.getInstance().nextVal(SEQUENCE); 199 idSet = true; 200 } 201 return id; 202 } 203 204 public int getId() 205 { 206 return id; 207 } 208 209 public void setId(int id) 210 { 211 this.id = id; 212 idSet = true; 213 } 214 215 public void store(Connection conn) throws SQLException  216 { 217 if (storePackage) 218 { 219 getPackage().store(conn); 221 } 222 223 Map fieldInfo = new HashMap (20); 224 fieldInfo.put("ID", new Integer (getId(conn))); 225 fieldInfo.put("TYPE", new Integer (getClassType())); 226 fieldInfo.put("QUALIFIEDNAME", StringUtils.truncate(getQualifiedName(), 150)); 227 fieldInfo.put("NAME", StringUtils.truncate(getName(), 100)); 228 fieldInfo.put("SUPERCLASSNAME", StringUtils.truncate(getSuperClassName(), 150)); 229 230 fieldInfo.put("CONTAININGCLASSNAME", StringUtils.truncate(getContainingClassName(), 150)); 231 232 int boolvalue = isAbstract() ? 1 : 0; 234 fieldInfo.put("ISABSTRACT", new Integer (boolvalue)); 235 236 fieldInfo.put("VERSION", StringUtils.truncate(getVersion(), 100)); 237 fieldInfo.put("DOCID", new Integer (getDoc().getId(conn))); 238 fieldInfo.put("PACKAGEID", new Integer (getPackage().getId(conn))); 239 240 boolvalue = isStatic() ? 1 : 0; 242 fieldInfo.put("ISSTATIC", new Integer (boolvalue)); 243 244 boolvalue = isFinal() ? 1 : 0; 246 fieldInfo.put("ISFINAL", new Integer (boolvalue)); 247 248 fieldInfo.put("ACCESSIBILITY", new Integer (getAccessibility())); 249 fieldInfo.put("MODIFIER", StringUtils.truncate(getModifiers(), 31)); 250 DBUtils.insert(conn, TABLENAME, fieldInfo); 251 252 getDoc().store(conn); 253 254 storeClassAuthors(conn); 255 storeInterfaces(conn); 256 storeSuperClass(conn); 257 258 for (int i=0; i<fields.size(); i++) 259 { 260 ((FieldMember) fields.get(i)).store(conn); 261 } 262 for (int i=0; i<constructors.size(); i++) 263 { 264 ((ConstructorMember) constructors.get(i)).store(conn); 265 } 266 for (int i=0; i<methods.size(); i++) 267 { 268 ((MethodMember) methods.get(i)).store(conn); 269 } 270 271 for (int i=0; i<innerClasses.size(); i++) 272 { 273 ((ClassType) innerClasses.get(i)).store(conn); 274 } 275 } 276 277 public void storeClassAuthors(Connection conn) throws SQLException  278 { 279 Map fieldInfo = new HashMap (5); 280 fieldInfo.put("CLASSID", new Integer (getId(conn))); 281 Author author = null; 282 for (int i=0; i<authors.size(); i++) 283 { 284 author = (Author) authors.get(i); 285 author.store(conn); 286 287 fieldInfo.put("AUTHORID", new Integer (author.getId(conn))); 288 DBUtils.insert(conn, "CLASS_AUTHOR", fieldInfo); 289 } 290 } 291 292 public void storeInterfaces(Connection conn) throws SQLException  293 { 294 Map fieldInfo = new HashMap (5); 295 fieldInfo.put("CLASSID", new Integer (getId(conn))); 296 String interface_name = ""; 297 for (int i=0; i<interfaces.size(); i++) 298 { 299 interface_name = ((ClassType) interfaces.get(i)).getQualifiedName(); 300 fieldInfo.put("NAME", StringUtils.truncate(interface_name, 150)); 301 DBUtils.insert(conn, "IMPL_INTERFACE", fieldInfo); 302 } 303 } 304 305 public void storeSuperClass(Connection conn) throws SQLException  306 { 307 if (StringUtils.isBlank(getSuperClassName())) 308 return; 309 Map fieldInfo = new HashMap (3); 310 fieldInfo.put("CLASSID", new Integer (getId(conn))); 311 fieldInfo.put("NAME", StringUtils.truncate(getSuperClassName(), 150)); 312 DBUtils.insert(conn, "SUPERCLASS", fieldInfo); 313 } 314 315 316 320 public static boolean delete(Connection conn, String className) throws SQLException  321 { 322 String sql = DBMgr.getInstance().getStatement("getclsanddocid"); 324 325 PreparedStatement pstmt = conn.prepareStatement(sql); 326 pstmt.setString(1, className); 327 ResultSet rset = pstmt.executeQuery(); 328 329 if (!rset.next()) 330 return false; 331 332 int classid = rset.getInt(1); 333 int classdocid = rset.getInt(2); 334 rset.close(); 335 pstmt.close(); 336 337 deleteInnerClasses(conn, className); 338 339 delete(conn, classid, classdocid); 340 return true; 341 } 342 343 public static void delete(Connection conn, int classid, int class_docid) throws SQLException  344 { 345 deleteFields(conn, classid); 346 deleteMethods(conn, classid); 347 deleteConstructors(conn, classid); 348 349 deleteInterfaces(conn, classid); 350 deleteSuperClass(conn, classid); 351 deleteClassAuthors(conn, classid); 352 353 DocInfo.delete(conn, class_docid); 354 355 String [][] params = {{"IMPL_INTERFACE", "interfaceid"}, 357 {"SUPERCLASS", "superclassid"}, 358 {"FIELD", "typeid"}, 359 {"METHOD", "returntypeid"}, 360 {"THROWNEXCEPTION", "exceptionid"}, 361 {"PARAMETER", "typeid"}, 362 {"REFERENCE", "refdoc_id"}}; 363 364 String sql = ""; 365 PreparedStatement pstmt; 366 for (int i=0; i<params.length; i++) 367 { 368 sql = "update " + params[i][0] + " set " + params[i][1] + " = null where " + params[i][1] + " = ?"; 369 Logger.getInstance().debug(sql); 370 pstmt = conn.prepareStatement(sql); 371 pstmt.setInt(1, classid); 372 pstmt.executeUpdate(); 373 pstmt.close(); 374 } 375 376 HashMap constraint = new HashMap (); 378 constraint.put("ID", new Integer (classid)); 379 DBUtils.delete(conn, TABLENAME, constraint); 380 } 381 382 public static void deleteFields(Connection conn, int classid) throws SQLException  383 { 384 String sql = DBMgr.getInstance().getStatement("getfieldanddocid"); 385 386 PreparedStatement pstmt = conn.prepareStatement(sql); 387 pstmt.setInt(1, classid); 388 ResultSet rset = pstmt.executeQuery(); 389 390 while (rset.next()) 391 { 392 FieldMember.delete(conn, rset.getInt(1), rset.getInt(2)); 393 } 394 395 rset.close(); 396 pstmt.close(); 397 } 398 399 public static void deleteMethods(Connection conn, int classid) throws SQLException  400 { 401 String sql = DBMgr.getInstance().getStatement("getmethodanddocid"); 402 403 PreparedStatement pstmt = conn.prepareStatement(sql); 404 pstmt.setInt(1, classid); 405 ResultSet rset = pstmt.executeQuery(); 406 407 while (rset.next()) 408 { 409 MethodMember.delete(conn, rset.getInt(1), rset.getInt(2)); 410 } 411 412 rset.close(); 413 pstmt.close(); 414 } 415 416 public static void deleteConstructors(Connection conn, int classid) throws SQLException  417 { 418 String sql = DBMgr.getInstance().getStatement("getconstranddocid"); 419 420 PreparedStatement pstmt = conn.prepareStatement(sql); 421 pstmt.setInt(1, classid); 422 ResultSet rset = pstmt.executeQuery(); 423 424 while (rset.next()) 425 { 426 ConstructorMember.delete(conn, rset.getInt(1), rset.getInt(2)); 427 } 428 429 rset.close(); 430 pstmt.close(); 431 } 432 433 public static void deleteClassAuthors(Connection conn, int classid) throws SQLException  434 { 435 String sql = DBMgr.getInstance().getStatement("deleteclassauthor"); 436 PreparedStatement pstmt = conn.prepareStatement(sql); 437 pstmt.setInt(1, classid); 438 pstmt.executeUpdate(); 439 pstmt.close(); 440 } 441 442 public static void deleteInterfaces(Connection conn, int classid) throws SQLException  443 { 444 String sql = DBMgr.getInstance().getStatement("deleteinterfaces"); 445 PreparedStatement pstmt = conn.prepareStatement(sql); 446 pstmt.setInt(1, classid); 447 pstmt.executeUpdate(); 448 pstmt.close(); 449 } 450 451 public static void deleteSuperClass(Connection conn, int classid) throws SQLException  452 { 453 String sql = DBMgr.getInstance().getStatement("deletesuperclass"); 454 PreparedStatement pstmt = conn.prepareStatement(sql); 455 pstmt.setInt(1, classid); 456 pstmt.executeUpdate(); 457 pstmt.close(); 458 } 459 460 public static void deleteInnerClasses(Connection conn, String containingClassName) throws SQLException  461 { 462 String sql = DBMgr.getInstance().getStatement("deleteinnercls"); 463 PreparedStatement pstmt = conn.prepareStatement(sql); 464 pstmt.setString(1, containingClassName); 465 pstmt.executeUpdate(); 466 pstmt.close(); 467 } 468 469 470 public boolean isInterface() 471 { 472 return (getClassType() == INTERFACE); 473 } 474 public boolean isClass() 475 { 476 return (getClassType() == ORDINARY_CLASS); 477 } 478 public boolean isException() 479 { 480 return (getClassType() == EXCEPTION_CLASS); 481 } 482 public boolean isError() 483 { 484 return (getClassType() == ERROR_CLASS); 485 } 486 487 public boolean isInnerClass() 488 { 489 return !StringUtils.isBlank(getContainingClassName()); 490 } 491 492 493 public int getClassType() { return classType; } 495 public void setClassType(int classType) { this.classType = classType; } 496 497 public String getClassTypeName() 498 { 499 int clsType = getClassType(); 500 if (clsType > CLASSTYPES.length || clsType <= 0) 501 { 502 return "unknown"; 503 } 504 return CLASSTYPES[clsType-1]; 505 } 506 507 public String getQualifiedName() { return qualifiedName; } 508 public void setQualifiedName(String qualifiedName) 509 { 510 this.qualifiedName = StringUtils.avoidNull(qualifiedName); 512 } 513 514 public String getName() { return name; } 516 public void setName(String name) 517 { 518 this.name = StringUtils.avoidNull(name); 519 } 520 521 public DocInfo getDoc() { return doc; } 522 public void setDoc(DocInfo doc) { this.doc = doc; } 523 524 public JPackage getPackage() { return jPackage; } 525 public void setPackage(JPackage jPackage) { this.jPackage = jPackage; } 526 527 public ClassType getSuperClass() { return superClass; } 528 public void setSuperClass(ClassType superClass) { this.superClass = superClass; } 529 530 531 public String getSuperClassName() { return superClassName; } 532 public void setSuperClassName(String superClassName) 533 { 534 this.superClassName = StringUtils.avoidNull(superClassName); 535 } 536 537 public String getContainingClassName() { return containingClassName; } 538 public void setContainingClassName(String containingClassName) 539 { 540 this.containingClassName = StringUtils.avoidNull(containingClassName); 541 } 542 543 public ClassType getContainingClass() { return containingClass; } 544 public void setContainingClass(ClassType containingClass) { this.containingClass = containingClass; } 545 546 547 public boolean isAbstract() { return isAbstract; } 548 public void setAbstract(boolean isAbstract) { this.isAbstract = isAbstract; } 549 550 public String getVersion() { return version; } 551 public void setVersion(String version) 552 { 553 this.version = StringUtils.avoidNull(version); 554 } 555 556 public boolean isStatic() { return isStatic; } 557 public void setStatic(boolean isStatic) { this.isStatic = isStatic; } 558 559 public boolean isFinal() { return isFinal; } 560 public void setFinal(boolean isFinal) { this.isFinal = isFinal; } 561 562 public int getAccessibility() { return accessibility; } 563 public void setAccessibility(int accessibility) { this.accessibility = accessibility; } 564 565 public String getModifiers() { return modifiers; } 566 public void setModifiers(String modifiers) { this.modifiers = modifiers; } 567 568 public void addAuthors(ClassDoc classdoc) 569 { 570 String [] names = JDocUtil.getTagList(classdoc.tags("@author")); 571 addAuthors(names); 572 } 573 574 public void addAuthors(String [] names) 575 { 576 for (int i=0; i<names.length; i++) 578 { 579 addAuthor(names[i]); 580 } 581 } 582 583 public void addAuthor(String authorName) 584 { 585 addAuthor(new Author(authorName)); 586 } 587 588 public void addAuthor(Author author) 589 { 590 authors.add(author); 591 author.addClass(this); 592 } 593 594 public List getAuthors() { return authors; } 595 public void setAuthors(List authors) { this.authors = authors; } 596 597 598 public void addInterfaces(ClassDoc[] impl_interfaces) 599 { 600 for (int i=0; i<impl_interfaces.length; i++) 601 { 602 addInterface(impl_interfaces[i].qualifiedName()); 603 } 604 } 605 606 public void addInterface(String qualifiedName) 607 { 608 if (StringUtils.isBlank(qualifiedName)) return; 609 interfaces.add(new ClassType(qualifiedName)); 610 } 611 612 public List getInterfaces() { return interfaces; } 613 public void setInterfaces(List interfaces) { this.interfaces = interfaces; } 614 615 616 public void addFields(FieldDoc[] fielddocs) 617 { 618 for (int i=0; i<fielddocs.length; i++) 620 { 621 addField(new FieldMember(fielddocs[i], this)); 622 } 623 } 624 625 public void addField(FieldMember fldMember) 626 { 627 fields.add(fldMember); 628 } 629 630 public void addConstructors(ConstructorDoc[] constructordocs) 631 { 632 for (int i=0; i<constructordocs.length; i++) 634 { 635 addConstructor(new ConstructorMember(constructordocs[i], this)); 636 } 637 } 638 639 public void addConstructor(ConstructorMember constr) 640 { 641 constructors.add(constr); 642 } 643 644 public void addMethods(MethodDoc[] methoddocs) 645 { 646 for (int i=0; i<methoddocs.length; i++) 648 { 649 addMethod(new MethodMember(methoddocs[i], this)); 650 } 651 } 652 653 public void addMethod(MethodMember method) 654 { 655 methods.add(method); 656 } 657 658 public List getFields() { return fields; } 659 public void setFields(List fields) { this.fields = fields; } 660 661 public List getConstructors() { return constructors; } 662 public void setConstructors(List constructors) { this.constructors = constructors; } 663 664 public List getMethods() { return methods; } 665 public void setMethods(List methods) { this.methods = methods; } 666 667 public boolean hasFields() { return !fields.isEmpty(); } 668 public boolean hasConstructors() { return !constructors.isEmpty(); } 669 public boolean hasMethods() { return !methods.isEmpty(); } 670 671 public boolean hasInnerClasses() { return !innerClasses.isEmpty(); } 672 673 public int getLevel() { return level; } 674 public void setLevel(int level) { this.level = level; } 675 676 677 public void addInnerClass(ClassType innerClass) 678 { 679 innerClasses.add(innerClass); 680 } 681 682 public void addInnerClasses(ClassDoc[] innerClasses) 683 { 684 for (int i=0; i<innerClasses.length; i++) 685 { 686 addInnerClass(new ClassType(innerClasses[i], getPackage(), (api==null) ? getAPI() : api)); 687 } 688 } 689 690 public List getInnerClasses() { return innerClasses; } 691 public void setInnerClasses(List innerClasses) { this.innerClasses = innerClasses; } 692 693 694 697 public static int getClassType(ClassDoc classdoc) 698 { 699 if (classdoc.isOrdinaryClass()) 700 { 701 return ORDINARY_CLASS; 702 } 703 else if (classdoc.isError()) 704 { 705 return ERROR_CLASS; 706 } 707 else if (classdoc.isException()) 708 { 709 return EXCEPTION_CLASS; 710 } 711 else if (classdoc.isInterface()) 712 { 713 return INTERFACE; 714 } 715 else 716 { 717 return JDocUtil.UNKNOWN_TYPE; 719 } 720 } 721 722 private List getDescendentList(Connection conn) throws SQLException  723 { 724 String sql = DBMgr.getInstance().getStatement("getdescendents"); 725 726 PreparedStatement pstmt = conn.prepareStatement(sql); 727 pstmt.setInt(1, getId()); 728 ResultSet rset = pstmt.executeQuery(); 729 730 List classes = new ArrayList (); 731 732 ClassType c; 733 while(rset.next()) 734 { 735 c = new ClassType(rset.getString(2)); 736 c.setId(rset.getInt(1)); 737 c.setSuperClassName(rset.getString(3)); 738 c.setClassType(rset.getInt(4)); 739 c.getDoc().setSummaryDescription(rset.getString(5)); 740 classes.add(c); 741 log.debug(c.getQualifiedName()); 742 } 743 744 return classes; 745 } 746 747 public TreeNode getSuperclassesConstrained(Connection conn, ClassType root) throws SQLException  748 { 749 TreeNode rootnode = getSuperclasses(conn); 750 if (root.getQualifiedName().equals("java.lang.Object")) 751 return rootnode; 752 753 TreeNode childnode = rootnode.getOnlyChild(); 754 while (((ClassType) childnode.getValue()).getId() != root.getId()) 755 childnode = childnode.getOnlyChild(); 756 757 return childnode.getOnlyChild(); 758 } 759 760 public TreeNode getDescendents(Connection conn) throws SQLException  761 { 762 if (DBMgr.getInstance().getDbtype().equals("oracle")) 763 { 764 return getDescendentsOra(conn); 765 } 766 767 List descendents = getDescendentList(conn); 768 769 List clstreelist = new ArrayList (); 770 ClassType c; 771 772 for (int i=0; i<descendents.size(); i++) 773 { 774 c = (ClassType) descendents.get(i); 775 777 TreeNode clstree = c.getSuperclassesConstrained(conn, this); 778 779 clstreelist.add(clstree); 781 } 782 783 log.debug(clstreelist.size()+" little trees to merge"); 784 785 TreeNode clsNode = new TreeNode(this); 786 TreeNode clstree; 787 788 for (int i=0; i<clstreelist.size(); i++) 789 { 790 clstree = (TreeNode) clstreelist.get(i); 791 793 String key = ((ClassType) clstree.getValue()).getQualifiedName(); 794 796 TreeNode node = clsNode; 797 TreeNode targetnode = clstree; 798 String targetkey = key; 799 800 while(node.getChild(targetkey)!=null) 801 { 802 node = node.getChild(targetkey); 804 targetnode = targetnode.getOnlyChild(); 805 if (targetnode == null) 806 { 807 continue; 808 } 809 targetkey = ((ClassType) targetnode.getValue()).getQualifiedName(); 810 } 811 if (targetnode == null) 812 { 813 continue; 814 } 815 816 820 node.addChild(targetkey, targetnode); 821 822 |