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 }