001    package org.hackystat.projectbrowser.page.dailyprojectdata.complexity;
002    
003    import java.io.Serializable;
004    import java.util.ArrayList;
005    import java.util.HashMap;
006    import java.util.List;
007    import java.util.Map;
008    import java.util.logging.Logger;
009    
010    import org.hackystat.dailyprojectdata.client.DailyProjectDataClient;
011    import org.hackystat.dailyprojectdata.resource.complexity.jaxb.ComplexityDailyProjectData;
012    import org.hackystat.dailyprojectdata.resource.complexity.jaxb.FileData;
013    import org.hackystat.projectbrowser.ProjectBrowserApplication;
014    import org.hackystat.projectbrowser.ProjectBrowserSession;
015    import org.hackystat.projectbrowser.page.dailyprojectdata.DailyProjectDataSession;
016    import org.hackystat.sensorbase.resource.projects.jaxb.Project;
017    import org.hackystat.utilities.stacktrace.StackTrace;
018    import org.hackystat.utilities.tstamp.Tstamp;
019    
020    /**
021     * The data model for Complexity DPD display.  This data model accommodates multiple Projects.
022     * For each project, the data model indicates the number of methods whose level of complexity
023     * falls into each of five buckets, from 0-10, 11-20, 21-30, 31-40, 41+.
024     * At present, we only get cyclomatic complexity from the JavaNCSS tool. This will change
025     * after we update the DPD client to not require the tool argument.
026     * @author Philip Johnson
027     *
028     */
029    public class ComplexityDataModel implements Serializable {
030    
031      /** Support serialization. */
032      private static final long serialVersionUID = 1L;
033      
034      /** Holds the complexity data, organized by Project.*/
035      private Map<Project, ComplexityData> complexityDataMap = new HashMap<Project, ComplexityData>();
036      
037      /**
038       * The default ComplexityDataModel, which contains no complexity information.
039       */
040      public ComplexityDataModel() {
041        // Do nothing.
042      }
043      
044      /**
045       * Updates this data model to reflect the complexity information associated with the selected 
046       * projects and granularity.
047       */
048      public void update() {
049        this.clear();
050        DailyProjectDataClient dpdClient = ProjectBrowserSession.get().getDailyProjectDataClient();
051        DailyProjectDataSession session = ProjectBrowserSession.get().getDailyProjectDataSession();
052        List<Project> projects = session.getSelectedProjects();
053        // Placeholders until we set this programmatically.
054        String complexityType = "Cyclomatic";
055        String complexityTool = "JavaNCSS";
056        
057        for (Project project : projects) {
058          Logger logger = ((ProjectBrowserApplication)ProjectBrowserApplication.get()).getLogger();
059          logger.fine("Getting Complexity DPD for project: " + project.getName());
060          try {
061            ComplexityDailyProjectData classData = dpdClient.getComplexity(project.getOwner(),
062                project.getName(), Tstamp.makeTimestamp(session.getDate().getTime()), complexityType,
063            complexityTool);
064            logger.fine("Finished getting Complexity DPD for project: " + project.getName());
065            ComplexityData complexityData = this.getComplexityData(project);
066            for (FileData data : classData.getFileData()) {
067              complexityData.addEntry(data);
068            }
069          }
070          catch (Exception e) {
071            session.setFeedback("Exception when getting complexity DPD for project " + project + ": " +
072                StackTrace.toString(e));
073          }
074        }
075      }
076      
077      /**
078       * Sets this model to its empty state. 
079       */
080      public void clear() {
081        this.complexityDataMap.clear();
082      }
083      
084    
085      /**
086       * Returns true if this data model contains no information.
087       * Used to figure out if the associated panel should be visible. 
088       * @return True if the data model is empty. 
089       */
090      public boolean isEmpty() {
091        return this.complexityDataMap.isEmpty();
092      }
093      
094      /**
095       * Return the ComplexityData instance associated with the specified project.
096       * Creates and returns a new ComplexityData instance if one is not yet present.
097       * @param project The project. 
098       * @return The ComplexityData instance for this project.  
099       */
100      public ComplexityData getComplexityData(Project project) {
101        if (!complexityDataMap.containsKey(project)) {
102          complexityDataMap.put(project, new ComplexityData(project));
103        }
104        return complexityDataMap.get(project);
105      }
106      
107      /**
108       * Returns the list of ComplexityData instances, needed for markup.
109       * @return The list of ComplexityData instances. 
110       */
111      public List<ComplexityData> getComplexityDataList() {
112        return new ArrayList<ComplexityData>(this.complexityDataMap.values());
113      }
114      
115    }