001 package hirondelle.web4jtools.taglet; 002 003 import java.util.*; 004 import com.sun.tools.doclets.Taglet; 005 import com.sun.javadoc.Tag; 006 import static hirondelle.web4j.util.Consts.NEW_LINE; 007 import hirondelle.web4j.util.Util; 008 009 /** 010 * Taglet for linking to <tt>.sql</tt> files. 011 * 012 * <P>The <tt>.sql</tt> files need to be copied into the javadoc tree. 013 * The typical use case is to place the <tt>.sql</tt> file in the same 014 * directory as the class that references it. 015 * 016 * <P>Example 1 :<br> 017 * <tt>&sql statements.sql</tt> 018 * 019 * <P>Example 2 :<br> 020 * <tt>&sql ../blah/statements.sql</tt> 021 * 022 * <P>This references a file in a nearby directory. 023 * 024 * <P>Example 3 :<br> 025 * <tt>&sql statements.sql ADD_BLAH, CHANGE_BLAH</tt> 026 * <P>This example references two specific SQL statements in the <tt>statements.sql</tt> file. 027 * That is, it references only a subset of the statements in the file. 028 */ 029 public final class SqlTaglet implements Taglet { 030 031 /** Register this taglet with the javadoc tool, under the taglet name 'sql'. */ 032 public static void register(Map aTagletMap){ 033 if ( aTagletMap.get(TAGLET_NAME) != null ) { 034 aTagletMap.remove(TAGLET_NAME); 035 } 036 aTagletMap.put(TAGLET_NAME, new SqlTaglet()); 037 } 038 039 /** Return 'sql'. */ 040 public String getName() { 041 return TAGLET_NAME; 042 } 043 044 /** Returns <tt>false</tt>. */ 045 public boolean isInlineTag() { 046 return false; 047 } 048 049 /** Returns <tt>false</tt>. */ 050 public boolean inOverview() { 051 return false; 052 } 053 054 /** Returns <tt>false</tt>. */ 055 public boolean inPackage() { 056 return false; 057 } 058 059 /** Returns <tt>true</tt>. */ 060 public boolean inType() { 061 return true; 062 } 063 064 /** Returns <tt>false</tt>. */ 065 public boolean inConstructor() { 066 return false; 067 } 068 069 /** Returns <tt>false</tt>. */ 070 public boolean inMethod() { 071 return false; 072 } 073 074 /** Returns <tt>false</tt>. */ 075 public boolean inField() { 076 return false; 077 } 078 079 /** Render a series of <tt>&sql</tt> items. */ 080 public String toString(Tag[] aTags) { 081 StringBuilder result = new StringBuilder(); 082 if ( aTags.length != 0) { 083 result.append(TAGLET_HEADER); 084 result.append(NEW_LINE); 085 result.append("<ul>" + NEW_LINE); 086 for(Tag tag: aTags){ 087 if( Util.textHasContent(tag.text()) ) { 088 result.append("<li>" + getLink(tag) + NEW_LINE); 089 } 090 } 091 result.append("</ul>" + NEW_LINE); 092 } 093 return result.toString(); 094 } 095 096 /** Render a single <tt>&sql</tt> item. */ 097 public String toString(Tag aTag) { 098 String result = ""; 099 if( Util.textHasContent(aTag.text()) ) { 100 result = TAGLET_HEADER + getLink(aTag) + NEW_LINE; 101 } 102 return result; 103 } 104 105 // PRIVATE // 106 private static final String TAGLET_NAME = "sql"; 107 private static final String TAGLET_HEADER = "<b>SQL Statements :</b> "; 108 109 private String getLink(Tag aTag){ 110 ParsedTag parsedTag = new ParsedTag(aTag); 111 String result = "<a href='" + parsedTag.getFileName() + "'><tt>" + parsedTag.getFileName() + "</tt></a>"; 112 if ( ! parsedTag.getOperations().isEmpty() ){ 113 result = result + getOperation(parsedTag); 114 for (String operation : parsedTag.getOperations() ){ 115 result = result + " <tt>" + operation + "</tt>"; 116 } 117 } 118 return result; 119 } 120 121 /** Return the list of operations, if any. */ 122 private String getOperation(ParsedTag aParsedTag) { 123 String result = ""; 124 if ( aParsedTag.getOperations().size() == 1 ){ 125 result = result + " - Single Operation"; 126 } 127 else { 128 result = result + " - Operations (" + aParsedTag.getOperations().size() + ")"; 129 } 130 result = result + ": "; 131 return result; 132 } 133 134 /** 135 * Parse a tag's text content into two parts: a link/file name, and an optional list of operations. 136 * The operations are simply the names attached to SQL statements, in .sql files. 137 */ 138 private static final class ParsedTag { 139 ParsedTag(Tag aTag){ 140 parseTag(aTag.text()); 141 } 142 String getFileName() { return fFileName; } 143 List<String> getOperations() { return fOperations; } 144 private void parseTag(String aRawTag){ 145 StringTokenizer parser = new StringTokenizer(aRawTag); 146 fFileName = parser.nextToken(); 147 while ( parser.hasMoreTokens() ) { 148 fOperations.add(parser.nextToken()); 149 } 150 } 151 private String fFileName; 152 private List<String> fOperations = new ArrayList<String>(); 153 } 154 }