Centralize query searching.
This commit is contained in:
@@ -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 <T extends Comparable<? super T>> Optional<Result<T>> find(final T option, final Function<T, CharSequence> keyForOption) {
|
||||
CharSequence key = keyForOption.apply( option );
|
||||
Result<T> result = Result.noneOf( option, key );
|
||||
public <V> Optional<Result<V>> matches(final V value, final CharSequence key) {
|
||||
Result<V> 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<T extends Comparable<? super T>> implements Comparable<Result<T>> {
|
||||
/**
|
||||
* @return Results for values that matched against the query, in the original values' order.
|
||||
*/
|
||||
@Nonnull
|
||||
public <V> ImmutableCollection<Result<? extends V>> find(final Iterable<? extends V> values,
|
||||
final Function<V, CharSequence> valueToKey) {
|
||||
ImmutableList.Builder<Result<? extends V>> 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<V> {
|
||||
|
||||
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 <T extends Comparable<? super T>> Result<T> noneOf(final T option, final CharSequence key) {
|
||||
return new Result<>( option, key );
|
||||
public static <T> Result<T> noneOf(final T value, final CharSequence key) {
|
||||
return new Result<>( value, key );
|
||||
}
|
||||
|
||||
public static <T extends Comparable<? super T>> Result<T> allOf(final T option, final CharSequence key) {
|
||||
Result<T> result = noneOf( option, key );
|
||||
public static <T> Result<T> allOf(final T value, final CharSequence key) {
|
||||
Result<T> 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<T> 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
|
||||
|
@@ -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<Q extends MPQuestion> extends Comparable<MPSite<?>> {
|
||||
|
||||
@Nonnull
|
||||
Collection<Q> getQuestions();
|
||||
|
||||
@Nonnull
|
||||
ImmutableCollection<MPQuery.Result<Q>> findQuestions(MPQuery query);
|
||||
}
|
||||
|
@@ -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<S extends MPSite<?>> extends Comparable<MPUser<?>> {
|
||||
@Nonnull
|
||||
Collection<S> getSites();
|
||||
|
||||
@Nonnull
|
||||
ImmutableCollection<MPQuery.Result<S>> findSites(MPQuery query);
|
||||
|
||||
void addListener(Listener listener);
|
||||
|
||||
void removeListener(Listener listener);
|
||||
|
@@ -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<U extends MPUser<?>, Q extends MPQuestion> ext
|
||||
|
||||
private final U user;
|
||||
private final String siteName;
|
||||
private final Collection<Q> questions = new LinkedHashSet<>();
|
||||
private final Collection<Q> questions = new TreeSet<>();
|
||||
|
||||
private MPAlgorithm algorithm;
|
||||
private UnsignedInteger counter;
|
||||
@@ -202,16 +200,6 @@ public abstract class MPBasicSite<U extends MPUser<?>, Q extends MPQuestion> ext
|
||||
return Collections.unmodifiableCollection( questions );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ImmutableCollection<MPQuery.Result<Q>> findQuestions(final MPQuery query) {
|
||||
ImmutableSortedSet.Builder<MPQuery.Result<Q>> 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();
|
||||
|
@@ -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<S extends MPBasicSite<?, ?>> extends Changeabl
|
||||
@Nullable
|
||||
protected MPMasterKey masterKey;
|
||||
|
||||
private final Map<String, S> sites = new LinkedHashMap<>();
|
||||
private final Set<S> sites = new TreeSet<>();
|
||||
|
||||
protected MPBasicUser(final String fullName, final MPAlgorithm algorithm) {
|
||||
this( 0, fullName, algorithm );
|
||||
@@ -177,7 +175,7 @@ public abstract class MPBasicUser<S extends MPBasicSite<?, ?>> 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<S extends MPBasicSite<?, ?>> 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<S extends MPBasicSite<?, ?>> extends Changeabl
|
||||
@Nonnull
|
||||
@Override
|
||||
public Collection<S> getSites() {
|
||||
return Collections.unmodifiableCollection( sites.values() );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ImmutableCollection<MPQuery.Result<S>> findSites(final MPQuery query) {
|
||||
ImmutableSortedSet.Builder<MPQuery.Result<S>> 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
|
||||
|
Reference in New Issue
Block a user