001    package org.hackystat.projectbrowser.page.dailyprojectdata.coupling;
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.client.DailyProjectDataClientException;
012    import org.hackystat.dailyprojectdata.resource.coupling.jaxb.CouplingDailyProjectData;
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.tstamp.Tstamp;
018    
019    /**
020     * The data model for Coupling DPD display.  This data model accommodates multiple Projects.
021     * For each project, the data model indicates the number of classes whose level of coupling
022     * falls into each of five buckets, from 0-10, 11-20, 21-30, 31-40, 41+.
023     * At present, we only get "class" coupling from the "DependencyFinder" tool. This will change
024     * after we update the DPD client to not require the tool argument.
025     * @author Philip Johnson
026     *
027     */
028    public class CouplingDataModel implements Serializable {
029    
030      /** Support serialization. */
031      private static final long serialVersionUID = 1L;
032      
033      /** Holds the coupling data, organized by Project.*/
034      private Map<Project, CouplingData> couplingDataMap = new HashMap<Project, CouplingData>();
035      
036      /**
037       * The default CouplingDataModel, which contains no coupling information.
038       */
039      public CouplingDataModel() {
040        // Do nothing
041      }
042      
043      /**
044       * Updates this data model to reflect the coupling information associated with the selected 
045       * projects and granularity.
046       */
047      public void update() {
048        this.clear();
049        DailyProjectDataClient dpdClient = ProjectBrowserSession.get().getDailyProjectDataClient();
050        DailyProjectDataSession session = ProjectBrowserSession.get().getDailyProjectDataSession();
051        List<Project> projects = session.getSelectedProjects();
052        String couplingType = session.getContextSensitiveMenu("Coupling Type").getSelectedValue();
053        
054        for (Project project : projects) {
055          Logger logger = ((ProjectBrowserApplication)ProjectBrowserApplication.get()).getLogger();
056          logger.fine("Getting Coupling DPD for project: " + project.getName());
057          try {
058            CouplingDailyProjectData classData = dpdClient.getCoupling(project.getOwner(),
059                project.getName(), Tstamp.makeTimestamp(session.getDate().getTime()), "class",
060                "DependencyFinder");
061            logger.fine("Finished getting Coupling DPD for project: " + project.getName());
062            CouplingData couplingData = this.getCouplingData(project);
063            for (org.hackystat.dailyprojectdata.resource.coupling.jaxb.CouplingData data : 
064              classData.getCouplingData()) {
065                int couplingCount = 0;
066                if ("Afferent".equals(couplingType)) {
067                  couplingCount = data.getAfferent().intValue();
068                }
069                else if ("Efferent".equals(couplingType)) {
070                  couplingCount = data.getEfferent().intValue();
071                }
072                else {
073                  couplingCount = data.getAfferent().intValue() + data.getEfferent().intValue();
074                }
075                
076              couplingData.addEntry(couplingCount, data);
077            }
078          }
079          catch (DailyProjectDataClientException e) {
080            session.setFeedback("Exception when getting coupling DPD for project " + project + ": " +
081                e.getMessage());
082          }
083        }
084      }
085      
086      
087      /**
088       * Sets this model to its empty state. 
089       */
090      public void clear() {
091        this.couplingDataMap.clear();
092      }
093      
094    
095      /**
096       * Returns true if this data model contains no information.
097       * Used to figure out if the associated panel should be visible. 
098       * @return True if the data model is empty. 
099       */
100      public boolean isEmpty() {
101        return this.couplingDataMap.isEmpty();
102      }
103      
104      /**
105       * Return the CouplingData instance associated with the specified project.
106       * Creates and returns a new CouplingData instance if one is not yet present.
107       * @param project The project. 
108       * @return The CouplingData instance for this project.  
109       */
110      public CouplingData getCouplingData(Project project) {
111        if (!couplingDataMap.containsKey(project)) {
112          couplingDataMap.put(project, new CouplingData(project));
113        }
114        return couplingDataMap.get(project);
115      }
116      
117      /**
118       * Returns the list of CouplingData instances, needed for markup.
119       * @return The list of CouplingData instances. 
120       */
121      public List<CouplingData> getCouplingDataList() {
122        return new ArrayList<CouplingData>(this.couplingDataMap.values());
123      }
124      
125    }