org.coronastreet.gpxconverter.Strava.java Source code

Java tutorial

Introduction

Here is the source code for org.coronastreet.gpxconverter.Strava.java

Source

/* 
*  Copyright 2012-2014 Coronastreet Networks 
*  Licensed under the Apache License, Version 2.0 (the "License"); 
*  you may not use this file except in compliance with the License. 
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0 
*
*  Unless required by applicable law or agreed to in writing, software 
*  distributed under the License is distributed on an "AS IS" BASIS, 
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
*  implied. See the License for the specific language governing 
*  permissions and limitations under the License 
*/
package org.coronastreet.gpxconverter;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.List;

import javax.swing.JTextArea;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

@SuppressWarnings("deprecation")
public class Strava {

    private int apiVersion = 2;
    private String authenticationURL = "http://www.strava.com/api/v" + apiVersion + "/authentication/login";
    private String uploadURL = "http://www.strava.com/api/v" + apiVersion + "/upload";

    private String email;
    private String password;
    private String tripName;
    private String authToken;
    private String activityType;
    private Document outDoc;
    private String rideStartTime;
    private String deviceType;
    private boolean hasAltimeter = false;

    private JTextArea statusTextArea;
    private List<Trkpt> trackPoints;

    public Strava() {

    }

    private String convertDoc() {
        OutputFormat format = new OutputFormat(outDoc);
        format.setIndenting(true);
        StringWriter stringOut = new StringWriter();
        XMLSerializer serializer = new XMLSerializer(stringOut, format);
        try {
            serializer.serialize(outDoc);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return stringOut.toString();
    }

    public boolean processData() {
        boolean success = false;

        //load the output template
        loadOutFile();

        setIdAndStartTime();
        setDeviceType();

        // Add the track data we imported to the output document
        if (addTrackData()) {
            success = true;
        }

        // Spit out the TCX file
        //printOutFile();
        success = true;
        return success;
    }

    private void setIdAndStartTime() {
        NodeList nl = outDoc.getElementsByTagName("Activity");

        NodeList nl2 = ((Element) nl.item(0)).getElementsByTagName("Id");
        if (nl2 != null && nl2.getLength() > 0) {
            Element el = (Element) nl2.item(0);
            el.appendChild(outDoc.createTextNode(rideStartTime));
        }

        NodeList nl3 = ((Element) nl.item(0)).getElementsByTagName("Lap");
        if (nl3 != null && nl3.getLength() > 0) {
            Element el = (Element) nl3.item(0);
            el.setAttribute("StartTime", rideStartTime);
        }

    }

    private Element createTrackPointElement(Trkpt tp) {

        Element eTrackpoint = outDoc.createElement("Trackpoint");

        //create time element and time text node and attach it to the trackpoint
        Element eTime = outDoc.createElement("Time");
        eTime.appendChild(outDoc.createTextNode(tp.getTime()));
        eTrackpoint.appendChild(eTime);

        //create elevation element and elevation text node and attach it to the trackpoint
        Element eElevation = outDoc.createElement("AltitudeMeters");
        eElevation.appendChild(outDoc.createTextNode(tp.getElevation()));
        eTrackpoint.appendChild(eElevation);

        //create Speed Sensor element and attach it to the trackpoint
        Element eSensorState = outDoc.createElement("SensorState");
        eSensorState.appendChild(outDoc.createTextNode("Absent"));
        eTrackpoint.appendChild(eSensorState);

        // Create Lat/Long and add them to Position
        Element ePosition = outDoc.createElement("Position");
        Element eLatitudeDegrees = outDoc.createElement("LatitudeDegrees");
        eLatitudeDegrees.appendChild(outDoc.createTextNode(tp.getLat()));
        Element eLongitudeDegrees = outDoc.createElement("LongitudeDegrees");
        eLongitudeDegrees.appendChild(outDoc.createTextNode(tp.getLon()));
        ePosition.appendChild(eLongitudeDegrees);
        ePosition.appendChild(eLatitudeDegrees);
        eTrackpoint.appendChild(ePosition);

        //create HeartRate and add it to the trackpoint
        Element eHR = outDoc.createElement("HeartRateBpm");
        eHR.setAttribute("xsi:type", "HeartRateInBeatsPerMinute_t");
        Element eHRValue = outDoc.createElement("Value");
        eHRValue.appendChild(outDoc.createTextNode(tp.getHr()));
        eHR.appendChild(eHRValue);
        eTrackpoint.appendChild(eHR);

        //create Cadence element text node and add it to the trackpoint
        Element eCad = outDoc.createElement("Cadence");
        eCad.appendChild(outDoc.createTextNode(tp.getCad()));
        eTrackpoint.appendChild(eCad);

        //create Temperature element text node and add it to the trackpoint
        Element eTemp = outDoc.createElement("Temperature");
        eTemp.appendChild(outDoc.createTextNode(tp.getTemp()));
        eTrackpoint.appendChild(eTemp);

        return eTrackpoint;

    }

    private void setDeviceType() {

        // Strava only recognizes Garmin devices for Altimeter stuff
        // Everything else shows up as "Mobile"
        if (hasAltimeter) {
            deviceType = "Garmin Edge 800";
        } else {
            deviceType = "Garmin Edge 200";
        }

        NodeList nl = outDoc.getElementsByTagName("Activity");
        NodeList nl1 = ((Element) nl.item(0)).getElementsByTagName("Creator");
        NodeList nl2 = ((Element) nl1.item(0)).getElementsByTagName("Name");
        if (nl2 != null && nl2.getLength() > 0) {
            Element el = (Element) nl2.item(0);
            el.appendChild(outDoc.createTextNode(deviceType));
        }
    }

    private boolean addTrackData() {
        boolean success = false;
        // Get the Track element
        Element track = null;
        Element docEle = outDoc.getDocumentElement();

        // GRabbing the track node. in theory, the node list should always return 1
        NodeList nl = docEle.getElementsByTagName("Track");
        if (nl != null && nl.getLength() > 0) {
            track = (Element) nl.item(0);
        }

        int trkCounter = 0;
        Iterator<Trkpt> it = trackPoints.iterator();
        while (it.hasNext()) {
            Trkpt t = (Trkpt) it.next();
            Element tp = createTrackPointElement(t);
            //dumpNode(tp);
            track.appendChild(tp);
            trkCounter++;
        }
        log("Added " + trkCounter + " trackpoints to the template.");
        if (trkCounter >= 1) {
            success = true;
        }
        return success;
    }

    public void upload() {
        HttpClient httpClient = HttpClientBuilder.create().build();
        if (doLogin()) {
            try {
                HttpPost request = new HttpPost(uploadURL);
                JSONObject activityObject = new JSONObject();
                activityObject.put("token", authToken);
                activityObject.put("type", "TCX");
                activityObject.put("activity_type", activityType);
                activityObject.put("activity_name", tripName);
                String xmlData = convertDoc();
                activityObject.put("data", xmlData);

                StringEntity params = new StringEntity(activityObject.toString());
                //statusLog("Sending Entity: " + activityObject.toString());
                request.addHeader("content-type", "application/json");
                request.setEntity(params);
                HttpResponse response = httpClient.execute(request);

                if (response.getStatusLine().getStatusCode() != 200) {
                    log("Failed to Upload");
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        String output = EntityUtils.toString(entity);
                        log(output);
                    }
                }

                HttpEntity entity = response.getEntity();

                if (entity != null) {
                    String output = EntityUtils.toString(entity);
                    //log(output);
                    JSONObject userInfo = new JSONObject(output);
                    log("Successful Uploaded. ID is " + userInfo.get("upload_id"));
                }
            } catch (Exception ex) {
                // handle exception here
            } finally {
                httpClient.getConnectionManager().shutdown();
            }
        } else {
            log("Failed to upload!");
        }
    }

