OSDN Git Service

Correct errors relating to LaTeX images & editing.
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / threads / SaveRunner.java
1 /*\r
2  * This file is part of NeverNote \r
3  * Copyright 2009 Randy Baumgarte\r
4  * \r
5  * This file may be licensed under the terms of of the\r
6  * GNU General Public License Version 2 (the ``GPL'').\r
7  *\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
12  *\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
17  *\r
18 */\r
19 \r
20 package cx.fbn.nevernote.threads;\r
21 \r
22 import java.util.GregorianCalendar;\r
23 import java.util.List;\r
24 import java.util.concurrent.LinkedBlockingQueue;\r
25 \r
26 import com.evernote.edam.type.Resource;\r
27 import com.trolltech.qt.core.QMutex;\r
28 import com.trolltech.qt.core.QObject;\r
29 \r
30 import cx.fbn.nevernote.Global;\r
31 import cx.fbn.nevernote.evernote.EnmlConverter;\r
32 import cx.fbn.nevernote.signals.NoteSignal;\r
33 import cx.fbn.nevernote.sql.DatabaseConnection;\r
34 import cx.fbn.nevernote.utilities.ApplicationLogger;\r
35 import cx.fbn.nevernote.utilities.Pair;\r
36 \r
37 public class SaveRunner extends QObject implements Runnable {\r
38          \r
39         private final ApplicationLogger         logger;\r
40         public volatile boolean                         keepRunning;\r
41         public QMutex                                           threadLock;\r
42         private final DatabaseConnection        conn;\r
43         private boolean                                         idle;\r
44         public NoteSignal                                       noteSignals;\r
45 \r
46         private volatile LinkedBlockingQueue<Pair<String, String>> workQueue = new LinkedBlockingQueue<Pair<String, String>>();\r
47         \r
48         \r
49         //*********************************************\r
50         //* Constructor                               *\r
51         //*********************************************\r
52         public SaveRunner(String logname, String u, String i, String r, String uid, String pswd, String cpswd) {\r
53                 logger = new ApplicationLogger(logname);\r
54                 conn = new DatabaseConnection(logger, u, i, r, uid, pswd, cpswd, 0);\r
55                 threadLock = new QMutex();\r
56                 keepRunning = true;\r
57                 noteSignals = new NoteSignal();\r
58         }\r
59         \r
60         public SaveRunner(ApplicationLogger l, DatabaseConnection c) {\r
61                 logger = l;\r
62                 conn = c;\r
63                 keepRunning = true;\r
64                 noteSignals = new NoteSignal();\r
65         }\r
66         \r
67         \r
68         \r
69         //*********************************************\r
70         //* Run unit                                  *\r
71         //*********************************************\r
72         @Override\r
73         public void run() {\r
74                 thread().setPriority(Thread.MIN_PRIORITY);\r
75                 boolean keepRunning = true;\r
76                 \r
77                 while(keepRunning) {\r
78                         try {\r
79                                 Pair<String, String> content;\r
80                                 idle = true;\r
81                                 content = workQueue.take();\r
82                                 if (!content.getFirst().equalsIgnoreCase("stop")) {                                             \r
83                                         idle = false;\r
84                                         \r
85                                         // This is a bit of a hack.  It causes this thread to pause for 0.2 seconds.\r
86                                         // This helps make sure that the main thread gets to the\r
87                                         // database first when switching notes, othrewise it really \r
88                                         // slows things down when fetching new notes.\r
89                                         GregorianCalendar now = new GregorianCalendar();\r
90                                         long prev = now.getTimeInMillis();\r
91                                         prev = prev+200;\r
92                                         while (prev>now.getTimeInMillis()) {\r
93                                                 now = new GregorianCalendar();                                          \r
94                                         }\r
95                                         \r
96                                         updateNoteContent(content.getFirst(), content.getSecond());\r
97                                 } else {\r
98                                         return;\r
99                                 }\r
100                                 threadLock.unlock();\r
101                         } catch (InterruptedException e) { }\r
102                 }\r
103                 conn.dbShutdown();\r
104         }\r
105         \r
106         \r
107         public synchronized void addWork(String guid, String content) {\r
108                 while(workQueue.size() > 0) {}\r
109                 Pair<String, String> pair = new Pair<String, String>(guid, content);\r
110                 workQueue.offer(pair);\r
111         }\r
112         \r
113         public synchronized void release(String guid, String content) {\r
114                 Pair<String, String> pair = new Pair<String, String>(guid, content);\r
115                 workQueue.add(pair);\r
116         }\r
117         \r
118         public synchronized int getWorkQueueSize() {\r
119                 return workQueue.size();\r
120         }\r
121 \r
122         \r
123         //*********************************************\r
124         //* Getter & Setter method to tell the thread *\r
125         //* to keep running.                          *\r
126         //*********************************************\r
127         public void setKeepRunning(boolean b) {\r
128                 keepRunning = b;\r
129         }\r
130         public boolean keepRunning() {\r
131                 return keepRunning;\r
132         }\r
133         \r
134         public boolean isIdle() {\r
135                 return idle;\r
136         }\r
137         \r
138         \r
139         //*********************************************\r
140         //* Do the actual work                                *\r
141         //*********************************************\r
142         public void updateNoteContent(String guid, String content) {\r
143                 logger.log(logger.HIGH, "Entering ListManager.updateNoteContent");\r
144                 \r
145                 // Actually save the content\r
146                 EnmlConverter enml = new EnmlConverter(logger);\r
147                 String newContent = enml.convert(guid, content);\r
148                 String fixedContent = enml.fixEnXMLCrap(newContent);\r
149                 if (fixedContent != null) {\r
150                         conn.getNoteTable().updateNoteContent(guid, fixedContent);\r
151                         logger.log(logger.EXTREME, "Saving new note resources");\r
152                         List<Resource> oldResources = conn.getNoteTable().noteResourceTable.getNoteResources(guid, false);\r
153                         List<String> newResources = enml.getResources();\r
154                         removeObsoleteResources(oldResources, newResources);\r
155                 } else {\r
156                         noteSignals.noteSaveRunnerError.emit(guid, null);\r
157                 }\r
158                 logger.log(logger.HIGH, "Leaving ListManager.updateNoteContent");\r
159         }\r
160         \r
161         // Remove resources that are no longer needed\r
162         private void removeObsoleteResources(List<Resource> oldResources, List<String> newResources) {\r
163                 if (oldResources == null || oldResources.size() == 0)\r
164                         return;\r
165                 if (newResources == null || newResources.size() == 0) {\r
166                         for (int i=0; i<oldResources.size(); i++) {\r
167                                 conn.getNoteTable().noteResourceTable.expungeNoteResource(oldResources.get(i).getGuid());\r
168                         }\r
169                 }\r
170                 for (int i=0; i<oldResources.size(); i++) {\r
171                         boolean matchFound = false;\r
172                         for (int j=0; j<newResources.size(); j++) {\r
173                                 if (newResources.get(j).equalsIgnoreCase(oldResources.get(i).getGuid())) \r
174                                         matchFound = true;\r
175                                 if (Global.resourceMap.get(newResources.get(j))!= null) {\r
176                                         if (Global.resourceMap.get(newResources.get(j)).equalsIgnoreCase(oldResources.get(i).getGuid())) \r
177                                                 matchFound = true;\r
178                                 }\r
179                                 if (matchFound)\r
180                                         j = newResources.size();\r
181                         }\r
182                         if (!matchFound)\r
183                                 conn.getNoteTable().noteResourceTable.expungeNoteResource(oldResources.get(i).getGuid());\r
184                 }\r
185         }\r
186 }\r