ch.simas.jtoggl.JToggl.java Source code

Java tutorial

Introduction

Here is the source code for ch.simas.jtoggl.JToggl.java

Source

/*
 * jtoggl - Java Wrapper for Toggl REST API https://www.toggl.com/public/api
 *
 * Copyright (C) 2011 by simas GmbH, Moosentli 7, 3235 Erlach, Switzerland
 * http://www.simas.ch
 * 
 * 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 ch.simas.jtoggl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import ch.simas.jtoggl.util.DateUtil;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
import com.sun.jersey.api.client.filter.LoggingFilter;
import com.sun.jersey.core.util.MultivaluedMapImpl;

/**
 * API Class for Toggl REST API.
 * 
 * @author Simon Martinelli
 */
public class JToggl {

    public static final String DATA = "data";
    public static final String PLACEHOLDER = "{0}";
    private final static String TIME_ENTRIES = "https://www.toggl.com/api/v8/time_entries";
    private final static String TIME_ENTRY = "https://www.toggl.com/api/v8/time_entries/{0}";
    private final static String CURRENT_TIME_ENTRY = "https://www.toggl.com/api/v8/time_entries/current";
    private final static String TIME_ENTRY_START = "https://www.toggl.com/api/v8/time_entries/start";
    private final static String TIME_ENTRY_STOP = "https://www.toggl.com/api/v8/time_entries/{0}/stop";
    private final static String WORKSPACES = "https://www.toggl.com/api/v8/workspaces";
    private final static String WORKSPACES_USERS = "https://www.toggl.com/api/v8/workspaces/{0}/users";
    private final static String WORKSPACE_PROJECTS = "https://www.toggl.com/api/v8/workspaces/{0}/projects";
    private final static String WORKSPACE_TASKS = "https://www.toggl.com/api/v8/workspaces/{0}/tasks";
    private final static String WORKSPACE_CLIENTS = "https://www.toggl.com/api/v8/workspaces/{0}/clients";
    private final static String CLIENTS = "https://www.toggl.com/api/v8/clients";
    private final static String CLIENT = "https://www.toggl.com/api/v8/clients/{0}";
    private final static String PROJECTS = "https://www.toggl.com/api/v8/projects";
    private final static String PROJECT = "https://www.toggl.com/api/v8/projects/{0}";
    private final static String TASKS = "https://www.toggl.com/api/v8/tasks";
    private final static String TASK = "https://www.toggl.com/api/v8/tasks/{0}";
    private final static String TAGS = "https://www.toggl.com/api/v8/tags";
    private final static String PROJECT_USERS = "https://www.toggl.com/api/v8/workspaces/31366/project_users";
    private final static String GET_CURRENT_USER = "https://www.toggl.com/api/v8/me";
    private final String user;
    private final String password;
    private boolean log = false;

    /**
     * Constructor to create an instance of JToggl that uses an api token to connect to toggl.
     * 
     * @param apiToken the api token to connect to toggl
     */
    public JToggl(String apiToken) {
        this(apiToken, "api_token");
    }

    /**
     * Constructor to create an instance of JToggl.
     * 
     * @param user username or api_token
     * @param password password or string "api_token"
     */
    public JToggl(String user, String password) {
        this.user = user;
        this.password = password;
    }

    /**
     * Get latest time entries.
     * 
     * @return list of {@link TimeEntry}
     */
    public List<TimeEntry> getTimeEntries() {
        return this.getTimeEntries(null, null);
    }

    /**
     * Get time entries started in a specific time range. 
     * By default, the number of days from the field "How long are time entries 
     * visible in the timer" under "My settings" in Toggl is used to determine 
     * which time entries to return but you can specify another date range using 
     * start_date and end_date parameters.
     * 
     * @param startDate
     * @param endDate
     * @return list of {@link TimeEntry}
     */
    public List<TimeEntry> getTimeEntries(Date startDate, Date endDate) {
        Client client = prepareClient();
        WebResource webResource = client.resource(TIME_ENTRIES);

        if (startDate != null && endDate != null) {
            MultivaluedMap queryParams = new MultivaluedMapImpl();
            queryParams.add("start_date", DateUtil.convertDateToString(startDate));
            queryParams.add("end_date", DateUtil.convertDateToString(endDate));
            webResource = webResource.queryParams(queryParams);
        }
        String response = webResource.get(String.class);
        JSONArray data = (JSONArray) JSONValue.parse(response);

        List<TimeEntry> entries = new ArrayList<TimeEntry>();
        if (data != null) {
            for (Object obj : data) {
                JSONObject entryObject = (JSONObject) obj;
                entries.add(new TimeEntry(entryObject.toJSONString()));
            }
        }
        return entries;
    }