    protected boolean doLogin() {
        boolean ret = false;
        HttpClient httpClient = HttpClientBuilder.create().build();
        log("Authenticating athlete...");
        try {
            HttpPost request = new HttpPost(authenticationURL);
            String jsonString = "{\"email\":\"" + email + "\",\"password\":\"" + password + "\"} ";
            StringEntity params = new StringEntity(jsonString);
            //log("Sending Entity: " + jsonString);
            request.addHeader("content-type", "application/json");
            request.setEntity(params);
            HttpResponse response = httpClient.execute(request);

            if (response.getStatusLine().getStatusCode() != 200) {
                log("Failed to Login.");
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    //String output = EntityUtils.toString(entity);
                    //log(output);
                }
            }

            HttpEntity entity = response.getEntity();

            if (entity != null) {
                String output = EntityUtils.toString(entity);
                //statusLog(output);
                JSONObject userInfo = new JSONObject(output);
                JSONObject athleteInfo = userInfo.getJSONObject("athlete");
                log("Logged in as " + athleteInfo.get("name"));
                authToken = (String) userInfo.get("token");
                if (authToken.length() > 0) {
                    ret = true;
                }
            } else {
                log("Something went wrong!");
            }

        } catch (Exception ex) {
            // handle exception here
            ex.printStackTrace();
        } finally {
            httpClient.getConnectionManager().shutdown();
        }

        return ret;
    }

    private void loadOutFile() {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder db = dbf.newDocumentBuilder();
            log("Loading TCX template file.");
            outDoc = db
                    .parse(this.getClass().getResourceAsStream("/org/coronastreet/gpxconverter/tcxtemplate.xml"));
        } catch (ParserConfigurationException pce) {
            pce.printStackTrace();
        } catch (SAXException se) {
            se.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    @SuppressWarnings("unused")
    private void dumpNode(JSONObject o) {
        log(o.toString(2));
    }

    private void log(String s) {
        this.statusTextArea.append("STRAVA: " + s + "\n");
        this.statusTextArea.repaint(1);
    }

    @SuppressWarnings("unused")
    private void log(InputStream is) {
        try {
            BufferedReader rd = new BufferedReader(new InputStreamReader(is));
            String line = "";
            while ((line = rd.readLine()) != null) {
                log(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public List<Trkpt> getTrackPoints() {
        return trackPoints;
    }

    public void setTrackPoints(List<Trkpt> trackPoints) {
        this.trackPoints = trackPoints;
    }

    public JTextArea getStatusTextArea() {
        return statusTextArea;
    }

    public void setStatusTextArea(JTextArea statusTextArea) {
        this.statusTextArea = statusTextArea;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getTripName() {
        return tripName;
    }

    public void setTripName(String tripName) {
        this.tripName = tripName;
    }

    public String getActivityType() {
        return activityType;
    }

    public void setActivityType(String at) {
        this.activityType = at;
    }

    public String getRideStartTime() {
        return rideStartTime;
    }

    public void setRideStartTime(String rideStartTime) {
        this.rideStartTime = rideStartTime;
    }

    public void setHasAltimeter(boolean hasAltimeter) {
        this.hasAltimeter = hasAltimeter;
    }

}