1. /**
  2. * Copyright: Copyright (c) 2002-2004
  3. * Company: JavaResearch(http://www.javaresearch.org)
  4. */
  5. package org.jr.java2html;
  6. import java.io.BufferedReader;
  7. import java.io.Writer;
  8. import java.text.MessageFormat;
  9. import org.jr.text.HTMLStyle;
  10. import org.jr.text.JavaToHTML;
  11. /**
  12. * 将Java源代码转换为相互链接的HTML源代码的工具类。
  13. * <br>最后更新日期:2004年11月30日
  14. * @author cherami@javaresearch.org
  15. * @version 0.9
  16. */
  17. public class LinkableJavaToHTML extends JavaToHTML {
  18. /**
  19. * 一般类缺省的链接风格。
  20. */
  21. protected static final HTMLStyle linkableClassNameStyle = new HTMLStyle(
  22. "<a href=\"{0}\"><font color='#ff0000'><u>", "</u></font></a>");
  23. ClassLink classLink;
  24. String packagePath;
  25. /**
  26. * 根据指定的参数构造一个LinkableJavaToHTML。
  27. * @param classLink 类名链接映射对象
  28. */
  29. public LinkableJavaToHTML(ClassLink classLink) {
  30. this(true,classLink);
  31. }
  32. /**
  33. * 根据指定的参数构造一个LinkableJavaToHTML。
  34. * @param useDefault 是否使用缺省设置
  35. * @param classLink 类名链接映射对象
  36. */
  37. public LinkableJavaToHTML(boolean useDefault,ClassLink classLink) {
  38. super(useDefault);
  39. setClassNameStyle(linkableClassNameStyle);
  40. this.classLink=classLink;
  41. }
  42. /**
  43. * 将单词转换为具有风格的结果。
  44. * 如果是java的保留字,则使用保留字风格;
  45. * 如果是JDK的核心类并且在链接映射里面有对应的映射,则是红色带下划线的黑体链接,否则是红色字体;
  46. * 如果是普通类并且在链接映射里面有对应的映射,则是红色带下划线的链接,否则是红色字体;
  47. * 如果是其他则直接返回。
  48. * @param word 原始的单词
  49. * @return 转换后的结果
  50. */
  51. protected String convertWord(String word) {
  52. if (reservedWords.contains(word)) {
  53. return reservedWordsStyle.getBegin() + word + reservedWordsStyle.getEnd();
  54. }
  55. else {
  56. String classPackage=getPackage();
  57. String link=classLink.getLink(word,packagePath,classPackage,importedClasses);
  58. if (link==null) {
  59. if (classNames.contains(word)) {
  60. return defaultClassNameStyle.getBegin() + word + defaultClassNameStyle.getEnd();
  61. } else {
  62. return word;
  63. }
  64. }
  65. else if (classNames.contains(word)) {
  66. String result=classNameStyle.getBegin() + word + classNameStyle.getEnd();
  67. Object links[] ={link};
  68. return "<b>"+MessageFormat.format(result,links)+"</b>";
  69. }
  70. else {
  71. String result=classNameStyle.getBegin() + word + classNameStyle.getEnd();
  72. Object links[] ={link};
  73. return MessageFormat.format(result,links);
  74. }
  75. }
  76. }
  77. /**
  78. * 将指定的缓冲阅读器中的内容读出进行转换并将转换后的结果写入记录器。
  79. * 之所以需要缓冲阅读器是因为在内部是以行为单位进行处理的。
  80. * @param reader 阅读器
  81. * @param writer 记录器
  82. * @param packagePath 当前解析的源代码的包路径
  83. */
  84. public void convert(BufferedReader reader, Writer writer,String packagePath) {
  85. this.packagePath=packagePath;
  86. convert(reader,writer);
  87. }
  88. /**
  89. * 根据当前行和当前位置得到类名对应的包名
  90. * @return 类的包名或者null
  91. */
  92. private String getPackage() {
  93. if (currentIndex>0) {
  94. char aheadChar=currentLine.charAt(currentIndex-1);
  95. if (aheadChar=='.') {
  96. StringBuffer buffer=new StringBuffer();
  97. buffer.insert(0,aheadChar);
  98. for (int i=currentIndex-2;i>=0;i--) {
  99. aheadChar=currentLine.charAt(i);
  100. if (Character.isJavaIdentifierPart(aheadChar)||aheadChar=='.') {
  101. buffer.insert(0,aheadChar);
  102. } else {
  103. break;
  104. }
  105. }
  106. return buffer.toString().replace('.','/');
  107. } else {
  108. return null;
  109. }
  110. } else {
  111. return null;
  112. }
  113. }
  114. }