    /**
     * Get a time entry.
     * 
     * @param id
     * @return TimeEntry or null if no Entry is found.
     */
    public TimeEntry getTimeEntry(Long id) {
        Client client = prepareClient();
        String url = TIME_ENTRY.replace(PLACEHOLDER, id.toString());
        WebResource webResource = client.resource(url);

        String response = null;
        try {
            response = webResource.get(String.class);
        } catch (UniformInterfaceException uniformInterfaceException) {
            return null;
        }

        JSONObject object = (JSONObject) JSONValue.parse(response);
        JSONObject data = (JSONObject) object.get(DATA);
        if (data == null)
            return null;

        return new TimeEntry(data.toJSONString());
    }

    /**
     * Get running time entry
     * 
     * @return The running time entry or null if none
     */
    public TimeEntry getCurrentTimeEntry() {
        Client client = prepareClient();
        WebResource webResource = client.resource(CURRENT_TIME_ENTRY);

        String response = null;
        try {
            response = webResource.get(String.class);
        } catch (UniformInterfaceException uniformInterfaceException) {
            return null;
        }

        JSONObject object = (JSONObject) JSONValue.parse(response);
        JSONObject data = (JSONObject) object.get(DATA);
        if (data == null)
            return null;

        return new TimeEntry(data.toJSONString());
    }

    /**
     * Create a new time entry.
     * 
     * @param timeEntry
     * @return created {@link TimeEntry}
     */
    public TimeEntry createTimeEntry(TimeEntry timeEntry) {
        Client client = prepareClient();
        WebResource webResource = client.resource(TIME_ENTRIES);

        JSONObject object = createTimeEntryRequestParameter(timeEntry);
        String response = webResource.entity(object.toJSONString(), MediaType.APPLICATION_JSON_TYPE)
                .post(String.class);

        object = (JSONObject) JSONValue.parse(response);
        JSONObject data = (JSONObject) object.get(DATA);
        return new TimeEntry(data.toJSONString());
    }

    /**
     * Create and then start the given time entry.
     * 
     * @param timeEntry
     *            the time entry to start
     * @return created {@link TimeEntry}
     */
    public TimeEntry startTimeEntry(TimeEntry timeEntry) {
        Client client = prepareClient();
        WebResource webResource = client.resource(TIME_ENTRY_START);

        JSONObject object = createTimeEntryRequestParameter(timeEntry);
        String response = webResource.entity(object.toJSONString(), MediaType.APPLICATION_JSON_TYPE)
                .post(String.class);

        object = (JSONObject) JSONValue.parse(response);
        JSONObject data = (JSONObject) object.get(DATA);
        return new TimeEntry(data.toJSONString());
    }

    /**
     * Stop the given time entry.
     * 
     * @param timeEntry
     *            to time entry to stop
     * @return the stopped {@link TimeEntry}
     */
    public TimeEntry stopTimeEntry(TimeEntry timeEntry) {
        Client client = prepareClient();
        String url = TIME_ENTRY_STOP.replace(PLACEHOLDER, timeEntry.getId().toString());
        WebResource webResource = client.resource(url);

        JSONObject object = createTimeEntryRequestParameter(timeEntry);
        String response = webResource.entity(object.toJSONString(), MediaType.APPLICATION_JSON_TYPE)
                .put(String.class);

        object = (JSONObject) JSONValue.parse(response);
        JSONObject data = (JSONObject) object.get(DATA);
        return new TimeEntry(data.toJSONString());
    }

    /**
     * Update a time entry.
     * 
     * @param timeEntry
     * @return created {@link TimeEntry}
     */
    public TimeEntry updateTimeEntry(TimeEntry timeEntry) {
        Client client = prepareClient();
        String url = TIME_ENTRY.replace(PLACEHOLDER, timeEntry.getId().toString());
        WebResource webResource = client.resource(url);

        JSONObject object = createTimeEntryRequestParameter(timeEntry);
        String response = webResource.entity(object.toJSONString(), MediaType.APPLICATION_JSON_TYPE)
                .put(String.class);

        object = (JSONObject) JSONValue.parse(response);
        JSONObject data = (JSONObject) object.get(DATA);
        return new TimeEntry(data.toJSONString());
    }

