nl.welteninstituut.tel.la.importers.rescuetime.RescueTimeTask.java Source code

Java tutorial

Introduction

Here is the source code for nl.welteninstituut.tel.la.importers.rescuetime.RescueTimeTask.java

Source

/*
 * Copyright (C) 2015 Open Universiteit Nederland
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */
package nl.welteninstituut.tel.la.importers.rescuetime;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Logger;

import nl.welteninstituut.tel.la.Configuration;
import nl.welteninstituut.tel.la.importers.ImportTask;
import nl.welteninstituut.tel.la.jdomanager.StatementManager;
import nl.welteninstituut.tel.oauth.jdo.AccountJDO;
import nl.welteninstituut.tel.oauth.jdo.AccountManager;
import nl.welteninstituut.tel.oauth.jdo.OauthServiceAccount;
import nl.welteninstituut.tel.oauth.jdo.OauthServiceAccountManager;

import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * This task fetches the RescueTime data for a user. Data is processed per day.
 * 
 * @author Harrie Martens
 *
 */
public class RescueTimeTask extends ImportTask {

    private static final long serialVersionUID = 2L;
    private static final Logger log = Logger.getLogger(RescueTimeTask.class.getName());

    private static final String URI_FORMAT = "https://www.rescuetime.com/anapi/data?key=%s&pv=interval&rs=minute&rb=%2$s&re=%2$s&format=json";
    private static final String XAPI_RESCUETIME_FORMAT = "{\"timestamp\":\"%s\","
            + "\"actor\": {\"objectType\": \"Agent\",\"mbox\":\"mailto:%s\"},"
            + "\"verb\":{\"id\":\"http://activitystrea.ms/schema/1.0/access\","
            + "\"display\":{\"en-US\":\"indicates the user accessed something\"}},"
            + "\"object\":{\"objectType\":\"Activity\",\"id\":\"%s\",\"definition\":{\"name\":{\"en-US\":\"name of the application\"},"
            + "\"description\":{\"en-US\":\"description of the application\"},\"type\":\"http://activitystrea.ms/schema/1.0/application\"}},"
            + "\"result\":{\"duration\":\"PT%d.00S\"}}";

    private String accountId;
    private DateTime start;

    public RescueTimeTask() {
    }

    public RescueTimeTask(final String accountId) {
        this.accountId = accountId;
    }

    public RescueTimeTask(final String accountId, final DateTime start) {
        this(accountId);
        this.start = start;
    }

    @Override
    public void run() {
        OauthServiceAccount account = getAccount(AccountJDO.RESCUETIMECLIENT, accountId);
        if (account != null) {

            if (start == null) {

                if (account.getLastSynced() == null) {
                    String startDate = Configuration.get(Configuration.STARTDATE);
                    if (startDate != null) {
                        start = new DateTime(startDate + "T00:00");
                    } else {
                        log.severe(Configuration.STARTDATE + " is missing from configuration");
                    }
                } else {
                    start = new DateTime(account.getLastSynced());
                }
            }

            if (start != null) {
                LocalDate localDate = start.toLocalDate();

                try {
                    JSONObject data = getData(account.getAccessToken(), localDate);

                    System.out.println(data);

                    JSONArray rows = data.getJSONArray("rows");
                    String mbox = null;

                    if (rows.length() > 0) {
                        AccountJDO pa = AccountManager.getAccount(account.getPrimaryAccount());
                        mbox = pa != null ? pa.getEmail() : null;
                    }

                    Row row = null;
                    for (int i = 0; i < rows.length(); i++) {
                        row = new Row(rows.getJSONArray(i));
                        if (row.getDate().isEqual(start) || row.getDate().isAfter(start)) {

                            if (isTimeAllowed(row.getDate())) {
                                String xapi = String.format(XAPI_RESCUETIME_FORMAT, row.getDate(), mbox,
                                        row.getActivity(), row.getTimeSpent());
                                StatementManager.addStatement(xapi, "rescuetime");
                            }
                        }
                    }

                    boolean isNotToday = localDate.isBefore(new LocalDate());

                    if (isNotToday) {
                        start = localDate.plusDays(1).toDateTimeAtStartOfDay();
                    } else {
                        if (row != null) {
                            start = row.getDate().plusSeconds(1);
                        }
                    }

                    account.setLastSynced(start.toDate());
                    OauthServiceAccountManager.updateOauthServiceAccount(account);

                    if (isNotToday) {
                        ImportTask.scheduleTask(new RescueTimeTask(accountId, start));
                    }

                } catch (JSONException | IOException e) {
                    e.printStackTrace();
                }

            }

        } else {
            log.severe("no RescueTime service account found for " + accountId);
        }
    }

    private JSONObject getData(final String apiKey, final LocalDate date)
            throws MalformedURLException, JSONException, IOException {
        String uri = String.format(URI_FORMAT, apiKey, date.toString());

        JSONObject data = new JSONObject(readURL(new URL(uri)));
        if (data.has("error")) {
            throw new JSONException(data.getString("error"));
        }

        return data;
    }

    private String readURL(URL url) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        InputStream is = connection.getInputStream();
        int r;
        while ((r = is.read()) != -1) {
            baos.write(r);
        }
        return new String(baos.toByteArray());
    }

    private class Row {
        private final DateTime date;
        private final long timeSpent;
        private final String activity;

        // private final String category;

        private Row(final JSONArray data) throws JSONException {
            date = new DateTime(data.getString(0));
            timeSpent = data.getLong(1);
            activity = data.getString(3);
            // category = data.getString(4);
        }

        protected DateTime getDate() {
            return date;
        }

        protected long getTimeSpent() {
            return timeSpent;
        }

        protected String getActivity() {
            return activity;
        }

        /*
         * protected String getcategory() { return category; }
         */
    }

}