2 * This file is part of NixNote/NeighborNote
3 * Copyright 2009 Randy Baumgarte
4 * Copyright 2013 Yuki Takahashi
6 * This file may be licensed under the terms of of the
7 * GNU General Public License Version 2 (the ``GPL'').
9 * Software distributed under the License is distributed
10 * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
11 * express or implied. See the GPL for the specific language
12 * governing rights and limitations.
14 * You should have received a copy of the GPL along with this
15 * program. If not, go to http://www.gnu.org/licenses/gpl.html
16 * or write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 package cx.fbn.nevernote.threads;
23 import java.util.GregorianCalendar;
24 import java.util.List;
25 import java.util.concurrent.LinkedBlockingQueue;
27 import com.evernote.edam.type.Resource;
28 import com.trolltech.qt.core.QMutex;
29 import com.trolltech.qt.core.QObject;
31 import cx.fbn.nevernote.Global;
32 import cx.fbn.nevernote.evernote.EnmlConverter;
33 import cx.fbn.nevernote.signals.NoteSignal;
34 import cx.fbn.nevernote.sql.DatabaseConnection;
35 import cx.fbn.nevernote.utilities.ApplicationLogger;
36 import cx.fbn.nevernote.utilities.Pair;
38 public class SaveRunner extends QObject implements Runnable {
40 private final ApplicationLogger logger;
41 public volatile boolean keepRunning;
42 public QMutex threadLock;
43 private final DatabaseConnection conn;
45 public NoteSignal noteSignals;
47 private volatile LinkedBlockingQueue<Pair<String, String>> workQueue = new LinkedBlockingQueue<Pair<String, String>>();
50 //*********************************************
52 //*********************************************
53 public SaveRunner(String logname, String u, String i, String r, String b, String uid, String pswd, String cpswd) {
54 logger = new ApplicationLogger(logname);
55 conn = new DatabaseConnection(logger, u, i, r, b, uid, pswd, cpswd, 0);
56 threadLock = new QMutex();
58 noteSignals = new NoteSignal();
61 public SaveRunner(ApplicationLogger l, DatabaseConnection c) {
65 noteSignals = new NoteSignal();
70 //*********************************************
72 //*********************************************
75 thread().setPriority(Thread.MIN_PRIORITY);
76 boolean keepRunning = true;
80 Pair<String, String> content;
82 content = workQueue.take();
83 if (!content.getFirst().equalsIgnoreCase("stop")) {
86 // This is a bit of a hack. It causes this thread to pause for 0.2 seconds.
87 // This helps make sure that the main thread gets to the
88 // database first when switching notes, othrewise it really
89 // slows things down when fetching new notes.
90 GregorianCalendar now = new GregorianCalendar();
91 long prev = now.getTimeInMillis();
93 while (prev>now.getTimeInMillis()) {
94 now = new GregorianCalendar();
97 updateNoteContent(content.getFirst(), content.getSecond());
102 } catch (InterruptedException e) { }
108 public synchronized void addWork(String guid, String content) {
109 while(workQueue.size() > 0) {}
110 Pair<String, String> pair = new Pair<String, String>(guid, content);
111 workQueue.offer(pair);
114 public synchronized void release(String guid, String content) {
115 Pair<String, String> pair = new Pair<String, String>(guid, content);
119 public synchronized int getWorkQueueSize() {
120 return workQueue.size();
124 //*********************************************
125 //* Getter & Setter method to tell the thread *
126 //* to keep running. *
127 //*********************************************
128 public void setKeepRunning(boolean b) {
131 public boolean keepRunning() {
135 public boolean isIdle() {
140 //*********************************************
141 //* Do the actual work *
142 //*********************************************
143 public void updateNoteContent(String guid, String content) {
144 logger.log(logger.HIGH, "Entering ListManager.updateNoteContent");
146 // Actually save the content
147 EnmlConverter enml = new EnmlConverter(logger);
148 String newContent = enml.convert(guid, content);
149 String fixedContent = enml.fixEnXMLCrap(newContent);
150 if (fixedContent != null) {
151 conn.getNoteTable().updateNoteContent(guid, fixedContent);
152 logger.log(logger.EXTREME, "Saving new note resources");
153 List<Resource> oldResources = conn.getNoteTable().noteResourceTable.getNoteResources(guid, false);
154 List<String> newResources = enml.getResources();
155 removeObsoleteResources(oldResources, newResources);
157 noteSignals.noteSaveRunnerError.emit(guid, null);
159 logger.log(logger.HIGH, "Leaving ListManager.updateNoteContent");
162 // Remove resources that are no longer needed
163 private void removeObsoleteResources(List<Resource> oldResources, List<String> newResources) {
164 if (oldResources == null || oldResources.size() == 0)
166 if (newResources == null || newResources.size() == 0) {
167 for (int i=0; i<oldResources.size(); i++) {
168 conn.getNoteTable().noteResourceTable.expungeNoteResource(oldResources.get(i).getGuid());
171 for (int i=0; i<oldResources.size(); i++) {
172 boolean matchFound = false;
173 for (int j=0; j<newResources.size(); j++) {
174 if (newResources.get(j).equalsIgnoreCase(oldResources.get(i).getGuid()))
176 if (Global.resourceMap.get(newResources.get(j))!= null) {
177 if (Global.resourceMap.get(newResources.get(j)).equalsIgnoreCase(oldResources.get(i).getGuid()))
181 j = newResources.size();
184 conn.getNoteTable().noteResourceTable.expungeNoteResource(oldResources.get(i).getGuid());