    /**
     * Destroy a time entry.
     * 
     * @param id 
     */
    public void destroyTimeEntry(Long id) {
        Client client = prepareClient();
        String url = TIME_ENTRY.replace(PLACEHOLDER, id.toString());
        WebResource webResource = client.resource(url);

        webResource.delete(String.class);
    }

    /**
     * Get workspaces.
     * 
     * @return list of {@link Workspace}
     */
    public List<Workspace> getWorkspaces() {
        Client client = prepareClient();
        WebResource webResource = client.resource(WORKSPACES);

        String response = webResource.get(String.class);
        JSONArray data = (JSONArray) JSONValue.parse(response);

        List<Workspace> workspaces = new ArrayList<Workspace>();
        if (data != null) {
            for (Object obj : data) {
                JSONObject entryObject = (JSONObject) obj;
                workspaces.add(new Workspace(entryObject.toJSONString()));
            }
        }
        return workspaces;
    }

    /**
     * Get clients.
     * 
     * @return list of {@link ch.simas.jtoggl.Client}
     */
    public List<ch.simas.jtoggl.Client> getClients() {
        Client client = prepareClient();
        WebResource webResource = client.resource(CLIENTS);

        String response = webResource.get(String.class);
        JSONArray data = (JSONArray) JSONValue.parse(response);

        List<ch.simas.jtoggl.Client> clients = new ArrayList<ch.simas.jtoggl.Client>();
        if (data != null) {
            for (Object obj : data) {
                JSONObject entryObject = (JSONObject) obj;
                clients.add(new ch.simas.jtoggl.Client(entryObject.toJSONString()));
            }
        }
        return clients;
    }

    /**
     * Create a new client.
     * 
     * @param clientObject
     * @return created {@link ch.simas.jtoggl.Client}
     */
    public ch.simas.jtoggl.Client createClient(ch.simas.jtoggl.Client clientObject) {
        Client client = prepareClient();
        WebResource webResource = client.resource(CLIENTS);

        JSONObject object = createClientRequestParameter(clientObject);
        String response = webResource.entity(object.toJSONString(), MediaType.APPLICATION_JSON_TYPE)
                .post(String.class);

        object = (JSONObject) JSONValue.parse(response);
        JSONObject data = (JSONObject) object.get(DATA);
        return new ch.simas.jtoggl.Client(data.toJSONString());
    }

    /**
     * Update a client.
     * 
     * @param clientObject
     * @return updated {@link ch.simas.jtoggl.Client}
     */
    public ch.simas.jtoggl.Client updateClient(ch.simas.jtoggl.Client clientObject) {
        Client client = prepareClient();
        String url = CLIENT.replace(PLACEHOLDER, clientObject.getId().toString());
        WebResource webResource = client.resource(url);

        JSONObject object = createClientRequestParameter(clientObject);
        String response = webResource.entity(object.toJSONString(), MediaType.APPLICATION_JSON_TYPE)
                .put(String.class);

        object = (JSONObject) JSONValue.parse(response);
        JSONObject data = (JSONObject) object.get(DATA);
        return new ch.simas.jtoggl.Client(data.toJSONString());
    }

    /**
     * Destroy a client.
     * 
     * @param id 
     */
    public void destroyClient(Long id) {
        Client client = prepareClient();
        String url = CLIENT.replace(PLACEHOLDER, id.toString());
        WebResource webResource = client.resource(url);

        webResource.delete(String.class);
    }

    /**
     * Get projects.
     * 
     * @return list of {@link Project}
     */
    public List<Project> getProjects() {
        List<Project> projects = new ArrayList<Project>();

        List<Workspace> workspaces = getWorkspaces();
        for (Workspace workspace : workspaces) {
            List<Project> workspaceProjects = getWorkspaceProjects(workspace.getId());
            for (Project project : workspaceProjects) {
                project.setWorkspace(workspace);
            }
            projects.addAll(workspaceProjects);
        }

        return projects;
    }

    /**
     * Create a new project.
     * @param project
     * @return created {@link Project}
     */
    public Project createProject(Project project) {
        Client client = prepareClient();
        WebResource webResource = client.resource(PROJECTS);

        JSONObject object = createProjectRequestParameter(project);
        String response = webResource.entity(object.toJSONString(), MediaType.APPLICATION_JSON_TYPE)
                .post(String.class);

        object = (JSONObject) JSONValue.parse(response);
        JSONObject data = (JSONObject) object.get(DATA);
        return new Project(data.toJSONString());
    }

