001    package hirondelle.web4jtools.metrics.comments;
002    
003    import java.util.*;
004    import hirondelle.web4j.request.RequestParser;
005    import hirondelle.web4j.action.ResponsePage;
006    import javax.servlet.ServletConfig;
007    import hirondelle.web4jtools.util.Ensure;
008    import hirondelle.web4jtools.metrics.base.FileInfo;
009    import hirondelle.web4jtools.metrics.base.MetricsAction;
010    import java.util.Comparator;
011    import java.util.List;
012    
013    
014    /**
015    * List java classes with a low number of comments.
016    * 
017    * <P>Calculate the overall percentage of comments in your code.
018    * Uses the <tt>ThresholdForLowComments</tt> setting in <tt>web.xml</tt>.
019    */
020    public final class CommentsAction extends MetricsAction {
021    
022      /**  Read in settings from <tt>web.xml</tt>.   */
023      public static void readConfig(ServletConfig aConfig){
024        String rawConfig = aConfig.getInitParameter(THRESHOLD_LOW_COMMENTS);
025        Ensure.isPresentInWebXml(THRESHOLD_LOW_COMMENTS, rawConfig);
026        fTHRESHOLD_LOW_COMMENTS = Long.valueOf(rawConfig);
027        if ( fTHRESHOLD_LOW_COMMENTS < 0 || 100 < fTHRESHOLD_LOW_COMMENTS) {
028          throw new IllegalArgumentException(THRESHOLD_LOW_COMMENTS + " in web.xml is not in range 0..100.");
029        }
030      }
031      
032      public CommentsAction(RequestParser aRequestParser){
033        super(FORWARD, aRequestParser);
034      }
035      
036      /** Calculate metrics and show list of classes with low numbers of comments. */
037      protected void calculateMetric() {
038        addToRequest("commentsThreshold", fTHRESHOLD_LOW_COMMENTS);
039        scanFiles(fFileList);
040        addToRequest("numLines", fNumLines);
041        addToRequest("numCommentLines",  fNumCommentLines);
042        Collections.sort(fFilesWithLowComments, byPercent());
043        addToRequest("filesWithLowComments", fFilesWithLowComments);
044      }
045      
046      // PRIVATE //
047      private long fNumLines;
048      private long fNumCommentLines;
049      private List<FileInfo> fFilesWithLowComments = new ArrayList<FileInfo>();
050      private static final String THRESHOLD_LOW_COMMENTS = "ThresholdForLowComments"; 
051      private static Long  fTHRESHOLD_LOW_COMMENTS; 
052      private static final ResponsePage FORWARD = new ResponsePage("Comment Frequency", "view.jsp", CommentsAction.class);
053      
054      private void scanFiles(List<FileInfo> aFiles){
055        for(FileInfo file : aFiles){
056          if (file.isJavaSourceFile()) {
057            fNumLines = file.getNumLines();
058            fNumCommentLines = file.getNumCommentLines();
059            if( lowInComments(file)){
060              fFilesWithLowComments.add(file);
061            }
062          }
063        }
064      }
065      
066      private boolean lowInComments(FileInfo aFile){
067        return  aFile.getPercentComments()  < fTHRESHOLD_LOW_COMMENTS;
068      }
069      
070      private Comparator<FileInfo> byPercent(){
071        class Result implements Comparator<FileInfo> {
072          public int compare(FileInfo aThis, FileInfo aThat) {
073            return aThis.getPercentComments().compareTo(aThat.getPercentComments());
074          }
075        }
076        return new Result();
077      }
078    }