001    package org.hackystat.sensorbase.resource.projects;
002    
003    import javax.xml.datatype.XMLGregorianCalendar;
004    
005    import org.hackystat.sensorbase.resource.sensorbase.SensorBaseResource;
006    import org.hackystat.utilities.tstamp.Tstamp;
007    import org.restlet.Context;
008    import org.restlet.data.MediaType;
009    import org.restlet.data.Request;
010    import org.restlet.data.Response;
011    import org.restlet.resource.Representation;
012    import org.restlet.resource.Variant;
013    
014    /**
015     * The resource for processing 
016     * [host]/projects/[owner]/[project]/snapshot?sdt=[sdt]&startTime=[tstamp]&endTime=[tstamp]&tool=[t]
017     * Returns a SensorDataIndex containing the "snapshot" sensor data for this project with the
018     * given sdt and time interval.   The "snapshot" is the data set with the most recent runtime
019     * value for the given time interval.  The tool parameter is optional.  
020     * 
021     * @author Philip Johnson
022     */
023    public class UserProjectSnapshotResource extends SensorBaseResource {
024      
025      /** An optional query parameter. */
026      private String startTime;
027      /** An optional query string parameter. */
028      private String endTime;
029      /** An optional query parameter. */
030      private String sdt;
031      /** An optional query parameter. */
032      private String tool;
033    
034      
035      /**
036       * Provides the following representational variants: TEXT_XML.
037       * @param context The context.
038       * @param request The request object.
039       * @param response The response object.
040       */
041      public UserProjectSnapshotResource(Context context, Request request, Response response) {
042        super(context, request, response);
043        this.startTime = (String) request.getAttributes().get("startTime");
044        this.endTime = (String) request.getAttributes().get("endTime");
045        this.sdt = (String) request.getAttributes().get("sdt");
046        this.tool = (String) request.getAttributes().get("tool");
047      }
048      
049      /**
050       * Returns a SensorDataIndex containing the "snapshot" for this sdt, time interval,
051       * and tool (if supplied).  The "snapshot" is the data with the most recent runtime value.
052       * 
053       * Returns an error condition if:
054       * <ul>
055       * <li> The user does not exist.
056       * <li> The authenticated user is not the uriUser or the Admin or a member of the project.
057       * <li> The Project Resource named by the User and Project does not exist.
058       * <li> startTime or endTime is not an XMLGregorianCalendar string.
059       * <li> endTime is earlier than startTime.
060       * </ul>
061       * 
062       * @param variant The representational variant requested.
063       * @return The representation. 
064       */
065      @Override
066      public Representation represent(Variant variant) {
067        if (!validateUriUserIsUser() ||
068            !validateUriProjectName() ||
069            !validateProjectViewer()) {
070          return null;
071        }  
072    
073        // If startTime is provided, then both startTime and endTime must be XMLGregorianCalendars,
074        // and startTime must be <= endTime.
075        XMLGregorianCalendar startTimeXml = null;
076        XMLGregorianCalendar endTimeXml = null;
077        if (this.startTime != null) {
078          try {
079            startTimeXml = Tstamp.makeTimestamp(this.startTime);
080          }
081          catch (Exception e) {
082            setStatusBadTimestamp(this.startTime);
083            return null;
084          }
085          try {
086            endTimeXml = Tstamp.makeTimestamp(this.endTime);
087          }
088          catch (Exception e) {
089            setStatusBadTimestamp(this.endTime);
090            return null;
091          }
092          // We have a start and end time. Make sure startTime is not greater than endTime.
093          if (Tstamp.greaterThan(startTimeXml, endTimeXml)) {
094            setStatusMiscError("startTime cannot be greater than endTime.");
095            return null;
096          }
097          // Make sure that startTime is not less than project.startTime.
098          if (!ProjectUtils.isValidStartTime(project, startTimeXml)) {
099            setStatusMiscError(String.format("%s cannot be less than project start time of %s", 
100                startTimeXml, project.getStartTime()));
101            return null;
102          }
103          // And that endTime is not past the project endTime (if there is a project endTime).
104          if ((project.getEndTime() != null) && 
105              (!ProjectUtils.isValidEndTime(project, endTimeXml))) {
106            setStatusMiscError(String.format("%s cannot be greater than project end time of %s", 
107                endTimeXml, project.getEndTime()));
108            return null;
109          }
110        }
111        if (variant.getMediaType().equals(MediaType.TEXT_XML)) {
112          try {
113            // Return the snapshot.
114            String data = super.projectManager.getProjectSensorDataSnapshot(project,
115                startTimeXml, endTimeXml, sdt, tool);
116            return SensorBaseResource.getStringRepresentation(data);
117          }
118          catch (Exception e) {
119            setStatusInternalError(e);
120          }
121        }
122        return null;
123      }
124    }