From 75a84af3f8ff7ccf5ce1c24c3b2291577ee972c6 Mon Sep 17 00:00:00 2001 From: Robin Bygrave Date: Thu, 10 Mar 2016 11:30:42 +1300 Subject: [PATCH] #594 - ElasticSearch - Use AbstractTextExpression --- .../com/avaje/ebean/search/AbstractMatch.java | 98 +++++++++++++ .../com/avaje/ebean/search/BaseMatch.java | 130 ------------------ .../java/com/avaje/ebean/search/Match.java | 21 +-- .../com/avaje/ebean/search/MultiMatch.java | 33 +---- .../expression/AbstractTextExpression.java | 48 +++++++ .../expression/TextMatchExpression.java | 67 +-------- .../expression/TextMultiMatchExpression.java | 52 +------ .../com/avaje/ebean/search/MatchTest.java | 75 ---------- 8 files changed, 150 insertions(+), 374 deletions(-) create mode 100644 src/main/java/com/avaje/ebean/search/AbstractMatch.java delete mode 100644 src/main/java/com/avaje/ebean/search/BaseMatch.java create mode 100644 src/main/java/com/avaje/ebeaninternal/server/expression/AbstractTextExpression.java delete mode 100644 src/test/java/com/avaje/ebean/search/MatchTest.java diff --git a/src/main/java/com/avaje/ebean/search/AbstractMatch.java b/src/main/java/com/avaje/ebean/search/AbstractMatch.java new file mode 100644 index 000000000..dcd0a6e79 --- /dev/null +++ b/src/main/java/com/avaje/ebean/search/AbstractMatch.java @@ -0,0 +1,98 @@ +package com.avaje.ebean.search; + +/** + * Options for the text match and multi match expressions. + */ +public abstract class AbstractMatch { + + protected boolean and; + + protected String analyzer; + + protected double boost; + + protected String minShouldMatch; + + protected int maxExpansions; + + protected String zeroTerms; + + protected double cutoffFrequency; + + protected String fuzziness; + + protected int prefixLength; + + protected String rewrite; + + /** + * Return true if using the AND operator otherwise using the OR operator. + */ + public boolean isAnd() { + return and; + } + + /** + * Return the boost. + */ + public double getBoost() { + return boost; + } + + /** + * Return the minimum should match. + */ + public String getMinShouldMatch() { + return minShouldMatch; + } + + /** + * Return the zero terms option. + */ + public String getZeroTerms() { + return zeroTerms; + } + + /** + * Return the cutoff frequency. + */ + public double getCutoffFrequency() { + return cutoffFrequency; + } + + /** + * Return the max expansions. + */ + public int getMaxExpansions() { + return maxExpansions; + } + + /** + * Return the analyzer. + */ + public String getAnalyzer() { + return analyzer; + } + + /** + * Return the fuzziness. + */ + public String getFuzziness() { + return fuzziness; + } + + /** + * Return the prefix length. + */ + public int getPrefixLength() { + return prefixLength; + } + + /** + * Return the rewrite option. + */ + public String getRewrite() { + return rewrite; + } + +} diff --git a/src/main/java/com/avaje/ebean/search/BaseMatch.java b/src/main/java/com/avaje/ebean/search/BaseMatch.java deleted file mode 100644 index 90daf51d2..000000000 --- a/src/main/java/com/avaje/ebean/search/BaseMatch.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.avaje.ebean.search; - -/** - * Options for the text match expression. - */ -public abstract class BaseMatch { - - protected boolean and; - - protected String analyzer; - - protected double boost; - - protected String minShouldMatch; - - protected int maxExpansions; - - protected String zeroTerms; - - protected double cutoffFrequency; - - protected String fuzziness; - - protected int prefixLength; - - protected String rewrite; - - /** - * Return true if using the AND operator otherwise using the OR operator. - */ - public boolean isAnd() { - return and; - } - - /** - * Return the boost. - */ - public double getBoost() { - return boost; - } - - /** - * Return the minimum should match. - */ - public String getMinShouldMatch() { - return minShouldMatch; - } - - /** - * Return the zero terms option. - */ - public String getZeroTerms() { - return zeroTerms; - } - - /** - * Return the cutoff frequency. - */ - public double getCutoffFrequency() { - return cutoffFrequency; - } - - /** - * Return the max expansions. - */ - public int getMaxExpansions() { - return maxExpansions; - } - - /** - * Return the analyzer. - */ - public String getAnalyzer() { - return analyzer; - } - - /** - * Return the fuzziness. - */ - public String getFuzziness() { - return fuzziness; - } - - /** - * Return the prefix length. - */ - public int getPrefixLength() { - return prefixLength; - } - - /** - * Return the rewrite option. - */ - public String getRewrite() { - return rewrite; - } - - protected boolean baseEquals(BaseMatch baseMatch) { - - if (and != baseMatch.and) return false; - if (Double.compare(baseMatch.boost, boost) != 0) return false; - if (maxExpansions != baseMatch.maxExpansions) return false; - if (Double.compare(baseMatch.cutoffFrequency, cutoffFrequency) != 0) return false; - if (prefixLength != baseMatch.prefixLength) return false; - if (analyzer != null ? !analyzer.equals(baseMatch.analyzer) : baseMatch.analyzer != null) return false; - if (minShouldMatch != null ? !minShouldMatch.equals(baseMatch.minShouldMatch) : baseMatch.minShouldMatch != null) return false; - if (zeroTerms != null ? !zeroTerms.equals(baseMatch.zeroTerms) : baseMatch.zeroTerms != null) return false; - if (fuzziness != null ? !fuzziness.equals(baseMatch.fuzziness) : baseMatch.fuzziness != null) return false; - return rewrite != null ? rewrite.equals(baseMatch.rewrite) : baseMatch.rewrite == null; - } - - protected int baseHashCode() { - - int result; - long temp; - result = (and ? 1 : 0); - result = 31 * result + (analyzer != null ? analyzer.hashCode() : 0); - temp = Double.doubleToLongBits(boost); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - result = 31 * result + (minShouldMatch != null ? minShouldMatch.hashCode() : 0); - result = 31 * result + maxExpansions; - result = 31 * result + (zeroTerms != null ? zeroTerms.hashCode() : 0); - temp = Double.doubleToLongBits(cutoffFrequency); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - result = 31 * result + (fuzziness != null ? fuzziness.hashCode() : 0); - result = 31 * result + prefixLength; - result = 31 * result + (rewrite != null ? rewrite.hashCode() : 0); - return result; - } -} diff --git a/src/main/java/com/avaje/ebean/search/Match.java b/src/main/java/com/avaje/ebean/search/Match.java index 391d7c184..03768f81c 100644 --- a/src/main/java/com/avaje/ebean/search/Match.java +++ b/src/main/java/com/avaje/ebean/search/Match.java @@ -3,7 +3,7 @@ package com.avaje.ebean.search; /** * Options for the text match expression. */ -public class Match extends BaseMatch { +public class Match extends AbstractMatch { protected boolean phrase; @@ -125,23 +125,4 @@ public class Match extends BaseMatch { return phrasePrefix; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Match match = (Match) o; - - if (phrase != match.phrase) return false; - if (phrasePrefix != match.phrasePrefix) return false; - return baseEquals(match); - } - - @Override - public int hashCode() { - int result = (phrase ? 1 : 0); - result = 31 * result + (phrasePrefix ? 1 : 0); - result = 31 * result + baseHashCode(); - return result; - } } diff --git a/src/main/java/com/avaje/ebean/search/MultiMatch.java b/src/main/java/com/avaje/ebean/search/MultiMatch.java index 175b6469c..83ae0f61b 100644 --- a/src/main/java/com/avaje/ebean/search/MultiMatch.java +++ b/src/main/java/com/avaje/ebean/search/MultiMatch.java @@ -1,11 +1,9 @@ package com.avaje.ebean.search; -import java.util.Arrays; - /** * Options for the text match expression. */ -public class MultiMatch extends BaseMatch { +public class MultiMatch extends AbstractMatch { /** * The MultiMatch type. @@ -154,33 +152,4 @@ public class MultiMatch extends BaseMatch { return tieBreaker; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - MultiMatch that = (MultiMatch) o; - - if (Double.compare(that.tieBreaker, tieBreaker) != 0) return false; - if (type != that.type) return false; - if (fields.length != that.fields.length) return false; - for (int i = 0; i < fields.length; i++) { - if (!fields[i].equals(that.fields[i])) { - return false; - } - } - return baseEquals(that); - } - - @Override - public int hashCode() { - int result; - long temp; - result = type.hashCode(); - result = 31 * result + Arrays.hashCode(fields); - temp = Double.doubleToLongBits(tieBreaker); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - result = 31 * result + baseHashCode(); - return result; - } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/AbstractTextExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/AbstractTextExpression.java new file mode 100644 index 000000000..9f9b04ae4 --- /dev/null +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/AbstractTextExpression.java @@ -0,0 +1,48 @@ +package com.avaje.ebeaninternal.server.expression; + +import com.avaje.ebeaninternal.api.HashQueryPlanBuilder; +import com.avaje.ebeaninternal.api.SpiExpression; +import com.avaje.ebeaninternal.api.SpiExpressionRequest; + +/** + * Base class for TextExpressions that are only executable by doc store. + *

