Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
8cc257c24e | |||
d720c6c645 |
@ -1,5 +1,5 @@
|
||||
#Sun, 22 Sep 2013 14:58:43 -0500
|
||||
#Fri, 11 Oct 2013 16:03:41 -0500
|
||||
name=timestamper-lib
|
||||
version=1.5
|
||||
version=2.1
|
||||
lib.local=true
|
||||
build.number=1
|
||||
|
Binary file not shown.
BIN
release/timestamper-lib-2.1.jar
Normal file
BIN
release/timestamper-lib-2.1.jar
Normal file
Binary file not shown.
@ -3,6 +3,7 @@ package com.jdblabs.timestamper.core
|
||||
import com.jdbernard.util.SmartConfig
|
||||
import groovyx.net.http.HTTPBuilder
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.UUID;
|
||||
|
||||
import static groovyx.net.http.ContentType.*
|
||||
import static groovyx.net.http.Method.*
|
||||
@ -27,7 +28,7 @@ public class JDBLabsWebTimelineSource extends TimelineSource {
|
||||
private URI baseUri
|
||||
private HTTPBuilder http
|
||||
|
||||
private Map entryHashes
|
||||
private Map serverEntryIds
|
||||
|
||||
public JDBLabsWebTimelineSource(URI uri, SmartConfig config) {
|
||||
super(uri)
|
||||
@ -50,8 +51,8 @@ public class JDBLabsWebTimelineSource extends TimelineSource {
|
||||
"communicating to the web timeline.\n" +
|
||||
"${resp.statusLine}: ${json}") }
|
||||
|
||||
// init our hash of known entries
|
||||
entryHashes = [:]
|
||||
// init our map of known entries
|
||||
serverEntryIds = [:]
|
||||
}
|
||||
|
||||
public Timeline read() {
|
||||
@ -76,11 +77,12 @@ public class JDBLabsWebTimelineSource extends TimelineSource {
|
||||
|
||||
timeline = new Timeline()
|
||||
|
||||
// create start and end times
|
||||
// create start and end times to use as parameters to the web service
|
||||
startDate = Calendar.getInstance()
|
||||
startDate.timeInMillis = 0
|
||||
startDate.timeInMillis = 0 // Beginning of the epoch
|
||||
startDate = isoDateFormat.format(startDate.time)
|
||||
|
||||
// Until now
|
||||
endDate = isoDateFormat.format(Calendar.getInstance().time)
|
||||
|
||||
// load the timeline entries
|
||||
@ -96,11 +98,12 @@ public class JDBLabsWebTimelineSource extends TimelineSource {
|
||||
|
||||
// parse and create the timeline marker
|
||||
def timestamp = isoDateFormat.parse(entry.timestamp)
|
||||
def marker = new TimelineMarker(timestamp, entry.mark, entry.notes)
|
||||
def marker = new TimelineMarker(timestamp, entry.mark, entry.notes,
|
||||
UUID.fromString(entry.uuid));
|
||||
|
||||
// add it to the timeline and our map of hashes
|
||||
timeline.addMarker(marker)
|
||||
entryHashes[fullHash(marker)] = entry.id
|
||||
serverEntryIds[marker.uuid] = entry.id
|
||||
}
|
||||
|
||||
// return the created timeline
|
||||
@ -114,28 +117,38 @@ public class JDBLabsWebTimelineSource extends TimelineSource {
|
||||
// make sure we have a fresh session
|
||||
authenticate()
|
||||
|
||||
// find differences since we last persisted
|
||||
deletedEntries = entryHashes.clone() // shallow copy
|
||||
// Find differences since we last persisted.
|
||||
|
||||
// We want to identify the set of entries that were previously present
|
||||
// on the server but are no longer present locally and delete them from
|
||||
// the server. We start with the set of all entries last seen on the
|
||||
// server. We look through our local entries and if we find the entry
|
||||
// locally we remove it from our set of deletion candidates.
|
||||
|
||||
// We will also be constructing a set of entries that we have locally
|
||||
// which were not present on the server. This set of entries will be
|
||||
// added to the server.
|
||||
|
||||
deletedEntries = serverEntryIds.clone() // shallow copy
|
||||
newEntries = []
|
||||
|
||||
t.each { marker ->
|
||||
def hash = fullHash(marker)
|
||||
// This marker is present on the server and is still present
|
||||
// locally, remove from deletedEntries
|
||||
if (deletedEntries.containsKey(marker.uuid)) {
|
||||
deletedEntries.remove(marker.uuid) }
|
||||
|
||||
// this marker is present, remove from deletedEntries
|
||||
if (deletedEntries.containsKey(hash)) {
|
||||
deletedEntries.remove(hash) }
|
||||
|
||||
// this marker is not present, add to newEntries
|
||||
// This marker is not present on the server, add to newEntries.
|
||||
else { newEntries << marker }
|
||||
}
|
||||
|
||||
// delete all entries that used to be present but are not any longer
|
||||
deletedEntries.each { hash, entryId ->
|
||||
// Delete all entries that used to be present but are not any longer
|
||||
deletedEntries.each { uuid, entryId ->
|
||||
http.request(DELETE) {
|
||||
uri.path = "entries/${username}/${timelineId}/${entryId}"
|
||||
|
||||
response.'404' = { resp -> entryHashes.remove(hash) }
|
||||
response.success = { resp -> entryHashes.remove(hash) }
|
||||
response.'404' = { resp -> serverEntryIds.remove(uuid) }
|
||||
response.success = { resp -> serverEntryIds.remove(uuid) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,6 +158,7 @@ public class JDBLabsWebTimelineSource extends TimelineSource {
|
||||
def entryBody = [
|
||||
mark: entry.mark,
|
||||
notes: entry.notes,
|
||||
uuid: entry.uuid.toString(),
|
||||
timestamp: isoDateFormat.format(entry.timestamp)
|
||||
]
|
||||
|
||||
@ -154,7 +168,7 @@ public class JDBLabsWebTimelineSource extends TimelineSource {
|
||||
body = entryBody
|
||||
|
||||
response.success = { resp, json ->
|
||||
entryHashes.put(fullHash(entry), json?.id ?: 0) }
|
||||
serverEntryIds.put(entry.uuid, json?.id ?: 0) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import java.io.Writer;
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
import java.util.Scanner;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -71,8 +72,9 @@ public class StreamBasedTimelineSource extends TimelineSource {
|
||||
Writer out = new OutputStreamWriter(stream);
|
||||
for (TimelineMarker tm : timeline) {
|
||||
|
||||
// write timestamp
|
||||
out.write(Timeline.longFormat.format(tm.getTimestamp()) + "\n");
|
||||
// write timestamp and UUID
|
||||
out.write(Timeline.longFormat.format(tm.getTimestamp()) + "," +
|
||||
tm.getUuid().toString() + "\n");
|
||||
|
||||
// write mark
|
||||
String mark = tm.getMark().replace('\n', '\u0000');
|
||||
@ -127,7 +129,8 @@ public class StreamBasedTimelineSource extends TimelineSource {
|
||||
null : new PrintWriter(commentStream);
|
||||
|
||||
ReadingState readingState = ReadingState.NewMarker;
|
||||
Date d = null;
|
||||
Date date = null;
|
||||
UUID uuid = null;
|
||||
StringBuilder mark = null;
|
||||
StringBuilder notes = null;
|
||||
String line;
|
||||
@ -146,11 +149,24 @@ public class StreamBasedTimelineSource extends TimelineSource {
|
||||
switch (readingState) {
|
||||
|
||||
case NewMarker:
|
||||
try { d = Timeline.longFormat.parse(line); }
|
||||
try {
|
||||
String[] parts = line.split(",");
|
||||
date = Timeline.longFormat.parse(parts[0]);
|
||||
|
||||
// If there is no UUID, we will ignore it. This allows us
|
||||
// to support timeline files generated by 1.x versions of
|
||||
// this library.
|
||||
// TODO: Remove this check in version 3.x
|
||||
if (parts.length > 1) uuid = UUID.fromString(parts[1]);
|
||||
else uuid = null; }
|
||||
catch (ParseException pe) {
|
||||
throw new IOException("Error parsing timeline file at line "
|
||||
+ lineNumber + ": expected a new marker date but could not parse"
|
||||
+ " the date. Error: " + pe.getLocalizedMessage()); }
|
||||
catch (IllegalArgumentException iae) {
|
||||
throw new IOException("Error parsing timeline file at line "
|
||||
+ lineNumber + ": Expected a UUID but could not parse "
|
||||
+ "the value. Details: " + iae.getLocalizedMessage()); }
|
||||
readingState = ReadingState.StartMark;
|
||||
break;
|
||||
|
||||
@ -179,7 +195,13 @@ public class StreamBasedTimelineSource extends TimelineSource {
|
||||
case EndMarker:
|
||||
String sMark = mark.toString().replace('\u0000', '\n');
|
||||
String sNotes = notes.toString().replace('\u0000', '\n');
|
||||
timeline.addMarker(d, sMark, sNotes);
|
||||
TimelineMarker marker;
|
||||
|
||||
// Support a missing UUID until version 3.x
|
||||
if (uuid == null)
|
||||
marker = new TimelineMarker(date, sMark, sNotes);
|
||||
else marker = new TimelineMarker(date, sMark, sNotes, uuid);
|
||||
timeline.addMarker(marker);
|
||||
readingState = ReadingState.NewMarker; } }
|
||||
|
||||
return timeline; }
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.jdblabs.timestamper.core;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Jonathan Bernard {@literal <jdbernard@gmail.com>}
|
||||
@ -11,16 +12,23 @@ public class TimelineMarker implements Comparable<TimelineMarker> {
|
||||
|
||||
private final Date timestamp;
|
||||
private final String mark;
|
||||
private final UUID uuid;
|
||||
private String notes;
|
||||
|
||||
public TimelineMarker(Date timestamp, String mark, String notes) {
|
||||
this(timestamp, mark, notes, UUID.randomUUID()); }
|
||||
|
||||
public TimelineMarker(Date timestamp, String mark, String notes, UUID uuid) {
|
||||
if (timestamp == null || mark == null)
|
||||
throw new IllegalArgumentException("Null timestamp or mark"
|
||||
+ " is not permitted.");
|
||||
|
||||
this.timestamp = timestamp;
|
||||
// We truncate milliseconds.
|
||||
long seconds = 1000l * (timestamp.getTime() / 1000l);
|
||||
this.timestamp = new Date(seconds);
|
||||
this.mark = mark;
|
||||
this.notes = notes;
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public Date getTimestamp() { return timestamp; }
|
||||
@ -29,12 +37,19 @@ public class TimelineMarker implements Comparable<TimelineMarker> {
|
||||
|
||||
public String getNotes() { return notes; }
|
||||
|
||||
public UUID getUuid() { return uuid; }
|
||||
|
||||
public void setNotes(String notes) { this.notes = notes; }
|
||||
|
||||
@Override
|
||||
public int compareTo(TimelineMarker that) {
|
||||
// Always greater than null
|
||||
if (that == null) return Integer.MAX_VALUE;
|
||||
|
||||
// Always equal to other instances of itself (same UUID).
|
||||
if (this.uuid.equals(that.uuid)) return 0;
|
||||
|
||||
// Check the timestamp, then the mark if the timestamps are equal.
|
||||
int val = this.timestamp.compareTo(that.timestamp);
|
||||
if (val == 0) val = this.mark.compareTo(that.mark);
|
||||
|
||||
@ -47,8 +62,7 @@ public class TimelineMarker implements Comparable<TimelineMarker> {
|
||||
if (!(o instanceof TimelineMarker)) return false;
|
||||
|
||||
TimelineMarker that = (TimelineMarker) o;
|
||||
return this.timestamp.equals(that.timestamp) &&
|
||||
this.mark.equals(that.mark);
|
||||
return this.uuid.equals(that.uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Reference in New Issue
Block a user