    /**
     * Update a project.
     * 
     * @param project
     * @return updated {@link Project}
     */
    public Project updateProject(Project project) {
        Client client = prepareClient();
        String url = PROJECT.replace(PLACEHOLDER, project.getId().toString());
        WebResource webResource = client.resource(url);

        JSONObject object = createProjectRequestParameter(project);
        String response = webResource.entity(object.toJSONString(), MediaType.APPLICATION_JSON_TYPE)
                .put(String.class);

        object = (JSONObject) JSONValue.parse(response);
        JSONObject data = (JSONObject) object.get(DATA);
        return new Project(data.toJSONString());
    }

    /**
     * Create a new project user.
     * 
     * @param projectUser
     * @return created {@link ProjectUser}
     */
    public ProjectUser createProjectUser(ProjectUser projectUser) {
        Client client = prepareClient();
        WebResource webResource = client.resource(PROJECT_USERS);

        JSONObject object = createProjectUserRequestParameter(projectUser);
        String response = webResource.entity(object.toJSONString(), MediaType.APPLICATION_JSON_TYPE)
                .post(String.class);

        object = (JSONObject) JSONValue.parse(response);
        JSONObject data = (JSONObject) object.get(DATA);
        return new ProjectUser(data.toJSONString());
    }

    /**
     * Get tasks
     * The user field may contain the users data who has been assigned with the task.
     * 
     * @return list of {@link Task}
     */
    public List<Task> getTasks() {
        List<Task> tasks = new ArrayList<Task>();

        List<Workspace> workspaces = getWorkspaces();
        for (Workspace workspace : workspaces) {
            List<Task> workspaceTasks = getActiveWorkspaceTasks(workspace.getId());
            tasks.addAll(workspaceTasks);
        }

        return tasks;
    }

    /** 
     * Create a new task.
     * 
     * @param task
     * @return created {@link Task}
     */
    public Task createTask(Task task) {
        Client client = prepareClient();
        WebResource webResource = client.resource(TASKS);

        JSONObject object = createTaskRequestParameter(task);
        String response = webResource.entity(object.toJSONString(), MediaType.APPLICATION_JSON_TYPE)
                .post(String.class);

        object = (JSONObject) JSONValue.parse(response);
        JSONObject data = (JSONObject) object.get(DATA);
        return new Task(data.toJSONString());
    }

    /**
     * Update a task.
     * 
     * @param task
     * @return updated {@link Task}
     */
    public Task updateTask(Task task) {
        Client client = prepareClient();
        String url = TASK.replace(PLACEHOLDER, task.getId().toString());
        WebResource webResource = client.resource(url);

        JSONObject object = createTaskRequestParameter(task);
        String response = webResource.entity(object.toJSONString(), MediaType.APPLICATION_JSON_TYPE)
                .put(String.class);

        object = (JSONObject) JSONValue.parse(response);
        JSONObject data = (JSONObject) object.get(DATA);
        return new Task(data.toJSONString());
    }

    /**
     * Destroy a task.
     * 
     * @param id
     */
    public void destroyTask(Long id) {
        Client client = prepareClient();
        String url = TASK.replace(PLACEHOLDER, id.toString());
        WebResource webResource = client.resource(url);

        webResource.delete(String.class);
    }

    /**
     * Get current user.
     * 
     * @return current user {@link User}
     */
    public User getCurrentUser() {
        Client client = prepareClient();
        WebResource webResource = client.resource(GET_CURRENT_USER);

        String response = webResource.get(String.class);
        JSONObject object = (JSONObject) JSONValue.parse(response);
        JSONObject data = (JSONObject) object.get(DATA);

        return new User(data.toJSONString());
    }

    /**
     * Get current user, including user's data.
     * It is possible to get the user's time entries, projects, tasks, tags, 
     * workspaces and clients when requesting the current user's data. 
     * 
     * @return current user {@link User}
     */
    public User getCurrentUserWithRelatedData() {
        throw new UnsupportedOperationException();
    }

    /**
     * All users in the workspace with the given id.
     * 
     * @param workspaceId
     *            id of the workspace
     * @return all users
     */
    public List<User> getWorkspaceUsers(long workspaceId) {
        Client client = prepareClient();
        String url = WORKSPACES_USERS.replace(PLACEHOLDER, String.valueOf(workspaceId));
        WebResource webResource = client.resource(url);

        String response = webResource.get(String.class);
        JSONArray data = (JSONArray) JSONValue.parse(response);

        List<User> users = new ArrayList<User>();
        if (data != null) {
            for (Object obj : data) {
                JSONObject entryObject = (JSONObject) obj;
                users.add(new User(entryObject.toJSONString()));
            }
        }
        return users;
    }

