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
29 import java.util.List;
\r
31 import javax.xml.bind.DatatypeConverter;
\r
33 import com.evernote.edam.type.Data;
\r
34 import com.evernote.edam.type.Note;
\r
35 import com.evernote.edam.type.NoteAttributes;
\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.xml.QXmlStreamReader;
\r
45 import cx.fbn.nevernote.sql.DatabaseConnection;
\r
46 import cx.fbn.nevernote.utilities.ApplicationLogger;
\r
48 public class ImportEnex {
\r
50 public int lastError;
\r
51 private String errorMessage;
\r
52 private String fileName;
\r
53 DatabaseConnection conn;
\r
54 QXmlStreamReader reader;
\r
56 public int highUpdateSequenceNumber;
\r
57 public long lastSequenceDate;
\r
58 private final ApplicationLogger logger;
\r
59 private String notebookGuid;
\r
60 public final boolean importTags = false;
\r
61 public final boolean importNotebooks = false;
\r
62 private String newGuid;
\r
64 public boolean createNewTags;
\r
66 public ImportEnex(DatabaseConnection c, boolean full) {
\r
67 logger = new ApplicationLogger("import.log");
\r
69 tags = conn.getTagTable().getAll();
\r
70 createNewTags = true;
\r
73 public void importData(String f) {
\r
79 QFile xmlFile = new QFile(fileName);
\r
80 if (!xmlFile.open(QIODevice.OpenModeFlag.ReadOnly)) {
\r
82 errorMessage = "Cannot open file.";
\r
85 reader = new QXmlStreamReader(xmlFile);
\r
86 while (!reader.atEnd()) {
\r
88 if (reader.hasError()) {
\r
89 errorMessage = reader.errorString();
\r
90 logger.log(logger.LOW, "************************* ERROR READING FILE " +reader.errorString());
\r
94 if (reader.name().equalsIgnoreCase("note") && reader.isStartElement()) {
\r
96 note.setUpdateSequenceNum(0);
\r
97 if (notebookGuid != null)
\r
98 note.setNotebookGuid(notebookGuid);
\r
99 for (int i=0; i<note.getResourcesSize(); i++) {
\r
100 note.getResources().get(i).setUpdateSequenceNum(0);
\r
102 note.setActive(true);
\r
103 if (note.getUpdated() == 0) {
\r
104 note.setUpdated(note.getCreated());
\r
106 conn.getNoteTable().addNote(note, true);
\r
113 private void processNoteNode() {
\r
115 newGuid = QUuid.createUuid().toString().replace("{", "").replace("}", "");
\r
116 note.setGuid(newGuid);
\r
117 note.setResources(new ArrayList<Resource>());
\r
119 boolean atEnd = false;
\r
121 if (reader.name().equalsIgnoreCase("title"))
\r
122 note.setTitle(textValue());
\r
123 if (reader.name().equalsIgnoreCase("Created"))
\r
124 note.setCreated(datetimeValue());
\r
125 if (reader.name().equalsIgnoreCase("updated"))
\r
126 note.setCreated(datetimeValue());
\r
127 if (reader.name().equalsIgnoreCase("Content"))
\r
128 note.setContent(textValue());
\r
129 if (reader.name().equalsIgnoreCase("tag") && createNewTags) {
\r
130 String tag = textValue();
\r
131 Tag noteTag = null;
\r
132 boolean found=false;
\r
133 for (int i=0; i<tags.size(); i++) {
\r
134 if (tags.get(i).getName().equalsIgnoreCase(tag)) {
\r
136 noteTag = tags.get(i);
\r
142 noteTag = new Tag();
\r
143 noteTag.setName(tag);
\r
144 String tagGuid = QUuid.createUuid().toString().replace("{", "").replace("}", "");
\r
145 noteTag.setGuid(tagGuid);
\r
146 noteTag.setName(tag);
\r
148 conn.getTagTable().addTag(noteTag, true);
\r
150 note.addToTagNames(noteTag.getName());
\r
151 note.addToTagGuids(noteTag.getGuid());
\r
153 if (reader.name().equalsIgnoreCase("note-attributes"))
\r
154 note.setAttributes(processNoteAttributes());
\r
155 if (reader.name().equalsIgnoreCase("resource")) {
\r
156 note.getResources().add(processResource());
\r
159 if (reader.name().equalsIgnoreCase("note") && reader.isEndElement())
\r
164 private Resource processResource() {
\r
165 Resource resource = new Resource();
\r
166 boolean atEnd = false;
\r
168 if (reader.isStartElement() && reader.name().equalsIgnoreCase("resource")) {
\r
169 String newResGuid = QUuid.createUuid().toString().replace("{", "").replace("}", "");
\r
170 resource.setGuid(newResGuid);
\r
171 resource.setNoteGuid(this.newGuid);
\r
173 if (reader.name().equalsIgnoreCase("mime"))
\r
174 resource.setMime(textValue());
\r
175 if (reader.name().equalsIgnoreCase("height"))
\r
176 resource.setHeight(shortValue());
\r
177 if (reader.name().equalsIgnoreCase("width"))
\r
178 resource.setWidth(shortValue());
\r
179 if (reader.name().equalsIgnoreCase("data"))
\r
180 resource.setData(processData("data"));
\r
181 if (reader.name().equalsIgnoreCase("resource-attributes"))
\r
182 resource.setAttributes(processResourceAttributes());
\r
183 if (reader.name().equalsIgnoreCase("recognition"))
\r
184 resource.setRecognition(processRecognition());
\r
186 if (reader.name().equalsIgnoreCase("resource") && reader.isEndElement())
\r
189 if (resource.getAttributes() == null)
\r
190 resource.setAttributes(new ResourceAttributes());
\r
191 conn.getNoteTable().noteResourceTable.updateNoteResource(resource, true);
\r
195 private Data processData(String nodeName) {
\r
196 Data data = new Data();
\r
197 boolean atEnd = false;
\r
199 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 String hexString = hexData.toString();
\r
205 data.setBody(DatatypeConverter.parseBase64Binary(hexString));
\r
208 md = MessageDigest.getInstance("MD5");
\r
209 md.update(data.getBody());
\r
210 data.setBodyHash(md.digest());
\r
211 } catch (NoSuchAlgorithmException e) {
\r
212 // TODO Auto-generated catch block
\r
213 e.printStackTrace();
\r
217 catch (Exception e) {};
\r
219 if (reader.name().equalsIgnoreCase(nodeName) && reader.isEndElement())
\r
228 private NoteAttributes processNoteAttributes() {
\r
229 NoteAttributes attributes = new NoteAttributes();
\r
231 boolean atEnd = false;
\r
233 if (reader.isStartElement()) {
\r
234 if (reader.name().equalsIgnoreCase("source-url"))
\r
235 attributes.setSourceURL(textValue());
\r
236 if (reader.name().equalsIgnoreCase("source"))
\r
237 attributes.setSource(textValue());
\r
238 if (reader.name().equalsIgnoreCase("longitude"))
\r
239 attributes.setLongitude(doubleValue());
\r
240 if (reader.name().equalsIgnoreCase("latitude"))
\r
241 attributes.setLatitude(doubleValue());
\r
242 if (reader.name().equalsIgnoreCase("altitude"))
\r
243 attributes.setAltitude(doubleValue());
\r
244 if (reader.name().equalsIgnoreCase("author"))
\r
245 attributes.setAuthor(textValue());
\r
246 if (reader.name().equalsIgnoreCase("subject-date"))
\r
247 attributes.setSubjectDate(datetimeValue());
\r
250 if (reader.name().equalsIgnoreCase("note-attributes") && reader.isEndElement())
\r
259 private Data processRecognition() {
\r
260 Data reco = new Data();
\r
261 reco.setBody(textValue().getBytes());
\r
264 md = MessageDigest.getInstance("MD5");
\r
265 md.update(reco.getBody());
\r
266 reco.setBodyHash(md.digest());
\r
267 reco.setSize(reco.getBody().length);
\r
268 } catch (NoSuchAlgorithmException e) {
\r
269 // TODO Auto-generated catch block
\r
270 e.printStackTrace();
\r
275 private ResourceAttributes processResourceAttributes() {
\r
276 ResourceAttributes attributes = new ResourceAttributes();
\r
277 boolean atEnd = false;
\r
279 if (reader.isStartElement()) {
\r
280 if (reader.name().equalsIgnoreCase("camera-model"))
\r
281 attributes.setCameraModel(textValue());
\r
282 if (reader.name().equalsIgnoreCase("file-name"))
\r
283 attributes.setFileName(textValue());
\r
284 if (reader.name().equalsIgnoreCase("reco-type"))
\r
285 attributes.setRecoType(textValue());
\r
286 if (reader.name().equalsIgnoreCase("camera-make"))
\r
287 attributes.setCameraMake(textValue());
\r
288 if (reader.name().equalsIgnoreCase("source-url"))
\r
289 attributes.setSourceURL(textValue());
\r
290 if (reader.name().equalsIgnoreCase("Altitude"))
\r
291 attributes.setAltitude(doubleValue());
\r
292 if (reader.name().equalsIgnoreCase("Longitude"))
\r
293 attributes.setLongitude(doubleValue());
\r
294 if (reader.name().equalsIgnoreCase("Latitude"))
\r
295 attributes.setLatitude(doubleValue());
\r
296 if (reader.name().equalsIgnoreCase("Timestamp"))
\r
297 attributes.setTimestamp(longValue());
\r
298 if (reader.name().equalsIgnoreCase("Attachment"))
\r
299 attributes.setAttachment(booleanValue());
\r
300 if (reader.name().equalsIgnoreCase("ClientWillIndex"))
\r
301 attributes.setClientWillIndex(booleanValue());
\r
304 if (reader.name().equalsIgnoreCase("resource-attributes") && reader.isEndElement())
\r
312 private String textValue() {
\r
313 return reader.readElementText();
\r
315 private long longValue() {
\r
316 return new Long(textValue());
\r
318 private long datetimeValue() {
\r
320 String time = textValue();
\r
321 String year = time.substring(0,4);
\r
322 String month = time.substring(4,6);
\r
323 String day = time.substring(6,8);
\r
324 String hour = time.substring(9,11);
\r
325 String minute = time.substring(11,13);
\r
326 String second = time.substring(13,15);
\r
327 DateFormat dfm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
\r
329 d = dfm.parse(year +"-" +month +"-" +day +" " +hour +":" +minute +":" +second);
\r
330 return d.getTime();
\r
331 } catch (ParseException e) {
\r
332 // TODO Auto-generated catch block
\r
333 e.printStackTrace();
\r
338 private boolean booleanValue() {
\r
339 String value = textValue();
\r
340 if (value.equalsIgnoreCase("true"))
\r
345 private short shortValue() {
\r
346 return new Short(textValue());
\r
349 public void setNotebookGuid(String g) {
\r
353 public String getErrorMessage() {
\r
354 return errorMessage;
\r
357 private double doubleValue() {
\r
358 return new Double(textValue());
\r