001    package org.hackystat.projectbrowser.page.sensordata;
002    
003    import java.io.Serializable;
004    import java.util.ArrayList;
005    import java.util.Iterator;
006    import java.util.List;
007    
008    import javax.xml.datatype.XMLGregorianCalendar;
009    
010    import org.apache.wicket.markup.repeater.data.IDataProvider;
011    import org.apache.wicket.model.IModel;
012    import org.apache.wicket.model.Model;
013    import org.hackystat.projectbrowser.ProjectBrowserSession;
014    import org.hackystat.sensorbase.client.SensorBaseClient;
015    import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorDataIndex;
016    import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorDataRef;
017    import org.hackystat.utilities.stacktrace.StackTrace;
018    import org.hackystat.utilities.tstamp.Tstamp;
019    
020    /**
021     * Provides an IDataProvider for the SensorDataDetails panel. The goal of this implementation is to
022     * support a pageable list view of the selected sensor data, where each page is retrieved from the
023     * SensorBase when it is actually requested by the user.
024     * 
025     * @author Philip Johnson
026     * 
027     */
028    public class SensorDataDetailsProvider implements IDataProvider {
029    
030      /** For serialization. */
031      private static final long serialVersionUID = 1L;
032      /** Contains the list of SensorDataDetails for the selected summary. */
033      private List<SensorDataDetails> detailsList = new ArrayList<SensorDataDetails>();
034      
035      /**
036       * Creates an empty SensorDataDetailsProvider. 
037       */
038      public SensorDataDetailsProvider () {
039        // don't do anything here. 
040      }
041      
042      /**
043       * Used by the SdtSummary link to indicate how the model should be updated.
044       * @param sdtName The sdtName.
045       * @param tool The tool.
046       * @param start The start time. 
047       */
048      public void setSensorDataDetailsProvider(String sdtName, String tool, long start) {
049        detailsList.clear();
050        SensorBaseClient client = ProjectBrowserSession.get().getSensorBaseClient();
051        SensorDataSession session = ProjectBrowserSession.get().getSensorDataSession();
052        String projectName = session.getProject().getName();
053        String owner = session.getProject().getOwner();
054        XMLGregorianCalendar startTime = Tstamp.makeTimestamp(start);
055        XMLGregorianCalendar endTime = Tstamp.incrementDays(startTime, 1);
056        try {
057          SensorDataIndex index =
058            client.getProjectSensorData(owner, projectName, startTime, endTime, sdtName, tool);
059          for (SensorDataRef ref : index.getSensorDataRef()) {
060            detailsList.add(new SensorDataDetails(ref));
061          }
062        }
063        catch (Exception e) {
064          System.out.println("Error getting sensor data: " + StackTrace.toString(e));
065        }
066      }
067    
068      /**
069       * Provides an iterator over the specified subset of SensorData.
070       * 
071       * @param first The first row to display.
072       * @param count The minimum number of rows that the iterator will work on.
073       * @return The iterator for the specified range. 
074       */
075      @SuppressWarnings("unchecked")
076      public Iterator iterator(int first, int count) {
077        return this.detailsList.subList(first, first + count).iterator();
078      }
079    
080      /**
081       * Callback used by the consumer of this data provider to wrap SensorDataDetails instances 
082       * retrieved from iterator(int, int) with a model (usually a detachable one).
083       * 
084       * @param data The SensorDataDetails instance returned from the iterator that needs to be wrapped.
085       * @return A model that wraps this instance.  
086       */
087      public IModel model(Object data) {
088        return new Model((Serializable) data);
089      }
090    
091      /**
092       * The total number of items in this provider.
093       * @return The total size of this model.
094       */
095      public int size() {
096        return this.detailsList.size();
097      }
098    
099      /**
100       * Hook for detachable models, but we're not doing that yet. 
101       */
102      public void detach() {
103        // Does nothing for now. 
104      }
105    
106      /**
107       * Returns true if this model does not contain any data. 
108       * @return True if no data. 
109       */
110      public boolean isEmpty() {
111        return detailsList.isEmpty();
112      }
113      
114    }