    /**
     * All projects in the workspace with the given id.
     * 
     * @param workspaceId
     *            id of the workspace
     * @return all projects
     */
    public List<Project> getWorkspaceProjects(long workspaceId) {
        Client client = prepareClient();
        String url = WORKSPACE_PROJECTS.replace(PLACEHOLDER, String.valueOf(workspaceId));
        WebResource webResource = client.resource(url);

        String response = webResource.get(String.class);
        JSONArray data = (JSONArray) JSONValue.parse(response);

        List<Project> projects = new ArrayList<Project>();
        if (data != null) {
            for (Object obj : data) {
                JSONObject entryObject = (JSONObject) obj;
                projects.add(new Project(entryObject.toJSONString()));
            }
        }
        return projects;
    }

    /**
     * All clients in the workspace with the given id.
     * 
     * @param workspaceId
     *            id of the workspace
     * @return all clients
     */
    public List<ch.simas.jtoggl.Client> getWorkspaceClients(long workspaceId) {
        Client client = prepareClient();
        String url = WORKSPACE_CLIENTS.replace(PLACEHOLDER, String.valueOf(workspaceId));
        WebResource webResource = client.resource(url);

        String response = webResource.get(String.class);
        JSONArray data = (JSONArray) JSONValue.parse(response);

        List<ch.simas.jtoggl.Client> clients = new ArrayList<ch.simas.jtoggl.Client>();
        if (data != null) {
            for (Object obj : data) {
                JSONObject entryObject = (JSONObject) obj;
                clients.add(new ch.simas.jtoggl.Client(entryObject.toJSONString()));
            }
        }
        return clients;
    }

    /**
     * All active tasks in the workspace with the given id.
     * 
     * @param workspaceId
     *            id of the workspace
     * @return all tasks
     */
    public List<Task> getActiveWorkspaceTasks(long workspaceId) {
        Client client = prepareClient();
        String url = WORKSPACE_TASKS.replace(PLACEHOLDER, String.valueOf(workspaceId));
        WebResource webResource = client.resource(url);

        String response = webResource.get(String.class);
        JSONArray data = (JSONArray) JSONValue.parse(response);

        List<Task> tasks = new ArrayList<Task>();
        if (data != null) {
            for (Object obj : data) {
                JSONObject entryObject = (JSONObject) obj;
                tasks.add(new Task(entryObject.toJSONString()));
            }
        }
        return tasks;
    }

    /**
     * All users in all workspaces.
     * 
     * @return all users in all workspaces
     */
    public List<User> getUsers() {
        HashSet<User> result = new HashSet<User>();
        List<Workspace> workspaces = getWorkspaces();
        for (Workspace workspace : workspaces) {
            List<User> workspaceUsers = getWorkspaceUsers(workspace.getId());
            result.addAll(workspaceUsers);
        }
        return new ArrayList<User>(result);
    }

    /**
     * Switch logging on.
     */
    public void switchLoggingOn() {
        this.log = true;
    }

    /**
     * Switch logging off.
     */
    public void switchLoggingOff() {
        this.log = false;
    }

    private Client prepareClient() {
        DefaultClientConfig clientConfig = new DefaultClientConfig();
        clientConfig.getProperties().put(ClientConfig.PROPERTY_CONNECT_TIMEOUT, 30 * 1000);
        clientConfig.getProperties().put(ClientConfig.PROPERTY_READ_TIMEOUT, 30 * 1000);
        Client client = Client.create(clientConfig);
        client.addFilter(new HTTPBasicAuthFilter(user, password));
        if (log) {
            client.addFilter(new LoggingFilter());
        }
        return client;
    }

    private JSONObject createTimeEntryRequestParameter(TimeEntry timeEntry) {
        JSONObject object = new JSONObject();
        object.put("time_entry", timeEntry.toJSONObject());
        return object;
    }

    private JSONObject createClientRequestParameter(ch.simas.jtoggl.Client client) {
        JSONObject object = new JSONObject();
        object.put("client", client.toJSONObject());
        return object;
    }

    private JSONObject createProjectRequestParameter(Project project) {
        JSONObject object = new JSONObject();
        object.put("project", project.toJSONObject());
        return object;
    }

    private JSONObject createProjectUserRequestParameter(ProjectUser projectUser) {
        JSONObject object = new JSONObject();
        object.put("project_user", projectUser.toJSONObject());
        return object;
    }

    private JSONObject createTaskRequestParameter(Task task) {
        JSONObject object = new JSONObject();
        object.put("task", task.toJSONObject());
        return object;
    }
}