This is an automated email from the git hooks/post-receive script. New commit to branch feature/sync in repository jtimer. See https://gitlab.nuiton.org/chorem/jtimer.git commit 9a1555e0af209f6dc507f4861a1c79ac5273f2fc Author: servantie <servantie.c@gmail.com> Date: Wed Jun 8 15:56:18 2016 +0200 changed syncURL to syncURLList, updated methods for sync accordingly --- .../org/chorem/jtimer/data/DataEventListener.java | 5 +- .../org/chorem/jtimer/data/TimerDataManager.java | 11 +-- .../java/org/chorem/jtimer/entities/TimerTask.java | 41 ++++++++--- .../chorem/jtimer/entities/TimerTaskHelper.java | 82 ++++++++++++---------- .../chorem/jtimer/io/GTimerIncrementalSaver.java | 23 ++++-- .../chorem/jtimer/io/TimerTaskSynchronizer.java | 44 ++++++------ .../java/org/chorem/jtimer/ui/TimerTaskEditor.java | 23 +++--- .../jtimer/ui/report/TimerTaskUpdaterView.java | 48 +++++++++---- 8 files changed, 167 insertions(+), 110 deletions(-) diff --git a/src/main/java/org/chorem/jtimer/data/DataEventListener.java b/src/main/java/org/chorem/jtimer/data/DataEventListener.java index c0f5a28..df1ad50 100644 --- a/src/main/java/org/chorem/jtimer/data/DataEventListener.java +++ b/src/main/java/org/chorem/jtimer/data/DataEventListener.java @@ -192,10 +192,9 @@ public interface DataEventListener extends EventListener { /** * Task url changed * @param task task with url change - * @param newURL new URl to change + * @param newURLList new URlList to change */ - default void modifyTaskURL(TimerTask task, String newURL) { - + default void modifyTaskURL(TimerTask task, List<String> newURLList) { } } diff --git a/src/main/java/org/chorem/jtimer/data/TimerDataManager.java b/src/main/java/org/chorem/jtimer/data/TimerDataManager.java index a5c957c..cea7003 100644 --- a/src/main/java/org/chorem/jtimer/data/TimerDataManager.java +++ b/src/main/java/org/chorem/jtimer/data/TimerDataManager.java @@ -411,17 +411,12 @@ public class TimerDataManager { /** * Edit Task URL */ - public void editTaskURL(TimerTask task, String newURL) { + public void editTaskURL(TimerTask task, List<String> newURLList) { - TimerTask newTask = task.clone(); - newTask.setSynchronisingURL(newURL); - for (VetoableDataEventListener vetoableDataEventListener : vetoableDataEventListeners) { - vetoableDataEventListener.checkSetTaskURL(task, newURL); - } - task.setSynchronisingURL(newURL); + task.setSynchronisingURLList(newURLList); // send notification for (DataEventListener dataEventListener : dataEventListeners) { - dataEventListener.modifyTaskURL(task, newURL); + dataEventListener.modifyTaskURL(task, newURLList); } } /** diff --git a/src/main/java/org/chorem/jtimer/entities/TimerTask.java b/src/main/java/org/chorem/jtimer/entities/TimerTask.java index f2fc144..a75d4b7 100644 --- a/src/main/java/org/chorem/jtimer/entities/TimerTask.java +++ b/src/main/java/org/chorem/jtimer/entities/TimerTask.java @@ -48,7 +48,7 @@ public class TimerTask implements Cloneable, /** serialVersionUID */ private static final long serialVersionUID = -7590755569706702695L; - /** Task uuid used to managed task equality. */s - + /** Task uuid used to managed task equality. */ protected String uuid = UUID.randomUUID().toString(); /** Task number. */ @@ -97,7 +97,7 @@ public class TimerTask implements Cloneable, /** * URL to synchronise task */ - protected String synchronisingURL; + protected List<String> synchronisingURLList; /** * Constructor. */ @@ -107,7 +107,7 @@ public class TimerTask implements Cloneable, allDaysAnnotations = new TreeMap<>(); subTasks = new ArrayList<>(); alerts = new ArrayList<>(); - + synchronisingURLList = new ArrayList<>(); // wrong value to detect bug number = -1; } @@ -241,19 +241,40 @@ public class TimerTask implements Cloneable, public void setLastSync(LocalDateTime syncDate) { this.lastSync = syncDate; } + + /** + * Get task's sync URL List + * @return the URL List + */ + public List<String> getSynchronisingURLList() { return synchronisingURLList; } + /** - * Get task's sync URL - * @return the URL + * Returns one String containing all the URLs for sync, separated by " , " + * @return a string of URLs */ - public String getSynchronisingURL() { return synchronisingURL; } + public String getSynchronizingURLAsString() { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < synchronisingURLList.size(); ++i) { + if (i == synchronisingURLList.size()-1) { + builder.append(synchronisingURLList.get(i)); + } + else { + builder.append(synchronisingURLList.get(i)); + builder.append(" , "); + } + } + String urlListString = builder.toString(); + return urlListString; + } /** - * Sets task's sync URL - * @param synchronisingURL : the sync URL + * Sets task's sync URLList + * @param synchronisingURLList : the sync URL List */ - public void setSynchronisingURL(String synchronisingURL) { - this.synchronisingURL = synchronisingURL; + public void setSynchronisingURLList(List<String> synchronisingURLList) { + this.synchronisingURLList = synchronisingURLList; } + /** * Add task's subtask. * diff --git a/src/main/java/org/chorem/jtimer/entities/TimerTaskHelper.java b/src/main/java/org/chorem/jtimer/entities/TimerTaskHelper.java index 9ecab69..a9a953e 100644 --- a/src/main/java/org/chorem/jtimer/entities/TimerTaskHelper.java +++ b/src/main/java/org/chorem/jtimer/entities/TimerTaskHelper.java @@ -339,18 +339,20 @@ public class TimerTaskHelper { * Returns a String in JSON format (cf schema (simplified) * with all times and annotations of a task (without subtasks) * @param task the task to make a JSON from + * @param withAnnotations true if annotations included + * @param timezone represents the timezone * @return result the string in JSON */ - public static JsonObject taskToJSONFormat(TimerTask task, boolean withAnnotations, String timezone) { + public static List<JsonObject> taskToJSONFormat(TimerTask task, boolean withAnnotations, String timezone) { Date startDate = task.getAllDaysAndTimes().firstKey(); Date endDate = new Date(); - JsonObject resultingJSON = taskToJSONFormat(task, startDate, endDate, withAnnotations, timezone); + List<JsonObject> resultingJSON = taskToJSONFormat(task, startDate, endDate, withAnnotations, timezone); return resultingJSON; } /** - * Returns a JSONObject (cf schema (simplified) + * Returns a list of JSONObject (one for each sync URL) * with all times of a task (without subtasks) * in a given period between two dates * with annotations if enabled @@ -358,44 +360,52 @@ public class TimerTaskHelper { * @param startDate the beginning date * @param endDate the end date * @param withAnnotations true if annotations included + * @param timezone represents the timezone * @return result the string in JSON */ - public static JsonObject taskToJSONFormat(TimerTask task, Date startDate, Date endDate, boolean withAnnotations, String timezone) { - JsonObject responseJSON = new JsonObject(); - LocalDate startPeriodDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); - LocalDate endPeriodDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); - - JsonArray periodArray = new JsonArray(); - SortedMap<Date, Long> dates = task.getAllDaysAndTimes().subMap(startDate, endDate); - if (dates.size() != 0) { - for (SortedMap.Entry<Date, Long> entry : dates.entrySet()) { - //adding id, startDate and duration - //converting Date to LocalDate (to ease the .toString()) - //deal with timezones ? - LocalDate date = entry.getKey().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); - String dateString = date.toString(); - //as jtimer has time entries only for a day, the id of the times will be the date in yyyy-mm-dd format - JsonObject periodElement = new JsonObject(); - periodElement.addProperty("periodId", dateString); - periodElement.addProperty("periodStartDate", dateString + "T00:00:00.000" + timezone); - periodElement.addProperty("periodDuration", entry.getValue()); - if (withAnnotations && getAnnotation(task, entry.getKey()).size() != 0 ) { - String annotations = ""; - for (String s : getAnnotation(task, entry.getKey())) { - annotations = annotations + s + ","; + public static List<JsonObject> taskToJSONFormat(TimerTask task, Date startDate, Date endDate, boolean withAnnotations, String timezone) { + + ArrayList<JsonObject> jsonObjectList = new ArrayList<>(); + + for (String url : task.getSynchronisingURLList()) { + + JsonObject responseJSON = new JsonObject(); + LocalDate startPeriodDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + LocalDate endPeriodDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + + JsonArray periodArray = new JsonArray(); + SortedMap<Date, Long> dates = task.getAllDaysAndTimes().subMap(startDate, endDate); + if (dates.size() != 0) { + for (SortedMap.Entry<Date, Long> entry : dates.entrySet()) { + //adding id, startDate and duration + //converting Date to LocalDate (to ease the .toString()) + LocalDate date = entry.getKey().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + String dateString = date.toString(); + //as jtimer has time entries only for a day, the id of the times will be the date in yyyy-mm-dd format + JsonObject periodElement = new JsonObject(); + periodElement.addProperty("periodId", dateString); + periodElement.addProperty("periodStartDate", dateString + "T00:00:00.000" + timezone); + periodElement.addProperty("periodDuration", entry.getValue()); + if (withAnnotations && !(getAnnotation(task, entry.getKey()).isEmpty())) { + StringBuilder builder = new StringBuilder(); + for (String s : getAnnotation(task, entry.getKey())) { + builder.append(s); + builder.append(","); + } + String annotations = builder.toString(); + periodElement.addProperty("periodInfo", annotations); + } - //remove trailing comma - annotations = annotations.substring(0, annotations.length()-1); - periodElement.addProperty("periodInfo", annotations); + periodArray.add(periodElement); } - periodArray.add(periodElement); } - } - responseJSON.addProperty("URL", task.getSynchronisingURL()); - responseJSON.addProperty("startDate", startPeriodDate.toString()); - responseJSON.addProperty("endDate", endPeriodDate.toString()); - responseJSON.add("periods", periodArray ); + responseJSON.addProperty("URL", url); + responseJSON.addProperty("startDate", startPeriodDate.toString()); + responseJSON.addProperty("endDate", endPeriodDate.toString()); + responseJSON.add("periods", periodArray); - return responseJSON; + jsonObjectList.add(responseJSON); + } + return jsonObjectList; } } diff --git a/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java b/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java index b9f822d..7ffbec0 100644 --- a/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java +++ b/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java @@ -615,8 +615,13 @@ public class GTimerIncrementalSaver extends AbstractSaver implements Saver, try { - if (syncType.equals("SyncURL:")) { - task.setSynchronisingURL(syncInfo); + if (syncType.equals("SyncURLList:")) { + String[] urlArray = syncInfo.trim().split(" , "); + List<String> urlList = new ArrayList<>(); + for (String url : urlArray) { + urlList.add(url); + } + task.setSynchronisingURLList(urlList); } else if (syncType.equals("LastSync:")) { @@ -1140,7 +1145,7 @@ public class GTimerIncrementalSaver extends AbstractSaver implements Saver, File synchronisationTaskFile = new File(dataSaveDirectory + File.separator + taskNumber + "." + GTIMER_TASK_EXTENSION + "." + GTIMER_SYNC_EXTENSION); - if (task.getSynchronisingURL() != null) { + if (task.getSynchronisingURLList() != null) { File backupfile = null; try (Writer out = new OutputStreamWriter(new FileOutputStream(synchronisationTaskFile), "ISO-8859-1")) { @@ -1149,9 +1154,8 @@ public class GTimerIncrementalSaver extends AbstractSaver implements Saver, out.write("Format: " + GTIMER_FILE_VERSION + "\n"); //save URL - if(!(task.getSynchronisingURL().equals("")) || task.getSynchronisingURL() !=null) { - String saveURL = task.getSynchronisingURL(); - out.write("SyncURL: " + saveURL + "\n"); + if(task.getSynchronisingURLList() !=null && !(task.getSynchronisingURLList().isEmpty())) { + out.write("SyncURLList: " + task.getSynchronizingURLAsString() + "\n"); } //save last sync (if there is one) if (task.getLastSync() !=null) { @@ -1515,4 +1519,11 @@ public class GTimerIncrementalSaver extends AbstractSaver implements Saver, } } + /* + * {@inheritDoc} + */ + @Override + public void modifyTaskURL(TimerTask task, List<String> newURL) { + saveSynchronisationInfo(task); + } } diff --git a/src/main/java/org/chorem/jtimer/io/TimerTaskSynchronizer.java b/src/main/java/org/chorem/jtimer/io/TimerTaskSynchronizer.java index e2e480c..7f48a49 100644 --- a/src/main/java/org/chorem/jtimer/io/TimerTaskSynchronizer.java +++ b/src/main/java/org/chorem/jtimer/io/TimerTaskSynchronizer.java @@ -1,5 +1,6 @@ package org.chorem.jtimer.io; +import com.google.gson.JsonObject; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.chorem.jtimer.data.DataEventListener; @@ -24,7 +25,7 @@ public class TimerTaskSynchronizer implements DataEventListener { private static Log log = LogFactory.getLog(TimerTaskSynchronizer.class); /** auto sync delay */ - protected long autoSyncDelay = 1000 * 10; //every 2 hours, check for modifications to sync + protected long autoSyncDelay = 1000 * 10L; //every 2 hours, check for modifications to sync /** timer to schedule syncs */ protected Timer timer; @@ -90,20 +91,11 @@ public class TimerTaskSynchronizer implements DataEventListener { if (log.isDebugEnabled()){ log.debug("task " + task.getName() + " being synced."); } - //do the sync, store the result - boolean syncDone = synchronizeSingleTask(task); + synchronizeSingleTask(task); //for now doesn't deal with failure in the update, just task already updated if (remainingTasks.contains(task)) { remainingTasks.remove(task); } - - if (syncDone) { - log.debug("Sync done"); - } - else { - log.debug("Sync failed"); - } - } tasksToSync.clear(); tasksToSync.addAll(remainingTasks); @@ -112,14 +104,22 @@ public class TimerTaskSynchronizer implements DataEventListener { } /** - * Makes one synchronization for a task, without annotations by default + * Synchronizes one Task (calls to synchronizeTaskOnURL for each syncURLList element of the task) * * @param task - * @return boolean for failure of sync (maybe make it return an int for better treatment of failure) */ - public boolean synchronizeSingleTask(TimerTask task) { - String updateJsonString = TimerTaskHelper.taskToJSONFormat(task, false, timezone).toString(); - String syncURL = task.getSynchronisingURL(); + public void synchronizeSingleTask(TimerTask task) { + List<JsonObject> jsonObjectList = TimerTaskHelper.taskToJSONFormat(task, false, timezone); + + for (JsonObject object : jsonObjectList) { + synchronizeTaskOnURL(task, object); + } + } + + public boolean synchronizeTaskOnURL(TimerTask task, JsonObject object) { + + String updateJsonString = object.toString(); + String syncURL = object.get("URL").getAsString(); String charset = "UTF-8"; HttpURLConnection connection; URL url; @@ -203,10 +203,8 @@ public class TimerTaskSynchronizer implements DataEventListener { //when a task is modified, add it to the to sync list (if it isn't already there) if(!tasksToSync.contains(task) && (!tasksToSync.isEmpty())) { //add it only if the URL is not empty - if (task.getSynchronisingURL() != null) { - if (task.getSynchronisingURL().isEmpty()){ - tasksToSync.add(task); - } + if ((task.getSynchronisingURLList() != null) && !(task.getSynchronisingURLList().isEmpty())){ + tasksToSync.add(task); } } } @@ -271,7 +269,7 @@ public class TimerTaskSynchronizer implements DataEventListener { public void stopTask(TimerTask task) { if (!tasksToSync.contains(task)) { //add it only if the URL is not empty - if ((task.getSynchronisingURL() != null) && !(task.getSynchronisingURL().isEmpty())) { + if ((task.getSynchronisingURLList() != null) && !(task.getSynchronisingURLList().isEmpty())) { tasksToSync.add(task); } } @@ -288,10 +286,10 @@ public class TimerTaskSynchronizer implements DataEventListener { * @param task modified task */ @Override - public void modifyTaskURL(TimerTask task, String newURL) { + public void modifyTaskURL(TimerTask task, List<String> newURL) { if (!tasksToSync.contains(task)) { //add it only if the URL is not empty - if ((task.getSynchronisingURL() != null) && !(task.getSynchronisingURL().isEmpty())){ + if ((task.getSynchronisingURLList() != null) && !(task.getSynchronisingURLList().isEmpty())){ tasksToSync.add(task); } } diff --git a/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java b/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java index 885f4f7..1b86b13 100644 --- a/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java +++ b/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java @@ -94,7 +94,7 @@ public class TimerTaskEditor extends DialogView { protected JTextField synchronizeURL; /** change listener on sync URl */ - protected DocumentListener URLChangeListener; + protected DocumentListener urlChangeListener; /** change listener on spinners */ protected ChangeListener spinnerListener; @@ -230,7 +230,7 @@ public class TimerTaskEditor extends DialogView { // text change listener on annotationTextArea, titleTextField and SyncURLTextField titleChangeListener = new TextChangeListener(); annotationChangeListener = new TextChangeListener(); - URLChangeListener = new TextChangeListener(); + urlChangeListener = new TextChangeListener(); panel.add(createTitlePanel(), BorderLayout.NORTH); panel.add(createJXMonthView(), BorderLayout.CENTER); @@ -253,7 +253,7 @@ public class TimerTaskEditor extends DialogView { titleText.getDocument().addDocumentListener(titleChangeListener); // task syncronizeURL and listener synchronizeURL = new JTextField("",20); - synchronizeURL.getDocument().addDocumentListener(URLChangeListener); + synchronizeURL.getDocument().addDocumentListener(urlChangeListener); //labels for title and url JLabel titleLabel = new JLabel(getResourceMap().getString("label.title.text")); JLabel URLLabel = new JLabel(getResourceMap().getString("label.syncURL.text")); @@ -573,9 +573,9 @@ public class TimerTaskEditor extends DialogView { titleText.getDocument().addDocumentListener(titleChangeListener); //URL - synchronizeURL.getDocument().removeDocumentListener(URLChangeListener); - synchronizeURL.setText(cloneTask.getSynchronisingURL()); - synchronizeURL.getDocument().addDocumentListener(URLChangeListener); + synchronizeURL.getDocument().removeDocumentListener(urlChangeListener); + synchronizeURL.setText(cloneTask.getSynchronizingURLAsString()); + synchronizeURL.getDocument().addDocumentListener(urlChangeListener); } @@ -589,7 +589,7 @@ public class TimerTaskEditor extends DialogView { isTitleChanged = true; } else if (issuer == annotationChangeListener) { isAnnotationChanged = true; - } else if (issuer == URLChangeListener) { + } else if (issuer == urlChangeListener) { isURLChanged = true; } updateTask(); @@ -631,7 +631,12 @@ public class TimerTaskEditor extends DialogView { // sync URL if (isURLChanged) { - cloneTask.setSynchronisingURL(synchronizeURL.getText()); + String[] urlArray = synchronizeURL.getText().trim().split(" , "); + List<String> urlList = new ArrayList<>(); + for (String url : urlArray) { + urlList.add(url); + } + cloneTask.setSynchronisingURLList(urlList); } dateChanged.add(getSelectedDay().getTime()); @@ -661,7 +666,7 @@ public class TimerTaskEditor extends DialogView { } // url if (isURLChanged) { - dataManager.editTaskURL(task, cloneTask.getSynchronisingURL()); + dataManager.editTaskURL(task, cloneTask.getSynchronisingURLList()); } for (Date date : dateChanged) { diff --git a/src/main/java/org/chorem/jtimer/ui/report/TimerTaskUpdaterView.java b/src/main/java/org/chorem/jtimer/ui/report/TimerTaskUpdaterView.java index 8c980a2..f2653ab 100644 --- a/src/main/java/org/chorem/jtimer/ui/report/TimerTaskUpdaterView.java +++ b/src/main/java/org/chorem/jtimer/ui/report/TimerTaskUpdaterView.java @@ -73,7 +73,7 @@ public class TimerTaskUpdaterView extends FrameView implements DocumentListener /** update output view*/ protected JTextArea updateArea; - protected JsonObject updateJson; + protected List<JsonObject> updateJson; /** task to update */ protected TimerTask task; @@ -103,6 +103,8 @@ public class TimerTaskUpdaterView extends FrameView implements DocumentListener //default the timezone timezone = "+0100"; + updateJson = new ArrayList<>(); + } /** @@ -342,18 +344,21 @@ public class TimerTaskUpdaterView extends FrameView implements DocumentListener */ @org.jdesktop.application.Action public void generateUpdate() { + //get the various objects for updates (on several urls) + updateJson = taskToJSONFormat(task, datePickerFrom.getDate(), + datePickerTo.getDate(), isIncludingAnnotations(), timezone); + if (!updateJson.isEmpty()) { + //to make it human readable + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + StringBuilder builder = new StringBuilder(); + for (JsonObject object : updateJson) { + builder.append(gson.toJson(object)); + } + updateArea.setText(builder.toString()); - // make the JSON Object of information - updateJson = taskToJSONFormat(task, datePickerFrom.getDate(), - datePickerTo.getDate(), isIncludingAnnotations(), timezone); - //make it human readable - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - String jsonOutput = gson.toJson(updateJson); - - if (updateJson != null) { - updateArea.setText(jsonOutput); - } else { - updateArea.setText(""); + } + else { + updateArea.setText("No data"); } } @@ -390,11 +395,24 @@ public class TimerTaskUpdaterView extends FrameView implements DocumentListener } /** - * send update + * goes through the Jsons to send and sends them */ @Action(enabledProperty = "updatingEnabled") public void sendUpdate() { - String syncURL = task.getSynchronisingURL(); + for (JsonObject object : updateJson) { + synchronizeTaskOnURL(task, object); + } + } + + + /** + * Sends the update of a task to one url + * @param task task to update + * @param object json of task info + */ + public void synchronizeTaskOnURL(TimerTask task, JsonObject object) { + String updateJsonString = object.toString(); + String syncURL = object.get("URL").getAsString(); String charset = "UTF-8"; if (syncURL != null) { HttpURLConnection connection= null; @@ -412,7 +430,7 @@ public class TimerTaskUpdaterView extends FrameView implements DocumentListener connection.setUseCaches(false); connection.setDoInput(true); - connection.setRequestProperty("Content-Length", "" + updateJson.toString().length()); + connection.setRequestProperty("Content-Length", "" + updateJsonString); connection.setDoOutput(true); connection.setRequestProperty("Accept-Charset", charset); connection.setRequestProperty("Content-Type", "application/json" + charset); -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.