From 46fe9194760e5228182e78c83c11eeeaba63594e Mon Sep 17 00:00:00 2001 From: Maarten Billemont Date: Mon, 8 Oct 2018 19:33:31 -0400 Subject: [PATCH] Centralize query searching. --- .../gui/view/UserContentPanel.java | 24 ++++---- .../lyndir/masterpassword/model/MPQuery.java | 56 +++++++++++-------- .../lyndir/masterpassword/model/MPSite.java | 4 -- .../lyndir/masterpassword/model/MPUser.java | 4 -- .../model/impl/MPBasicSite.java | 14 +---- .../model/impl/MPBasicUser.java | 20 ++----- 6 files changed, 50 insertions(+), 72 deletions(-) diff --git a/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/view/UserContentPanel.java b/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/view/UserContentPanel.java index 1992fa17..3e656e7c 100644 --- a/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/view/UserContentPanel.java +++ b/platform-independent/java/gui/src/main/java/com/lyndir/masterpassword/gui/view/UserContentPanel.java @@ -3,7 +3,7 @@ package com.lyndir.masterpassword.gui.view; import static com.lyndir.lhunath.opal.system.util.StringUtils.*; import com.google.common.base.*; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.*; import com.google.common.primitives.UnsignedInteger; import com.google.common.util.concurrent.ListenableFuture; import com.lyndir.lhunath.opal.system.logging.Logger; @@ -650,8 +650,10 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener, JList> questionsList = Components.list( questionsModel, this::getQuestionDescription ); JTextField queryField = Components.textField( null, queryText -> Res.job( () -> { - MPQuery query = new MPQuery( queryText ); - Collection> questionItems = new LinkedList<>( site.findQuestions( query ) ); + MPQuery query = new MPQuery( queryText ); + Collection> questionItems = new LinkedList>( + query.find( site.getQuestions(), MPQuestion::getKeyword ) ); + if (questionItems.stream().noneMatch( MPQuery.Result::isExact )) questionItems.add( MPQuery.Result.allOf( new MPNewQuestion( site, query.getQuery() ), query.getQuery() ) ); @@ -814,7 +816,7 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener, } private String getSiteDescription(@Nullable final MPQuery.Result> item) { - MPSite site = (item != null)? item.getOption(): null; + MPSite site = (item != null)? item.getValue(): null; if (site == null) return " "; if (site instanceof MPNewSite) @@ -834,7 +836,7 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener, } private String getQuestionDescription(@Nullable final MPQuery.Result item) { - MPQuestion question = (item != null)? item.getOption(): null; + MPQuestion question = (item != null)? item.getValue(): null; if (question == null) return ""; if (question instanceof MPNewQuestion) @@ -876,7 +878,7 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener, } private void showSiteItem(@Nullable final MPQuery.Result> item) { - MPSite site = (item != null)? item.getOption(): null; + MPSite site = (item != null)? item.getValue(): null; Res.ui( getSiteResult( site, showLogin ), result -> { if (!showLogin && (site != null)) resultLabel.setText( (result != null)? strf( "Your password for %s:", site.getSiteName() ): " " ); @@ -937,7 +939,7 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener, } private void showQuestionItem(@Nullable final MPQuery.Result item) { - MPQuestion question = (item != null)? item.getOption(): null; + MPQuestion question = (item != null)? item.getValue(): null; Res.ui( getQuestionResult( question ), answer -> { if ((answer == null) || (question == null)) answerLabel.setText( " " ); @@ -988,7 +990,7 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener, if (selectedSite == null) return null; - return selectedSite.getOption(); + return selectedSite.getValue(); } @Nullable @@ -997,7 +999,7 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener, if (selectedQuestion == null) return null; - return selectedQuestion.getOption(); + return selectedQuestion.getValue(); } @Override @@ -1022,8 +1024,8 @@ public class UserContentPanel extends JPanel implements MasterPassword.Listener, updateSitesJob = Res.job( () -> { MPQuery query = new MPQuery( queryText ); - Collection>> siteItems = - new LinkedList<>( user.findSites( query ) ); + Collection>> siteItems = new LinkedList>>( + query.find( user.getSites(), MPSite::getSiteName ) ); if (!Strings.isNullOrEmpty( queryText )) if (siteItems.stream().noneMatch( MPQuery.Result::isExact )) { diff --git a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPQuery.java b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPQuery.java index 79a11214..ae8944bb 100644 --- a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPQuery.java +++ b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPQuery.java @@ -1,12 +1,13 @@ package com.lyndir.masterpassword.model; -import static com.lyndir.lhunath.opal.system.util.StringUtils.strf; +import static com.lyndir.lhunath.opal.system.util.StringUtils.*; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; import java.util.*; import java.util.function.Function; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import org.jetbrains.annotations.NotNull; /** @@ -30,9 +31,8 @@ public class MPQuery { * @return {@code true} if this query is contained wholly inside the given {@code key}. */ @Nonnull - public > Optional> find(final T option, final Function keyForOption) { - CharSequence key = keyForOption.apply( option ); - Result result = Result.noneOf( option, key ); + public Optional> matches(final V value, final CharSequence key) { + Result result = Result.noneOf( value, key ); if (query.isEmpty()) return Optional.of( result ); if (key.length() == 0) @@ -49,36 +49,49 @@ public class MPQuery { ++k; } - // If query is consumed, the result is a hit. - return (q >= query.length())? Optional.of( result ): Optional.empty(); + // If the match against the query broke before the end of the query, it failed. + return (q < query.length())? Optional.empty(): Optional.of( result ); } - public static class Result> implements Comparable> { + /** + * @return Results for values that matched against the query, in the original values' order. + */ + @Nonnull + public ImmutableCollection> find(final Iterable values, + final Function valueToKey) { + ImmutableList.Builder> results = ImmutableList.builder(); + for (final V value : values) + matches( value, valueToKey.apply( value ) ).ifPresent( results::add ); - private final T option; + return results.build(); + } + + public static class Result { + + private final V value; private final CharSequence key; private final boolean[] keyMatches; - Result(final T option, final CharSequence key) { - this.option = option; + Result(final V value, final CharSequence key) { + this.value = value; this.key = key; keyMatches = new boolean[key.length()]; } - public static > Result noneOf(final T option, final CharSequence key) { - return new Result<>( option, key ); + public static Result noneOf(final T value, final CharSequence key) { + return new Result<>( value, key ); } - public static > Result allOf(final T option, final CharSequence key) { - Result result = noneOf( option, key ); + public static Result allOf(final T value, final CharSequence key) { + Result result = noneOf( value, key ); Arrays.fill( result.keyMatches, true ); return result; } @Nonnull - public T getOption() { - return option; + public V getValue() { + return value; } @Nonnull @@ -130,23 +143,18 @@ public class MPQuery { keyMatches[k] = true; } - @Override - public int compareTo(@NotNull final Result o) { - return getOption().compareTo( o.getOption() ); - } - @Override public boolean equals(final Object o) { if (!(o instanceof Result)) return false; Result r = (Result) o; - return Objects.equals( option, r.option ) && Objects.equals( key, r.key ) && Arrays.equals( keyMatches, r.keyMatches ); + return Objects.equals( value, r.value ) && Objects.equals( key, r.key ) && Arrays.equals( keyMatches, r.keyMatches ); } @Override public int hashCode() { - return getOption().hashCode(); + return getValue().hashCode(); } @Override diff --git a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPSite.java b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPSite.java index f93f3f1d..fa810c54 100644 --- a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPSite.java +++ b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPSite.java @@ -18,7 +18,6 @@ package com.lyndir.masterpassword.model; -import com.google.common.collect.ImmutableCollection; import com.google.common.primitives.UnsignedInteger; import com.lyndir.masterpassword.*; import java.util.Collection; @@ -118,7 +117,4 @@ public interface MPSite extends Comparable> { @Nonnull Collection getQuestions(); - - @Nonnull - ImmutableCollection> findQuestions(MPQuery query); } diff --git a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPUser.java b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPUser.java index 88c3b084..808eb811 100644 --- a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPUser.java +++ b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/MPUser.java @@ -18,7 +18,6 @@ package com.lyndir.masterpassword.model; -import com.google.common.collect.ImmutableCollection; import com.lyndir.masterpassword.*; import java.util.Collection; import javax.annotation.Nonnull; @@ -111,9 +110,6 @@ public interface MPUser> extends Comparable> { @Nonnull Collection getSites(); - @Nonnull - ImmutableCollection> findSites(MPQuery query); - void addListener(Listener listener); void removeListener(Listener listener); diff --git a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPBasicSite.java b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPBasicSite.java index 5f1d5450..5abb44c4 100644 --- a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPBasicSite.java +++ b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPBasicSite.java @@ -21,8 +21,6 @@ package com.lyndir.masterpassword.model.impl; import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*; import static com.lyndir.lhunath.opal.system.util.StringUtils.*; -import com.google.common.collect.ImmutableCollection; -import com.google.common.collect.ImmutableSortedSet; import com.google.common.primitives.UnsignedInteger; import com.lyndir.masterpassword.*; import com.lyndir.masterpassword.model.*; @@ -39,7 +37,7 @@ public abstract class MPBasicSite, Q extends MPQuestion> ext private final U user; private final String siteName; - private final Collection questions = new LinkedHashSet<>(); + private final Collection questions = new TreeSet<>(); private MPAlgorithm algorithm; private UnsignedInteger counter; @@ -202,16 +200,6 @@ public abstract class MPBasicSite, Q extends MPQuestion> ext return Collections.unmodifiableCollection( questions ); } - @Nonnull - @Override - public ImmutableCollection> findQuestions(final MPQuery query) { - ImmutableSortedSet.Builder> results = ImmutableSortedSet.naturalOrder(); - for (final Q question : questions) - query.find( question, MPQuestion::getKeyword ).ifPresent( results::add ); - - return results.build(); - } - @Override protected void onChanged() { super.onChanged(); diff --git a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPBasicUser.java b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPBasicUser.java index d8dacf7c..80c90d89 100755 --- a/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPBasicUser.java +++ b/platform-independent/java/model/src/main/java/com/lyndir/masterpassword/model/impl/MPBasicUser.java @@ -20,8 +20,6 @@ package com.lyndir.masterpassword.model.impl; import static com.lyndir.lhunath.opal.system.util.StringUtils.*; -import com.google.common.collect.ImmutableCollection; -import com.google.common.collect.ImmutableSortedSet; import com.lyndir.lhunath.opal.system.CodeUtils; import com.lyndir.lhunath.opal.system.logging.Logger; import com.lyndir.masterpassword.*; @@ -47,7 +45,7 @@ public abstract class MPBasicUser> extends Changeabl @Nullable protected MPMasterKey masterKey; - private final Map sites = new LinkedHashMap<>(); + private final Set sites = new TreeSet<>(); protected MPBasicUser(final String fullName, final MPAlgorithm algorithm) { this( 0, fullName, algorithm ); @@ -177,7 +175,7 @@ public abstract class MPBasicUser> extends Changeabl @Nonnull @Override public S addSite(final S site) { - sites.put( site.getSiteName(), site ); + sites.add( site ); setChanged(); return site; @@ -185,7 +183,7 @@ public abstract class MPBasicUser> extends Changeabl @Override public boolean deleteSite(final MPSite site) { - if (!sites.values().remove( site )) + if (!sites.remove( site )) return false; setChanged(); @@ -195,17 +193,7 @@ public abstract class MPBasicUser> extends Changeabl @Nonnull @Override public Collection getSites() { - return Collections.unmodifiableCollection( sites.values() ); - } - - @Nonnull - @Override - public ImmutableCollection> findSites(final MPQuery query) { - ImmutableSortedSet.Builder> results = ImmutableSortedSet.naturalOrder(); - for (final S site : sites.values()) - query.find( site, MPSite::getSiteName ).ifPresent( results::add ); - - return results.build(); + return Collections.unmodifiableCollection( sites ); } @Override