2 * This file is part of NixNote
\r
3 * Copyright 2011 Randy Baumgarte
\r
5 * This file may be licensed under the terms of of the
\r
6 * GNU General Public License Version 2 (the ``GPL'').
\r
8 * Software distributed under the License is distributed
\r
9 * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
\r
10 * express or implied. See the GPL for the specific language
\r
11 * governing rights and limitations.
\r
13 * You should have received a copy of the GPL along with this
\r
14 * program. If not, go to http://www.gnu.org/licenses/gpl.html
\r
15 * or write to the Free Software Foundation, Inc.,
\r
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
\r
20 package cx.fbn.nevernote.xml;
\r
22 import java.security.MessageDigest;
\r
23 import java.security.NoSuchAlgorithmException;
\r
24 import java.text.DateFormat;
\r
25 import java.text.ParseException;
\r
26 import java.text.SimpleDateFormat;
\r
27 import java.util.ArrayList;
\r
28 import java.util.Date;
\r
30 import com.evernote.edam.type.Data;
\r
31 import com.evernote.edam.type.Note;
\r
32 import com.evernote.edam.type.NoteAttributes;
\r
33 import com.evernote.edam.type.NoteSortOrder;
\r
34 import com.evernote.edam.type.Notebook;
\r
35 import com.evernote.edam.type.Publishing;
\r
36 import com.evernote.edam.type.Resource;
\r
37 import com.evernote.edam.type.ResourceAttributes;
\r
38 import com.evernote.edam.type.Tag;
\r
39 import com.trolltech.qt.core.QByteArray;
\r
40 import com.trolltech.qt.core.QFile;
\r
41 import com.trolltech.qt.core.QIODevice;
\r
42 import com.trolltech.qt.core.QUuid;
\r
43 import com.trolltech.qt.gui.QIcon;
\r
44 import com.trolltech.qt.gui.QImage;
\r
45 import com.trolltech.qt.gui.QPixmap;
\r
46 import com.trolltech.qt.xml.QXmlStreamReader;
\r
48 import cx.fbn.nevernote.sql.DatabaseConnection;
\r
49 import cx.fbn.nevernote.utilities.ApplicationLogger;
\r
51 public class ImportEnex {
\r
53 public int lastError;
\r
54 private String errorMessage;
\r
55 private String fileName;
\r
56 DatabaseConnection conn;
\r
57 QXmlStreamReader reader;
\r
59 private Notebook notebook;
\r
60 private boolean notebookIsDirty;
\r
61 private boolean notebookIsLocal;
\r
62 private boolean notebookIsReadOnly;
\r
63 private QIcon notebookIcon;
\r
65 private boolean tagIsDirty;
\r
66 public int highUpdateSequenceNumber;
\r
67 public long lastSequenceDate;
\r
68 private final ApplicationLogger logger;
\r
69 private final boolean backup;
\r
70 private String notebookGuid;
\r
71 public final boolean importTags = false;
\r
72 public final boolean importNotebooks = false;
\r
73 private String newGuid;
\r
75 public ImportEnex(DatabaseConnection c, boolean full) {
\r
76 logger = new ApplicationLogger("import.log");
\r
81 public void importData(String f) {
\r
87 QFile xmlFile = new QFile(fileName);
\r
88 if (!xmlFile.open(QIODevice.OpenModeFlag.ReadOnly)) {
\r
90 errorMessage = "Cannot open file.";
\r
93 reader = new QXmlStreamReader(xmlFile);
\r
94 while (!reader.atEnd()) {
\r
96 if (reader.hasError()) {
\r
97 errorMessage = reader.errorString();
\r
98 logger.log(logger.LOW, "************************* ERROR READING FILE " +reader.errorString());
\r
102 if (reader.name().equalsIgnoreCase("note") && reader.isStartElement()) {
\r
104 note.setUpdateSequenceNum(0);
\r
105 if (notebookGuid != null)
\r
106 note.setNotebookGuid(notebookGuid);
\r
107 for (int i=0; i<note.getResourcesSize(); i++) {
\r
108 note.getResources().get(i).setUpdateSequenceNum(0);
\r
110 note.setActive(true);
\r
111 conn.getNoteTable().addNote(note, true);
\r
113 if (reader.name().equalsIgnoreCase("notebook") && reader.isStartElement() && (backup || importNotebooks)) {
\r
114 processNotebookNode();
\r
115 String existingGuid = conn.getNotebookTable().findNotebookByName(notebook.getName());
\r
116 if (existingGuid == null) {
\r
117 conn.getNotebookTable().addNotebook(notebook, notebookIsDirty, notebookIsLocal);
\r
119 conn.getNotebookTable().updateNotebookGuid(existingGuid, notebook.getGuid());
\r
120 conn.getNotebookTable().updateNotebook(notebook, notebookIsDirty);
\r
122 conn.getNotebookTable().setIcon(notebook.getGuid(), notebookIcon, "PNG");
\r
123 conn.getNotebookTable().setReadOnly(notebook.getGuid(), notebookIsReadOnly);
\r
125 if (reader.name().equalsIgnoreCase("tag") && reader.isStartElement() && (backup || importTags)) {
\r
127 String testGuid = conn.getTagTable().findTagByName(tag.getName());
\r
128 if (testGuid == null)
\r
129 conn.getTagTable().addTag(tag, tagIsDirty);
\r
131 conn.getTagTable().updateTagGuid(testGuid, tag.getGuid());
\r
132 conn.getTagTable().updateTag(tag,tagIsDirty);
\r
140 private void processNoteNode() {
\r
142 newGuid = QUuid.createUuid().toString().replace("{", "").replace("}", "");
\r
143 note.setGuid(newGuid);
\r
144 note.setResources(new ArrayList<Resource>());
\r
146 boolean atEnd = false;
\r
148 if (reader.name().equalsIgnoreCase("title"))
\r
149 note.setTitle(textValue());
\r
150 if (reader.name().equalsIgnoreCase("Created"))
\r
151 note.setCreated(datetimeValue());
\r
152 if (reader.name().equalsIgnoreCase("Content"))
\r
153 note.setContent(textValue());
\r
154 if (reader.name().equalsIgnoreCase("note-attributes"))
\r
155 note.setAttributes(processNoteAttributes());
\r
156 if (reader.name().equalsIgnoreCase("resource")) {
\r
157 note.getResources().add(processResource());
\r
160 if (reader.name().equalsIgnoreCase("note") && reader.isEndElement())
\r
165 private Resource processResource() {
\r
166 Resource resource = new Resource();
\r
167 boolean atEnd = false;
\r
169 if (reader.isStartElement()) {
\r
170 String newResGuid = QUuid.createUuid().toString().replace("{", "").replace("}", "");
\r
171 resource.setGuid(newResGuid);
\r
172 resource.setNoteGuid(this.newGuid);
\r
174 if (reader.name().equalsIgnoreCase("mime"))
\r
175 resource.setMime(textValue());
\r
176 if (reader.name().equalsIgnoreCase("height"))
\r
177 resource.setHeight(shortValue());
\r
178 if (reader.name().equalsIgnoreCase("width"))
\r
179 resource.setWidth(shortValue());
\r
180 if (reader.name().equalsIgnoreCase("data"))
\r
181 resource.setData(processData("data"));
\r
182 // if (reader.name().equalsIgnoreCase("recognition"))
\r
183 // resource.setRecognition(processData("NoteResourceAttribute"));
\r
185 if (reader.name().equalsIgnoreCase("resource") && reader.isEndElement())
\r
188 resource.setAttributes(new ResourceAttributes());
\r
189 resource.getAttributes().setSourceURL("");
\r
190 conn.getNoteTable().noteResourceTable.saveNoteResource(resource, true);
\r
196 private Data processData(String nodeName) {
\r
197 Data data = new Data();
\r
198 boolean atEnd = false;
\r
200 if (reader.isStartElement()) {
\r
201 byte[] b = textValue().getBytes(); // data binary
\r
202 if (b.length > 0) {
\r
203 QByteArray hexData = new QByteArray(b);
\r
204 QByteArray binData = new QByteArray(QByteArray.fromHex(hexData));
\r
205 data.setBody(binData.toByteArray());
\r
208 md = MessageDigest.getInstance("MD5");
\r
210 data.setBodyHash(md.digest());
\r
211 } catch (NoSuchAlgorithmException e) {
\r
212 // TODO Auto-generated catch block
\r
213 e.printStackTrace();
\r
217 if (reader.name().equalsIgnoreCase(nodeName) && reader.isEndElement())
\r
226 private NoteAttributes processNoteAttributes() {
\r
227 NoteAttributes attributes = new NoteAttributes();
\r
229 boolean atEnd = false;
\r
231 if (reader.isStartElement()) {
\r
232 if (reader.name().equalsIgnoreCase("source-url"))
\r
233 attributes.setSourceURL(textValue());
\r
234 if (reader.name().equalsIgnoreCase("source"))
\r
235 attributes.setSource(textValue());
\r
238 if (reader.name().equalsIgnoreCase("note-attributes") && reader.isEndElement())
\r
251 private void processNotebookNode() {
\r
252 notebook = new Notebook();
\r
253 Publishing p = new Publishing();
\r
254 notebook.setPublishing(p);
\r
255 notebookIsDirty = false;
\r
256 notebookIsLocal = false;
\r
257 notebookIsReadOnly = false;
\r
258 notebookIcon = null;
\r
259 boolean atEnd = false;
\r
261 if (reader.isStartElement()) {
\r
262 if (reader.name().equalsIgnoreCase("Guid"))
\r
263 notebook.setGuid(textValue());
\r
264 if (reader.name().equalsIgnoreCase("Name"))
\r
265 notebook.setName(textValue());
\r
266 if (reader.name().equalsIgnoreCase("UpdateSequenceNumber"))
\r
267 notebook.setUpdateSequenceNum(intValue());
\r
268 if (reader.name().equalsIgnoreCase("ServiceCreated"))
\r
269 notebook.setServiceCreated(longValue());
\r
270 if (reader.name().equalsIgnoreCase("ServiceUpdated"))
\r
271 notebook.setServiceUpdated(longValue());
\r
272 if (reader.name().equalsIgnoreCase("DefaultNotebook")) {
\r
273 notebook.setDefaultNotebook(booleanValue());
\r
275 if (reader.name().equalsIgnoreCase("Dirty")) {
\r
276 if (booleanValue())
\r
277 notebookIsDirty = true;
\r
279 if (reader.name().equalsIgnoreCase("LocalNotebook")) {
\r
280 if (booleanValue())
\r
281 notebookIsLocal = true;
\r
283 if (reader.name().equalsIgnoreCase("ReadOnly")) {
\r
284 if (booleanValue())
\r
285 notebookIsReadOnly = true;
\r
287 if (reader.name().equalsIgnoreCase("PublishingPublicDescription")) {
\r
288 notebook.getPublishing().setPublicDescription(textValue());
\r
290 if (reader.name().equalsIgnoreCase("PublishingUri")) {
\r
291 notebook.getPublishing().setUri(textValue());
\r
293 if (reader.name().equalsIgnoreCase("PublishingOrder")) {
\r
294 notebook.getPublishing().setOrder(NoteSortOrder.findByValue(intValue()));
\r
296 if (reader.name().equalsIgnoreCase("ReadOnly")) {
\r
297 if (booleanValue())
\r
298 notebookIsReadOnly = true;
\r
300 if (reader.name().equalsIgnoreCase("PublishingAscending")) {
\r
301 if (booleanValue())
\r
302 notebook.getPublishing().setAscending(true);
\r
304 notebook.getPublishing().setAscending(false);
\r
306 if (reader.name().equalsIgnoreCase("Icon")) {
\r
307 byte[] b = textValue().getBytes(); // data binary
\r
308 QByteArray hexData = new QByteArray(b);
\r
309 QByteArray binData = new QByteArray(QByteArray.fromHex(hexData));
\r
310 notebookIcon = new QIcon(QPixmap.fromImage(QImage.fromData(binData)));
\r
312 if (reader.name().equalsIgnoreCase("Stack"))
\r
313 notebook.setStack(textValue());
\r
316 if (reader.name().equalsIgnoreCase("notebook") && reader.isEndElement())
\r
324 private void processTagNode() {
\r
326 tagIsDirty = false;
\r
327 boolean atEnd = false;
\r
329 if (reader.isStartElement()) {
\r
330 if (reader.name().equalsIgnoreCase("Guid"))
\r
331 tag.setGuid(textValue());
\r
332 if (reader.name().equalsIgnoreCase("Name"))
\r
333 tag.setName(textValue());
\r
334 if (reader.name().equalsIgnoreCase("UpdateSequenceNumber"))
\r
335 tag.setUpdateSequenceNum(intValue());
\r
336 if (reader.name().equalsIgnoreCase("ParentGuid"))
\r
337 tag.setParentGuid(textValue());
\r
338 if (reader.name().equalsIgnoreCase("Dirty")) {
\r
339 if (booleanValue())
\r
344 if (reader.name().equalsIgnoreCase("tag") && reader.isEndElement())
\r
353 private String textValue() {
\r
354 return reader.readElementText();
\r
356 private int intValue() {
\r
357 return new Integer(textValue());
\r
359 private long longValue() {
\r
360 return new Long(textValue());
\r
362 private long datetimeValue() {
\r
364 String time = textValue();
\r
365 String year = time.substring(0,4);
\r
366 String month = time.substring(4,6);
\r
367 String day = time.substring(6,8);
\r
368 String hour = time.substring(9,11);
\r
369 String minute = time.substring(11,13);
\r
370 String second = time.substring(13,15);
\r
371 DateFormat dfm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
\r
373 d = dfm.parse(year +"-" +month +"-" +day +" " +hour +":" +minute +":" +second);
\r
374 return d.getTime();
\r
375 } catch (ParseException e) {
\r
376 // TODO Auto-generated catch block
\r
377 e.printStackTrace();
\r
382 private boolean booleanValue() {
\r
383 String value = textValue();
\r
384 if (value.equalsIgnoreCase("true"))
\r
389 private short shortValue() {
\r
390 return new Short(textValue());
\r
393 public void setNotebookGuid(String g) {
\r
397 public String getErrorMessage() {
\r
398 return errorMessage;
\r