summaryrefslogtreecommitdiffstats
path: root/predicate-search-core/src/main/java/com/yahoo/document/predicate/FeatureRange.java
diff options
context:
space:
mode:
Diffstat (limited to 'predicate-search-core/src/main/java/com/yahoo/document/predicate/FeatureRange.java')
-rw-r--r--predicate-search-core/src/main/java/com/yahoo/document/predicate/FeatureRange.java190
1 files changed, 190 insertions, 0 deletions
diff --git a/predicate-search-core/src/main/java/com/yahoo/document/predicate/FeatureRange.java b/predicate-search-core/src/main/java/com/yahoo/document/predicate/FeatureRange.java
new file mode 100644
index 00000000000..2ca09ee98f0
--- /dev/null
+++ b/predicate-search-core/src/main/java/com/yahoo/document/predicate/FeatureRange.java
@@ -0,0 +1,190 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.document.predicate;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * @author <a href="mailto:simon@yahoo-inc.com">Simon Thoresen Hult</a>
+ */
+public class FeatureRange extends PredicateValue {
+
+ private String key;
+ private Long from;
+ private Long to;
+ private List<RangePartition> partitions;
+ private List<RangeEdgePartition> edgePartitions;
+
+ public FeatureRange(String key) {
+ this(key, null, null);
+ }
+
+ public FeatureRange(String key, Long fromInclusive, Long toInclusive) {
+ setKey(key);
+ setFromInclusive(fromInclusive);
+ setToInclusive(toInclusive);
+ partitions = new ArrayList<>();
+ edgePartitions = new ArrayList<>();
+ }
+
+ public FeatureRange setKey(String key) {
+ Objects.requireNonNull(key, "key");
+ this.key = key;
+ return this;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public FeatureRange setFromInclusive(Long from) {
+ if (from != null && to != null && from > to) {
+ throw new IllegalArgumentException("Expected 'from' less than or equal to " + to + ", got " + from + ".");
+ }
+ this.from = from;
+ return this;
+ }
+
+ public Long getFromInclusive() {
+ return from;
+ }
+
+ public FeatureRange setToInclusive(Long to) {
+ if (from != null && to != null && from > to) {
+ throw new IllegalArgumentException("Expected 'to' greater than or equal to " + from + ", got " + to + ".");
+ }
+ this.to = to;
+ return this;
+ }
+
+ public Long getToInclusive() {
+ return to;
+ }
+
+ public void addPartition(RangePartition p) {
+ if (p instanceof RangeEdgePartition) {
+ edgePartitions.add((RangeEdgePartition)p);
+ } else {
+ partitions.add(p);
+ }
+ }
+
+ public List<RangeEdgePartition> getEdgePartitions() {
+ return edgePartitions;
+ }
+
+ public List<RangePartition> getPartitions() {
+ return partitions;
+ }
+
+ public void clearPartitions() {
+ partitions.clear();
+ edgePartitions.clear();
+ }
+
+ @Override
+ public FeatureRange clone() throws CloneNotSupportedException {
+ return (FeatureRange)super.clone();
+ }
+
+ @Override
+ public int hashCode() {
+ return ((key.hashCode() + (from != null ? from.hashCode() : 0)) * 31 + (to != null ? to.hashCode() : 0)) * 31;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof FeatureRange)) {
+ return false;
+ }
+ FeatureRange rhs = (FeatureRange)obj;
+ if (!key.equals(rhs.key)) {
+ return false;
+ }
+ if (!Objects.equals(from, rhs.from)) {
+ return false;
+ }
+ if (!Objects.equals(to, rhs.to)) {
+ return false;
+ }
+ return partitions.equals(rhs.partitions) && edgePartitions.equals(rhs.edgePartitions);
+ }
+
+ @Override
+ protected void appendTo(StringBuilder out) {
+ appendQuotedTo(key, out);
+ out.append(" in [");
+ if (from != null) {
+ out.append(from);
+ }
+ out.append("..");
+ if (to != null) {
+ out.append(to);
+ }
+ if (!partitions.isEmpty() || !edgePartitions.isEmpty()) {
+ out.append(" (");
+ for (RangeEdgePartition p : edgePartitions) {
+ p.appendTo(out);
+ out.append(',');
+ }
+ for (RangePartition p : partitions) {
+ p.appendTo(out);
+ out.append(',');
+ }
+ out.deleteCharAt(out.length() - 1); // Remove extra ','
+ out.append(")");
+ }
+ out.append("]");
+ }
+
+ public static FeatureRange buildFromMixedIn(String key, List<String> partitions, int arity) {
+ Long fromInclusive = null;
+ Long toInclusive = null;
+ long from = 0;
+ long to = 0;
+ for (String p : partitions) {
+ String[] parts = p.split(",");
+ if (parts.length == 1) {
+ String[] subparts = parts[0].split("=|-");
+ int offset = subparts.length == 3? 0 : 1;
+ if (subparts.length < 3 || subparts.length > 4) {
+ throw new IllegalArgumentException("MIXED_IN range partition must be on the form label=val-val");
+ }
+ from = Long.parseLong(subparts[offset + 1]);
+ to = Long.parseLong(subparts[offset + 2]);
+ if (parts[0].contains("=-")) {
+ long tmp = from;
+ from = -to;
+ to = -tmp;
+ }
+ } else {
+ if (parts.length != 3) {
+ throw new IllegalArgumentException("MIXED_IN range edge partition must be on the form label=val,val,payload");
+ }
+ long value = Long.parseLong(parts[1]);
+ long payload = Long.parseLong(parts[2]);
+ if ((payload & 0xc0000000) == 0x80000000L) {
+ from = value + (payload & 0xffff);
+ to = value + arity - 1;
+ } else if ((payload & 0xc0000000) == 0x40000000L) {
+ from = value;
+ to = value + (payload & 0xffff);
+ } else {
+ from = value + (payload >> 16);
+ to = value + (payload & 0xffff);
+ }
+ }
+ if (fromInclusive == null || fromInclusive > from) {
+ fromInclusive = from;
+ }
+ if (toInclusive == null || toInclusive > to) {
+ toInclusive = to;
+ }
+ }
+ return new FeatureRange(key, fromInclusive, toInclusive);
+ }
+}