001    package org.hackystat.projectbrowser.page.sensordata;
002    
003    import java.util.Calendar;
004    
005    import javax.xml.datatype.XMLGregorianCalendar;
006    
007    import org.hackystat.projectbrowser.page.ProjectBrowserBasePage;
008    import org.hackystat.projectbrowser.ProjectBrowserSession;
009    import org.hackystat.sensorbase.client.SensorBaseClient;
010    import org.hackystat.sensorbase.resource.projects.jaxb.MultiDayProjectSummary;
011    import org.hackystat.sensorbase.resource.projects.jaxb.Project;
012    import org.hackystat.utilities.stacktrace.StackTrace;
013    import org.hackystat.utilities.tstamp.Tstamp;
014    
015    /**
016     * Provides a page with information about SensorData. 
017     * @author Philip Johnson
018     */
019    public class SensorDataPage extends ProjectBrowserBasePage {
020    
021      /** Support serialization. */
022      private static final long serialVersionUID = 1L;
023      
024      SdtSummaryModel sdtSummaryModel = null;
025      
026      /**
027       * Creates this page. 
028       */
029      public SensorDataPage() {
030        add(new SensorDataForm("sensorDataForm", this));
031        add(new SensorDataTablePanel("SensorDataTablePanel", this));
032      }
033      
034      /**
035       * What to do when the user selects a project and date. 
036       */
037      @Override
038      public void onProjectDateSubmit() {
039        try {
040          // Set the footerFeedback to null. 
041          this.footerFeedback = "";
042          SensorDataSession session = ProjectBrowserSession.get().getSensorDataSession();
043          Project project = session.getProject();
044          SensorBaseClient client = ProjectBrowserSession.get().getSensorBaseClient();
045          
046          // Get the first day for which we want data, either the project start day or 1st of month.
047          XMLGregorianCalendar startDay = getStartTime(project, session.getYear(), session.getMonth());
048          // Get number of days for which we can get data, either the project end day or last of month.
049          int numDays = getNumDays(project, startDay, session.getYear(), session.getMonth());
050    
051          MultiDayProjectSummary summary =
052            client.getMultiDayProjectSummary(project.getOwner(), project.getName(), startDay, numDays);
053          // Update the model with this info.
054          session.getSensorDataTableModel().setModel(summary, project);
055          // Since the table in this panel has a variable number of columns that depend upon the model
056          // data, we must rebuild this panel each time we update the model.
057          addOrReplace(new SensorDataTablePanel("SensorDataTablePanel", this));
058          
059        }
060        catch (Exception e) {
061          this.footerFeedback = "Exception getting project summary: " + StackTrace.toString(e);
062        }
063    
064      }
065      
066      /**
067       * Returns the start day to be provided to the MultiDayProjectSummary call. 
068       * The start day is either the first day of the year/month or the first day of the project, 
069       * whichever comes later. 
070       * @param project The project of interest.
071       * @param year The year specified by the user. 
072       * @param month The month specified by the user. 
073       * @return The start day to be used. 
074       */
075      private XMLGregorianCalendar getStartTime(Project project, int year, int month) {
076        // Get the project start time. 
077        XMLGregorianCalendar projectStartTime = project.getStartTime();
078        // Now make a timestamp representing the first day of the passed month.
079        Calendar calendar = Calendar.getInstance();
080        calendar.set(Calendar.YEAR, year);
081        calendar.set(Calendar.MONTH, month);
082        calendar.set(Calendar.DAY_OF_MONTH, calendar.getMinimum(Calendar.DAY_OF_MONTH));
083        calendar.set(Calendar.HOUR, 0);
084        calendar.set(Calendar.MINUTE, 0);
085        calendar.set(Calendar.SECOND, 0);
086        calendar.set(Calendar.MILLISECOND, 0);
087        XMLGregorianCalendar userStartTime = Tstamp.makeTimestamp(calendar.getTimeInMillis());
088        return Tstamp.greaterThan(projectStartTime, userStartTime) ? projectStartTime : userStartTime;
089      }
090      
091      /**
092       * Returns the number of days in the interval between the startTime and either the project
093       * end day or the last day of the passed month, whichever comes first. 
094       * @param project The project that we use to get the project end date.
095       * @param startTime The startTime. 
096       * @param year The user-specified year, from which we get the user's end day.
097       * @param month The user-specified month, from which we get the user's end day.
098       * @return The number of days of data that we can retrieve.
099       */
100      private int getNumDays(Project project, XMLGregorianCalendar startTime, int year, int month) {
101        // Get the project end time. 
102        XMLGregorianCalendar projectEndTime = project.getEndTime();
103        // Now make a timestamp representing the last day of the passed month.
104        Calendar calendar = Calendar.getInstance();
105        calendar.set(Calendar.YEAR, year);
106        calendar.set(Calendar.MONTH, month);
107        calendar.set(Calendar.DAY_OF_MONTH, calendar.getMaximum(Calendar.DAY_OF_MONTH));
108        calendar.set(Calendar.HOUR, 0);
109        calendar.set(Calendar.MINUTE, 0);
110        calendar.set(Calendar.SECOND, 0);
111        calendar.set(Calendar.MILLISECOND, 0);
112        XMLGregorianCalendar userEndTime = Tstamp.makeTimestamp(calendar.getTimeInMillis());
113        
114        // Figure out which is the real end time. 
115        XMLGregorianCalendar endTime = 
116          Tstamp.lessThan(projectEndTime, userEndTime) ? projectEndTime : userEndTime;
117        
118        // Now figure out the number of days in this interval.
119        return Tstamp.daysBetween(startTime, endTime);
120      }
121      
122    }