/* * This file is part of NeighborNote * Copyright 2013 Yuki Takahashi * * This file may be licensed under the terms of of the * GNU General Public License Version 2 (the ``GPL''). * * Software distributed under the License is distributed * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either * express or implied. See the GPL for the specific language * governing rights and limitations. * * You should have received a copy of the GPL along with this * program. If not, go to http://www.gnu.org/licenses/gpl.html * or write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ package cx.fbn.nevernote.threads; import java.util.ArrayList; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; import com.evernote.edam.error.EDAMErrorCode; import com.evernote.edam.error.EDAMNotFoundException; import com.evernote.edam.error.EDAMSystemException; import com.evernote.edam.error.EDAMUserException; import com.evernote.edam.notestore.RelatedQuery; import com.evernote.edam.notestore.RelatedResult; import com.evernote.edam.notestore.RelatedResultSpec; import com.evernote.edam.type.Note; import com.evernote.thrift.TException; import com.trolltech.qt.core.QMutex; import com.trolltech.qt.core.QObject; import cx.fbn.nevernote.Global; import cx.fbn.nevernote.signals.ENRelatedNotesSignal; import cx.fbn.nevernote.signals.LimitSignal; import cx.fbn.nevernote.utilities.ApplicationLogger; import cx.fbn.nevernote.utilities.Pair; public class ENRelatedNotesRunner extends QObject implements Runnable{ private final ApplicationLogger logger; private final SyncRunner syncRunner; public volatile ENRelatedNotesSignal enRelatedNotesSignal; public QMutex mutex; private volatile boolean keepRunning; private volatile LinkedBlockingQueue<String> workQueue; private volatile LinkedBlockingQueue<Pair<String, List<String>>> resultQueue; // ペア<元ノートguid, 関連ノートguidリスト>を溜めておくキュー public volatile LimitSignal limitSignal; public ENRelatedNotesRunner(SyncRunner syncRunner, String logname) { this.logger = new ApplicationLogger(logname); this.syncRunner = syncRunner; this.enRelatedNotesSignal = new ENRelatedNotesSignal(); this.mutex = new QMutex(); this.keepRunning = true; this.workQueue = new LinkedBlockingQueue<String>(); this.resultQueue = new LinkedBlockingQueue<Pair<String, List<String>>>(); this.limitSignal = new LimitSignal(); } @Override public void run() { thread().setPriority(Thread.MIN_PRIORITY); logger.log(logger.MEDIUM, "ENRelatedNotesスレッド開始"); while (keepRunning) { try { String work = workQueue.take(); mutex.lock(); if (work.startsWith("GET")) { String guid = work.replace("GET ", ""); logger.log(logger.EXTREME, "Evernote関連ノート取得開始 guid = " + guid); List<Note> relatedNotes = getENRelatedNotes(guid); Pair<String, List<String>> resultPair = new Pair<String, List<String>>(); resultPair.setFirst(guid); if (relatedNotes == null) { // 取得に失敗 logger.log(logger.EXTREME, "Evernote関連ノートの取得に失敗"); } else if (relatedNotes.isEmpty()) { // このノートにEvernote関連ノートは存在しない logger.log(logger.EXTREME, "Evernote関連ノートの取得に成功 関連ノートは存在しなかった"); resultPair.setSecond(new ArrayList<String>()); } else { // Evernote関連ノートが存在する logger.log(logger.EXTREME, "Evernote関連ノートの取得に成功 関連ノートは存在した"); List<String> relatedNoteGuids = new ArrayList<String>(); for (Note relatedNote : relatedNotes) { relatedNoteGuids.add(relatedNote.getGuid()); } resultPair.setSecond(relatedNoteGuids); } resultQueue.offer(resultPair); enRelatedNotesSignal.getENRelatedNotesFinished.emit(); logger.log(logger.EXTREME, "Evernote関連ノート取得完了 guid = " + guid); } else if (work.startsWith("STOP")) { logger.log(logger.MEDIUM, "ENRelatedNotesスレッド停止"); keepRunning = false; } mutex.unlock(); } catch (InterruptedException e) { // TODO 自動生成された catch ブロック e.printStackTrace(); } } } private List<Note> getENRelatedNotes(String guid) { RelatedResult result = getENRelatedResult(guid); List<Note> relatedNotes = new ArrayList<Note>(); if (result != null) { relatedNotes = result.getNotes(); return relatedNotes; } return null; } private RelatedResult getENRelatedResult(String guid) { if (!Global.isConnected) { return null; } RelatedQuery rquery = new RelatedQuery(); rquery.setNoteGuid(guid); RelatedResultSpec resultSpec = new RelatedResultSpec(); resultSpec.setMaxNotes(5); if (syncRunner != null && syncRunner.localNoteStore != null) { try { RelatedResult result = syncRunner.localNoteStore.findRelated(syncRunner.authToken, rquery, resultSpec); return result; } catch (EDAMUserException e) { logger.log(logger.HIGH, "Evernote関連ノート取得中に例外発生:EDAMUserException"); } catch (EDAMSystemException e) { if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) { limitSignal.rateLimitReached.emit(e.getRateLimitDuration()); } logger.log(logger.HIGH, "Evernote関連ノート取得中に例外発生:EDAMSystemException"); } catch (EDAMNotFoundException e) { logger.log(logger.HIGH, "Evernote関連ノート取得中に例外発生:EDAMnotFoundException guid = " + guid); } catch (TException e) { logger.log(logger.HIGH, "Evernote関連ノート取得中に例外発生:TException"); } } return null; } public boolean isKeepRunning() { return keepRunning; } public void setKeepRunning(boolean keepRunning) { this.keepRunning = keepRunning; } public boolean addGuid(String guid) { if (workQueue.offer("GET " + guid)) { return true; } return false; } public boolean addStop() { if (workQueue.offer("STOP")) { return true; } return false; } public synchronized Pair<String, List<String>> getENRelatedNoteGuids() { try { return resultQueue.take(); } catch (InterruptedException e) { // TODO 自動生成された catch ブロック e.printStackTrace(); } return null; } }