001    package org.hackystat.dailyprojectdata.resource.commit;
002    
003    import static org.hackystat.dailyprojectdata.server.ServerProperties.SENSORBASE_FULLHOST_KEY;
004    
005    import java.io.StringWriter;
006    import java.util.logging.Logger;
007    
008    import javax.xml.bind.JAXBContext;
009    import javax.xml.bind.Marshaller;
010    import javax.xml.datatype.XMLGregorianCalendar;
011    import javax.xml.parsers.DocumentBuilder;
012    import javax.xml.parsers.DocumentBuilderFactory;
013    import javax.xml.transform.Transformer;
014    import javax.xml.transform.TransformerFactory;
015    import javax.xml.transform.dom.DOMSource;
016    import javax.xml.transform.stream.StreamResult;
017    
018    import org.hackystat.dailyprojectdata.resource.commit.jaxb.CommitDailyProjectData;
019    import org.hackystat.dailyprojectdata.resource.commit.jaxb.MemberData;
020    import org.hackystat.dailyprojectdata.resource.dailyprojectdata.DailyProjectDataResource;
021    import org.hackystat.sensorbase.client.SensorBaseClient;
022    import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorDataIndex;
023    import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorDataRef;
024    import org.hackystat.utilities.tstamp.Tstamp;
025    import org.restlet.Context;
026    import org.restlet.data.MediaType;
027    import org.restlet.data.Request;
028    import org.restlet.data.Response;
029    import org.restlet.resource.Representation;
030    import org.restlet.resource.Variant;
031    import org.w3c.dom.Document;
032    
033    /**
034     * Implements the Resource for processing GET
035     * {host}/commit/{user}/{project}/{timestamp}/ requests. 
036     * 
037     * Authenticated user must be the uriUser, or Admin, or project member. 
038     * 
039     * @author jsakuda
040     * @author austen
041     */
042    public class CommitResource extends DailyProjectDataResource {
043      /**
044       * The standard constructor.
045       * 
046       * @param context The context.
047       * @param request The request object.
048       * @param response The response object.
049       */
050      public CommitResource(Context context, Request request, Response response) {
051        super(context, request, response);
052      }
053    
054      /**
055       * Returns an CoverageDailyProjectData instance representing the Coverage
056       * associated with the Project data, or null if not authorized.
057       * @param variant The representational variant requested.
058       * @return The representation.
059       */
060      @Override
061      public Representation represent(Variant variant) {
062        Logger logger = this.server.getLogger();
063        logger.fine("Commit DPD: Starting");
064        if (variant.getMediaType().equals(MediaType.TEXT_XML)) {
065          try {
066            // [1] get the SensorBaseClient for the user making this request.
067            SensorBaseClient client = super.getSensorBaseClient();
068            // [2] Check the front side cache and return if the DPD is found and is OK to access.
069            String cachedDpd = this.server.getFrontSideCache().get(uriUser, project, uriString);
070            if ((cachedDpd != null) && client.inProject(uriUser, project)) {
071              return super.getStringRepresentation(cachedDpd);
072            }
073            // [2] get a SensorDataIndex of all Coverage data for this Project on
074            // the requested day.
075            XMLGregorianCalendar startTime = Tstamp.makeTimestamp(this.timestamp);
076            XMLGregorianCalendar endTime = Tstamp.incrementDays(startTime, 1);
077            logger.fine("Commit DPD: Requesting index: " + uriUser + " " + project);
078            SensorDataIndex index = client.getProjectSensorData(this.uriUser, this.project,
079                startTime, endTime, "Commit");
080            logger.fine("Commit DPD: Got index: " + index.getSensorDataRef().size() + " instances");
081    
082            // [3] Add all of the appropriate data to the data container.
083            CommitDataContainer container = new CommitDataContainer();
084            for (SensorDataRef ref : index.getSensorDataRef()) {
085              container.addCommitData(client.getSensorData(ref));
086            }
087            logger.fine("Commit DPD: retrieved instances, now building the DPD instance.");
088    
089            // [4] Get the aggregate data for each project member.
090            String sensorBaseHost = this.server.getServerProperties().get(SENSORBASE_FULLHOST_KEY);
091            CommitDailyProjectData commitData = new CommitDailyProjectData();
092            for (String owner : container.getOwners()) {
093              MemberData memberData = new MemberData();
094              memberData.setMemberUri(sensorBaseHost + "users/" + owner);
095              memberData.setCommits(container.getCommits(owner));
096              memberData.setLinesAdded(container.getLinesAdded(owner));
097              memberData.setLinesDeleted(container.getLinesDeleted(owner));
098              memberData.setLinesModified(container.getLinesModified(owner));
099              commitData.getMemberData().add(memberData);
100            }
101    
102            commitData.setStartTime(startTime);
103            commitData.setOwner(this.uriUser);
104            commitData.setProject(this.project);
105            String xmlData = this.makeCommit(commitData);
106            if (!Tstamp.isYesterdayOrLater(startTime)) {
107              this.server.getFrontSideCache().put(uriUser, project, uriString, xmlData);
108            }
109            logRequest("Commit");
110            return super.getStringRepresentation(xmlData);
111          }
112          catch (Exception e) {
113            setStatusError("Error creating Commit DPD.", e);
114            return null;
115          }
116        }
117        return null;
118      }
119    
120      /**
121       * Returns the passed SensorData instance as a String encoding of its XML
122       * representation.
123       * 
124       * @param data The SensorData instance.
125       * @return The XML String representation.
126       * @throws Exception If problems occur during translation.
127       */
128      private String makeCommit(CommitDailyProjectData data) throws Exception {
129        JAXBContext codeIssueJAXB = (JAXBContext) this.server.getContext().getAttributes().get(
130            "CommitJAXB");
131        Marshaller marshaller = codeIssueJAXB.createMarshaller();
132        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
133        dbf.setNamespaceAware(true);
134        DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
135        Document doc = documentBuilder.newDocument();
136        marshaller.marshal(data, doc);
137        DOMSource domSource = new DOMSource(doc);
138        StringWriter writer = new StringWriter();
139        StreamResult result = new StreamResult(writer);
140        TransformerFactory tf = TransformerFactory.newInstance();
141        Transformer transformer = tf.newTransformer();
142        transformer.transform(domSource, result);
143        return writer.toString();
144      }
145    }