You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

HtmlDecorator.java 38KB

4 yıl önce
4 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
4 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
4 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
4 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
4 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
4 yıl önce
15 yıl önce
15 yıl önce
4 yıl önce
4 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
15 yıl önce
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. /* *******************************************************************
  2. * Copyright (c) 1999-2001 Xerox Corporation,
  3. * 2002 Palo Alto Research Center, Incorporated (PARC).
  4. * All rights reserved.
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Public License v1.0
  7. * which accompanies this distribution and is available at
  8. * http://www.eclipse.org/legal/epl-v10.html
  9. *
  10. * Contributors:
  11. * Xerox/PARC initial implementation
  12. * Mik Kersten port to AspectJ 1.1+ code base
  13. * ******************************************************************/
  14. package org.aspectj.tools.ajdoc;
  15. import java.io.BufferedReader;
  16. import java.io.DataInputStream;
  17. import java.io.File;
  18. import java.io.FileOutputStream;
  19. import java.io.FileReader;
  20. import java.io.IOException;
  21. import java.io.StringReader;
  22. import java.util.ArrayList;
  23. import java.util.Hashtable;
  24. import java.util.Iterator;
  25. import java.util.List;
  26. import java.util.StringTokenizer;
  27. import org.aspectj.asm.AsmManager;
  28. import org.aspectj.asm.HierarchyWalker;
  29. import org.aspectj.asm.IProgramElement;
  30. import org.aspectj.asm.IRelationship;
  31. import org.aspectj.util.TypeSafeEnum;
  32. /**
  33. * @author Mik Kersten
  34. */
  35. class HtmlDecorator {
  36. private static final String POINTCUT_DETAIL = "Pointcut Detail";
  37. private static final String ADVICE_DETAIL = "Advice Detail";
  38. private static final String DECLARE_DETAIL = "Declare Detail";
  39. private static final String ADVICE_SUMMARY = "Advice Summary";
  40. private static final String POINTCUT_SUMMARY = "Pointcut Summary";
  41. private static final String DECLARE_SUMMARY = "Declare Summary";
  42. private static final String ITD_METHOD_SUMMARY = "Inter-Type Method Summary";
  43. private static final String ITD_FIELD_SUMMARY = "Inter-Type Field Summary";
  44. private static final String ITD_CONSTRUCTOR_SUMMARY = "Inter-Type Constructor Summary";
  45. static List<String> visibleFileList = new ArrayList<String>();
  46. static Hashtable declIDTable = null;
  47. static File rootDir = null;
  48. static String docVisibilityModifier;
  49. static void decorateHTMLFromInputFiles(AsmManager model, Hashtable table, File newRootDir, File[] inputFiles, String docModifier)
  50. throws IOException {
  51. rootDir = newRootDir;
  52. declIDTable = table;
  53. docVisibilityModifier = docModifier;
  54. for (File inputFile : inputFiles) {
  55. decorateHTMLFromIPEs(getProgramElements(model, inputFile.getCanonicalPath()), rootDir.getCanonicalPath()
  56. + Config.DIR_SEP_CHAR, docModifier, false);
  57. }
  58. }
  59. static void decorateHTMLFromIPEs(IProgramElement[] decls, String base, String docModifier, boolean exceededNestingLevel)
  60. throws IOException {
  61. if (decls != null) {
  62. for (IProgramElement decl : decls) {
  63. decorateHTMLFromIPE(decl, base, docModifier, exceededNestingLevel);
  64. }
  65. }
  66. }
  67. /**
  68. * Before attempting to decorate the HTML file we have to verify that it exists, which depends on the documentation visibility
  69. * specified to c.
  70. *
  71. * Depending on docModifier, can document - public: only public - protected: protected and public (default) - package: package
  72. * protected and public - private: everything
  73. */
  74. static void decorateHTMLFromIPE(IProgramElement decl, String base, String docModifier, boolean exceededNestingLevel)
  75. throws IOException {
  76. boolean nestedClass = false;
  77. if (decl.getKind().isType()) {
  78. boolean decorateFile = true;
  79. if (isAboveVisibility(decl)) {
  80. visibleFileList.add(decl.toSignatureString());
  81. String packageName = decl.getPackageName();
  82. String filename = "";
  83. if (packageName != null) {
  84. int index1 = base.lastIndexOf(Config.DIR_SEP_CHAR);
  85. int index2 = base.lastIndexOf(".");
  86. String currFileClass = "";
  87. if (index1 > -1 && index2 > 0 && index1 < index2) {
  88. currFileClass = base.substring(index1 + 1, index2);
  89. }
  90. // XXX only one level of nexting
  91. if (currFileClass.equals(decl.getDeclaringType())) {
  92. nestedClass = true;
  93. packageName = packageName.replace('.', '/');
  94. String newBase = "";
  95. if (base.lastIndexOf(Config.DIR_SEP_CHAR) > 0) {
  96. newBase = base.substring(0, base.lastIndexOf(Config.DIR_SEP_CHAR));
  97. }
  98. String signature = constructNestedTypeName(decl);
  99. filename = newBase + Config.DIR_SEP_CHAR + packageName + Config.DIR_SEP_CHAR + currFileClass + // "." +
  100. signature + ".html";
  101. } else {
  102. packageName = packageName.replace('.', '/');
  103. filename = base + packageName + Config.DIR_SEP_CHAR + decl.toSignatureString() + ".html";
  104. }
  105. } else {
  106. filename = base + decl.toSignatureString() + ".html";
  107. }
  108. if (!exceededNestingLevel) {
  109. decorateHTMLFile(new File(filename));
  110. } else {
  111. System.out.println("Warning: can not generate documentation for nested " + "inner class: "
  112. + decl.toSignatureString());
  113. }
  114. }
  115. }
  116. }
  117. private static String constructNestedTypeName(IProgramElement node) {
  118. if (node.getParent().getKind().isSourceFile()) {
  119. return node.getName();
  120. } else {
  121. String nodeName = "";
  122. if (node.getKind().isType())
  123. nodeName += '.' + node.getName();
  124. return constructNestedTypeName(node.getParent()) + nodeName;
  125. }
  126. }
  127. /**
  128. * Skips files that are public in the model but not public in the source, e.g. nested aspects.
  129. */
  130. static void decorateHTMLFile(File file) throws IOException {
  131. if (!file.exists())
  132. return;
  133. System.out.println("> Decorating " + file.getCanonicalPath() + "...");
  134. BufferedReader reader = new BufferedReader(new FileReader(file));
  135. StringBuffer fileContents = new StringBuffer();
  136. String line = reader.readLine();
  137. while (line != null) {
  138. fileContents.append(line + "\n");
  139. line = reader.readLine();
  140. }
  141. boolean isSecond = false;
  142. int index = 0;
  143. IProgramElement decl;
  144. while (true) {
  145. // ---this next part is an inlined procedure that returns two values---
  146. // ---the next declaration and the index at which that declaration's---
  147. // ---DeclID sits in the .html file ---
  148. String contents = fileContents.toString();
  149. int start = contents.indexOf(Config.DECL_ID_STRING, index);
  150. int end = contents.indexOf(Config.DECL_ID_TERMINATOR, index);
  151. if (start == -1)
  152. decl = null;
  153. else if (end == -1)
  154. throw new Error("Malformed DeclID.");
  155. else {
  156. String tid = contents.substring(start + Config.DECL_ID_STRING.length(), end);
  157. decl = (IProgramElement) declIDTable.get(tid);
  158. index = start;
  159. }
  160. // --- ---
  161. // --- ---
  162. if (decl == null)
  163. break;
  164. fileContents.delete(start, end + Config.DECL_ID_TERMINATOR.length());
  165. if (decl.getKind().isType()) {
  166. isSecond = true;
  167. String fullname = "";
  168. if (decl.getParent().getKind().equals(IProgramElement.Kind.ASPECT)
  169. || decl.getParent().getKind().equals(IProgramElement.Kind.CLASS)) {
  170. fullname += decl.getParent().toSignatureString().concat(".").concat(decl.toSignatureString());
  171. } else {
  172. fullname += decl.toSignatureString();
  173. }
  174. // only add aspect documentation if we're in the correct
  175. // file for the given IProgramElement
  176. if (file.getName().contains(fullname + ".html")) {
  177. addAspectDocumentation(decl, fileContents, index);
  178. }
  179. } else {
  180. decorateMemberDocumentation(decl, fileContents, index);
  181. }
  182. // Change "Class" to "Aspect"
  183. // moved this here because then can use the IProgramElement.Kind
  184. // rather than checking to see if there's advice - this fixes
  185. // the case with an inner aspect not having the title "Aspect"
  186. if (decl.getKind().equals(IProgramElement.Kind.ASPECT) && file.getName().contains(decl.toSignatureString())) {
  187. // only want to change "Class" to "Aspect" if we're in the
  188. // file corresponding to the IProgramElement
  189. String fullname = "";
  190. if (decl.getParent().getKind().equals(IProgramElement.Kind.ASPECT)
  191. || decl.getParent().getKind().equals(IProgramElement.Kind.CLASS)) {
  192. fullname += decl.getParent().toSignatureString().concat(".").concat(decl.toSignatureString());
  193. } else {
  194. fullname += decl.toSignatureString();
  195. }
  196. if (!file.getName().contains(fullname + ".html")) {
  197. // we're still in the file for a parent IPE
  198. continue;
  199. }
  200. boolean br = true;
  201. int classStartIndex = fileContents.toString().indexOf("<BR>\nClass ");
  202. if (classStartIndex == -1) {
  203. classStartIndex = fileContents.toString().indexOf("<H2>\nClass ");
  204. br = false;
  205. }
  206. if (classStartIndex == -1) {
  207. // Java8 looks more like this:
  208. // <h2 title="Class A" class="title">Class A</h2>
  209. classStartIndex = fileContents.toString().indexOf("<h2 title=\"Class ");
  210. int classEndIndex = fileContents.toString().indexOf("</h2>", classStartIndex);
  211. if (classStartIndex == -1) {
  212. // Java 13 - replaced h2 with h1 here
  213. classStartIndex = fileContents.toString().indexOf("<h1 title=\"Class ");
  214. classEndIndex = fileContents.toString().indexOf("</h1>", classStartIndex);
  215. }
  216. if (classEndIndex != -1) {
  217. // Convert it to "<h2 title="Aspect A" class="title">Aspect A</h2>"
  218. String classLine = fileContents.toString().substring(classStartIndex, classEndIndex);
  219. String aspectLine = classLine.replaceAll("Class ","Aspect ");
  220. fileContents.delete(classStartIndex, classEndIndex);
  221. fileContents.insert(classStartIndex, aspectLine);
  222. }
  223. }
  224. else if (classStartIndex != -1) {
  225. int classEndIndex = fileContents.toString().indexOf("</H2>", classStartIndex);
  226. if (classStartIndex != -1 && classEndIndex != -1) {
  227. String classLine = fileContents.toString().substring(classStartIndex, classEndIndex);
  228. String aspectLine = "";
  229. if (br) {
  230. aspectLine += "<BR>\n" + "Aspect " + classLine.substring(11, classLine.length());
  231. } else {
  232. aspectLine += "<H2>\n" + "Aspect " + classLine.substring(11, classLine.length());
  233. }
  234. fileContents.delete(classStartIndex, classEndIndex);
  235. fileContents.insert(classStartIndex, aspectLine);
  236. }
  237. }
  238. int secondClassStartIndex = fileContents.toString().indexOf("class <B>");
  239. if (secondClassStartIndex != -1) {
  240. String name = decl.toSignatureString();
  241. int classEndIndex = fileContents.toString().indexOf(name + "</B><DT>");
  242. if (secondClassStartIndex != -1 && classEndIndex != -1) {
  243. StringBuffer sb = new StringBuffer(fileContents.toString().substring(secondClassStartIndex, classEndIndex));
  244. sb.replace(0, 5, "aspect");
  245. fileContents.delete(secondClassStartIndex, classEndIndex);
  246. fileContents.insert(secondClassStartIndex, sb.toString());
  247. }
  248. }
  249. else {
  250. // Java8:
  251. // <pre>static class <span class="typeNameLabel">ClassA.InnerAspect</span>
  252. classStartIndex = fileContents.toString().indexOf("class <span class=\"typeNameLabel\">");
  253. if (classStartIndex == -1) {
  254. // Java7: 464604
  255. // <pre>public class <span class="strong">Azpect</span>
  256. classStartIndex = fileContents.toString().indexOf("class <span class=\"strong\">");
  257. }
  258. int classEndIndex = fileContents.toString().indexOf("</span>", classStartIndex);
  259. if (classEndIndex != -1) {
  260. // Convert it to "aspect <span class="typeNameLabel">ClassA.InnerAspect</span>"
  261. String classLine = fileContents.toString().substring(classStartIndex, classEndIndex);
  262. String aspectLine = "aspect"+fileContents.substring(classStartIndex+5,classEndIndex);
  263. fileContents.delete(classStartIndex, classEndIndex);
  264. fileContents.insert(classStartIndex, aspectLine);
  265. }
  266. }
  267. }
  268. }
  269. file.delete();
  270. FileOutputStream fos = new FileOutputStream(file);
  271. fos.write(fileContents.toString().getBytes());
  272. reader.close();
  273. fos.close();
  274. }
  275. static void addAspectDocumentation(IProgramElement node, StringBuffer fileBuffer, int index) {
  276. List<IProgramElement> pointcuts = new ArrayList<IProgramElement>();
  277. List<IProgramElement> advice = new ArrayList<IProgramElement>();
  278. List<IProgramElement> declares = new ArrayList<IProgramElement>();
  279. List<IProgramElement> methodsDeclaredOn = StructureUtil.getDeclareInterTypeTargets(node, IProgramElement.Kind.INTER_TYPE_METHOD);
  280. if (methodsDeclaredOn != null && !methodsDeclaredOn.isEmpty()) {
  281. insertDeclarationsSummary(fileBuffer, methodsDeclaredOn, ITD_METHOD_SUMMARY, index);
  282. }
  283. List<IProgramElement> fieldsDeclaredOn = StructureUtil.getDeclareInterTypeTargets(node, IProgramElement.Kind.INTER_TYPE_FIELD);
  284. if (fieldsDeclaredOn != null && !fieldsDeclaredOn.isEmpty()) {
  285. insertDeclarationsSummary(fileBuffer, fieldsDeclaredOn, ITD_FIELD_SUMMARY, index);
  286. }
  287. List<IProgramElement> constDeclaredOn = StructureUtil.getDeclareInterTypeTargets(node, IProgramElement.Kind.INTER_TYPE_CONSTRUCTOR);
  288. if (fieldsDeclaredOn != null && !constDeclaredOn.isEmpty()) {
  289. insertDeclarationsSummary(fileBuffer, constDeclaredOn, ITD_CONSTRUCTOR_SUMMARY, index);
  290. }
  291. for (IProgramElement member : node.getChildren()) {
  292. if (member.getKind().equals(IProgramElement.Kind.POINTCUT)) {
  293. pointcuts.add(member);
  294. } else if (member.getKind().equals(IProgramElement.Kind.ADVICE)) {
  295. advice.add(member);
  296. } else if (member.getKind().isDeclare() || member.getKind().isInterTypeMember()) {
  297. declares.add(member);
  298. }
  299. }
  300. if (declares.size() > 0) {
  301. insertDeclarationsDetails(fileBuffer, declares, DECLARE_DETAIL, index);
  302. insertDeclarationsSummary(fileBuffer, declares, DECLARE_SUMMARY, index);
  303. }
  304. if (pointcuts.size() > 0) {
  305. insertDeclarationsSummary(fileBuffer, pointcuts, POINTCUT_SUMMARY, index);
  306. insertDeclarationsDetails(fileBuffer, pointcuts, POINTCUT_DETAIL, index);
  307. }
  308. if (advice.size() > 0) {
  309. insertDeclarationsSummary(fileBuffer, advice, ADVICE_SUMMARY, index);
  310. insertDeclarationsDetails(fileBuffer, advice, ADVICE_DETAIL, index);
  311. }
  312. // add the 'aspect declarations' information against the type
  313. List<IProgramElement> parentsDeclaredOn = StructureUtil.getDeclareInterTypeTargets(node, IProgramElement.Kind.DECLARE_PARENTS);
  314. if (parentsDeclaredOn != null && parentsDeclaredOn.size() > 0) {
  315. decorateDocWithRel(node, fileBuffer, index, parentsDeclaredOn, HtmlRelationshipKind.ASPECT_DECLARATIONS);
  316. }
  317. // add the 'annotated by' information against the type
  318. List<String> annotatedBy = StructureUtil.getTargets(node, IRelationship.Kind.DECLARE_INTER_TYPE, "annotated by");
  319. if (annotatedBy != null && annotatedBy.size() > 0) {
  320. decorateDocWithRel(node, fileBuffer, index, annotatedBy, HtmlRelationshipKind.ANNOTATED_BY);
  321. }
  322. // add the 'advised by' information against the type
  323. List<String> advisedBy = StructureUtil.getTargets(node, IRelationship.Kind.ADVICE);
  324. if (advisedBy != null && advisedBy.size() > 0) {
  325. decorateDocWithRel(node, fileBuffer, index, advisedBy, HtmlRelationshipKind.ADVISED_BY);
  326. }
  327. }
  328. static void insertDeclarationsSummary(StringBuffer fileBuffer, List decls, String kind, int index) {
  329. if (!declsAboveVisibilityExist(decls))
  330. return;
  331. int insertIndex = findSummaryIndex(fileBuffer, index);
  332. // insert the head of the table
  333. String tableHead = "<!-- ======== " + kind.toUpperCase() + " ======= -->\n\n"
  334. + "<TABLE BORDER=\"1\" WIDTH=\"100%\" CELLPADDING=\"1\""
  335. + "CELLSPACING=\"0\"><TR><TD COLSPAN=2 BGCOLOR=\"#CCCCFF\">" + "<FONT SIZE=\"+2\"><B>" + kind
  336. + "</B></FONT></TD></TR>\n";
  337. fileBuffer.insert(insertIndex, tableHead);
  338. insertIndex += tableHead.length();
  339. // insert the body of the table
  340. for (Object o : decls) {
  341. IProgramElement decl = (IProgramElement) o;
  342. if (isAboveVisibility(decl)) {
  343. // insert the table row accordingly
  344. String comment = generateSummaryComment(decl);
  345. String entry = "";
  346. if (kind.equals(ADVICE_SUMMARY)) {
  347. entry += "<TR><TD>" + "<A HREF=\"#" + generateHREFName(decl) + "\">" + "<TT>" + generateSignatures(decl)
  348. + "</TT></A><BR>&nbsp;";
  349. if (!comment.equals("")) {
  350. entry += comment + "<P>";
  351. }
  352. entry += generateAffects(decl) + "</TD>" + "</TR><TD>\n";
  353. } else if (kind.equals(POINTCUT_SUMMARY)) {
  354. entry += "<TR><TD WIDTH=\"1%\">" + "<FONT SIZE=-1><TT>" + genAccessibility(decl) + "</TT></FONT>" + "</TD>\n"
  355. + "<TD>" + "<TT><A HREF=\"#" + generateHREFName(decl) + "\">" + decl.toLabelString()
  356. + "</A></TT><BR>&nbsp;";
  357. if (!comment.equals("")) {
  358. entry += comment + "<P>";
  359. }
  360. entry += "</TR></TD>\n";
  361. } else if (kind.equals(DECLARE_SUMMARY)) {
  362. entry += "<TR><TD WIDTH=\"1%\">" + "<FONT SIZE=-1><TT>" + generateModifierInformation(decl, false)
  363. + "</TT></FONT>" + "</TD>" + "<TD>" + "<A HREF=\"#" + generateHREFName(decl) + "\">" + "<TT>"
  364. + decl.toLabelString() + "</TT></A><P>" + generateAffects(decl);
  365. } else if (kind.equals(ITD_FIELD_SUMMARY) || kind.equals(ITD_METHOD_SUMMARY)) {
  366. entry += "<TR><TD WIDTH=\"1%\">" + "<FONT SIZE=-1><TT>" + generateModifierInformation(decl, false)
  367. + "</TT></FONT>" + "</TD>" + "<TD>" + "<A HREF=\"#" + generateHREFName(decl) + "\">" + "<TT>"
  368. + decl.toLabelString() + "</TT></A><P>" + generateDeclaredBy(decl);
  369. } else if (kind.equals(ITD_CONSTRUCTOR_SUMMARY)) {
  370. entry += "<TD>" + "<A HREF=\"#" + generateHREFName(decl) + "\">" + "<TT>" + decl.toLabelString()
  371. + "</TT></A><P>" + generateDeclaredBy(decl);
  372. }
  373. // insert the entry
  374. fileBuffer.insert(insertIndex, entry);
  375. insertIndex += entry.length();
  376. }
  377. }
  378. // insert the end of the table
  379. String tableTail = "</TABLE><P>&nbsp;\n";
  380. fileBuffer.insert(insertIndex, tableTail);
  381. insertIndex += tableTail.length();
  382. }
  383. private static boolean declsAboveVisibilityExist(List decls) {
  384. boolean exist = false;
  385. for (Object decl : decls) {
  386. IProgramElement element = (IProgramElement) decl;
  387. if (isAboveVisibility(element))
  388. exist = true;
  389. }
  390. return exist;
  391. }
  392. private static boolean isAboveVisibility(IProgramElement element) {
  393. IProgramElement.Accessibility acc = element.getAccessibility();
  394. if (docVisibilityModifier.equals("private")) {
  395. // show all classes and members
  396. return true;
  397. } else if (docVisibilityModifier.equals("package")) {
  398. // show package, protected and public classes and members
  399. return acc.equals(IProgramElement.Accessibility.PACKAGE) || acc.equals(IProgramElement.Accessibility.PROTECTED)
  400. || acc.equals(IProgramElement.Accessibility.PUBLIC);
  401. } else if (docVisibilityModifier.equals("protected")) {
  402. // show protected and public classes and members
  403. return acc.equals(IProgramElement.Accessibility.PROTECTED) || acc.equals(IProgramElement.Accessibility.PUBLIC);
  404. } else if (docVisibilityModifier.equals("public")) {
  405. // show public classes and members
  406. return acc.equals(IProgramElement.Accessibility.PUBLIC);
  407. }
  408. return false;
  409. }
  410. private static String genAccessibility(IProgramElement decl) {
  411. if (decl.getAccessibility().equals(IProgramElement.Accessibility.PACKAGE)) {
  412. return "(package private)";
  413. } else {
  414. return decl.getAccessibility().toString();
  415. }
  416. }
  417. static void insertDeclarationsDetails(StringBuffer fileBuffer, List decls, String kind, int index) {
  418. if (!declsAboveVisibilityExist(decls))
  419. return;
  420. int insertIndex = findDetailsIndex(fileBuffer, index);
  421. // insert the table heading
  422. String detailsHeading = "<P>&nbsp;\n" + "<!-- ======== " + kind.toUpperCase() + " SUMMARY ======= -->\n\n"
  423. + "<TABLE BORDER=\"1\" CELLPADDING=\"3\" CELLSPACING=\"0\" WIDTH=\"100%\">\n"
  424. + "<TR BGCOLOR=\"#CCCCFF\" CLASS=\"TableHeadingColor\">\n" + "<TD COLSPAN=1><FONT SIZE=\"+2\">\n" + "<B>" + kind
  425. + "</B></FONT></TD>\n" + "</TR>\n" + "</TABLE>";
  426. fileBuffer.insert(insertIndex, detailsHeading);
  427. insertIndex += detailsHeading.length();
  428. // insert the details
  429. for (int i = 0; i < decls.size(); i++) {
  430. IProgramElement decl = (IProgramElement) decls.get(i);
  431. if (isAboveVisibility(decl)) {
  432. String entry = "";
  433. // insert the table row accordingly
  434. entry += "<A NAME=\"" + generateHREFName(decl) + "\"><!-- --></A>\n";
  435. if (kind.equals(ADVICE_DETAIL)) {
  436. entry += "<H3>" + decl.getName() + "</H3><P>";
  437. entry += "<TT>" + generateSignatures(decl) + "</TT>\n" + "<P>" + generateDetailsComment(decl) + "<P>"
  438. + generateAffects(decl);
  439. } else if (kind.equals(POINTCUT_DETAIL)) {
  440. entry += "<H3>" + decl.toLabelString() + "</H3><P>" + generateDetailsComment(decl);
  441. } else if (kind.equals(DECLARE_DETAIL)) {
  442. entry += "<H3>" + decl.toLabelString() + "</H3><P>" + generateModifierInformation(decl, true);
  443. if (!decl.getKind().equals(IProgramElement.Kind.INTER_TYPE_CONSTRUCTOR)) {
  444. entry += "&nbsp;&nbsp;";
  445. }
  446. // if we're not a declare statement then we need to generate the signature.
  447. // If we did this for declare statements we get two repeated lines
  448. if (!decl.getKind().isDeclare()) {
  449. String sigs = generateSignatures(decl);
  450. entry += sigs + "<P>";
  451. }
  452. entry += generateAffects(decl) + generateDetailsComment(decl);
  453. }
  454. // insert the entry
  455. if (i != decls.size() - 1) {
  456. entry += "<P><HR>\n";
  457. } else {
  458. entry += "<P>";
  459. }
  460. fileBuffer.insert(insertIndex, entry);
  461. insertIndex += entry.length();
  462. }
  463. }
  464. }
  465. /**
  466. * TODO: don't place the summary first.
  467. */
  468. static int findSummaryIndex(StringBuffer fileBuffer, int index) {
  469. String fbs = fileBuffer.toString();
  470. String MARKER_1 = "<!-- =========== FIELD SUMMARY =========== -->";
  471. String MARKER_2 = "<!-- ======== CONSTRUCTOR SUMMARY ======== -->";
  472. int index1 = fbs.indexOf(MARKER_1, index);
  473. int index2 = fbs.indexOf(MARKER_2, index);
  474. if (index1 < index2 && index1 != -1) {
  475. return index1;
  476. } else if (index2 != -1) {
  477. return index2;
  478. } else {
  479. return index;
  480. }
  481. }
  482. static int findDetailsIndex(StringBuffer fileBuffer, int index) {
  483. String fbs = fileBuffer.toString();
  484. String MARKER_1 = "<!-- ========= CONSTRUCTOR DETAIL ======== -->";
  485. String MARKER_2 = "<!-- ============ FIELD DETAIL =========== -->";
  486. String MARKER_3 = "<!-- ============ METHOD DETAIL ========== -->";
  487. int index1 = fbs.indexOf(MARKER_1, index);
  488. int index2 = fbs.indexOf(MARKER_2, index);
  489. int index3 = fbs.indexOf(MARKER_3, index);
  490. if (index1 != -1 && index1 < index2 && index1 < index3) {
  491. return index1;
  492. } else if (index2 != -1 && index2 < index1 && index2 < index3) {
  493. return index2;
  494. } else if (index3 != -1) {
  495. return index3;
  496. } else {
  497. return index;
  498. }
  499. }
  500. static void decorateDocWithRel(IProgramElement node, StringBuffer fileContentsBuffer, int index, List targets,
  501. HtmlRelationshipKind relKind) {
  502. if (targets != null && !targets.isEmpty()) {
  503. String adviceDoc = "<TABLE WIDTH=\"100%\" BGCOLOR=#FFFFFF><TR>"
  504. + "<TD width=\"15%\" bgcolor=\"#FFD8B0\"><B><FONT COLOR=000000>" + relKind.toString() + "</font></b></td><td>";
  505. String relativePackagePath = getRelativePathFromHere(node.getPackageName().replace('.', '/') + Config.DIR_SEP_CHAR);
  506. List addedNames = new ArrayList();
  507. for (Iterator it = targets.iterator(); it.hasNext();) {
  508. Object o = it.next();
  509. IProgramElement currDecl = null;
  510. if (o instanceof String) {
  511. String currHandle = (String) o;
  512. currDecl = node.getModel().getHierarchy().findElementForHandle(currHandle);
  513. } else if (o instanceof IProgramElement) {
  514. currDecl = (IProgramElement) o;
  515. } else {
  516. return;
  517. }
  518. String packagePath = "";
  519. if (currDecl.getPackageName() != null && !currDecl.getPackageName().equals("")) {
  520. packagePath = currDecl.getPackageName().replace('.', '/') + Config.DIR_SEP_CHAR;
  521. }
  522. String hrefName = "";
  523. String hrefLink = "";
  524. // Start the hRefLink with the relative path based on where
  525. // *this* type (i.e. the advised) is in the package structure.
  526. hrefLink = relativePackagePath + packagePath;
  527. if (currDecl.getPackageName() != null) {
  528. hrefName = currDecl.getPackageName().replace('.', '/');
  529. }
  530. // in the case of nested classes, in order for the links to work,
  531. // need to have the correct file name which is something of the
  532. // form parentClass.nestedAspect.html
  533. List names = new ArrayList();
  534. IProgramElement parent = currDecl;
  535. while (parent != null
  536. && parent.getParent() != null
  537. && (!parent.getParent().getKind().equals(IProgramElement.Kind.FILE_JAVA) && !parent.getParent().getKind()
  538. .equals(IProgramElement.Kind.FILE_ASPECTJ))) {
  539. parent = parent.getParent();
  540. names.add(parent.toLinkLabelString());
  541. }
  542. StringBuffer sbuff = new StringBuffer();
  543. for (int i = names.size() - 1; i >= 0; i--) {
  544. String element = (String) names.get(i);
  545. if (i == 0) {
  546. sbuff.append(element);
  547. } else {
  548. sbuff.append(element + ".");
  549. }
  550. }
  551. // use the currDecl.toLabelString rather than currDecl.getName()
  552. // because two distinct advice blocks can have the same
  553. // currDecl.getName() and wouldn't both appear in the ajdoc
  554. hrefName += Config.DIR_SEP_CHAR + sbuff.toString() + "." + currDecl.toLabelString();
  555. // need to replace " with quot; otherwise the links wont work
  556. // for 'matches declare' relationship
  557. StringBuffer sb = new StringBuffer(currDecl.toLabelString());
  558. int nextQuote = sb.toString().indexOf("\"");
  559. while (nextQuote != -1) {
  560. sb.deleteCharAt(nextQuote);
  561. sb.insert(nextQuote, "quot;");
  562. nextQuote = sb.toString().indexOf("\"");
  563. }
  564. hrefLink += sbuff.toString() + ".html" + "#" + sb.toString();
  565. if (!addedNames.contains(hrefName)) {
  566. adviceDoc = adviceDoc + "<A HREF=\"" + hrefLink + "\"><tt>" + hrefName.replace('/', '.') + "</tt></A>";
  567. if (it.hasNext())
  568. adviceDoc += ", ";
  569. addedNames.add(hrefName);
  570. }
  571. }
  572. adviceDoc += "</TR></TD></TABLE>\n";
  573. fileContentsBuffer.insert(index, adviceDoc);
  574. }
  575. }
  576. static void decorateMemberDocumentation(IProgramElement node, StringBuffer fileContentsBuffer, int index) {
  577. List<String> targets = StructureUtil.getTargets(node, IRelationship.Kind.ADVICE);
  578. decorateDocWithRel(node, fileContentsBuffer, index, targets, HtmlRelationshipKind.ADVISED_BY);
  579. List<String> warnings = StructureUtil.getTargets(node, IRelationship.Kind.DECLARE, "matches declare");
  580. decorateDocWithRel(node, fileContentsBuffer, index, warnings, HtmlRelationshipKind.MATCHES_DECLARE);
  581. List<String> softenedBy = StructureUtil.getTargets(node, IRelationship.Kind.DECLARE, "softened by");
  582. decorateDocWithRel(node, fileContentsBuffer, index, softenedBy, HtmlRelationshipKind.SOFTENED_BY);
  583. List<String> annotatedBy = StructureUtil.getTargets(node, IRelationship.Kind.DECLARE_INTER_TYPE, "annotated by");
  584. decorateDocWithRel(node, fileContentsBuffer, index, annotatedBy, HtmlRelationshipKind.ANNOTATED_BY);
  585. }
  586. /**
  587. * pr119453 - adding "declared by" relationship
  588. */
  589. static String generateDeclaredBy(IProgramElement decl) {
  590. String entry = "<TABLE WIDTH=\"100%\" BGCOLOR=#FFFFFF><TR>"
  591. + "<TD width=\"10%\" bgcolor=\"#FFD8B0\"><B><FONT COLOR=000000>" + "&nbsp;Declared&nbsp;by:</b></font></td><td>";
  592. String relativePackagePath = getRelativePathFromHere(decl.getPackageName().replace('.', '/') + Config.DIR_SEP_CHAR);
  593. if (decl != null && !StructureUtil.isAnonymous(decl.getParent())) {
  594. String packagePath = "";
  595. if (decl.getPackageName() != null && !decl.getPackageName().equals("")) {
  596. packagePath = decl.getPackageName().replace('.', '/') + Config.DIR_SEP_CHAR;
  597. }
  598. String typeSignature = constructNestedTypeName(decl);
  599. String hrefName = packagePath + typeSignature;
  600. // The hrefLink needs to just be the corresponding aspect
  601. String hrefLink = relativePackagePath + packagePath + typeSignature + ".html";
  602. entry += "<A HREF=\"" + hrefLink + "\"><tt>" + hrefName.replace('/', '.') + "</tt></A>"; // !!! don't replace
  603. }
  604. entry += "</B></FONT></TD></TR></TABLE>\n</TR></TD>\n";
  605. return entry;
  606. }
  607. /**
  608. * TODO: probably want to make this the same for intros and advice.
  609. */
  610. static String generateAffects(IProgramElement decl) {
  611. List targets = null;
  612. if (decl.getKind().isDeclare() || decl.getKind().isInterTypeMember()) {
  613. targets = StructureUtil.getDeclareTargets(decl);
  614. } else {
  615. targets = StructureUtil.getTargets(decl, IRelationship.Kind.ADVICE);
  616. }
  617. if (targets == null)
  618. return "";
  619. String entry = "<TABLE WIDTH=\"100%\" BGCOLOR=#FFFFFF><TR>";
  620. IProgramElement.Kind kind = decl.getKind();
  621. if (kind.equals(IProgramElement.Kind.ADVICE)) {
  622. entry += "<TD width=\"10%\" bgcolor=\"#FFD8B0\"><B><FONT COLOR=000000>" + HtmlRelationshipKind.ADVISES.toString()
  623. + "</b></font></td><td>";
  624. } else if (kind.equals(IProgramElement.Kind.DECLARE_WARNING) || kind.equals(IProgramElement.Kind.DECLARE_ERROR)) {
  625. entry += "<TD width=\"10%\" bgcolor=\"#FFD8B0\"><B><FONT COLOR=000000>" + HtmlRelationshipKind.MATCHED_BY.toString()
  626. + "</b></font></td><td>";
  627. } else if (kind.isDeclareAnnotation()) {
  628. entry += "<TD width=\"10%\" bgcolor=\"#FFD8B0\"><B><FONT COLOR=000000>" + HtmlRelationshipKind.ANNOTATES.toString()
  629. + "</b></font></td><td>";
  630. } else if (kind.equals(IProgramElement.Kind.DECLARE_SOFT)) {
  631. entry += "<TD width=\"10%\" bgcolor=\"#FFD8B0\"><B><FONT COLOR=000000>" + HtmlRelationshipKind.SOFTENS.toString()
  632. + "</b></font></td><td>";
  633. } else {
  634. entry += "<TD width=\"10%\" bgcolor=\"#FFD8B0\"><B><FONT COLOR=000000>" + HtmlRelationshipKind.DECLARED_ON.toString()
  635. + "</b></font></td><td>";
  636. }
  637. String relativePackagePath = getRelativePathFromHere(decl.getPackageName().replace('.', '/') + Config.DIR_SEP_CHAR);
  638. List addedNames = new ArrayList(); // for ensuring that we don't add duplciates
  639. for (Iterator it = targets.iterator(); it.hasNext();) {
  640. String currHandle = (String) it.next();
  641. IProgramElement currDecl = decl.getModel().getHierarchy().findElementForHandle(currHandle);
  642. if (currDecl.getKind().equals(IProgramElement.Kind.CODE)) {
  643. currDecl = currDecl.getParent(); // promote to enclosing
  644. }
  645. if (currDecl != null && !StructureUtil.isAnonymous(currDecl.getParent())) {
  646. String packagePath = "";
  647. if (currDecl.getPackageName() != null && !currDecl.getPackageName().equals("")) {
  648. packagePath = currDecl.getPackageName().replace('.', '/') + Config.DIR_SEP_CHAR;
  649. }
  650. String typeSignature = constructNestedTypeName(currDecl);
  651. String hrefName = packagePath + typeSignature;
  652. // Start the hRefLink with the relative path based on where
  653. // *this* type (i.e. the advisor) is in the package structure.
  654. String hrefLink = relativePackagePath + packagePath + typeSignature + ".html";
  655. if (!currDecl.getKind().isType()) {
  656. hrefName += '.' + currDecl.getName();
  657. hrefLink += "#" + currDecl.toLabelString();
  658. }
  659. if (!addedNames.contains(hrefName)) {
  660. entry += "<A HREF=\"" + hrefLink + "\"><tt>" + hrefName.replace('/', '.') + "</tt></A>"; // !!! don't replace
  661. if (it.hasNext())
  662. entry += ", ";
  663. addedNames.add(hrefName);
  664. }
  665. }
  666. }
  667. entry += "</B></FONT></TD></TR></TABLE>\n</TR></TD>\n";
  668. return entry;
  669. }
  670. /**
  671. * Generates a relative directory path fragment that can be used to navigate "upwards" from the directory location implied by
  672. * the argument.
  673. *
  674. * @param packagePath
  675. * @return String consisting of multiple "../" parts, one for each component part of the input <code>packagePath</code>.
  676. */
  677. private static String getRelativePathFromHere(String packagePath) {
  678. StringBuffer result = new StringBuffer("");
  679. if (packagePath != null && (packagePath.contains("/"))) {
  680. StringTokenizer sTok = new StringTokenizer(packagePath, "/", false);
  681. while (sTok.hasMoreTokens()) {
  682. sTok.nextToken(); // don't care about the token value
  683. result.append(".." + Config.DIR_SEP_CHAR);
  684. }// end while
  685. }// end if
  686. return result.toString();
  687. }
  688. /**
  689. * Generate the "public int"-type information about the given IProgramElement. Used when dealing with ITDs. To mirror the
  690. * behaviour of methods and fields in classes, if we're generating the summary information we don't want to include "public" if
  691. * the accessibility of the IProgramElement is public.
  692. *
  693. */
  694. private static String generateModifierInformation(IProgramElement decl, boolean isDetails) {
  695. String intro = "";
  696. if (decl.getKind().isDeclare()) {
  697. return intro + "</TT>";
  698. }
  699. if (isDetails || !decl.getAccessibility().equals(IProgramElement.Accessibility.PUBLIC)) {
  700. intro += "<TT>" + decl.getAccessibility().toString() + "&nbsp;";
  701. }
  702. if (decl.getKind().equals(IProgramElement.Kind.INTER_TYPE_FIELD)) {
  703. return intro + decl.getCorrespondingType() + "</TT>";
  704. } else if (decl.getKind().equals(IProgramElement.Kind.INTER_TYPE_CONSTRUCTOR) && isDetails) {
  705. return intro + "</TT>";
  706. } else {
  707. return intro + decl.getCorrespondingType(true) + "</TT>";
  708. }
  709. }
  710. static String generateIntroductionSignatures(IProgramElement decl, boolean isDetails) {
  711. return "<not implemented>";
  712. }
  713. static String generateSignatures(IProgramElement decl) {
  714. return "<B>" + decl.toLabelString() + "</B>";
  715. }
  716. static String generateSummaryComment(IProgramElement decl) {
  717. String COMMENT_INDENT = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"; // !!!
  718. String formattedComment = getFormattedComment(decl);
  719. int periodIndex = formattedComment.indexOf('.');
  720. if (formattedComment.equals("")) {
  721. return "";
  722. } else if (periodIndex != -1) {
  723. return COMMENT_INDENT + formattedComment.substring(0, periodIndex + 1);
  724. } else {
  725. return COMMENT_INDENT + formattedComment;
  726. }
  727. }
  728. static String generateDetailsComment(IProgramElement decl) {
  729. return getFormattedComment(decl);
  730. }
  731. static String generateHREFName(IProgramElement decl) {
  732. StringBuffer hrefLinkBuffer = new StringBuffer();
  733. char[] declChars = decl.toLabelString().toCharArray();
  734. for (char declChar : declChars) {
  735. if (declChar == '"') {
  736. hrefLinkBuffer.append("quot;");
  737. } else {
  738. hrefLinkBuffer.append(declChar);
  739. }
  740. }
  741. return hrefLinkBuffer.toString();
  742. }
  743. /**
  744. * Figure out the link relative to the package.
  745. */
  746. static String generateAffectsHREFLink(String declaringType) {
  747. String link = rootDir.getAbsolutePath() + "/" + declaringType + ".html";
  748. return link;
  749. }
  750. /**
  751. * This formats a comment according to the rules in the Java Langauge Spec: <I>The text of a docuemntation comment consists of
  752. * the characters between the /** that begins the comment and the 'star-slash' that ends it. The text is devided into one or
  753. * more lines. On each of these lines, the leading * characters are ignored; for lines other than the first, blanks and tabs
  754. * preceding the initial * characters are also discarded.</I>
  755. *
  756. * TODO: implement formatting or linking for tags.
  757. */
  758. static String getFormattedComment(IProgramElement decl) {
  759. String comment = decl.getFormalComment();
  760. if (comment == null)
  761. return "";
  762. String formattedComment = "";
  763. // strip the comment markers
  764. int startIndex = comment.indexOf("/**");
  765. int endIndex = comment.indexOf("*/");
  766. if (startIndex == -1) {
  767. startIndex = 0;
  768. } else {
  769. startIndex += 3;
  770. }
  771. if (endIndex == -1) {
  772. endIndex = comment.length();
  773. }
  774. comment = comment.substring(startIndex, endIndex);
  775. // string the leading whitespace and '*' characters at the beginning of each line
  776. BufferedReader reader = new BufferedReader(new StringReader(comment));
  777. try {
  778. for (String line = reader.readLine(); line != null; line = reader.readLine()) {
  779. line = line.trim();
  780. for (int i = 0; i < line.length(); i++) {
  781. if (line.charAt(0) == '*') {
  782. line = line.substring(1, line.length());
  783. } else {
  784. break;
  785. }
  786. }
  787. // !!! remove any @see and @link tags from the line
  788. // int seeIndex = line.indexOf("@see");
  789. // int linkIndex = line.indexOf("@link");
  790. // if ( seeIndex != -1 ) {
  791. // line = line.substring(0, seeIndex) + line.substring(seeIndex);
  792. // }
  793. // if ( linkIndex != -1 ) {
  794. // line = line.substring(0, linkIndex) + line.substring(linkIndex);
  795. // }
  796. formattedComment += line;
  797. }
  798. } catch (IOException ioe) {
  799. throw new Error("Couldn't format comment for declaration: " + decl.getName());
  800. }
  801. return formattedComment;
  802. }
  803. static public IProgramElement[] getProgramElements(AsmManager model, String filename) {
  804. IProgramElement file = model.getHierarchy().findElementForSourceFile(filename);
  805. final List nodes = new ArrayList();
  806. HierarchyWalker walker = new HierarchyWalker() {
  807. public void preProcess(IProgramElement node) {
  808. IProgramElement p = node;
  809. if (accept(node))
  810. nodes.add(p);
  811. }
  812. };
  813. file.walk(walker);
  814. return (IProgramElement[]) nodes.toArray(new IProgramElement[nodes.size()]);
  815. }
  816. /**
  817. * Rejects anonymous kinds by checking if their name is an integer
  818. */
  819. static private boolean accept(IProgramElement node) {
  820. if (node.getKind().isType()) {
  821. boolean isAnonymous = StructureUtil.isAnonymous(node);
  822. return !node.getParent().getKind().equals(IProgramElement.Kind.METHOD) && !isAnonymous;
  823. } else {
  824. return !node.getKind().equals(IProgramElement.Kind.IMPORT_REFERENCE);
  825. }
  826. }
  827. /**
  828. * TypeSafeEnum for the entries which need to be put in the html doc
  829. */
  830. public static class HtmlRelationshipKind extends TypeSafeEnum {
  831. public HtmlRelationshipKind(String name, int key) {
  832. super(name, key);
  833. }
  834. public static HtmlRelationshipKind read(DataInputStream s) throws IOException {
  835. int key = s.readByte();
  836. switch (key) {
  837. case 1:
  838. return ADVISES;
  839. case 2:
  840. return ADVISED_BY;
  841. case 3:
  842. return MATCHED_BY;
  843. case 4:
  844. return MATCHES_DECLARE;
  845. case 5:
  846. return DECLARED_ON;
  847. case 6:
  848. return ASPECT_DECLARATIONS;
  849. case 7:
  850. return SOFTENS;
  851. case 8:
  852. return SOFTENED_BY;
  853. case 9:
  854. return ANNOTATES;
  855. case 10:
  856. return ANNOTATED_BY;
  857. case 11:
  858. return USES_POINTCUT;
  859. case 12:
  860. return POINTCUT_USED_BY;
  861. }
  862. throw new Error("weird relationship kind " + key);
  863. }
  864. public static final HtmlRelationshipKind ADVISES = new HtmlRelationshipKind("&nbsp;Advises:", 1);
  865. public static final HtmlRelationshipKind ADVISED_BY = new HtmlRelationshipKind("&nbsp;Advised&nbsp;by:", 2);
  866. public static final HtmlRelationshipKind MATCHED_BY = new HtmlRelationshipKind("&nbsp;Matched&nbsp;by:", 3);
  867. public static final HtmlRelationshipKind MATCHES_DECLARE = new HtmlRelationshipKind("&nbsp;Matches&nbsp;declare:", 4);
  868. public static final HtmlRelationshipKind DECLARED_ON = new HtmlRelationshipKind("&nbsp;Declared&nbsp;on:", 5);
  869. public static final HtmlRelationshipKind ASPECT_DECLARATIONS = new HtmlRelationshipKind("&nbsp;Aspect&nbsp;declarations:",
  870. 6);
  871. public static final HtmlRelationshipKind SOFTENS = new HtmlRelationshipKind("&nbsp;Softens:", 7);
  872. public static final HtmlRelationshipKind SOFTENED_BY = new HtmlRelationshipKind("&nbsp;Softened&nbsp;by:", 8);
  873. public static final HtmlRelationshipKind ANNOTATES = new HtmlRelationshipKind("&nbsp;Annotates:", 9);
  874. public static final HtmlRelationshipKind ANNOTATED_BY = new HtmlRelationshipKind("&nbsp;Annotated&nbsp;by:", 10);
  875. public static final HtmlRelationshipKind USES_POINTCUT = new HtmlRelationshipKind("&nbsp;Uses&nbsp;pointcut:", 11);
  876. public static final HtmlRelationshipKind POINTCUT_USED_BY = new HtmlRelationshipKind("&nbsp;Pointcut&nbsp;used&nbsp;by:",
  877. 12);
  878. }
  879. }