2 * This file is part of NixNote
\r
3 * Copyright 2009 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
21 package cx.fbn.nevernote.sql;
\r
23 import java.text.SimpleDateFormat;
\r
24 import java.util.ArrayList;
\r
25 import java.util.Calendar;
\r
26 import java.util.GregorianCalendar;
\r
27 import java.util.List;
\r
28 import java.util.regex.Pattern;
\r
30 import org.apache.commons.lang3.StringEscapeUtils;
\r
32 import com.evernote.edam.type.Note;
\r
33 import com.evernote.edam.type.Notebook;
\r
34 import com.evernote.edam.type.Tag;
\r
36 import cx.fbn.nevernote.Global;
\r
37 import cx.fbn.nevernote.sql.driver.NSqlQuery;
\r
38 import cx.fbn.nevernote.utilities.ApplicationLogger;
\r
40 public class REnSearch {
\r
42 private final List<String> searchWords;
\r
43 private final List<String> searchPhrases;
\r
44 private final List<String> notebooks;
\r
45 private final List<String> tags;
\r
46 private final List<String> intitle;
\r
47 private final List<String> created;
\r
48 private final List<String> updated;
\r
49 private final List<String> resource;
\r
50 private final List<String> subjectDate;
\r
51 private final List<String> longitude;
\r
52 private final List<String> latitude;
\r
53 private final List<String> altitude;
\r
54 private final List<String> author;
\r
55 private final List<String> source;
\r
56 private final List<String> sourceApplication;
\r
57 private final List<String> recoType;
\r
58 private final List<String> todo;
\r
59 private final List<String> stack;
\r
60 private final List<Tag> tagIndex;
\r
61 private final ApplicationLogger logger;
\r
62 // private final DatabaseConnection db;
\r
63 private boolean any;
\r
64 private int minimumRecognitionWeight = 80;
\r
65 private final DatabaseConnection conn;
\r
67 public REnSearch(DatabaseConnection c, ApplicationLogger l, String s, List<Tag> t, int r) {
\r
71 minimumRecognitionWeight = r;
\r
72 searchWords = new ArrayList<String>();
\r
73 searchPhrases = new ArrayList<String>();
\r
74 notebooks = new ArrayList<String>();
\r
75 tags = new ArrayList<String>();
\r
76 intitle = new ArrayList<String>();
\r
77 created = new ArrayList<String>();
\r
78 updated = new ArrayList<String>();
\r
79 resource = new ArrayList<String>();
\r
80 subjectDate = new ArrayList<String>();
\r
81 longitude = new ArrayList<String>();
\r
82 latitude = new ArrayList<String>();
\r
83 altitude = new ArrayList<String>();
\r
84 author = new ArrayList<String>();
\r
85 source = new ArrayList<String>();
\r
86 sourceApplication = new ArrayList<String>();
\r
87 recoType = new ArrayList<String>();
\r
88 todo = new ArrayList<String>();
\r
90 stack = new ArrayList<String>();
\r
94 if (s.trim().equals(""))
\r
100 public List<String> getWords() { return searchWords; }
\r
101 public List<String> getNotebooks() { return notebooks; }
\r
102 public List<String> getIntitle() { return intitle; }
\r
103 public List<String> getTags() { return tags; }
\r
104 public List<String> getResource() { return resource; }
\r
105 public List<String> getAuthor() { return author; }
\r
106 public List<String> getSource() { return source; }
\r
107 public List<String> getSourceApplication() { return sourceApplication; }
\r
108 public List<String> getRecoType() { return recoType; }
\r
109 public List<String> getToDo() { return todo; }
\r
110 public List<String> getLongitude() { return longitude; }
\r
111 public List<String> getLatitude() { return latitude; }
\r
112 public List<String> getAltitude() { return altitude; }
\r
113 public List<String> getCreated() { return created; }
\r
114 public List<String> getUpdated() { return updated; }
\r
115 public List<String> getSubjectDate() { return subjectDate; }
\r
116 public List<String> getStack() { return stack; }
\r
119 private boolean matchTagsAll(List<String> tagNames, List<String> list) {
\r
121 for (int j=0; j<list.size(); j++) {
\r
122 boolean negative = false;
\r
124 if (list.get(j).startsWith("-"))
\r
126 int pos = list.get(j).indexOf(":");
\r
127 String filterName = cleanupWord(list.get(j).substring(pos+1));
\r
128 filterName = filterName.replace("*", ".*"); // setup for regular expression pattern match
\r
130 if (tagNames.size() == 0 && !negative)
\r
133 boolean matchFound = false;
\r
134 for (int i=0; i<tagNames.size(); i++) {
\r
135 boolean matches = Pattern.matches(filterName.toLowerCase(),tagNames.get(i).toLowerCase());
\r
140 matchFound = !matchFound;
\r
148 private boolean matchTagsAny(List<String> tagNames, List<String> list) {
\r
149 if (list.size() == 0)
\r
152 boolean negative = false;
\r
154 for (int j=0; j<list.size(); j++) {
\r
156 if (list.get(j).startsWith("-"))
\r
158 int pos = list.get(j).indexOf(":");
\r
159 String filterName = cleanupWord(list.get(j).substring(pos+1));
\r
160 filterName = filterName.replace("*", ".*"); // setup for regular expression pattern match
\r
162 if (tagNames.size() == 0 && !negative)
\r
165 for (int i=0; i<tagNames.size(); i++) {
\r
166 boolean matches = Pattern.matches(filterName.toLowerCase(),tagNames.get(i).toLowerCase());
\r
167 if (!matches && !negative)
\r
175 // Match notebooks in search terms against notes
\r
176 private boolean matchNotebook(String guid) {
\r
177 if (getNotebooks().size() == 0)
\r
179 NotebookTable bookTable = new NotebookTable(logger, conn);
\r
180 List<Notebook> books = bookTable.getAll();
\r
182 String name = new String("");
\r
183 for (int i=0; i<books.size(); i++) {
\r
184 if (guid.equalsIgnoreCase(books.get(i).getGuid())) {
\r
185 name = books.get(i).getName();
\r
190 return matchListAny(getNotebooks(), name);
\r
192 return matchListAll(getNotebooks(), name);
\r
194 // Match notebooks in search terms against notes
\r
195 private boolean matchNotebookStack(String guid) {
\r
196 if (getStack().size() == 0)
\r
198 NotebookTable bookTable = new NotebookTable(logger, conn);
\r
199 List<Notebook> books = bookTable.getAll();
\r
201 String name = new String("");
\r
202 for (int i=0; i<books.size(); i++) {
\r
203 if (guid.equalsIgnoreCase(books.get(i).getGuid())) {
\r
204 name = books.get(i).getStack();
\r
211 return matchListAny(getStack(), name);
\r
213 return matchListAll(getStack(), name);
\r
216 // Match notebooks in search terms against notes
\r
217 private boolean matchListAny(List<String> list, String title) {
\r
218 if (list.size() == 0)
\r
220 boolean negative = false;
\r
221 boolean found = false;
\r
222 for (int i=0; i<list.size(); i++) {
\r
223 int pos = list.get(i).indexOf(":");
\r
225 if (list.get(i).startsWith("-"))
\r
227 String filterName = cleanupWord(list.get(i).substring(pos+1));
\r
228 filterName = filterName.replace("*", ".*"); // setup for regular expression pattern match
\r
229 boolean matches = Pattern.matches(filterName.toLowerCase(),title.toLowerCase());
\r
238 // Match notebooks in search terms against notes
\r
239 private boolean matchContentAny(Note n) {
\r
240 if (todo.size() == 0 && resource.size() == 0 && searchPhrases.size() == 0)
\r
243 // pull back the record
\r
244 n = conn.getNoteTable().getNote(n.getGuid(), true, true, false, false, false);
\r
246 // Check for search phrases
\r
247 String text = StringEscapeUtils.unescapeHtml4(n.getContent().replaceAll("\\<.*?\\>", "")).toLowerCase();
\r
248 boolean negative = false;
\r
249 for (int i=0; i<searchPhrases.size(); i++) {
\r
250 String phrase = searchPhrases.get(i);
\r
251 if (phrase.startsWith("-")) {
\r
253 phrase = phrase.substring(1);
\r
256 phrase = phrase.substring(1);
\r
257 phrase = phrase.substring(0,phrase.length()-1);
\r
258 if (text.indexOf(phrase)>=0) {
\r
264 if (text.indexOf(phrase)<0 && negative)
\r
268 for (int i=0; i<todo.size(); i++) {
\r
269 String value = todo.get(i);
\r
270 value = value.replace("\"", "");
\r
271 boolean desiredState;
\r
272 if (!value.endsWith(":false") && !value.endsWith(":true") && !value.endsWith(":*") && !value.endsWith("*"))
\r
274 if (value.endsWith(":false"))
\r
275 desiredState = false;
\r
277 desiredState = true;
\r
278 if (value.startsWith("-"))
\r
279 desiredState = !desiredState;
\r
280 int pos = n.getContent().indexOf("<en-todo");
\r
281 if (pos == -1 && value.startsWith("-") && (value.endsWith("*") || value.endsWith(":")))
\r
283 if (value.endsWith("*"))
\r
286 int endPos = n.getContent().indexOf("/>", pos);
\r
287 String segment = n.getContent().substring(pos, endPos);
\r
288 boolean currentState;
\r
289 if (segment.toLowerCase().indexOf("checked=\"true\"") == -1)
\r
290 currentState = false;
\r
292 currentState = true;
\r
293 if (desiredState == currentState)
\r
296 pos = n.getContent().indexOf("<en-todo", pos+1);
\r
301 for (int i=0; i<resource.size(); i++) {
\r
302 String resourceString = resource.get(i);
\r
303 resourceString = resourceString.replace("\"", "");
\r
304 if (resourceString.startsWith("-"))
\r
306 resourceString = resourceString.substring(resourceString.indexOf(":")+1);
\r
307 for (int j=0; j<n.getResourcesSize(); j++) {
\r
308 boolean match = stringMatch(n.getResources().get(j).getMime(), resourceString, negative);
\r
317 // Take the initial search & split it apart
\r
318 private void resolveSearch(String search) {
\r
319 List<String> words = new ArrayList<String>();
\r
320 StringBuffer b = new StringBuffer(search);
\r
322 int len = search.length();
\r
323 char nextChar = ' ';
\r
324 boolean quote = false;
\r
325 for (int i=0, j=0; i<len; i++, j++) {
\r
326 if (search.charAt(i)==nextChar && !quote) {
\r
327 b.setCharAt(j,'\0');
\r
330 if (search.charAt(i)=='\"') {
\r
340 if (((i+2)<len) && search.charAt(i) == '\\') {
\r
345 search = b.toString();
\r
347 for (int i=0; i<search.length(); i++) {
\r
348 if (search.charAt(i) == '\0') {
\r
349 search = search.substring(1);
\r
352 pos = search.indexOf('\0');
\r
354 words.add(search.substring(0,pos).toLowerCase());
\r
355 search = search.substring(pos);
\r
360 if (search.charAt(0)=='\0')
\r
361 words.add(search.substring(1).toLowerCase());
\r
363 words.add(search.toLowerCase());
\r
368 // Parse out individual words into separate lists
\r
369 // Supported options
\r
375 // source application
\r
380 private void parseTerms(List<String> words) {
\r
381 for (int i=0; i<words.size(); i++) {
\r
382 String word = words.get(i);
\r
383 int pos = word.indexOf(":");
\r
384 if (word.startsWith("any:")) {
\r
386 word = word.substring(4).trim();
\r
387 pos = word.indexOf(":");
\r
389 boolean searchPhrase = false;
\r
390 if (pos < 0 && word.indexOf(" ") > 0) {
\r
392 searchPhrases.add(word.toLowerCase());
\r
394 if (!searchPhrase && pos < 0) {
\r
395 if (word != null && word.length() > 0 && !Global.automaticWildcardSearches())
\r
396 getWords().add(word);
\r
397 if (word != null && word.length() > 0 && Global.automaticWildcardSearches()) {
\r
398 String wildcardWord = word;
\r
399 if (!wildcardWord.startsWith("*"))
\r
400 wildcardWord = "*"+wildcardWord;
\r
401 if (!wildcardWord.endsWith("*"))
\r
402 wildcardWord = wildcardWord+"*";
\r
403 getWords().add(wildcardWord);
\r
405 // getWords().add("*"+word+"*"); //// WILDCARD
\r
407 if (word.startsWith("intitle:"))
\r
408 intitle.add("*"+word+"*");
\r
409 if (word.startsWith("-intitle:"))
\r
410 intitle.add("*"+word+"*");
\r
411 if (word.startsWith("notebook:"))
\r
412 notebooks.add(word);
\r
413 if (word.startsWith("-notebook:"))
\r
414 notebooks.add(word);
\r
415 if (word.startsWith("tag:"))
\r
417 if (word.startsWith("-tag:"))
\r
419 if (word.startsWith("resource:"))
\r
420 resource.add(word);
\r
421 if (word.startsWith("-resource:"))
\r
422 resource.add(word);
\r
423 if (word.startsWith("author:"))
\r
425 if (word.startsWith("-author:"))
\r
427 if (word.startsWith("source:"))
\r
429 if (word.startsWith("-source:"))
\r
431 if (word.startsWith("sourceapplication:"))
\r
432 sourceApplication.add(word);
\r
433 if (word.startsWith("-sourceapplication:"))
\r
434 sourceApplication.add(word);
\r
435 if (word.startsWith("recotype:"))
\r
436 recoType.add(word);
\r
437 if (word.startsWith("-recotype:"))
\r
438 recoType.add(word);
\r
439 if (word.startsWith("todo:"))
\r
441 if (word.startsWith("-todo:"))
\r
443 if (word.startsWith("stack:"))
\r
445 if (word.startsWith("-stack:"))
\r
448 if (word.startsWith("latitude:"))
\r
449 latitude.add(word);
\r
450 if (word.startsWith("-latitude:"))
\r
451 latitude.add(word);
\r
452 if (word.startsWith("longitude:"))
\r
453 longitude.add(word);
\r
454 if (word.startsWith("-longitude:"))
\r
455 longitude.add(word);
\r
456 if (word.startsWith("altitude:"))
\r
457 altitude.add(word);
\r
458 if (word.startsWith("-altitude:"))
\r
459 altitude.add(word);
\r
461 if (word.startsWith("created:"))
\r
463 if (word.startsWith("-created:"))
\r
465 if (word.startsWith("updated:"))
\r
467 if (word.startsWith("-updated:"))
\r
469 if (word.startsWith("subjectdate:"))
\r
471 if (word.startsWith("-subjectdate:"))
\r
476 // Match notebooks in search terms against notes
\r
477 private boolean matchListAll(List<String> list, String title) {
\r
478 if (list.size() == 0)
\r
480 boolean negative = false;
\r
481 for (int i=0; i<list.size(); i++) {
\r
482 int pos = list.get(i).indexOf(":");
\r
484 if (list.get(i).startsWith("-"))
\r
486 String filterName = cleanupWord(list.get(i).substring(pos+1));
\r
487 filterName = filterName.replace("*", ".*"); // setup for regular expression pattern match
\r
488 boolean matches = Pattern.matches(filterName.toLowerCase(),title.toLowerCase());
\r
489 if (matches && negative)
\r
491 if (matches && !negative)
\r
499 // Match notebooks in search terms against notes
\r
500 private boolean matchContentAll(Note n) {
\r
501 if (todo.size() == 0 && resource.size() == 0 && searchPhrases.size() == 0)
\r
504 n = conn.getNoteTable().getNote(n.getGuid(), true, true, false, false, false);
\r
506 // Check for search phrases
\r
507 String text = StringEscapeUtils.unescapeHtml4(n.getContent().replaceAll("\\<.*?\\>", "")).toLowerCase();
\r
508 boolean negative = false;
\r
509 for (int i=0; i<searchPhrases.size(); i++) {
\r
510 String phrase = searchPhrases.get(i);
\r
511 if (phrase.startsWith("-")) {
\r
513 phrase = phrase.substring(1);
\r
516 phrase = phrase.substring(1);
\r
517 phrase = phrase.substring(0,phrase.length()-1);
\r
518 if (text.indexOf(phrase)>=0 && negative) {
\r
521 if (text.indexOf(phrase) < 0 && !negative)
\r
526 for (int i=0; i<todo.size(); i++) {
\r
527 String value = todo.get(i);
\r
528 value = value.replace("\"", "");
\r
529 boolean desiredState;
\r
530 if (!value.endsWith(":false") && !value.endsWith(":true") && !value.endsWith(":*") && !value.endsWith("*"))
\r
532 if (value.endsWith(":false"))
\r
533 desiredState = false;
\r
535 desiredState = true;
\r
536 if (value.startsWith("-"))
\r
537 desiredState = !desiredState;
\r
538 int pos = n.getContent().indexOf("<en-todo");
\r
539 if (pos == -1 && !value.startsWith("-"))
\r
541 if (pos > -1 && value.startsWith("-") && (value.endsWith("*") || value.endsWith(":")))
\r
543 if (pos == -1 && !value.startsWith("-"))
\r
545 boolean returnTodo = false;
\r
547 int endPos = n.getContent().indexOf(">", pos);
\r
548 String segment = n.getContent().substring(pos, endPos);
\r
549 boolean currentState;
\r
550 if (segment.toLowerCase().indexOf("checked=\"true\"") == -1)
\r
551 currentState = false;
\r
553 currentState = true;
\r
554 if (desiredState == currentState)
\r
556 if (value.endsWith("*") || value.endsWith(":"))
\r
559 pos = n.getContent().indexOf("<en-todo", pos+1);
\r
566 for (int i=0; i<resource.size(); i++) {
\r
567 String resourceString = resource.get(i);
\r
568 resourceString = resourceString.replace("\"", "");
\r
570 if (resourceString.startsWith("-"))
\r
572 resourceString = resourceString.substring(resourceString.indexOf(":")+1);
\r
573 if (resourceString.equals(""))
\r
575 for (int j=0; j<n.getResourcesSize(); j++) {
\r
576 boolean match = stringMatch(n.getResources().get(j).getMime(), resourceString, negative);
\r
577 if (!match && !negative)
\r
579 if (match && negative)
\r
587 private boolean stringMatch(String content, String text, boolean negative) {
\r
589 if (content == null && !negative)
\r
591 if (content == null && negative)
\r
594 if (text.endsWith("*")) {
\r
595 text = text.substring(0,text.length()-1);
\r
600 content = content.toLowerCase();
\r
601 regex = regex.toLowerCase();
\r
602 boolean matches = content.startsWith(regex);
\r
608 // Remove odd strings from search terms
\r
609 private String cleanupWord(String word) {
\r
610 if (word.startsWith("\""))
\r
611 word = word.substring(1);
\r
612 if (word.endsWith("\""))
\r
613 word = word.substring(0,word.length()-1);
\r
614 word = word.replace("\\\"","\"");
\r
615 word = word.replace("\\\\","\\");
\r
622 private boolean matchDatesAll(List<String> dates, long noteDate) {
\r
623 if (dates.size()== 0)
\r
626 boolean negative = false;
\r
627 for (int i=0; i<dates.size(); i++) {
\r
628 String requiredDate = dates.get(i);
\r
629 if (requiredDate.startsWith("-"))
\r
633 requiredDate = requiredDate.substring(requiredDate.indexOf(":")+1);
\r
635 response = dateCheck(requiredDate, noteDate);
\r
636 } catch (java.lang.NumberFormatException e) {return false;} {
\r
637 if (negative && response < 0)
\r
639 if (!negative && response > 0)
\r
645 private boolean matchDatesAny(List<String> dates, long noteDate) {
\r
646 if (dates.size()== 0)
\r
649 boolean negative = false;
\r
650 for (int i=0; i<dates.size(); i++) {
\r
651 String requiredDate = dates.get(i);
\r
652 if (requiredDate.startsWith("-"))
\r
656 requiredDate = requiredDate.substring(requiredDate.indexOf(":")+1);
\r
658 response = dateCheck(requiredDate, noteDate);
\r
659 } catch (java.lang.NumberFormatException e) {return false;} {
\r
660 if (negative && response > 0)
\r
662 if (!negative && response < 0)
\r
669 @SuppressWarnings("unused")
\r
670 private void printCalendar(Calendar calendar) {
\r
671 // define output format and print
\r
672 SimpleDateFormat sdf = new SimpleDateFormat("d MMM yyyy hh:mm:ss aaa");
\r
673 String date = sdf.format(calendar.getTime());
\r
674 System.err.print(date);
\r
675 calendar = new GregorianCalendar();
\r
679 //****************************************
\r
680 //****************************************
\r
681 // Match search terms against notes
\r
682 //****************************************
\r
683 //****************************************
\r
684 public List<Note> matchWords() {
\r
685 logger.log(logger.EXTREME, "Inside EnSearch.matchWords()");
\r
686 boolean subSelect = false;
\r
688 NoteTable noteTable = new NoteTable(logger, conn);
\r
689 List<String> validGuids = new ArrayList<String>();
\r
691 if (searchWords.size() > 0)
\r
694 NSqlQuery query = new NSqlQuery(conn.getConnection());
\r
695 // Build a temp table for GUID results
\r
696 if (!conn.dbTableExists("SEARCH_RESULTS")) {
\r
697 query.exec("create temporary table SEARCH_RESULTS (guid varchar)");
\r
698 query.exec("create temporary table SEARCH_RESULTS_MERGE (guid varchar)");
\r
700 query. exec("Delete from SEARCH_RESULTS");
\r
701 query. exec("Delete from SEARCH_RESULTS_MERGE");
\r
704 NSqlQuery insertQuery = new NSqlQuery(conn.getConnection());
\r
705 NSqlQuery indexQuery = new NSqlQuery(conn.getIndexConnection());
\r
706 NSqlQuery mergeQuery = new NSqlQuery(conn.getConnection());
\r
707 NSqlQuery deleteQuery = new NSqlQuery(conn.getConnection());
\r
709 insertQuery.prepare("Insert into SEARCH_RESULTS (guid) values (:guid)");
\r
710 mergeQuery.prepare("Insert into SEARCH_RESULTS_MERGE (guid) values (:guid)");
\r
713 for (int i=0; i<getWords().size(); i++) {
\r
714 if (getWords().get(i).indexOf("*") == -1) {
\r
715 indexQuery.prepare("Select distinct guid from words where weight >= " +minimumRecognitionWeight +
\r
716 " and word=:word");
\r
717 indexQuery.bindValue(":word", getWords().get(i));
\r
719 indexQuery.prepare("Select distinct guid from words where weight >= " +minimumRecognitionWeight +
\r
720 " and word like :word");
\r
721 indexQuery.bindValue(":word", getWords().get(i).replace("*", "%"));
\r
724 String guid = null;
\r
725 while(indexQuery.next()) {
\r
726 guid = indexQuery.valueString(0);
\r
728 insertQuery.bindValue(":guid", guid);
\r
729 insertQuery.exec();
\r
731 mergeQuery.bindValue(":guid", guid);
\r
736 deleteQuery.exec("Delete from SEARCH_RESULTS where guid not in (select guid from SEARCH_RESULTS_MERGE)");
\r
737 deleteQuery.exec("Delete from SEARCH_RESULTS_MERGE");
\r
741 query.prepare("Select distinct guid from Note where guid in (Select guid from SEARCH_RESULTS)");
\r
742 if (!query.exec())
\r
743 logger.log(logger.LOW, "Error merging search results:" + query.lastError());
\r
745 while (query.next()) {
\r
746 validGuids.add(query.valueString(0));
\r
750 List<Note> noteIndex = noteTable.getAllNotes();
\r
751 List<Note> guids = new ArrayList<Note>();
\r
752 for (int i=0; i<noteIndex.size(); i++) {
\r
753 Note n = noteIndex.get(i);
\r
754 boolean good = true;
\r
756 if (!validGuids.contains(n.getGuid()) && subSelect)
\r
759 // Start matching special stuff, like tags & notebooks
\r
761 if (good && !matchTagsAny(n.getTagNames(), getTags()))
\r
763 if (good && !matchNotebook(n.getNotebookGuid()))
\r
765 if (good && !matchNotebookStack(n.getNotebookGuid()))
\r
767 if (good && !matchListAny(getIntitle(), n.getTitle()))
\r
769 if (good && !matchListAny(getAuthor(), n.getAttributes().getAuthor()))
\r
771 if (good && !matchListAny(getSource(), n.getAttributes().getSource()))
\r
773 if (good && !matchListAny(getSourceApplication(), n.getAttributes().getSourceApplication()))
\r
775 if (good && !matchContentAny(n))
\r
777 if (good && !matchDatesAny(getCreated(), n.getCreated()))
\r
779 if (good && !matchDatesAny(getUpdated(), n.getUpdated()))
\r
781 if (good && n.getAttributes() != null && !matchDatesAny(getSubjectDate(), n.getAttributes().getSubjectDate()))
\r
784 if (good && !matchTagsAll(n.getTagNames(), getTags()))
\r
786 if (good && !matchNotebook(n.getNotebookGuid()))
\r
788 if (good && !matchNotebookStack(n.getNotebookGuid()))
\r
790 if (good && !matchListAll(getIntitle(), n.getTitle()))
\r
792 if (good && !matchListAll(getAuthor(), n.getAttributes().getAuthor()))
\r
794 if (good && !matchListAll(getSource(), n.getAttributes().getSource()))
\r
796 if (good && !matchListAll(getSourceApplication(), n.getAttributes().getSourceApplication()))
\r
798 if (good && !matchContentAll(n))
\r
800 if (good && !matchDatesAll(getCreated(), n.getCreated()))
\r
802 if (good && !matchDatesAll(getUpdated(), n.getUpdated()))
\r
804 if (good && n.getAttributes() != null && !matchDatesAll(getSubjectDate(), n.getAttributes().getSubjectDate()))
\r
812 // For performance reasons, we didn't get the tags for every note individually. We now need to
\r
814 List<NoteTagsRecord> noteTags = noteTable.noteTagsTable.getAllNoteTags();
\r
815 for (int i=0; i<guids.size(); i++) {
\r
816 List<String> tags = new ArrayList<String>();
\r
817 List<String> names = new ArrayList<String>();
\r
818 for (int j=0; j<noteTags.size(); j++) {
\r
819 if (guids.get(i).getGuid().equals(noteTags.get(j).noteGuid)) {
\r
820 tags.add(noteTags.get(j).tagGuid);
\r
821 names.add(getTagNameByGuid(noteTags.get(j).tagGuid));
\r
825 guids.get(i).setTagGuids(tags);
\r
826 guids.get(i).setTagNames(names);
\r
828 logger.log(logger.EXTREME, "Leaving EnSearch.matchWords()");
\r
834 private String getTagNameByGuid(String guid) {
\r
835 for (int i=0; i<tagIndex.size(); i++) {
\r
836 if (tagIndex.get(i).getGuid().equals(guid))
\r
837 return tagIndex.get(i).getName();
\r
843 public int dateCheck(String date, long noteDate) throws java.lang.NumberFormatException {
\r
845 boolean found = false;
\r
846 GregorianCalendar calendar = new GregorianCalendar();
\r
848 if (date.contains("-")) {
\r
849 String modifier = date.substring(date.indexOf("-")+1);
\r
850 offset = new Integer(modifier);
\r
852 date = date.substring(0,date.indexOf("-"));
\r
855 if (date.contains("+")) {
\r
856 String modifier = date.substring(date.indexOf("+")+1);
\r
857 offset = new Integer(modifier);
\r
858 date = date.substring(0,date.indexOf("+"));
\r
861 if (date.equalsIgnoreCase("today")) {
\r
862 calendar.add(Calendar.DATE, offset);
\r
863 calendar.set(Calendar.HOUR, 0);
\r
864 calendar.set(Calendar.MINUTE, 0);
\r
865 calendar.set(Calendar.SECOND, 1);
\r
869 if (date.equalsIgnoreCase("month")) {
\r
870 calendar.add(Calendar.MONTH, offset);
\r
871 calendar.set(Calendar.DAY_OF_MONTH, 1);
\r
872 calendar.set(Calendar.HOUR, 0);
\r
873 calendar.set(Calendar.MINUTE, 0);
\r
874 calendar.set(Calendar.SECOND, 1);
\r
878 if (date.equalsIgnoreCase("year")) {
\r
879 calendar.add(Calendar.YEAR, offset);
\r
880 calendar.set(Calendar.MONTH, Calendar.JANUARY);
\r
881 calendar.set(Calendar.DAY_OF_MONTH, 1);
\r
882 calendar.set(Calendar.HOUR, 0);
\r
883 calendar.set(Calendar.MINUTE, 0);
\r
884 calendar.set(Calendar.SECOND, 1);
\r
888 if (date.equalsIgnoreCase("week")) {
\r
889 calendar.add(Calendar.DATE, 0-calendar.get(Calendar.DAY_OF_WEEK)+1);
\r
890 calendar.add(Calendar.DATE,(offset*7));
\r
891 calendar.set(Calendar.HOUR, 0);
\r
892 calendar.set(Calendar.MINUTE, 0);
\r
893 calendar.set(Calendar.SECOND, 1);
\r
898 // If nothing was found, then we have a date number
\r
900 calendar = stringToGregorianCalendar(date);
\r
904 String dateTimeFormat = new String("yyyyMMdd-HHmmss");
\r
905 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
\r
906 StringBuilder creationDate = new StringBuilder(simple.format(noteDate));
\r
907 GregorianCalendar nCalendar = stringToGregorianCalendar(creationDate.toString().replace("-", "T"));
\r
908 if (calendar == null || nCalendar == null) // If we have something invalid, it automatically fails
\r
910 return calendar.compareTo(nCalendar);
\r
912 private GregorianCalendar stringToGregorianCalendar(String date) {
\r
913 String datePart = date;
\r
914 GregorianCalendar calendar = new GregorianCalendar();
\r
915 boolean GMT = false;
\r
916 String timePart = "";
\r
917 if (date.contains("T")) {
\r
918 datePart = date.substring(0,date.indexOf("T"));
\r
919 timePart = date.substring(date.indexOf("T")+1);
\r
921 timePart = "000001";
\r
923 if (datePart.length() != 8)
\r
925 calendar.set(Calendar.YEAR, new Integer(datePart.substring(0,4)));
\r
926 calendar.set(Calendar.MONTH, new Integer(datePart.substring(4,6))-1);
\r
927 calendar.set(Calendar.DAY_OF_MONTH, new Integer(datePart.substring(6)));
\r
928 if (timePart.endsWith("Z")) {
\r
930 timePart = timePart.substring(0,timePart.length()-1);
\r
932 timePart = timePart.concat("000000");
\r
933 timePart = timePart.substring(0,6);
\r
934 calendar.set(Calendar.HOUR, new Integer(timePart.substring(0,2)));
\r
935 calendar.set(Calendar.MINUTE, new Integer(timePart.substring(2,4)));
\r
936 calendar.set(Calendar.SECOND, new Integer(timePart.substring(4)));
\r
938 calendar.set(Calendar.ZONE_OFFSET, -1*(calendar.get(Calendar.ZONE_OFFSET)/(1000*60*60)));
\r