Refactor entry search

This commit is contained in:
J-Jamet
2018-03-27 18:46:59 +02:00
parent 10c32266c2
commit a8d07c3e82
11 changed files with 113 additions and 155 deletions

View File

@@ -19,25 +19,24 @@
*/
package com.keepassdroid.database;
import com.keepassdroid.database.iterator.EntrySearchStringIterator;
import java.util.Date;
import java.util.List;
import com.keepassdroid.database.iterator.EntrySearchStringIterator;
public abstract class EntrySearchHandler extends EntryHandler<PwEntry> {
private List<PwEntry> listStorage;
private SearchParameters sp;
private Date now;
public static EntrySearchHandler getInstance(PwGroup group, SearchParameters sp, List<PwEntry> listStorage) {
if (group instanceof PwGroupV3) {
return new EntrySearchHandlerV4(sp, listStorage);
if (group instanceof PwGroupV3) { // TODO WTF ?
return new EntrySearchHandlerV4(sp, listStorage);
} else if (group instanceof PwGroupV4) {
return new EntrySearchHandlerV4(sp, listStorage);
} else {
throw new RuntimeException("Not implemented.");
}
}
protected EntrySearchHandler(SearchParameters sp, List<PwEntry> listStorage) {
@@ -75,7 +74,7 @@ public abstract class EntrySearchHandler extends EntryHandler<PwEntry> {
groupName = groupName.toLowerCase();
}
if (groupName.indexOf(term) >= 0) {
if (groupName.contains(term)) {
listStorage.add(entry);
return true;
}
@@ -99,12 +98,12 @@ public abstract class EntrySearchHandler extends EntryHandler<PwEntry> {
EntrySearchStringIterator iter = EntrySearchStringIterator.getInstance(entry, sp);
while (iter.hasNext()) {
String str = iter.next();
if (str != null & str.length() > 0) {
if (str != null && str.length() > 0) {
if (sp.ignoreCase) {
str = str.toLowerCase();
}
if (str.indexOf(term) >= 0) {
if (str.contains(term)) {
return true;
}
}

View File

@@ -0,0 +1,82 @@
package com.keepassdroid.database;
import com.keepassdroid.utils.StrUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class EntrySearchV4 {
private PwGroupV4 root;
public EntrySearchV4(PwGroupV4 root) {
this.root = root;
}
public void searchEntries(SearchParameters sp, List<PwEntry> listStorage) {
if (sp == null) { return; }
if (listStorage == null) { return; }
List<String> terms = StrUtil.splitSearchTerms(sp.searchString);
if (terms.size() <= 1 || sp.regularExpression) {
searchEntriesSingle(sp, listStorage);
return;
}
// Search longest term first
Comparator<String> stringLengthComparator = (lhs, rhs) -> lhs.length() - rhs.length();
Collections.sort(terms, stringLengthComparator);
String fullSearch = sp.searchString;
List<PwEntry> pg = root.getChildEntries();
for (int i = 0; i < terms.size(); i ++) {
List<PwEntry> pgNew = new ArrayList<>();
sp.searchString = terms.get(i);
boolean negate = false;
if (sp.searchString.startsWith("-")) {
sp.searchString.substring(1); // TODO Verify bug or no need ?
negate = sp.searchString.length() > 0;
}
if (!searchEntriesSingle(sp, pgNew)) {
pg = null;
break;
}
List<PwEntry> complement = new ArrayList<>();
if (negate) {
for (PwEntry entry: pg) {
if (!pgNew.contains(entry)) {
complement.add(entry);
}
}
pg = complement;
}
else {
pg = pgNew;
}
}
if (pg != null) {
listStorage.addAll(pg);
}
sp.searchString = fullSearch;
}
private boolean searchEntriesSingle(SearchParameters spIn, List<PwEntry> listStorage) {
SearchParameters sp = (SearchParameters) spIn.clone();
EntryHandler<PwEntry> eh;
if (sp.searchString.length() <= 0) {
eh = new EntrySearchHandlerAll(sp, listStorage);
} else {
eh = EntrySearchHandler.getInstance(root, sp, listStorage);
}
return root.preOrderTraverseTree(null, eh);
}
}

View File

@@ -721,7 +721,7 @@ public class PwDatabaseV4 extends PwDatabase {
PwGroupV4 g = (PwGroupV4) group;
return g.isSearchEnabled();
return g.isSearchingEnabled();
}
@Override

View File

@@ -195,7 +195,7 @@ public abstract class PwEntry extends PwNode implements Cloneable {
}
public void touchLocation() { }
public boolean isSearchingEnabled() {
return false;
}

View File

@@ -508,7 +508,6 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger {
@Override
public void touch(boolean modified, boolean touchParents) {
super.touch(modified, touchParents);
++usageCount;
}
@@ -519,7 +518,7 @@ public class PwEntryV4 extends PwEntry implements ITimeLogger {
public boolean isSearchingEnabled() {
if (parent != null) {
return parent.isSearchEnabled();
return parent.isSearchingEnabled();
}
return PwGroupV4.DEFAULT_SEARCHING_ENABLED;
}

View File

@@ -19,11 +19,7 @@
*/
package com.keepassdroid.database;
import com.keepassdroid.utils.StrUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public abstract class PwGroup extends PwNode {
@@ -150,81 +146,6 @@ public abstract class PwGroup extends PwNode {
parent.touch(modified, true);
}
}
public void searchEntries(SearchParameters sp, List<PwEntry> listStorage) {
if (sp == null) { return; }
if (listStorage == null) { return; }
List<String> terms = StrUtil.splitSearchTerms(sp.searchString);
if (terms.size() <= 1 || sp.regularExpression) {
searchEntriesSingle(sp, listStorage);
return;
}
// Search longest term first
Comparator<String> stringLengthComparator = new Comparator<String>() {
@Override
public int compare(String lhs, String rhs) {
return lhs.length() - rhs.length();
}
};
Collections.sort(terms, stringLengthComparator);
String fullSearch = sp.searchString;
List<PwEntry> pg = this.childEntries;
for (int i = 0; i < terms.size(); i ++) {
List<PwEntry> pgNew = new ArrayList<PwEntry>();
sp.searchString = terms.get(i);
boolean negate = false;
if (sp.searchString.startsWith("-")) {
sp.searchString.substring(1);
negate = sp.searchString.length() > 0;
}
if (!searchEntriesSingle(sp, pgNew)) {
pg = null;
break;
}
List<PwEntry> complement = new ArrayList<PwEntry>();
if (negate) {
for (PwEntry entry: pg) {
if (!pgNew.contains(entry)) {
complement.add(entry);
}
}
pg = complement;
}
else {
pg = pgNew;
}
}
if (pg != null) {
listStorage.addAll(pg);
}
sp.searchString = fullSearch;
}
private boolean searchEntriesSingle(SearchParameters spIn, List<PwEntry> listStorage) {
SearchParameters sp = (SearchParameters) spIn.clone();
EntryHandler<PwEntry> eh;
if (sp.searchString.length() <= 0) {
eh = new EntrySearchHandlerAll(sp, listStorage);
} else {
eh = EntrySearchHandler.getInstance(this, sp, listStorage);
}
if (!preOrderTraverseTree(null, eh)) { return false; }
return true;
}
public boolean preOrderTraverseTree(GroupHandler<PwGroup> groupHandler, EntryHandler<PwEntry> entryHandler) {
if (entryHandler != null) {

View File

@@ -209,14 +209,13 @@ public class PwGroupV4 extends PwGroup implements ITimeLogger {
this.lastTopVisibleEntry = lastTopVisibleEntry;
}
public boolean isSearchEnabled() {
public boolean isSearchingEnabled() {
PwGroupV4 group = this;
while (group != null) {
Boolean search = group.enableSearching;
if (search != null) {
return search;
}
group = group.parent;
}

View File

@@ -1,47 +0,0 @@
/*
* Copyright 2017 Brian Pellin, Jeremy Jamet / Kunzisoft.
*
* This file is part of KeePass DX.
*
* KeePass DX is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* KeePass DX is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.keepassdroid.database;
public class SearchParametersFactory {
public static SearchParameters getNone(PwDatabase db) {
SearchParameters sp = getInstance(db);
sp.setupNone();
return sp;
}
public static SearchParameters getInstance(PwDatabase db) {
if (db instanceof PwDatabase) {
return new SearchParametersV4();
}
else {
return new SearchParameters();
}
}
public static SearchParameters getInstance(PwGroup group) {
if (group instanceof PwGroupV4) {
return new SearchParametersV4();
}
else {
return new SearchParameters();
}
}
}

View File

@@ -295,7 +295,8 @@ public class PwDbV4Output extends PwDbOutput {
Stack<PwGroupV4> groupStack = new Stack<PwGroupV4>();
groupStack.push(root);
if (!root.preOrderTraverseTree(new GroupWriter(groupStack), new EntryWriter())) throw new RuntimeException("Writing groups failed");
if (!root.preOrderTraverseTree(new GroupWriter(groupStack), new EntryWriter()))
throw new RuntimeException("Writing groups failed");
while (groupStack.size() > 1) {
xml.endTag(null, ElemGroup);

View File

@@ -19,16 +19,16 @@
*/
package com.keepassdroid.utils;
import java.util.HashMap;
import java.util.Map;
import com.keepassdroid.database.PwDatabaseV4;
import com.keepassdroid.database.PwEntryV4;
import java.util.HashMap;
import java.util.Map;
public class SprContextV4 implements Cloneable {
public PwDatabaseV4 db;
public PwEntryV4 entry;
public Map<String, String> refsCache = new HashMap<String, String>();
public Map<String, String> refsCache = new HashMap<>();
public SprContextV4(PwDatabaseV4 db, PwEntryV4 entry) {
this.db = db;

View File

@@ -19,21 +19,23 @@
*/
package com.keepassdroid.utils;
import com.keepassdroid.database.PwDatabase;
import com.keepassdroid.database.PwDatabaseV4;
import com.keepassdroid.database.PwEntry;
import com.keepassdroid.database.PwEntryV4;
import com.keepassdroid.database.PwGroupV4;
import com.keepassdroid.database.EntrySearchV4;
import com.keepassdroid.database.SearchParametersV4;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map.Entry;
import com.keepassdroid.database.PwDatabase;
import com.keepassdroid.database.PwDatabaseV4;
import com.keepassdroid.database.PwEntry;
import com.keepassdroid.database.PwEntryV4;
import com.keepassdroid.database.SearchParametersV4;
public class SprEngineV4 {
private final int MAX_RECURSION_DEPTH = 12;
private final String STR_REF_START = "{REF:";
private final String STR_REF_END = "}";
private static final int MAX_RECURSION_DEPTH = 12;
private static final String STR_REF_START = "{REF:";
private static final String STR_REF_END = "}";
public class TargetResult {
public PwEntryV4 entry;
@@ -155,7 +157,9 @@ public class SprEngineV4 {
else { return null; }
List<PwEntry> list = new ArrayList<>();
ctx.db.getRootGroup().searchEntries(sp, list);
// TODO type parameter
EntrySearchV4 entrySearchV4 = new EntrySearchV4((PwGroupV4) ctx.db.getRootGroup());
entrySearchV4.searchEntries(sp, list);
if (list.size() > 0) {
return new TargetResult((PwEntryV4)list.get(0), wanted);