OSDN Git Service

Evernote APIの帯域制限超過時にエラーメッセージを表示するようにした
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / threads / ENRelatedNotesRunner.java
1 /*
2  * This file is part of NeighborNote
3  * Copyright 2013 Yuki Takahashi
4  * 
5  * This file may be licensed under the terms of of the
6  * GNU General Public License Version 2 (the ``GPL'').
7  *
8  * Software distributed under the License is distributed
9  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
10  * express or implied. See the GPL for the specific language
11  * governing rights and limitations.
12  *
13  * You should have received a copy of the GPL along with this
14  * program. If not, go to http://www.gnu.org/licenses/gpl.html
15  * or write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18 */
19
20 package cx.fbn.nevernote.threads;
21
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.concurrent.LinkedBlockingQueue;
25
26 import com.evernote.edam.error.EDAMErrorCode;
27 import com.evernote.edam.error.EDAMNotFoundException;
28 import com.evernote.edam.error.EDAMSystemException;
29 import com.evernote.edam.error.EDAMUserException;
30 import com.evernote.edam.limits.Constants;
31 import com.evernote.edam.notestore.RelatedQuery;
32 import com.evernote.edam.notestore.RelatedResult;
33 import com.evernote.edam.notestore.RelatedResultSpec;
34 import com.evernote.edam.type.Note;
35 import com.evernote.thrift.TException;
36 import com.trolltech.qt.core.QMutex;
37 import com.trolltech.qt.core.QObject;
38
39 import cx.fbn.nevernote.Global;
40 import cx.fbn.nevernote.signals.ENRelatedNotesSignal;
41 import cx.fbn.nevernote.signals.LimitSignal;
42 import cx.fbn.nevernote.utilities.ApplicationLogger;
43 import cx.fbn.nevernote.utilities.Pair;
44
45 public class ENRelatedNotesRunner extends QObject implements Runnable{
46         
47         private final ApplicationLogger                                 logger;
48         private final SyncRunner                                                syncRunner;
49         public volatile ENRelatedNotesSignal                    enRelatedNotesSignal;
50         public QMutex                                                                   mutex;
51         private volatile boolean                                                keepRunning;
52         private volatile LinkedBlockingQueue<String>    workQueue;
53         private volatile LinkedBlockingQueue<Pair<String, List<String>>> resultQueue;   // ペア<元ノートguid, 関連ノートguidリスト>を溜めておくキュー
54         public volatile LimitSignal                                     limitSignal;
55         
56         public ENRelatedNotesRunner(SyncRunner syncRunner, ApplicationLogger logger) {
57                 this.logger = logger;
58                 this.syncRunner = syncRunner;
59                 this.enRelatedNotesSignal = new ENRelatedNotesSignal();
60                 this.mutex = new QMutex();
61                 this.keepRunning = true;
62                 this.workQueue = new LinkedBlockingQueue<String>();
63                 this.resultQueue = new LinkedBlockingQueue<Pair<String, List<String>>>();
64                 this.limitSignal = new LimitSignal();
65         }
66
67         @Override
68         public void run() {
69                 thread().setPriority(Thread.MIN_PRIORITY);
70                 
71                 logger.log(logger.MEDIUM, "ENRelatedNotesスレッド開始");
72                 while (keepRunning) {
73                         try {
74                                 String work = workQueue.take();
75                                 mutex.lock();
76                                 if (work.startsWith("GET")) {
77                                         String guid = work.replace("GET ", "");
78                                         logger.log(logger.EXTREME, "Evernote関連ノート取得開始 guid = " + guid);
79                                         
80                                         List<Note> relatedNotes = getENRelatedNotes(guid);
81                                         
82                                         Pair<String, List<String>> resultPair = new Pair<String, List<String>>();
83                                         resultPair.setFirst(guid);
84                                         if (relatedNotes == null) {                             // 取得に失敗
85                                                 logger.log(logger.EXTREME, "Evernote関連ノートの取得に失敗");
86                                         } else if (relatedNotes.isEmpty()) {    // このノートにEvernote関連ノートは存在しない
87                                                 logger.log(logger.EXTREME, "Evernote関連ノートの取得に成功 関連ノートは存在しなかった");
88                                                 resultPair.setSecond(new ArrayList<String>());
89                                         } else {                                                                // Evernote関連ノートが存在する
90                                                 logger.log(logger.EXTREME, "Evernote関連ノートの取得に成功 関連ノートは存在した");
91                                                 List<String> relatedNoteGuids = new ArrayList<String>();
92                                                 for (Note relatedNote : relatedNotes) {
93                                                         relatedNoteGuids.add(relatedNote.getGuid());
94                                                 }
95                                                 resultPair.setSecond(relatedNoteGuids);
96                                         }
97                                         
98                                         resultQueue.offer(resultPair);
99                                         enRelatedNotesSignal.getENRelatedNotesFinished.emit();
100                                         logger.log(logger.EXTREME, "Evernote関連ノート取得完了 guid = " + guid);
101                                 } else if (work.startsWith("STOP")) {
102                                         logger.log(logger.MEDIUM, "ENRelatedNotesスレッド停止");
103                                         keepRunning = false;
104                                 }
105                                 mutex.unlock();
106                         } catch (InterruptedException e) {
107                                 // TODO 自動生成された catch ブロック
108                                 e.printStackTrace();
109                         }
110                 }
111         }
112         
113         private List<Note> getENRelatedNotes(String guid) {
114                 RelatedResult result = getENRelatedResult(guid);
115                 List<Note> relatedNotes = new ArrayList<Note>();
116                 
117                 if (result != null) {
118                         relatedNotes = result.getNotes();
119                         return relatedNotes;
120                 }
121                 
122                 return null;
123         }
124         
125         private RelatedResult getENRelatedResult(String guid) {
126                 if (!Global.isConnected) {
127                         return null;
128                 }
129                 
130                 RelatedQuery rquery = new RelatedQuery();
131                 rquery.setNoteGuid(guid);
132                 RelatedResultSpec resultSpec = new RelatedResultSpec();
133                 resultSpec.setMaxNotes(Constants.EDAM_RELATED_MAX_NOTES);
134                 if (syncRunner != null && syncRunner.localNoteStore != null) {
135                         try {
136                                 RelatedResult result = syncRunner.localNoteStore.findRelated(syncRunner.authToken, rquery, resultSpec);
137                                 return result;
138                         } catch (EDAMUserException e) {
139                                 logger.log(logger.HIGH, "Evernote関連ノート取得中に例外発生:EDAMUserException");
140                         } catch (EDAMSystemException e) {
141                                 if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) {
142                                         limitSignal.rateLimitReached.emit(e.getRateLimitDuration());
143                                 }
144                                 logger.log(logger.HIGH, "Evernote関連ノート取得中に例外発生:EDAMSystemException");
145                         } catch (EDAMNotFoundException e) {
146                                 logger.log(logger.HIGH, "Evernote関連ノート取得中に例外発生:EDAMnotFoundException guid = " + guid);
147                         } catch (TException e) {
148                                 logger.log(logger.HIGH, "Evernote関連ノート取得中に例外発生:TException");
149                         }
150                 }
151                 return null;
152         }
153
154         public boolean isKeepRunning() {
155                 return keepRunning;
156         }
157
158         public void setKeepRunning(boolean keepRunning) {
159                 this.keepRunning = keepRunning;
160         }
161         
162         public synchronized boolean addGuid(String guid) {
163                 if (workQueue.offer("GET " + guid)) {
164                         return true;
165                 }
166                 
167                 return false;
168         }
169         
170         public synchronized boolean addStop() {
171                 if (workQueue.offer("STOP")) {
172                         return true;
173                 }
174                 return false;
175         }
176         
177         public synchronized Pair<String, List<String>> getENRelatedNoteGuids() {
178                 try {
179                         return resultQueue.take();
180                 } catch (InterruptedException e) {
181                         // TODO 自動生成された catch ブロック
182                         e.printStackTrace();
183                 }
184                 
185                 return null;
186         }
187 }