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 b342e9ef3465ea90450855941e4940344a2f03ea Author: servantie <servantie.c@gmail.com> Date: Tue May 10 11:30:43 2016 +0200 "use of simpler json format, sends update request to url when url is changed with the json of the task." --- .../org/chorem/jtimer/data/CommonVetoable.java | 8 ++ .../org/chorem/jtimer/data/DataEventListener.java | 9 ++ .../org/chorem/jtimer/data/TimerDataManager.java | 16 +++ .../jtimer/data/VetoableDataEventListener.java | 8 ++ .../java/org/chorem/jtimer/entities/TimerTask.java | 38 ++++++- .../chorem/jtimer/io/GTimerIncrementalSaver.java | 116 +++++++++++++++++++++ .../java/org/chorem/jtimer/ui/TimerTaskEditor.java | 82 +++++++++++++-- .../jtimer/ui/resources/TimerTaskEditor.properties | 2 + .../ui/resources/TimerTaskEditor_fr.properties | 2 + 9 files changed, 272 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/chorem/jtimer/data/CommonVetoable.java b/src/main/java/org/chorem/jtimer/data/CommonVetoable.java index 8510936..f74f4d3 100644 --- a/src/main/java/org/chorem/jtimer/data/CommonVetoable.java +++ b/src/main/java/org/chorem/jtimer/data/CommonVetoable.java @@ -202,4 +202,12 @@ public class CommonVetoable implements VetoableDataEventListener { // mais pas une combinaison des deux } } + + /* + * {@inheritDoc} + */ + @Override + public void checkSetTaskURL(TimerTask task, String newURL) { + + } } diff --git a/src/main/java/org/chorem/jtimer/data/DataEventListener.java b/src/main/java/org/chorem/jtimer/data/DataEventListener.java index 78a30b5..c0f5a28 100644 --- a/src/main/java/org/chorem/jtimer/data/DataEventListener.java +++ b/src/main/java/org/chorem/jtimer/data/DataEventListener.java @@ -189,4 +189,13 @@ public interface DataEventListener extends EventListener { default void dataLoaded(Collection<TimerProject> projects) { } + /** + * Task url changed + * @param task task with url change + * @param newURL new URl to change + */ + default void modifyTaskURL(TimerTask task, String newURL) { + + } } + diff --git a/src/main/java/org/chorem/jtimer/data/TimerDataManager.java b/src/main/java/org/chorem/jtimer/data/TimerDataManager.java index 25453c6..a5c957c 100644 --- a/src/main/java/org/chorem/jtimer/data/TimerDataManager.java +++ b/src/main/java/org/chorem/jtimer/data/TimerDataManager.java @@ -409,6 +409,22 @@ public class TimerDataManager { } /** + * Edit Task URL + */ + public void editTaskURL(TimerTask task, String newURL) { + + TimerTask newTask = task.clone(); + newTask.setSynchronisingURL(newURL); + for (VetoableDataEventListener vetoableDataEventListener : vetoableDataEventListeners) { + vetoableDataEventListener.checkSetTaskURL(task, newURL); + } + task.setSynchronisingURL(newURL); + // send notification + for (DataEventListener dataEventListener : dataEventListeners) { + dataEventListener.modifyTaskURL(task, newURL); + } + } + /** * Move task. * * @param destination task to move to diff --git a/src/main/java/org/chorem/jtimer/data/VetoableDataEventListener.java b/src/main/java/org/chorem/jtimer/data/VetoableDataEventListener.java index ac7a801..3c5e144 100644 --- a/src/main/java/org/chorem/jtimer/data/VetoableDataEventListener.java +++ b/src/main/java/org/chorem/jtimer/data/VetoableDataEventListener.java @@ -146,4 +146,12 @@ public interface VetoableDataEventListener extends EventListener { } + /** + * Check sync URL ofr a task + * @param task task to change the url + * @param newURL the new URL + */ + default void checkSetTaskURL(TimerTask task, String newURL) { + + } } diff --git a/src/main/java/org/chorem/jtimer/entities/TimerTask.java b/src/main/java/org/chorem/jtimer/entities/TimerTask.java index 586baa8..f2fc144 100644 --- a/src/main/java/org/chorem/jtimer/entities/TimerTask.java +++ b/src/main/java/org/chorem/jtimer/entities/TimerTask.java @@ -23,6 +23,7 @@ package org.chorem.jtimer.entities; import java.io.Serializable; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -47,7 +48,7 @@ public class TimerTask implements Cloneable, /** serialVersionUID */ private static final long serialVersionUID = -7590755569706702695L; - /** Task uuid used to managed task equality. */ + /** Task uuid used to managed task equality. */s - protected String uuid = UUID.randomUUID().toString(); /** Task number. */ @@ -89,6 +90,15 @@ public class TimerTask implements Cloneable, protected List<TimerAlert> alerts; /** + * Last synchronisation date + */ + protected LocalDateTime lastSync; + + /** + * URL to synchronise task + */ + protected String synchronisingURL; + /** * Constructor. */ public TimerTask() { @@ -219,6 +229,32 @@ public class TimerTask implements Cloneable, } /** + * Get task's last sync + * @return the date of the sync + */ + public LocalDateTime getLastSync() { return lastSync; } + + /** + * Sets task's last sync + * @param syncDate : date of the sync + */ + public void setLastSync(LocalDateTime syncDate) { + this.lastSync = syncDate; + } + /** + * Get task's sync URL + * @return the URL + */ + public String getSynchronisingURL() { return synchronisingURL; } + + /** + * Sets task's sync URL + * @param synchronisingURL : the sync URL + */ + public void setSynchronisingURL(String synchronisingURL) { + this.synchronisingURL = synchronisingURL; + } + /** * Add task's subtask. * * Also add parent reference. diff --git a/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java b/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java index 67f2f01..d979c43 100644 --- a/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java +++ b/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java @@ -43,6 +43,7 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -115,6 +116,9 @@ public class GTimerIncrementalSaver extends AbstractSaver implements Saver, /** Extension alert. */ protected static final String GTIMER_ALERT_EXTENSION = "alert"; + /** Extension sync. */ + protected static final String GTIMER_SYNC_EXTENSION = "sync"; + /** Empty gtimer project name. */ protected static final String GTIMER_EMPTY_PROJECT_NAME = "No project"; @@ -346,6 +350,7 @@ public class GTimerIncrementalSaver extends AbstractSaver implements Saver, parseAnnotations(task); parseAlerts(task); + parseSyncURL(task); } } catch (NumberFormatException e) { if (log.isWarnEnabled()) { @@ -584,6 +589,61 @@ public class GTimerIncrementalSaver extends AbstractSaver implements Saver, } } + /** Try and find sync information and load it + * + * @param task task to load sync info + */ + protected void parseSyncURL(TimerTask task) throws IOException { + int taskNumber = task.getNumber(); + File syncTaskFile = new File(dataSaveDirectory + File.separator + taskNumber +"."+ GTIMER_TASK_EXTENSION +"."+ GTIMER_SYNC_EXTENSION); + + if (syncTaskFile.exists()) { + if (log.isDebugEnabled()) { + log.debug("Synchronisation information found for task " + task.getName()); + } + + try (BufferedReader parseIn = new BufferedReader(new FileReader(syncTaskFile))) { + + // first line : "format: 1.2" + String line = parseIn.readLine(); + while ((line = parseIn.readLine()) != null) { + line = line.trim(); + + if (!line.isEmpty()) { + String syncType = line.substring(0, line.indexOf(' ')); + String syncInfo = line.substring(line.indexOf(' ') +1, line.length()); + + + try { + if (syncType.equals("SyncURL:")) { + task.setSynchronisingURL(syncInfo); + + } + else if (syncType.equals("LastSync:")) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS"); + LocalDateTime date = LocalDateTime.parse(syncInfo, formatter); + task.setLastSync(date); + } + else { + if (log.isWarnEnabled()) { + log.warn("Unknown synchronisation type " + syncType); + } + } + }catch (DateTimeParseException e) { + if (log.isErrorEnabled()) { + log.error("Can't parse " + syncInfo + + " as synchronisation date"); + } + + } + + } + } + } + } + + } + /** * Find task alert and load it. * @@ -1067,6 +1127,54 @@ public class GTimerIncrementalSaver extends AbstractSaver implements Saver, } } + /** + * Save synchronisation info for a task. + * + * @param task task to save annotation + */ + protected void saveSynchronisationInfo(TimerTask task) { + + + int taskNumber = task.getNumber(); + + File synchronisationTaskFile = new File(dataSaveDirectory + File.separator + + taskNumber + "." + GTIMER_TASK_EXTENSION + "." + GTIMER_SYNC_EXTENSION); + + if (task.getSynchronisingURL() != null) { + File backupfile = null; + try (Writer out = new OutputStreamWriter(new FileOutputStream(synchronisationTaskFile), "ISO-8859-1")) { + + // first make backup + backupfile = makeBackupFile(synchronisationTaskFile); + out.write("Format: " + GTIMER_FILE_VERSION + "\n"); + + //save URL + String saveURL = task.getSynchronisingURL(); + out.write("SyncURL: " + saveURL + "\n"); + + //save last sync (if there is one) + if (task.getLastSync() !=null) { + String saveLastSync = task.getLastSync().toString(); + out.write("LastSync: " + saveLastSync + "\n"); + + } + + deleteBackupFile(backupfile); + } catch (IOException e) { + if (log.isErrorEnabled()) { + log.debug("Can't save task synchronisation information", e); + } + + // can be null if backup throws the exception + if (backupfile != null) { + restoreBackupFile(backupfile); + } + } + } else { + synchronisationTaskFile.delete(); + } + + } /** * Save task alerts. @@ -1227,6 +1335,14 @@ public class GTimerIncrementalSaver extends AbstractSaver implements Saver, + alertFileToDelete.getPath() + ")"); } } + //and delete sync information file + File syncFileToDelete = new File(dataSaveDirectory + File.separator + fileNumber+ "."+ GTIMER_TASK_EXTENSION + "." + GTIMER_SYNC_EXTENSION); + if (syncFileToDelete.exists()) { + syncFileToDelete.delete(); + if (log.isDebugEnabled()) { + log.debug("Synchronisation file deleted for " + taskOrProject.getName() + "(" + syncFileToDelete.getPath() +")"); + } + } } // second, go recursively on subtasks diff --git a/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java b/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java index 8ecfbb0..885f4f7 100644 --- a/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java +++ b/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java @@ -34,7 +34,6 @@ import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import java.util.stream.Collectors; - import javax.swing.ActionMap; import javax.swing.JButton; import javax.swing.JComponent; @@ -52,7 +51,6 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.chorem.jtimer.JTimer; @@ -91,6 +89,13 @@ public class TimerTaskEditor extends DialogView { protected JSpinner spinnerS; /** annotation textarea */ protected JTextArea annotationText; + + /** task sync URL */ + protected JTextField synchronizeURL; + + /** change listener on sync URl */ + protected DocumentListener URLChangeListener; + /** change listener on spinners */ protected ChangeListener spinnerListener; @@ -114,6 +119,9 @@ public class TimerTaskEditor extends DialogView { /** did the modified annotation ? */ protected boolean isAnnotationChanged; + /** was the url modified ?*/ + protected boolean isURLChanged; + /** * days modified: You can modify any number of days before you apply changes, * this set keep track of days modified (for time, annotations or title). @@ -219,17 +227,59 @@ public class TimerTaskEditor extends DialogView { JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); - // text change listener on annotationTextArea and titleTextField + // text change listener on annotationTextArea, titleTextField and SyncURLTextField titleChangeListener = new TextChangeListener(); annotationChangeListener = new TextChangeListener(); + URLChangeListener = new TextChangeListener(); + + panel.add(createTitlePanel(), BorderLayout.NORTH); + panel.add(createJXMonthView(), BorderLayout.CENTER); + panel.add(createEditionPanel(), BorderLayout.SOUTH); - // task title + return panel; + } + + /** + * Create title panel + * @return title panel + */ + protected JPanel createTitlePanel(){ + + SpringLayout layout = new SpringLayout(); + JPanel panel = new JPanel(layout); + + // task title and listener titleText = new JTextField("", 20); // prevent too long task names titleText.getDocument().addDocumentListener(titleChangeListener); + // task syncronizeURL and listener + synchronizeURL = new JTextField("",20); + 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")); + + panel.add(titleLabel); + panel.add(titleText); + panel.add(synchronizeURL); + panel.add(URLLabel); + + JLabel largerLabel = titleLabel.getText().length() < URLLabel.getText().length() ? URLLabel : titleLabel; + + layout.putConstraint(SpringLayout.NORTH, titleLabel, 2, SpringLayout.NORTH, panel); + layout.putConstraint(SpringLayout.WEST, titleLabel, 2, SpringLayout.WEST, panel); + + layout.putConstraint(SpringLayout.NORTH, titleText, 2, SpringLayout.NORTH, panel); + layout.putConstraint(SpringLayout.WEST, titleText, 2, SpringLayout.EAST, largerLabel); + + layout.putConstraint(SpringLayout.NORTH, URLLabel, 2, SpringLayout.SOUTH, titleText); + layout.putConstraint(SpringLayout.WEST, URLLabel, 2, SpringLayout.WEST, largerLabel); + + layout.putConstraint(SpringLayout.NORTH, synchronizeURL, 2, SpringLayout.SOUTH, titleText); + layout.putConstraint(SpringLayout.WEST, synchronizeURL, 2, SpringLayout.EAST, largerLabel); + + layout.putConstraint(SpringLayout.SOUTH, panel, 2, SpringLayout.SOUTH, synchronizeURL); + layout.putConstraint(SpringLayout.EAST, panel, 2, SpringLayout.EAST, synchronizeURL); - panel.add(titleText, BorderLayout.NORTH); - panel.add(createJXMonthView(), BorderLayout.CENTER); - panel.add(createEditionPanel(), BorderLayout.SOUTH); return panel; } @@ -522,6 +572,11 @@ public class TimerTaskEditor extends DialogView { titleText.setCaretPosition(0); titleText.getDocument().addDocumentListener(titleChangeListener); + //URL + synchronizeURL.getDocument().removeDocumentListener(URLChangeListener); + synchronizeURL.setText(cloneTask.getSynchronisingURL()); + synchronizeURL.getDocument().addDocumentListener(URLChangeListener); + } /** @@ -534,6 +589,8 @@ public class TimerTaskEditor extends DialogView { isTitleChanged = true; } else if (issuer == annotationChangeListener) { isAnnotationChanged = true; + } else if (issuer == URLChangeListener) { + isURLChanged = true; } updateTask(); } @@ -572,6 +629,11 @@ public class TimerTaskEditor extends DialogView { cloneTask.setName(titleText.getText()); } + // sync URL + if (isURLChanged) { + cloneTask.setSynchronisingURL(synchronizeURL.getText()); + } + dateChanged.add(getSelectedDay().getTime()); setDataChanged(true); @@ -597,7 +659,11 @@ public class TimerTaskEditor extends DialogView { if (isTitleChanged) { dataManager.editTask(task, cloneTask.getName()); } - + // url + if (isURLChanged) { + dataManager.editTaskURL(task, cloneTask.getSynchronisingURL()); + } + for (Date date : dateChanged) { if (log.isDebugEnabled()) { log.debug("Applying changes on: " + date); diff --git a/src/main/resources/org/chorem/jtimer/ui/resources/TimerTaskEditor.properties b/src/main/resources/org/chorem/jtimer/ui/resources/TimerTaskEditor.properties index ddf2b8e..027a244 100644 --- a/src/main/resources/org/chorem/jtimer/ui/resources/TimerTaskEditor.properties +++ b/src/main/resources/org/chorem/jtimer/ui/resources/TimerTaskEditor.properties @@ -29,3 +29,5 @@ cancel.Action.shortDescription = Revert changes and quit label.time.text = Time: label.annotation.text = Annotation: +label.syncURL.text = URL: +label.title.text = Title: \ No newline at end of file diff --git a/src/main/resources/org/chorem/jtimer/ui/resources/TimerTaskEditor_fr.properties b/src/main/resources/org/chorem/jtimer/ui/resources/TimerTaskEditor_fr.properties index 6cd6223..9f6b39f 100644 --- a/src/main/resources/org/chorem/jtimer/ui/resources/TimerTaskEditor_fr.properties +++ b/src/main/resources/org/chorem/jtimer/ui/resources/TimerTaskEditor_fr.properties @@ -29,3 +29,5 @@ cancel.Action.shortDescription = Annuler et quitter label.time.text = Temps: label.annotation.text = Note: +label.syncURL.text = URL: +label.title.text = Titre: \ No newline at end of file -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.