├── run.bat
├── .gitignore
├── lib
├── log4j-1.2.jar
├── httpcore-4.0.1.jar
├── httpmime-4.0.3.jar
├── commons-logging.jar
├── httpclient-4.0.3.jar
├── apache-mime4j-0.6.jar
├── commons-codec-1.4.jar
├── httpcore-nio-4.0.1.jar
├── jackson-core-lgpl-1.5.6.jar
└── jackson-mapper-lgpl-1.5.6.jar
├── authentication.properties
├── src
├── authentication.properties
├── log4j.properties
└── cl
│ └── continuum
│ └── harvest
│ ├── console
│ ├── Option.java
│ └── Main.java
│ ├── Timer.java
│ ├── RESTParameterizedType.java
│ ├── Request.java
│ ├── DayEntry.java
│ ├── Client.java
│ ├── util
│ └── DebugServer.java
│ ├── Daily.java
│ ├── TaskAssignment.java
│ ├── Task.java
│ ├── HarvestCore.java
│ ├── AbstractSerializer.java
│ └── Project.java
├── .project
├── log4j.properties
├── README.txt
└── .classpath
/run.bat:
--------------------------------------------------------------------------------
1 | java -jar harvest-plugin.jar
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | bin
2 | data
3 | .idea
4 | log
5 | out
6 | Harvest-client.iml
7 |
--------------------------------------------------------------------------------
/lib/log4j-1.2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phase2/harvest-client/master/lib/log4j-1.2.jar
--------------------------------------------------------------------------------
/lib/httpcore-4.0.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phase2/harvest-client/master/lib/httpcore-4.0.1.jar
--------------------------------------------------------------------------------
/lib/httpmime-4.0.3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phase2/harvest-client/master/lib/httpmime-4.0.3.jar
--------------------------------------------------------------------------------
/lib/commons-logging.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phase2/harvest-client/master/lib/commons-logging.jar
--------------------------------------------------------------------------------
/lib/httpclient-4.0.3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phase2/harvest-client/master/lib/httpclient-4.0.3.jar
--------------------------------------------------------------------------------
/lib/apache-mime4j-0.6.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phase2/harvest-client/master/lib/apache-mime4j-0.6.jar
--------------------------------------------------------------------------------
/lib/commons-codec-1.4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phase2/harvest-client/master/lib/commons-codec-1.4.jar
--------------------------------------------------------------------------------
/lib/httpcore-nio-4.0.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phase2/harvest-client/master/lib/httpcore-nio-4.0.1.jar
--------------------------------------------------------------------------------
/authentication.properties:
--------------------------------------------------------------------------------
1 | username=mauricio@radiochela.com
2 | password=asdfasdf
3 | host=radiochela.harvestapp.com
--------------------------------------------------------------------------------
/src/authentication.properties:
--------------------------------------------------------------------------------
1 | username=mauricio@radiochela.com
2 | password=asdfasdf
3 | host=radiochela.harvestapp.com
--------------------------------------------------------------------------------
/lib/jackson-core-lgpl-1.5.6.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phase2/harvest-client/master/lib/jackson-core-lgpl-1.5.6.jar
--------------------------------------------------------------------------------
/lib/jackson-mapper-lgpl-1.5.6.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/phase2/harvest-client/master/lib/jackson-mapper-lgpl-1.5.6.jar
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | harvest-client
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.jdt.core.javanature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/log4j.properties:
--------------------------------------------------------------------------------
1 | log4j.rootLogger=DEBUG,FILEAPPENDER
2 |
3 | log4j.appender.FILEAPPENDER=org.apache.log4j.DailyRollingFileAppender
4 | log4j.appender.FILEAPPENDER.File=./log/harvest-console.log
5 | log4j.appender.FILEAPPENDER.layout=org.apache.log4j.PatternLayout
6 | log4j.appender.FILEAPPENDER.append=true
7 | log4j.appender.FILEAPPENDER.layout.ConversionPattern=%d{ABSOLUTE} | %-5p [%c{1}:%L] - %m%n
8 | log4j.appender.FILEAPPENDER.DatePattern='.'yyyy-MM-dd'.log'
9 | log4j.appender.FILEAPPENDER.Threshold=ALL
10 |
11 | log4j.logger.httpclient.wire.header=DEBUG
12 | log4j.logger.org.apache.commons.httpclient=DEBUG
--------------------------------------------------------------------------------
/src/log4j.properties:
--------------------------------------------------------------------------------
1 | log4j.rootLogger=DEBUG,FILEAPPENDER
2 |
3 | log4j.appender.FILEAPPENDER=org.apache.log4j.DailyRollingFileAppender
4 | log4j.appender.FILEAPPENDER.File=./log/harvest-console.log
5 | log4j.appender.FILEAPPENDER.layout=org.apache.log4j.PatternLayout
6 | log4j.appender.FILEAPPENDER.append=true
7 | log4j.appender.FILEAPPENDER.layout.ConversionPattern=%d{ABSOLUTE} | %-5p [%c{1}:%L] - %m%n
8 | log4j.appender.FILEAPPENDER.DatePattern='.'yyyy-MM-dd'.log'
9 | log4j.appender.FILEAPPENDER.Threshold=ALL
10 |
11 | log4j.logger.httpclient.wire.header=DEBUG
12 | log4j.logger.org.apache.commons.httpclient=DEBUG
--------------------------------------------------------------------------------
/README.txt:
--------------------------------------------------------------------------------
1 | Harvest Plugin
2 |
3 | This is an open source project, built in Santiago of Chile by Mauricio Offermann to Continnuum Chile,
4 | http://www.continuum.cl.
5 |
6 | The initial mainidea was to build a Eclipse plugin, but for many reasons the final project is only a
7 | harvest console client. The target is assign shortcuts in Eclipse IDE to admin Daily entries.
8 |
9 | If you want continues this project feel free to do.
10 |
11 | Instalation
12 |
13 | 1º Open file authentication.properties, set your account information and save it.
14 | 2º Run the file run.bat
15 |
16 | if you have problems to run, probably you need to install Java and set the JAVA_HOME enviroment variable.
--------------------------------------------------------------------------------
/src/cl/continuum/harvest/console/Option.java:
--------------------------------------------------------------------------------
1 | package cl.continuum.harvest.console;
2 |
3 | import java.lang.reflect.Method;
4 |
5 | public class Option {
6 |
7 | private char codigo;
8 | private String descripcion;
9 | private String metodo;
10 | public Option(char codigo, String descripcion, String metodo) {
11 | super();
12 | this.codigo = codigo;
13 | this.descripcion = descripcion;
14 | this.metodo = metodo;
15 | }
16 |
17 | public void execute() throws Exception {
18 | Method method = Main.class.getMethod(metodo);
19 | method.invoke(null);
20 | }
21 |
22 | public String toString() {
23 | return "(" + codigo + ") " + descripcion;
24 | }
25 |
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/cl/continuum/harvest/Timer.java:
--------------------------------------------------------------------------------
1 | package cl.continuum.harvest;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 |
6 | import org.codehaus.jackson.JsonParseException;
7 | import org.codehaus.jackson.map.JsonMappingException;
8 |
9 | public class Timer extends AbstractSerializer {
10 |
11 | private DayEntry day_entry;
12 | private float hours_for_previously_running_timer;
13 | public DayEntry getDay_entry() {
14 | return day_entry;
15 | }
16 | public void setDay_entry(DayEntry dayEntry) {
17 | day_entry = dayEntry;
18 | }
19 | public float getHours_for_previously_running_timer() {
20 | return hours_for_previously_running_timer;
21 | }
22 | public void setHours_for_previously_running_timer(
23 | float hoursForPreviouslyRunningTimer) {
24 | hours_for_previously_running_timer = hoursForPreviouslyRunningTimer;
25 | }
26 |
27 | public static Timer get(int day_entry_id) throws JsonParseException, JsonMappingException, IOException {
28 | String uri = "/daily/show/" + day_entry_id;
29 | InputStream content = HarvestCore.get(uri);
30 | return HarvestCore.mapper.readValue(content, Timer.class);
31 | }
32 |
33 |
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/cl/continuum/harvest/RESTParameterizedType.java:
--------------------------------------------------------------------------------
1 | package cl.continuum.harvest;
2 |
3 |
4 | import java.lang.reflect.ParameterizedType;
5 | import java.lang.reflect.Type;
6 | import java.util.List;
7 | import java.util.Map;
8 |
9 |
10 |
11 | public class RESTParameterizedType implements ParameterizedType {
12 |
13 | private Type rawType;
14 | private Type[] actualTypeArguments;
15 |
16 | private RESTParameterizedType(Type rawType, Type[] actualTypeArguments) {
17 | super();
18 | this.rawType = rawType;
19 | this.actualTypeArguments = actualTypeArguments;
20 | }
21 |
22 | public RESTParameterizedType(Type targetType, boolean isList) {
23 | if (isList) {
24 | this.rawType = List.class;
25 | this.actualTypeArguments = new Type[] {new RESTParameterizedType(Map.class, new Type[] {String.class, targetType})};
26 | } else {
27 | this.rawType = Map.class;
28 | this.actualTypeArguments = new Type[] {String.class, targetType};
29 | }
30 |
31 | }
32 |
33 |
34 | public boolean isList() {
35 | return List.class.isAssignableFrom((Class>)rawType);
36 | }
37 |
38 | @Override
39 | public Type[] getActualTypeArguments() {
40 | return this.actualTypeArguments;
41 | }
42 |
43 | @Override
44 | public Type getOwnerType() {
45 | return null;
46 | }
47 |
48 | @Override
49 | public Type getRawType() {
50 | return this.rawType;
51 | }
52 |
53 |
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/cl/continuum/harvest/Request.java:
--------------------------------------------------------------------------------
1 | package cl.continuum.harvest;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 |
6 | import org.apache.http.client.ClientProtocolException;
7 |
8 | public class Request extends AbstractSerializer {
9 |
10 | private String notes;
11 | private float hours;
12 | private int project_id;
13 | private int task_id;
14 | private String spent_at;
15 |
16 | public String getNotes() {
17 | return notes;
18 | }
19 | public void setNotes(String notes) {
20 | this.notes = notes;
21 | }
22 | public float getHours() {
23 | return hours;
24 | }
25 | public void setHours(float hours) {
26 | this.hours = hours;
27 | }
28 | public int getProject_id() {
29 | return project_id;
30 | }
31 | public void setProject_id(int projectId) {
32 | project_id = projectId;
33 | }
34 | public int getTask_id() {
35 | return task_id;
36 | }
37 | public void setTask_id(int taskId) {
38 | task_id = taskId;
39 | }
40 | public String getSpent_at() {
41 | return spent_at;
42 | }
43 | public void setSpent_at(String spentAt) {
44 | spent_at = spentAt;
45 | }
46 |
47 | public DayEntry add() throws ClientProtocolException, IOException {
48 | String uri = "/daily/add";
49 | InputStream content = HarvestCore.post(uri, toJson(false, this));
50 | if (content != null)
51 | return HarvestCore.mapper.readValue(content, DayEntry.class);
52 | System.out.println("Problems to save ");
53 | return null;
54 | }
55 |
56 | public Request update(int day_entry_id) throws ClientProtocolException, IOException {
57 | return (Request) add("/daily/update/" + day_entry_id);
58 | }
59 |
60 | public static void main(String[] args) throws ClientProtocolException, IOException {
61 | Request request = new Request();
62 | request.setProject_id(876359);
63 | request.setTask_id(655857);
64 | request.setNotes("Esta es la primera nota asignada");
65 | request.setSpent_at("Mon, 18 Oct 2010");
66 | request.setHours(0);
67 | request.add();
68 | }
69 |
70 |
71 |
72 |
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/src/cl/continuum/harvest/DayEntry.java:
--------------------------------------------------------------------------------
1 | package cl.continuum.harvest;
2 |
3 | import java.io.InputStream;
4 | import java.io.Serializable;
5 |
6 | public class DayEntry extends AbstractSerializer implements Serializable {
7 |
8 | /**
9 | *
10 | */
11 | private static final long serialVersionUID = 7511143115137074613L;
12 | private String client;
13 | private int project_id;
14 | private String project;
15 | private int task_id;
16 | private String task;
17 | private float hours;
18 | private String notes;
19 | private String timer_started_at;
20 | private float hours_for_previously_running_timer;
21 |
22 |
23 | public String getClient() {
24 | return client;
25 | }
26 | public float getHours_for_previously_running_timer() {
27 | return hours_for_previously_running_timer;
28 | }
29 | public void setHours_for_previously_running_timer(
30 | float hoursForPreviouslyRunningTimer) {
31 | hours_for_previously_running_timer = hoursForPreviouslyRunningTimer;
32 | }
33 | public void setClient(String client) {
34 | this.client = client;
35 | }
36 | public String getProject() {
37 | return project;
38 | }
39 | public void setProject(String project) {
40 | this.project = project;
41 | }
42 | public String getTask() {
43 | return task;
44 | }
45 | public void setTask(String task) {
46 | this.task = task;
47 | }
48 | public float getHours() {
49 | return hours;
50 | }
51 | public void setHours(float hours) {
52 | this.hours = hours;
53 | }
54 | public String getNotes() {
55 | return notes;
56 | }
57 | public void setNotes(String notes) {
58 | this.notes = notes;
59 | }
60 | public String getTimer_started_at() {
61 | return timer_started_at;
62 | }
63 | public void setTimer_started_at(String timerStartedAt) {
64 | timer_started_at = timerStartedAt;
65 | }
66 | public int getProject_id() {
67 | return project_id;
68 | }
69 | public void setProject_id(int projectId) {
70 | project_id = projectId;
71 | }
72 | public int getTask_id() {
73 | return task_id;
74 | }
75 | public void setTask_id(int taskId) {
76 | task_id = taskId;
77 | }
78 |
79 |
80 | public DayEntry togleTimer() throws Exception {
81 | if (getId() == 0)
82 | return null;
83 | String uri ="/daily/timer/" + getId();
84 | InputStream content = HarvestCore.get(uri);
85 | return HarvestCore.mapper.readValue(content, DayEntry.class);
86 | }
87 |
88 |
89 |
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/src/cl/continuum/harvest/Client.java:
--------------------------------------------------------------------------------
1 | package cl.continuum.harvest;
2 |
3 | import org.apache.http.client.ClientProtocolException;
4 | import org.codehaus.jackson.JsonParseException;
5 | import org.codehaus.jackson.map.JsonMappingException;
6 |
7 | import java.io.IOException;
8 | import java.io.Serializable;
9 | import java.util.List;
10 | import java.util.Scanner;
11 | import java.util.regex.Pattern;
12 |
13 | /**
14 | *
15 | */
16 | public class Client extends AbstractSerializer implements Serializable {
17 |
18 | private static final long serialVersionUID = 8926028143190627264L;
19 |
20 | private String name;
21 |
22 | public String getName() {
23 | return name;
24 | }
25 |
26 | public void setName(String name) {
27 | this.name = name;
28 | }
29 |
30 | public static List list() throws ClientProtocolException, IOException, ClassNotFoundException {
31 | return list(Client.class);
32 | }
33 |
34 | public static Client get(int id) throws JsonParseException, JsonMappingException, IOException, ClassNotFoundException {
35 | return get(id, Client.class);
36 | }
37 |
38 | public static Client select() throws IOException, ClassNotFoundException {
39 | List clients = list();
40 | return select(clients);
41 |
42 | }
43 |
44 | public static Client select(List clients) throws IOException, ClassNotFoundException {
45 | System.out.println("Select client");
46 | System.out.println("=======================");
47 | System.out.println("\tq: Quit");
48 | System.out.println("\t0: None");
49 | for (int i=0; i < clients.size(); i++) {
50 | Client client = clients.get(i);
51 | System.out.println("\t" + (i+1) + ": " + client.getName());
52 | }
53 | Scanner scan = new Scanner(System.in);
54 | String option = "";
55 | while (true) {
56 | System.out.print("\nChoose project number:");
57 | option = scan.next();
58 | if (option.equalsIgnoreCase("q")) {
59 | System.out.println("Good bye!");
60 | System.exit(0);
61 | }
62 | if (!Pattern.matches("[0-9]+", option)) {
63 | System.out.println("You must enter a number");
64 | continue;
65 | }
66 | int index = Integer.parseInt(option);
67 | if (index < 0 || index > clients.size()) {
68 | System.out.println("Option out of range");
69 | continue;
70 | }
71 | if (index == 0)
72 | return null;
73 | return clients.get(index - 1);
74 | }
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/src/cl/continuum/harvest/util/DebugServer.java:
--------------------------------------------------------------------------------
1 | package cl.continuum.harvest.util;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.File;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.io.OutputStream;
10 | import java.net.ServerSocket;
11 | import java.net.Socket;
12 | import java.util.regex.Matcher;
13 | import java.util.regex.Pattern;
14 |
15 | public class DebugServer {
16 |
17 | public static final String SHUTDOWN_TOKEN = "/shutdown";
18 | public static final String SHUTDOWN_REGEX = "GET (.*) HTTP";
19 |
20 |
21 | public static void copy(InputStream in, OutputStream out, boolean closeAll) throws IOException {
22 | try {
23 | // String endMark = new String(new byte[] {13,10,13,10, 0});
24 | String endMark = new String(new byte[] {0, 0, 0});
25 | Pattern p = Pattern.compile(endMark);
26 | while (true) {
27 | byte[] buffer = new byte[1024];
28 |
29 | int amountRead = in.read(buffer);
30 | out.write(buffer, 0, amountRead);
31 | Matcher m = p.matcher(new String(buffer));
32 | if (m.find())
33 | break;
34 | }
35 | } catch (Exception e) {
36 | throw new IOException("Problemas al copiar los datos", e);
37 | } finally {
38 | if (closeAll) {
39 | in.close();
40 | out.close();
41 | }
42 | }
43 | }
44 |
45 |
46 | public static void start(int port, File outputFile) throws IOException {
47 | System.out.println("Iniciando server ...");
48 | System.out.println("PUERTO: " + port);
49 | System.out.println("SHUTDOWN: http://localhost:" + port + SHUTDOWN_TOKEN);
50 | Pattern pattern = Pattern.compile(SHUTDOWN_REGEX);
51 | ServerSocket server = new ServerSocket(port);
52 | while (true) {
53 | Socket socket = server.accept();
54 | ByteArrayOutputStream bos = new ByteArrayOutputStream();
55 | System.out.println("DATOS RECIBIDOS!");
56 | copy(socket.getInputStream(), bos, false);
57 | socket.getOutputStream().write("HTTP/1.1 404 Not Found\n\r\n\r".getBytes());
58 | socket.close();
59 |
60 | byte[] outputBytes = bos.toByteArray();
61 | bos.close();
62 |
63 | ByteArrayInputStream bis = new ByteArrayInputStream(outputBytes);
64 | copy(bis, new FileOutputStream(outputFile), true);
65 |
66 | String outputString = new String(outputBytes);
67 | System.out.println("RECIBIENDO:\n" + outputString);
68 | Matcher matcher = pattern.matcher(outputString);
69 | if (matcher.find() && SHUTDOWN_TOKEN.equalsIgnoreCase(matcher.group(1)))
70 | break;
71 | }
72 | System.out.println("Cerrando server ...");
73 | server.close();
74 | }
75 |
76 | public static void main(String[] args) throws IOException {
77 | start(80, new File("d:/output.dat"));
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/src/cl/continuum/harvest/Daily.java:
--------------------------------------------------------------------------------
1 | package cl.continuum.harvest;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.util.List;
6 | import java.util.Scanner;
7 | import java.util.regex.Pattern;
8 |
9 | import org.apache.http.client.ClientProtocolException;
10 | import org.codehaus.jackson.map.DeserializationConfig.Feature;
11 |
12 | public class Daily extends AbstractSerializer {
13 |
14 | private String for_day;
15 | private List day_entries;
16 | private List projects;
17 | public String getFor_day() {
18 | return for_day;
19 | }
20 | public void setFor_day(String forDay) {
21 | for_day = forDay;
22 | }
23 | public List getDay_entries() {
24 | return day_entries;
25 | }
26 | public void setDay_entries(List dayEntries) {
27 | day_entries = dayEntries;
28 | }
29 | public List getProjects() {
30 | return projects;
31 | }
32 | public void setProjects(List projects) {
33 | this.projects = projects;
34 | }
35 |
36 |
37 | public static Daily get() throws ClientProtocolException, IOException {
38 | String uri = "/daily";
39 | InputStream content = HarvestCore.get(uri);
40 | HarvestCore.mapper.configure(Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
41 | return HarvestCore.mapper.readValue(content, Daily.class);
42 |
43 | }
44 |
45 | public DayEntry select() throws IOException, ClassNotFoundException {
46 | System.out.println("Select an entry:");
47 | System.out.println("=======================");
48 | System.out.println("\tq: Quit");
49 | System.out.println("\t0: None");
50 | for (int i=0; i < day_entries.size(); i++) {
51 | DayEntry day_entry = day_entries.get(i);
52 | System.out.println("\t" + (i+1) + ": " + day_entry.getNotes());
53 | }
54 | Scanner scan = new Scanner(System.in);
55 | String option = "";
56 | while (true) {
57 | System.out.print("\nChoose an entry:");
58 | option = scan.next();
59 | if (option.equalsIgnoreCase("q")) {
60 | System.out.println("Good bye!");
61 | System.exit(0);
62 | }
63 | if (!Pattern.matches("[0-9]+", option)) {
64 | System.out.println("You must to enter a number");
65 | continue;
66 | }
67 | int index = Integer.parseInt(option);
68 | if (index < 0 || index > day_entries.size()) {
69 | System.out.println("Option out of range");
70 | continue;
71 | }
72 | if (index == 0)
73 | return null;
74 | return day_entries.get(index - 1);
75 | }
76 | }
77 |
78 |
79 |
80 | public static void main(String[] args) throws ClientProtocolException, IOException {
81 |
82 | Daily daily = get();
83 | for (Project project : daily.getProjects()) {
84 | System.out.println(project.getName() + "\t" + project.getId());
85 | System.out.println("===========");
86 | for (Task task : project.getTasks())
87 | System.out.println("\t" + task.getName() + "\t" + task.getId());
88 | }
89 |
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/src/cl/continuum/harvest/TaskAssignment.java:
--------------------------------------------------------------------------------
1 | package cl.continuum.harvest;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.util.List;
6 |
7 | import org.apache.http.client.ClientProtocolException;
8 | import org.codehaus.jackson.JsonGenerationException;
9 | import org.codehaus.jackson.JsonParseException;
10 | import org.codehaus.jackson.map.JsonMappingException;
11 |
12 | public class TaskAssignment extends AbstractSerializer {
13 |
14 | private int project_id;
15 | private int task_id;
16 | private boolean billable;
17 | private boolean deactivated;
18 | private int budget;
19 | private int hourly_rate;
20 | public int getProject_id() {
21 | return project_id;
22 | }
23 | public void setProject_id(int projectId) {
24 | project_id = projectId;
25 | }
26 | public int getTask_id() {
27 | return task_id;
28 | }
29 | public void setTask_id(int taskId) {
30 | task_id = taskId;
31 | }
32 | public boolean isBillable() {
33 | return billable;
34 | }
35 | public void setBillable(boolean billable) {
36 | this.billable = billable;
37 | }
38 | public boolean isDeactivated() {
39 | return deactivated;
40 | }
41 | public void setDeactivated(boolean deactivated) {
42 | this.deactivated = deactivated;
43 | }
44 | public int getBudget() {
45 | return budget;
46 | }
47 | public void setBudget(int budget) {
48 | this.budget = budget;
49 | }
50 | public int getHourly_rate() {
51 | return hourly_rate;
52 | }
53 | public void setHourly_rate(int hourlyRate) {
54 | hourly_rate = hourlyRate;
55 | }
56 |
57 |
58 |
59 | public AbstractSerializer add() throws ClientProtocolException, IOException {
60 | String plural = getClass().getSimpleName().toLowerCase() + "s";
61 | InputStream content = HarvestCore.post("/" + plural, toJson());
62 | return fromJson(content, getClass());
63 | }
64 |
65 | public static List list(int project_id) throws ClientProtocolException, IOException, ClassNotFoundException {
66 | String uri = "/projects/" + project_id + "/task_assignments";
67 | InputStream content = HarvestCore.get(uri);
68 | return fromJsonList(content, TaskAssignment.class);
69 | }
70 |
71 | public static TaskAssignment get(int project_id, long id) throws JsonParseException, JsonMappingException, IOException, ClassNotFoundException {
72 | String uri = "/projects/" + project_id + "/task_assignments/" + id;
73 | InputStream content = HarvestCore.get(uri);
74 | return fromJson(content, TaskAssignment.class);
75 | }
76 |
77 | public void delete() throws ClientProtocolException, IOException {
78 | String uri = "/projects/" + project_id + "/task_assignments/" + getId();
79 | HarvestCore.delete(uri);
80 | }
81 |
82 | public TaskAssignment update() throws JsonGenerationException, JsonMappingException, ClientProtocolException, IOException {
83 | String uri = "/projects/" + project_id + "/task_assignments/" + getId();
84 | InputStream content = HarvestCore.put(uri, toJson());
85 | return fromJson(content, TaskAssignment.class);
86 | }
87 |
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/src/cl/continuum/harvest/Task.java:
--------------------------------------------------------------------------------
1 | package cl.continuum.harvest;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.io.Serializable;
6 | import java.util.List;
7 | import java.util.Scanner;
8 | import java.util.regex.Pattern;
9 |
10 | import org.apache.commons.logging.Log;
11 | import org.apache.commons.logging.LogFactory;
12 | import org.apache.http.client.ClientProtocolException;
13 | import org.codehaus.jackson.JsonGenerationException;
14 | import org.codehaus.jackson.JsonParseException;
15 | import org.codehaus.jackson.map.JsonMappingException;
16 |
17 | /**
18 | * Project clas to admin projects requests
19 | *
20 | * @author Mauricio Offermann Palma
21 | *
22 | */
23 | public class Task extends AbstractSerializer implements Serializable {
24 |
25 |
26 | /**
27 | *
28 | */
29 | private static final long serialVersionUID = 4381249959658450952L;
30 | private boolean billable_by_default;
31 | private float default_hourly_rate;
32 | private boolean is_default;
33 | private String name;
34 | private boolean deactivated;
35 |
36 |
37 | private static final Log log = LogFactory.getLog(Task.class);
38 |
39 |
40 | public boolean isBillable_by_default() {
41 | return billable_by_default;
42 | }
43 |
44 | public void setBillable_by_default(boolean billableByDefault) {
45 | billable_by_default = billableByDefault;
46 | }
47 |
48 | public float getDefault_hourly_rate() {
49 | return default_hourly_rate;
50 | }
51 |
52 | public void setDefault_hourly_rate(float defaultHourlyRate) {
53 | default_hourly_rate = defaultHourlyRate;
54 | }
55 |
56 | public boolean isIs_default() {
57 | return is_default;
58 | }
59 |
60 | public void setIs_default(boolean isDefault) {
61 | is_default = isDefault;
62 | }
63 |
64 | public String getName() {
65 | return name;
66 | }
67 |
68 | public void setName(String name) {
69 | this.name = name;
70 | }
71 |
72 |
73 |
74 |
75 | public static Log getLog() {
76 | return log;
77 | }
78 |
79 |
80 |
81 | public boolean isDeactivated() {
82 | return deactivated;
83 | }
84 |
85 |
86 | public void setDeactivated(boolean deactivated) {
87 | this.deactivated = deactivated;
88 | }
89 |
90 | public static List list() throws ClientProtocolException, IOException, ClassNotFoundException {
91 | return list(Task.class);
92 | }
93 |
94 | public static Task get(int id) throws JsonParseException, JsonMappingException, IOException, ClassNotFoundException {
95 | return get(id, Task.class);
96 | }
97 |
98 | public TaskAssignment assign(int project_id) throws JsonGenerationException, JsonMappingException, ClientProtocolException, IOException {
99 | String uri = "/projects/" + project_id + "/task_assignments/add_with_create_new_task";
100 | InputStream content = HarvestCore.post(uri, toJson());
101 | if (content == null)
102 | return null;
103 | return fromJson(content, TaskAssignment.class);
104 | }
105 |
106 | public static Task select() throws IOException, ClassNotFoundException {
107 | List tasks = list();
108 | return select(tasks);
109 | }
110 |
111 |
112 | public static Task select(List tasks) throws IOException, ClassNotFoundException {
113 | System.out.println("Task selection");
114 | System.out.println("=======================");
115 | System.out.println("\tq: Quit");
116 | System.out.println("\t0: None");
117 | for (int i=0; i < tasks.size(); i++) {
118 | Task task = tasks.get(i);
119 | System.out.println("\t" + (i+1) + ": " + task.getName());
120 | }
121 | Scanner scan = new Scanner(System.in);
122 | String option = "";
123 | while (true) {
124 | System.out.print("\nChoose task number:");
125 | option = scan.next();
126 | if (option.equalsIgnoreCase("q")) {
127 | System.out.println("Good bye!");
128 | System.exit(0);
129 | }
130 | if (!Pattern.matches("[0-9]+", option)) {
131 | System.out.println("You must enter a number");
132 | continue;
133 | }
134 | int index = Integer.parseInt(option);
135 | if (index < 0 || index > tasks.size()) {
136 | System.out.println("Opcion fuera de rango");
137 | continue;
138 | }
139 | if (index == 0)
140 | return null;
141 | return tasks.get(index - 1);
142 | }
143 | }
144 |
145 |
146 |
147 | public static void main(String[] args) throws ClientProtocolException, IOException, ClassNotFoundException {
148 | Task task = select();
149 | System.out.println(task.getName());
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/src/cl/continuum/harvest/HarvestCore.java:
--------------------------------------------------------------------------------
1 | package cl.continuum.harvest;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.FileReader;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.io.OutputStream;
9 | import java.lang.reflect.Constructor;
10 | import java.util.Properties;
11 |
12 | import org.apache.commons.codec.binary.Base64;
13 | import org.apache.http.Header;
14 | import org.apache.http.HttpEntity;
15 | import org.apache.http.HttpResponse;
16 | import org.apache.http.auth.AuthScope;
17 | import org.apache.http.auth.UsernamePasswordCredentials;
18 | import org.apache.http.client.ClientProtocolException;
19 | import org.apache.http.client.HttpClient;
20 | import org.apache.http.client.methods.HttpDelete;
21 | import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
22 | import org.apache.http.client.methods.HttpGet;
23 | import org.apache.http.client.methods.HttpPost;
24 | import org.apache.http.client.methods.HttpPut;
25 | import org.apache.http.client.methods.HttpUriRequest;
26 | import org.apache.http.entity.StringEntity;
27 | import org.apache.http.impl.client.DefaultHttpClient;
28 | import org.apache.http.params.CoreProtocolPNames;
29 | import org.codehaus.jackson.map.DeserializationConfig;
30 | import org.codehaus.jackson.map.ObjectMapper;
31 |
32 | /**
33 | * This class provides methods to send request to harvest.
34 | * TODO: Probably is necesary to control more error codes.
35 | * @author Mauricio Offermann
36 | *
37 | */
38 | public class HarvestCore {
39 |
40 | private static String USERNAME;
41 | private static String PASSWORD;
42 | private static String HOST;
43 | public static final ObjectMapper mapper = new ObjectMapper();
44 | public static String credentials;
45 |
46 | static {
47 | try{
48 | Properties property = new Properties();
49 | property.load(new FileReader("authentication.properties"));
50 | USERNAME = property.getProperty("username");
51 | PASSWORD = property.getProperty("password");
52 | HOST = property.getProperty("host");
53 | credentials = USERNAME + ":" + PASSWORD;
54 | } catch (IOException e) {
55 | e.printStackTrace();
56 | System.out.println("Can't find authentication.properties");
57 | }
58 |
59 | mapper.getDeserializationConfig().set(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
60 | }
61 |
62 |
63 | public static void copy(InputStream in, OutputStream out) throws IOException {
64 | byte[] buffer = new byte[1024];
65 | while (true) {
66 | int amountRead = in.read(buffer);
67 | if (amountRead == -1)
68 | break;
69 | out.write(buffer, 0, amountRead);
70 | }
71 | }
72 |
73 | public static HttpClient openConnection() {
74 | DefaultHttpClient httpclient = new DefaultHttpClient();
75 | httpclient.getCredentialsProvider().setCredentials(
76 | new AuthScope(HOST, 443),
77 | new UsernamePasswordCredentials(USERNAME, PASSWORD));
78 |
79 | httpclient.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);
80 | httpclient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, "Java");
81 | return httpclient;
82 | }
83 |
84 |
85 | public static InputStream send(HttpClient httpclient, HttpUriRequest request, String parameters) throws ClientProtocolException, IOException {
86 | request.setHeader("Accept", "application/json");
87 | request.setHeader("Content-Type", "application/json");
88 | request.setHeader("Authorization", "Basic " + Base64.encodeBase64String(credentials.getBytes()).trim());
89 | if (parameters != null) {
90 | StringEntity reqentity = new StringEntity(parameters);
91 | if (request instanceof HttpEntityEnclosingRequestBase)
92 | ((HttpEntityEnclosingRequestBase)request).setEntity(reqentity);
93 | else
94 | throw new ClientProtocolException("Method not allowed. Don't send parameters or use POST or PUT");
95 |
96 | }
97 | HttpResponse response = httpclient.execute(request);
98 | System.out.println(response.getStatusLine());
99 | if (response.getStatusLine().getStatusCode() == 404) {
100 | System.out.println("Service not found");
101 | return null;
102 | }
103 | ByteArrayOutputStream bos = new ByteArrayOutputStream();
104 | HttpEntity entity = response.getEntity();
105 | if (entity != null)
106 | entity.writeTo(bos);
107 | Header[] locations = response.getHeaders("Location");
108 | if (locations == null || locations.length == 0)
109 | return new ByteArrayInputStream(bos.toByteArray());
110 | String uri = "https://" + HOST;
111 | uri += locations[0].getValue();
112 | HttpGet get = new HttpGet(uri);
113 | return send(httpclient, get, null);
114 | }
115 |
116 | public static InputStream send(Class extends HttpUriRequest> methodClass, String uri, String parameters) throws ClientProtocolException, IOException {
117 | try {
118 | uri = "https://" + HOST + uri;
119 | Constructor extends HttpUriRequest> constructor = methodClass.getConstructor(String.class);
120 | HttpUriRequest request = constructor.newInstance(uri);
121 | HttpClient httpclient = openConnection();
122 | InputStream content = send(httpclient, request, parameters);
123 | httpclient.getConnectionManager().shutdown();
124 | return content;
125 | } catch (Exception e) {
126 | throw new ClientProtocolException("Problems to send", e);
127 | }
128 | }
129 |
130 | public static InputStream send(Class extends HttpUriRequest> methodClass, String uri) throws ClientProtocolException, IOException {
131 | return send(methodClass, uri, null);
132 | }
133 |
134 | public static InputStream get(String uri) throws ClientProtocolException, IOException {
135 | return send(HttpGet.class, uri);
136 | }
137 |
138 | public static InputStream post(String uri, final String parameters) throws ClientProtocolException, IOException {
139 | return send(HttpPost.class, uri, parameters);
140 | }
141 |
142 | public static InputStream delete(String uri) throws ClientProtocolException, IOException {
143 | return send(HttpDelete.class, uri);
144 | }
145 |
146 | public static InputStream put(String uri, final String parameters) throws ClientProtocolException, IOException {
147 | return send(HttpPut.class, uri, parameters);
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/src/cl/continuum/harvest/console/Main.java:
--------------------------------------------------------------------------------
1 | package cl.continuum.harvest.console;
2 |
3 | import java.io.Closeable;
4 | import java.io.File;
5 | import java.io.FileInputStream;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.io.ObjectInputStream;
9 | import java.io.ObjectOutputStream;
10 | import java.util.HashMap;
11 | import java.util.Map;
12 | import java.util.Scanner;
13 | import java.util.regex.Pattern;
14 |
15 | import org.apache.http.client.ClientProtocolException;
16 |
17 | import cl.continuum.harvest.Client;
18 | import cl.continuum.harvest.Daily;
19 | import cl.continuum.harvest.DayEntry;
20 | import cl.continuum.harvest.Project;
21 | import cl.continuum.harvest.Request;
22 | import cl.continuum.harvest.Task;
23 |
24 | /**
25 | * Main console testing
26 | * You can execute this class without arguments and follow the menu options.
27 | * Also you can use classic flags as arguments, example:
28 | *
29 | * java -jar harvest-plugin.jar -a
30 | * To assign selected task to actual project.
31 | *
32 | * The flags used are the same options than menu.
33 | *
34 | * @author Mauricio Offermann
35 | *
36 | */
37 | public class Main {
38 |
39 | private static final Map options = new HashMap();
40 |
41 | private static Client client = null;
42 | private static Project project = null;
43 | private static Task task = null;
44 | private static DayEntry dayEntry = null;
45 |
46 |
47 | static {
48 | Main.client = readObject(Client.class);
49 | Main.project = readObject(Project.class);
50 | Main.task = readObject(Task.class);
51 | Main.dayEntry = readObject(DayEntry.class);
52 |
53 | options.put("a", new Option('a', "Assign task to project", "assignTask"));
54 | options.put("c", new Option('c', "Select client", "selectClient"));
55 | options.put("p", new Option('p', "Select project", "selectProject"));
56 | options.put("t", new Option('t', "Select task from project", "selectTask"));
57 | options.put("k", new Option('k', "List all tasks", "listTasks"));
58 | options.put("s", new Option('s', "Stop/Start timer from actual dayentry", "toggleTimer"));
59 | options.put("l", new Option('l', "List day entries and selected project", "show"));
60 | options.put("n", new Option('n', "Add day entry", "addDayEntry"));
61 | options.put("q", new Option('q', "Quit", "exit"));
62 | }
63 |
64 | public static void exit() {
65 | System.out.println("Good bye");
66 | System.exit(0);
67 | }
68 |
69 | public static void selectProject() throws IOException, ClassNotFoundException {
70 | Main.project = Project.select();
71 | writeObject(Main.project);
72 | }
73 |
74 | public static void selectClient() throws IOException, ClassNotFoundException {
75 | Main.client = Client.select();
76 | writeObject(Main.client);
77 | }
78 |
79 | public static void listTasks() throws IOException, ClassNotFoundException {
80 | Main.task = Task.select();
81 | writeObject(Main.task);
82 | }
83 |
84 | public static void assignTask() throws IOException, ClassNotFoundException {
85 | if (Main.project == null)
86 | selectProject();
87 | if (Main.task == null)
88 | listTasks();
89 | Main.task.assign((int) Main.project.getId());
90 | }
91 |
92 | public static void show() throws ClientProtocolException, IOException, ClassNotFoundException {
93 | Main.dayEntry = Daily.get().select();
94 | writeObject(Main.dayEntry);
95 | }
96 |
97 | public static void addDayEntry() throws IOException, ClassNotFoundException {
98 | if (Main.project == null)
99 | selectProject();
100 | if (Main.task == null)
101 | listTasks();
102 | Scanner scan = new Scanner(System.in);
103 | System.out.print("Notes: ");
104 | String notes = scan.nextLine();
105 | Request request = new Request();
106 | request.setNotes(notes);
107 | request.setProject_id((int) Main.project.getId());
108 | request.setTask_id((int) Main.task.getId());
109 | Main.dayEntry = request.add();
110 | writeObject(Main.dayEntry);
111 | }
112 |
113 | public static void toggleTimer() throws Exception {
114 | if (Main.project == null)
115 | selectProject();
116 | if (Main.task == null)
117 | listTasks();
118 | if (Main.dayEntry == null)
119 | Main.dayEntry = Daily.get().select();
120 | Main.dayEntry = Main.dayEntry.togleTimer();
121 | writeObject(Main.dayEntry);
122 | }
123 |
124 | public static void selectTask() throws IOException, ClassNotFoundException {
125 | Daily daily = Daily.get();
126 | if (Main.project == null)
127 | selectProject();
128 | if (Main.project == null)
129 | return;
130 | for (Project project : daily.getProjects()) {
131 | if (Main.project.getId() == project.getId()) {
132 | Main.task = Task.select(project.getTasks());
133 | writeObject(Main.task);
134 | break;
135 | }
136 |
137 | }
138 |
139 | }
140 |
141 |
142 | private static void printMenu() {
143 | for (Option option : options.values())
144 | System.out.println("\t" + option);
145 | System.out.println("");
146 | if (Main.project != null)
147 | System.out.println("\nACTUAL PROJECT: " + Main.project.getName());
148 | if (Main.task != null)
149 | System.out.println("\nACTUAL TASK: " + Main.task.getName());
150 | if (Main.dayEntry != null)
151 | System.out.println("\nACTUAL DAY ENTRY: " + Main.dayEntry.getNotes());
152 | System.out.print("\nChoose an option:");
153 | }
154 |
155 |
156 | private static void menu() throws Exception {
157 | System.out.println("------ HARVEST CONSOLE ------\n");
158 | Scanner scan = new Scanner(System.in);
159 | while (true) {
160 | printMenu();
161 | String o =scan.next().toLowerCase();
162 | if (!options.containsKey(o)) {
163 | System.out.println("Unknown option");
164 | continue;
165 | }
166 | Option option = options.get(o);
167 | option.execute();
168 | }
169 | }
170 |
171 | private static void close(Closeable c) {
172 | try {
173 | if (c != null)
174 | c.close();
175 | } catch (IOException e) {
176 | //e.printStackTrace();
177 | }
178 | }
179 |
180 | public static void writeObject(Object object) {
181 | if (object == null)
182 | return;
183 | ObjectOutputStream os = null;
184 | try {
185 | File dir = new File("data");
186 | dir.mkdirs();
187 | File file = new File(dir, object.getClass().getSimpleName());
188 | os = new ObjectOutputStream(new FileOutputStream(file));
189 | os.writeObject(object);
190 | } catch (Exception e) {
191 | e.printStackTrace();
192 | } finally {
193 | close(os);
194 | }
195 |
196 | }
197 |
198 | public static T readObject(Class objectClass) {
199 | ObjectInputStream is = null;
200 | try {
201 | File file = new File("data", objectClass.getSimpleName());
202 | if (!file.exists())
203 | return null;
204 | is = new ObjectInputStream(new FileInputStream(file));
205 | return objectClass.cast(is.readObject());
206 | } catch (Exception e) {
207 | e.printStackTrace();
208 | } finally {
209 | close(is);
210 | }
211 | return null;
212 | }
213 |
214 |
215 | public static void main(String[] args) throws Exception {
216 | if (args.length > 0){
217 | for (String argument : args) {
218 | if (!Pattern.compile("^-[a-z]$").matcher(argument).matches())
219 | throw new Exception("The argument '" + argument + "' is invalid.");
220 | String option = argument.substring(1);
221 | if (!options.containsKey(option))
222 | throw new Exception("The argument '" + argument + "' is invalid.");
223 | options.get(option).execute();
224 | }
225 | }else{
226 | menu();
227 | }
228 | }
229 |
230 | }
231 | ;
--------------------------------------------------------------------------------
/src/cl/continuum/harvest/AbstractSerializer.java:
--------------------------------------------------------------------------------
1 | package cl.continuum.harvest;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.util.ArrayList;
6 | import java.util.HashMap;
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | import org.apache.http.client.ClientProtocolException;
11 | import org.codehaus.jackson.JsonGenerationException;
12 | import org.codehaus.jackson.JsonParseException;
13 | import org.codehaus.jackson.map.JsonMappingException;
14 | import org.codehaus.jackson.map.type.TypeFactory;
15 | /**
16 | * Base entries class thats provides funtions to serialize to JSON an unserialize
17 | * to java objects.
18 | * Also contains methods to make requests easy from childrens.
19 | * IMPORTANT: Not all methods as add,delete, update, get and list have sense from inherit classes
20 | * due to some entities don't use classic plural to make requests. In this cases you must
21 | * override this methods passing the uri to methods that can accept it.
22 | *
23 | * @author Mauricio Offermann Palma
24 | *
25 | */
26 | public abstract class AbstractSerializer {
27 |
28 | private long id;
29 | private int company_id;
30 | private String created_at;
31 | private String updated_at;
32 | private long cache_version;
33 |
34 |
35 |
36 | public long getId() {
37 | return id;
38 | }
39 |
40 |
41 |
42 | public void setId(long id) {
43 | this.id = id;
44 | }
45 |
46 |
47 |
48 | public int getCompany_id() {
49 | return company_id;
50 | }
51 |
52 |
53 |
54 | public void setCompany_id(int companyId) {
55 | company_id = companyId;
56 | }
57 |
58 |
59 |
60 | public String getCreated_at() {
61 | return created_at;
62 | }
63 |
64 |
65 |
66 | public void setCreated_at(String createdAt) {
67 | created_at = createdAt;
68 | }
69 |
70 |
71 |
72 | public String getUpdated_at() {
73 | return updated_at;
74 | }
75 |
76 |
77 |
78 | public void setUpdated_at(String updatedAt) {
79 | updated_at = updatedAt;
80 | }
81 |
82 |
83 |
84 | public long getCache_version() {
85 | return cache_version;
86 | }
87 |
88 |
89 |
90 | public void setCache_version(long cacheVersion) {
91 | cache_version = cacheVersion;
92 | }
93 |
94 | public static String getObjectName(Class> objectClass) {
95 | return objectClass.getSimpleName().replaceAll("([A-Z])", "_$1").substring(1).toLowerCase();
96 |
97 | }
98 |
99 |
100 |
101 | public static String toJson(boolean mapWrapped, Object target) throws JsonGenerationException, JsonMappingException, IOException {
102 | if (mapWrapped) {
103 | Map map = new HashMap();
104 | map.put(target.getClass().getSimpleName().toLowerCase(), target);
105 | return HarvestCore.mapper.writeValueAsString(map);
106 | }
107 | return HarvestCore.mapper.writeValueAsString(target);
108 | }
109 | public String toJson() throws JsonGenerationException, JsonMappingException, IOException {
110 | return toJson(true, this);
111 | }
112 |
113 | public static T fromJson(String source, Class objectClass) throws JsonParseException, JsonMappingException, IOException {
114 | Map map = HarvestCore.mapper.readValue(source, TypeFactory.fromType(new RESTParameterizedType(objectClass, false)));
115 | return map.get(getObjectName(objectClass));
116 | }
117 |
118 | public static T fromJson(InputStream source, Class objectClass) throws JsonParseException, JsonMappingException, IOException {
119 | if (source == null)
120 | throw new IOException("Source is null");
121 | Map map = HarvestCore.mapper.readValue(source, TypeFactory.fromType(new RESTParameterizedType(objectClass, false)));
122 | return map.get(getObjectName(objectClass));
123 | }
124 |
125 | public static List fromJsonList(String source, Class objectClass) throws JsonParseException, JsonMappingException, IOException {
126 | List