+ * This means they can not be part of a SQL query nor do they use the built in query plan cache etc. + *

+ */ +public abstract class AbstractTextExpression extends AbstractExpression { + + protected AbstractTextExpression(String propName) { + super(propName); + } + + @Override + public void addSql(SpiExpressionRequest request) { + throw new IllegalStateException("Not implemented - DocStore/Elastic only"); + } + + @Override + public void addBindValues(SpiExpressionRequest request) { + throw new IllegalStateException("Not implemented - DocStore/Elastic only"); + } + + @Override + public void queryPlanHash(HashQueryPlanBuilder builder) { + throw new IllegalStateException("Not implemented - query plan caching done explicitly by the doc store"); + } + + @Override + public int queryBindHash() { + throw new IllegalStateException("Not implemented - query plan caching done explicitly by the doc store"); + } + + @Override + public boolean isSameByPlan(SpiExpression other) { + throw new IllegalStateException("Not implemented - query plan caching done explicitly by the doc store"); + } + + @Override + public boolean isSameByBind(SpiExpression other) { + throw new IllegalStateException("Not implemented - query plan caching done explicitly by the doc store"); + } +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/TextMatchExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/TextMatchExpression.java index 850382727..a0630ade7 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/TextMatchExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/TextMatchExpression.java @@ -1,17 +1,13 @@ package com.avaje.ebeaninternal.server.expression; -import com.avaje.ebean.search.BaseMatch; import com.avaje.ebean.search.Match; -import com.avaje.ebeaninternal.api.HashQueryPlanBuilder; -import com.avaje.ebeaninternal.api.SpiExpression; -import com.avaje.ebeaninternal.api.SpiExpressionRequest; import java.io.IOException; /** * Full text MATCH expression. */ -public class TextMatchExpression extends AbstractExpression { +public class TextMatchExpression extends AbstractTextExpression { private final String search; @@ -28,65 +24,4 @@ public class TextMatchExpression extends AbstractExpression { context.writeMatch(propName, search, options); } - @Override - public void addSql(SpiExpressionRequest request) { - throw new IllegalStateException("Not implemented - DocStore/Elastic only"); - } - - @Override - public void addBindValues(SpiExpressionRequest request) { - throw new IllegalStateException("Not implemented - DocStore/Elastic only"); - } - - /** - * Based on the type and propertyName. - */ - @Override - public void queryPlanHash(HashQueryPlanBuilder builder) { - builder.add(TextMatchExpression.class).add(propName).add(search); - if (options != null) { - builder.add(options.isPhrase()); - builder.add(options.isPhrasePrefix()); - addHash(builder, options); - } - } - - @Override - public int queryBindHash() { - return search.hashCode(); - } - - @Override - public boolean isSameByPlan(SpiExpression other) { - if (!(other instanceof TextMatchExpression)) { - return false; - } - - TextMatchExpression that = (TextMatchExpression) other; - return this.propName.equals(that.propName) - && this.search.equals(that.search) - && this.options == null ? that.options == null : options.equals(that.options); - } - - @Override - public boolean isSameByBind(SpiExpression other) { - TextMatchExpression that = (TextMatchExpression) other; - return search.equals(that.search); - } - - /** - * Add the hash to the builder for the base/common options. - */ - public static void addHash(HashQueryPlanBuilder builder, BaseMatch options) { - builder.add(options.isAnd()); - builder.add(options.getAnalyzer()); - builder.add(options.getBoost()); - builder.add(options.getCutoffFrequency()); - builder.add(options.getFuzziness()); - builder.add(options.getMaxExpansions()); - builder.add(options.getMinShouldMatch()); - builder.add(options.getPrefixLength()); - builder.add(options.getRewrite()); - builder.add(options.getZeroTerms()); - } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/TextMultiMatchExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/TextMultiMatchExpression.java index 7eee078e2..786da9f18 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/TextMultiMatchExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/TextMultiMatchExpression.java @@ -1,16 +1,13 @@ package com.avaje.ebeaninternal.server.expression; import com.avaje.ebean.search.MultiMatch; -import com.avaje.ebeaninternal.api.HashQueryPlanBuilder; -import com.avaje.ebeaninternal.api.SpiExpression; -import com.avaje.ebeaninternal.api.SpiExpressionRequest; import java.io.IOException; /** * Full text Multi-Match expression. */ -public class TextMultiMatchExpression extends AbstractExpression { +public class TextMultiMatchExpression extends AbstractTextExpression { private final String search; @@ -27,51 +24,4 @@ public class TextMultiMatchExpression extends AbstractExpression { context.writeMultiMatch(search, options); } - @Override - public void addSql(SpiExpressionRequest request) { - throw new IllegalStateException("Not implemented - DocStore/Elastic only"); - } - - @Override - public void addBindValues(SpiExpressionRequest request) { - throw new IllegalStateException("Not implemented - DocStore/Elastic only"); - } - - /** - * Based on the type and propertyName. - */ - @Override - public void queryPlanHash(HashQueryPlanBuilder builder) { - builder.add(TextMultiMatchExpression.class).add(search); - builder.add(options.getType()); - builder.add(options.getTieBreaker()); - String[] fields = options.getFields(); - builder.add(fields.length); - for (int i = 0; i < fields.length; i++) { - builder.add(fields[i]); - } - TextMatchExpression.addHash(builder, options); - } - - @Override - public int queryBindHash() { - return search.hashCode(); - } - - @Override - public boolean isSameByPlan(SpiExpression other) { - if (!(other instanceof TextMultiMatchExpression)) { - return false; - } - - TextMultiMatchExpression that = (TextMultiMatchExpression) other; - return this.search.equals(that.search) - && this.options == null ? that.options == null : options.equals(that.options); - } - - @Override - public boolean isSameByBind(SpiExpression other) { - TextMultiMatchExpression that = (TextMultiMatchExpression) other; - return search.equals(that.search); - } } diff --git a/src/test/java/com/avaje/ebean/search/MatchTest.java b/src/test/java/com/avaje/ebean/search/MatchTest.java deleted file mode 100644 index 7906ef3a1..000000000 --- a/src/test/java/com/avaje/ebean/search/MatchTest.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.avaje.ebean.search; - - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -public class MatchTest { - - Match match() { - return Match.AND() - .analyzer("whitespace") - .boost(2) - .cutoffFrequency(1) - .minShouldMatch("50%") - .maxExpansions(3) - .zeroTerms("all"); - } - - @Test - public void equals_when_allSet() { - assertEquals(match(), match()); - assertEquals(match().hashCode(), match().hashCode()); - } - - @Test - public void notEquals_when_analyzer() { - assertNotEquals(match(), match().analyzer("foo")); - assertNotEquals(match().hashCode(), match().analyzer("foo").hashCode()); - assertNotEquals(match(), match().analyzer(null)); - assertNotEquals(match().hashCode(), match().analyzer(null).hashCode()); - } - - @Test - public void notEquals_when_boost() { - assertNotEquals(match(), match().boost(3)); - } - - @Test - public void notEquals_when_cutoffFrequency() { - assertNotEquals(match(), match().cutoffFrequency(3)); - } - - @Test - public void notEquals_when_maxExpansions() { - assertNotEquals(match(), match().maxExpansions(100)); - } - - @Test - public void notEquals_when_minShouldMatch() { - assertNotEquals(match(), match().minShouldMatch("12%")); - } - - @Test - public void notEquals_when_zeroTerms() { - assertNotEquals(match(), match().zeroTerms("none")); - } - - @Test - public void notEquals_when_phrase() { - assertNotEquals(match(), match().phrase()); - } - - @Test - public void notEquals_when_phrasePrefix() { - assertNotEquals(match(), match().phrasePrefix()); - } - - @Test - public void notEquals_when_operator() { - assertNotEquals(match(), match().opOr()); - } - -} \ No newline at end of file