package edu.uiuc.cs.fsl.propertydocs.taglets;
import com.sun.javadoc.Tag;
import com.sun.tools.doclets.Taglet;
import com.sun.tools.doclets.standard.Standard;
import java.io.File;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import edu.uiuc.cs.fsl.propertydocs.util.DefaultMap;
import edu.uiuc.cs.fsl.propertydocs.util.FinishUp;
import edu.uiuc.cs.fsl.propertydocs.util.GenerateUrls;
import edu.uiuc.cs.fsl.propertydocs.util.PositionWrapper;
/**
* This Taglet allows for marking the beginning of an new property specification
*
* @author Patrick Meredith
*
*/
public class NewOpenTaglet implements Taglet {
private static final String NAME = "new.open";
private static final String dir = System.getProperty( "outputpath" );
private File stats = new File(dir + File.separator + "__properties" + File.separator + "new.stats");
private static final String GLOBAL = "<global>";
private Set<PositionWrapper> seenDocs = new HashSet<PositionWrapper>();
private Map<String, Integer> statsDB = new DefaultMap<String, Integer>(0);
public String getName() { return NAME; }
/** can be used in a field comment*/
public boolean inField() { return true; }
/**can be used in a constructor comment*/
public boolean inConstructor() { return true; }
/**can be used in a method comment*/
public boolean inMethod() { return true; }
/**can be used in overview comment*/
public boolean inOverview() { return true; }
/**can be used in package comment*/
public boolean inPackage() { return true; }
/**can be used in type comment (classes or interfaces)*/
public boolean inType() { return true; }
/**this IS an inline tag*/
public boolean isInlineTag() { return true; }
// private int words = 0; //number of new text words
/**
* Register this Taglet.
* @param tagletMap the map to register this tag to.
*/
@SuppressWarnings("unchecked")
public static void register(Map tagletMap) {
NewOpenTaglet tag = new NewOpenTaglet();
Taglet t = (Taglet) tagletMap.get(tag.getName());
if (t != null) {
tagletMap.remove(tag.getName());
}
tagletMap.put(tag.getName(), tag);
}
/**
* Given the <code>Tag</code> representation of this custom
* tag, return its string representation.
*
* Here we have to do some annoying garbage because you there is no
* way short of file io to share info between Taglets. Instead
* I am going to parse all the inline tags if the whole document
* and collect statistics on <b>all</b> the new sections in the
* document.
*
* Statistics will only be collected if we have not already seen an
* new.open tag for this document. We keep track of the document
* by hashing its SourcePosition. The PositionWrapper makes these
* hashable.
*
* @param tag he <code>Tag</code> representation of this custom tag.
*/
public String toString(Tag tag) {
PositionWrapper p = new PositionWrapper(tag.holder().position());
if(!(seenDocs.contains(p))){
seenDocs.add(p);
handleTags(tag);
}
// This part is always executed, but for new we simply return the
// empty String. For other tags we will output fancy html/javascript
return "<DIV CLASS=\"NavBarCell1\" NAME=\"new\""
+ " ONMOUSEOVER=\"balloon.showTooltip(event,'This is text that has been added to the API.')\""
+ " STYLE=\"display:inline\">";
}
private void handleTags(Tag t){
Tag[] tags = t.holder().inlineTags();
boolean inNew = false;
//not sure if trim() is necessary. I doubt it is, but speed isn't
//an issue here
String packageName = GenerateUrls.getPackageDoc(t).toString().trim();
int w = 0; //word count
for(Tag tag : tags){
if(tag.name().equals("@new.open")){
inNew = true;
}
else if(tag.name().equals("@new.close")){
inNew = false;
}
else if(tag.name().equals("Text") && inNew){
String text = tag.text().trim();
if(text.length() == 0) continue;
w += text.split("\\s+").length;
}
}
if(inNew) {
System.err.println("ERROR: @new.open tag in comment near "
+ tags[0].holder().position() + " was not closed");
System.exit(1);
}
Integer globalWords = statsDB.get(GLOBAL);
Integer packageWords = statsDB.get(packageName);
statsDB.put(GLOBAL, globalWords + w);
statsDB.put(packageName, packageWords + w);
try {
FileOutputStream fos = new FileOutputStream(stats);
ObjectOutputStream ps = new ObjectOutputStream(fos);
ps.writeObject(statsDB);
ps.close();
} catch (java.io.IOException e){
throw new RuntimeException(e);
}
}
/**
* This method should not be called since arrays of inline tags do not
* exist. Method {@link #tostring(Tag)} should be used to convert this
* inline tag to a string.
* @param tags the array of <code>Tag</code>s representing of this custom tag.
*/
public String toString(Tag[] tags) {
return null;
}
}