From a50536d87873bce8f9ead5987dcf03f25834b949 Mon Sep 17 00:00:00 2001 From: Randy Baumgarte Date: Sun, 28 Aug 2011 08:35:08 -0400 Subject: [PATCH] Save non-standard metadata to note attribute.sourceApplication for DB restores. --- src/cx/fbn/nevernote/evernote/NoteMetadata.java | 3 +- src/cx/fbn/nevernote/sql/NoteTable.java | 222 ++++++++++++++++-------- src/cx/fbn/nevernote/threads/SyncRunner.java | 2 +- src/cx/fbn/nevernote/utilities/ListManager.java | 12 +- src/cx/fbn/nevernote/xml/ExportData.java | 2 +- src/cx/fbn/nevernote/xml/ImportData.java | 20 ++- 6 files changed, 177 insertions(+), 84 deletions(-) diff --git a/src/cx/fbn/nevernote/evernote/NoteMetadata.java b/src/cx/fbn/nevernote/evernote/NoteMetadata.java index 3bec18a..a6139b1 100644 --- a/src/cx/fbn/nevernote/evernote/NoteMetadata.java +++ b/src/cx/fbn/nevernote/evernote/NoteMetadata.java @@ -1,6 +1,5 @@ package cx.fbn.nevernote.evernote; -import com.trolltech.qt.gui.QColor; public class NoteMetadata { private String guid; @@ -9,7 +8,7 @@ public class NoteMetadata { private boolean dirty; public NoteMetadata() { - color = QColor.white.rgb(); + color = -1; pinned = false; dirty = false; } diff --git a/src/cx/fbn/nevernote/sql/NoteTable.java b/src/cx/fbn/nevernote/sql/NoteTable.java index 264ae7a..ac0aeb1 100644 --- a/src/cx/fbn/nevernote/sql/NoteTable.java +++ b/src/cx/fbn/nevernote/sql/NoteTable.java @@ -43,7 +43,6 @@ import cx.fbn.nevernote.evernote.EnmlConverter; import cx.fbn.nevernote.evernote.NoteMetadata; import cx.fbn.nevernote.sql.driver.NSqlQuery; import cx.fbn.nevernote.utilities.ApplicationLogger; -import cx.fbn.nevernote.utilities.Pair; public class NoteTable { private final ApplicationLogger logger; @@ -223,6 +222,8 @@ public class NoteTable { } // Get a note by Guid public Note getNote(String noteGuid, boolean loadContent, boolean loadResources, boolean loadRecognition, boolean loadBinary, boolean loadTags) { + +// extractMetadata("otherKey:{values};baumgarte:{titleColor=fff;pinned=true;};finalKey:{values1);"); if (noteGuid == null) return null; if (noteGuid.trim().equals("")) @@ -747,13 +748,14 @@ public class NoteTable { } } // Update a note - public void updateNote(Note n, boolean isNew) { - int titleColor = getNoteTitleColor(n.getGuid()); + public void updateNote(Note n) { + NoteMetadata meta = getNoteMetaInformation(n.getGuid()); String originalGuid = findAlternateGuid(n.getGuid()); expungeNote(n.getGuid(), true, false); addNote(n, false); - if (titleColor != -1) - setNoteTitleColor(n.getGuid(), titleColor); + if (n!=null) { + updateNoteMetadata(meta); + } if (originalGuid != null) { updateNoteGuid(n.getGuid(), originalGuid); updateNoteGuid(originalGuid, n.getGuid()); @@ -787,12 +789,29 @@ public class NoteTable { boolean retVal = query.next(); return retVal; } - // This is a convience method to check if a tag exists & update/create based upon it - public void syncNote(Note tag, boolean isDirty) { - if (exists(tag.getGuid())) - updateNote(tag, isDirty); + // This is a convience method to check if a note exists & update/create based upon it + public void syncNote(Note note) { + // If we got the note from Evernote we use its + // metadata instead of the local copy. + NoteMetadata meta = null; + if (note.getAttributes() != null && note.getAttributes().getSourceApplication() != null) { + meta = extractMetadata(note.getAttributes().getSourceApplication()); + } else + meta = getNoteMetaInformation(note.getGuid()); + + // Now, if the note exists we simply update it. Otherwise we + // add a new note. + if (exists(note.getGuid())) { + updateNote(note); + } else - addNote(tag, isDirty); + addNote(note, false); + + // If we have metadata, we write it out. + if (meta != null) { + meta.setGuid(note.getGuid()); + updateNoteMetadata(meta); + } } // Get a list of notes that need to be updated public List getDirty() { @@ -1189,50 +1208,24 @@ public class NoteTable { } return guids; } - - - //********************************************************************************** - //* Title color functions - //********************************************************************************** - // Get the title color of all notes -/* public List> getNoteTitleColors() { - List> returnValue = new ArrayList>(); - NSqlQuery query = new NSqlQuery(db.getConnection()); - - if (!query.exec("Select guid,titleColor from Note where titleColor != -1")) - logger.log(logger.EXTREME, "Note SQL retrieve has failed on getUnindexed()."); - - String guid; - Integer color; - - // Get a list of the notes - while (query.next()) { - Pair pair = new Pair(); - guid = query.valueString(0); - color = query.valueInteger(1); - pair.setFirst(guid); - pair.setSecond(color); - returnValue.add(pair); - } - return returnValue; - } - */ // Get note meta information public void updateNoteMetadata(NoteMetadata meta) { NSqlQuery query = new NSqlQuery(db.getConnection()); - if (!query.prepare("Update Note set titleColor=:color, pinned=:pinned where guid=:guid")) + if (!query.prepare("Update Note set titleColor=:color, pinned=:pinned, attributeSourceApplication=:metaString where guid=:guid")) logger.log(logger.EXTREME, "Note SQL prepare has failed on updateNoteMetadata."); query.bindValue(":color", meta.getColor()); query.bindValue(":pinned", meta.isPinned()); query.bindValue(":guid", meta.getGuid()); - query.exec(); + query.bindValue(":metaString", buildMetadataString(meta)); + if (!query.exec()) + logger.log(logger.EXTREME, "Note SQL exec has failed on updateNoteMetadata."); return; } - // Get note meta information - public HashMap getNoteMetaInformation() { + // Get all note meta information + public HashMap getNotesMetaInformation() { HashMap returnValue = new HashMap(); NSqlQuery query = new NSqlQuery(db.getConnection()); @@ -1253,41 +1246,30 @@ public class NoteTable { return returnValue; } - // Set a title color - public void setNoteTitleColor(String guid, int color) { - NSqlQuery query = new NSqlQuery(db.getConnection()); - - query.prepare("Update note set titlecolor=:color where guid=:guid"); - query.bindValue(":guid", guid); - query.bindValue(":color", color); - if (!query.exec()) - logger.log(logger.EXTREME, "Error updating title color."); - } - // Get in individual note's title color - // Get the title color of all notes - public Integer getNoteTitleColor(String guid) { - List> returnValue = new ArrayList>(); + // Get note meta information + public NoteMetadata getNoteMetaInformation(String guid) { NSqlQuery query = new NSqlQuery(db.getConnection()); - query.prepare("Select titleColor from Note where titleColor != -1 and guid=:guid"); - query.bindValue(":guid", guid); - if (!query.exec()) - logger.log(logger.EXTREME, "Note SQL retrieve has failed on getNoteTitleColor(guid)."); + if (!query.prepare("Select guid,titleColor, isDirty, pinned from Note where guid=:guid")) { + logger.log(logger.EXTREME, "Note SQL retrieve has failed on getNoteMetaInformation."); + return null; + } + query.bindValue(":guid", guid); + query.exec(); - Integer color = -1; - // Get a list of the notes while (query.next()) { - Pair pair = new Pair(); - guid = query.valueString(0); - color = query.valueInteger(1); - pair.setFirst(guid); - pair.setSecond(color); - returnValue.add(pair); + NoteMetadata note = new NoteMetadata(); + note.setGuid(query.valueString(0)); + note.setColor(query.valueInteger(1)); + note.setDirty(query.valueBoolean(2, false)); + int pinned = query.valueInteger(3); + if (pinned > 0) + note.setPinned(true); + return note; } - - return color; + return null; } @@ -1494,6 +1476,106 @@ public class NoteTable { } } + // Extract metadata from a note's Note.attributes.sourceApplication + private NoteMetadata extractMetadata(String sourceApplication) { + String consumerKey = "baumgarte:{"; + int startPos = sourceApplication.indexOf(consumerKey); + if (startPos < 0 ) + return null; + + NoteMetadata meta = new NoteMetadata(); + startPos = startPos+consumerKey.length(); + +// String startString = sourceApplication.substring(0,startPos); + String metaString = sourceApplication.substring(startPos); +// String endString = metaString.substring(metaString.indexOf("};")); + int endPos = metaString.indexOf("};"); + if (endPos > 0) + metaString = metaString.substring(0,endPos); + + String value = parseMetaString(metaString, "titleColor"); + if (value != null) + meta.setColor(Integer.parseInt(value)); + + value = parseMetaString(metaString, "pinned"); + if (value != null && value.equals(true)) + meta.setPinned(true); + + return meta; + } + + // Given a metadata string from attribute.sourceApplication, we + // extract the information for a given key. + private String parseMetaString(String metaString, String key) { + int startPos = metaString.indexOf(key); + if (startPos < 0) + return null; + + String value = metaString.substring(startPos+key.length()+1); + int endPos = value.indexOf(";"); + if (endPos > 0) + value = value.substring(0,endPos); + + return value; + } + + // Given a set of metadata, we build a string that can be inserted + // into the attribute.sourceApplication string. + private String buildMetadataString(NoteMetadata meta) { + StringBuffer value = new StringBuffer(removeExistingMetaString(meta.getGuid())); + StringBuffer metaString = new StringBuffer(); + + if (meta.isPinned()) { + metaString.append("pinned=true;"); + } + if (meta.getColor() != -1) { + metaString.append("titleColor=" +new Integer(meta.getColor()).toString()+";"); + } + if (metaString.length()>0) { + + // Adda any missing ";" or " " at the end of the existing + // string. + if (value.length()>1 && (!value.toString().trim().endsWith(";") || !value.toString().trim().endsWith(";"))) + value.append("; "); + + value.append("baumgarte:{"); + value.append(metaString); + value.append("};"); + return value.toString(); + } + return null; + } + + // This will remove the existing metadata string from the attribute.sourceApplication string. + private String removeExistingMetaString(String guid) { + NSqlQuery query = new NSqlQuery(db.getConnection()); + + if (!query.prepare("Select attributeSourceApplication from Note where guid=:guid")) { + logger.log(logger.EXTREME, "Note SQL retrieve has failed in removeExistingMetaString."); + return null; + } + query.bindValue(":guid", guid); + query.exec(); + + // Get the application source string + String sourceApplication = null; + while (query.next()) { + sourceApplication = query.valueString(0); + } + if (sourceApplication == null) + return ""; + + String consumerKey = "baumgarte:{"; + int startPos = sourceApplication.indexOf(consumerKey); + if (startPos < 0 ) + return sourceApplication; + String startString = sourceApplication.substring(0,startPos); + String metaString = sourceApplication.substring(startPos); + String endString = metaString.substring(metaString.indexOf("};")+2); + + return startString+endString; + } + } diff --git a/src/cx/fbn/nevernote/threads/SyncRunner.java b/src/cx/fbn/nevernote/threads/SyncRunner.java index 16286e6..68dbd02 100644 --- a/src/cx/fbn/nevernote/threads/SyncRunner.java +++ b/src/cx/fbn/nevernote/threads/SyncRunner.java @@ -1292,7 +1292,7 @@ public class SyncRunner extends QObject implements Runnable { if ((conflictingNote || fullSync) && !ignoreNote) { logger.log(logger.EXTREME, "Saving Note"); - conn.getNoteTable().syncNote(n, false); + conn.getNoteTable().syncNote(n); // The following was commented out because it caused a race condition on the database where resources // may be lost. We do the same thing elsewhere;. // noteSignal.noteChanged.emit(n.getGuid(), null); // Signal to ivalidate note cache diff --git a/src/cx/fbn/nevernote/utilities/ListManager.java b/src/cx/fbn/nevernote/utilities/ListManager.java index 323a861..49036c1 100644 --- a/src/cx/fbn/nevernote/utilities/ListManager.java +++ b/src/cx/fbn/nevernote/utilities/ListManager.java @@ -372,7 +372,7 @@ public class ListManager { refreshNoteMetadata(); } public void refreshNoteMetadata() { - noteModel.setNoteMetadata(conn.getNoteTable().getNoteMetaInformation()); + noteModel.setNoteMetadata(conn.getNoteTable().getNotesMetaInformation()); } // Update a note's meta data public void updateNoteMetadata(NoteMetadata meta) { @@ -596,7 +596,7 @@ public class ListManager { i=getNoteIndex().size(); } } - conn.getNoteTable().updateNote(n, true); + conn.getNoteTable().updateNote(n); } // Add a note. public void addNote(Note n, NoteMetadata meta) { @@ -1132,8 +1132,12 @@ public class ListManager { } public void updateNoteTitleColor(String guid, Integer color) { - noteModel.updateNoteTitleColor(guid, color); - conn.getNoteTable().setNoteTitleColor(guid, color); + NoteMetadata meta = getNoteMetadata().get(guid); + if (meta != null) { + noteModel.updateNoteTitleColor(guid, color); + meta.setColor(color); + conn.getNoteTable().updateNoteMetadata(meta); + } } public void loadNoteTitleColors() { noteModel.setMetaData(getNoteMetadata()); diff --git a/src/cx/fbn/nevernote/xml/ExportData.java b/src/cx/fbn/nevernote/xml/ExportData.java index a15ad8d..20161d9 100644 --- a/src/cx/fbn/nevernote/xml/ExportData.java +++ b/src/cx/fbn/nevernote/xml/ExportData.java @@ -148,7 +148,7 @@ public class ExportData { dirtyNotes.put(dn.get(i).getGuid(), ""); } - noteMeta = conn.getNoteTable().getNoteMetaInformation(); + noteMeta = conn.getNoteTable().getNotesMetaInformation(); searches = conn.getSavedSearchTable().getAll(); diff --git a/src/cx/fbn/nevernote/xml/ImportData.java b/src/cx/fbn/nevernote/xml/ImportData.java index 8070b9a..9e95bab 100644 --- a/src/cx/fbn/nevernote/xml/ImportData.java +++ b/src/cx/fbn/nevernote/xml/ImportData.java @@ -45,6 +45,7 @@ import com.trolltech.qt.gui.QPixmap; import com.trolltech.qt.xml.QXmlStreamAttributes; import com.trolltech.qt.xml.QXmlStreamReader; +import cx.fbn.nevernote.evernote.NoteMetadata; import cx.fbn.nevernote.sql.DatabaseConnection; import cx.fbn.nevernote.utilities.ApplicationLogger; @@ -64,7 +65,7 @@ public class ImportData { private QIcon notebookIcon; private Tag tag; private boolean tagIsDirty; - private final HashMap titleColors; +// private final HashMap titleColors; private SavedSearch search; private boolean searchIsDirty; public int highUpdateSequenceNumber; @@ -79,12 +80,13 @@ public class ImportData { public final boolean importTags = false; public final boolean importNotebooks = false; private final HashMap noteMap; + private final HashMap metaData; public ImportData(DatabaseConnection c, boolean full) { logger = new ApplicationLogger("import.log"); backup = full; conn = c; - titleColors = new HashMap(); + metaData = new HashMap(); noteMap = new HashMap(); } @@ -157,8 +159,8 @@ public class ImportData { } conn.getNoteTable().addNote(note, true); } - if (titleColors.containsKey(note.getGuid())) - conn.getNoteTable().setNoteTitleColor(note.getGuid(), titleColors.get(note.getGuid())); + if (metaData.containsKey(note.getGuid())) + conn.getNoteTable().updateNoteMetadata(metaData.get(note.getGuid())); } if (reader.name().equalsIgnoreCase("notebook") && reader.isStartElement() && (backup || importNotebooks)) { processNotebookNode(); @@ -245,8 +247,14 @@ public class ImportData { if (booleanValue()) noteIsDirty=true; } - if (reader.name().equalsIgnoreCase("TitleColor")) - titleColors.put(note.getGuid(), intValue()); + if (reader.name().equalsIgnoreCase("TitleColor")) { + if (metaData.get(note.getGuid()) == null) { + NoteMetadata m = new NoteMetadata(); + m.setColor(intValue()); + metaData.put(note.getGuid(), m); + } else + metaData.get(note.getGuid()).setColor(intValue()); + } } reader.readNext(); if (reader.name().equalsIgnoreCase("note") && reader.isEndElement()) -- 2.11.0