1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.search.grouping.request;
import java.util.LinkedList;
import java.util.List;
/**
* This is a helper class for resolving buckets to a list of
* {@link GroupingExpression} objects. To resolve a list simply
* {@link #push(ConstantValue, boolean)} onto it, before calling
* {@link #resolve(GroupingExpression)} to retrieve the list of corresponding
* grouping expression object.
*
* @author <a href="mailto:simon@yahoo-inc.com">Simon Thoresen</a>
*/
public class BucketResolver {
private final List<BucketValue> buckets = new LinkedList<>();
private ConstantValue<?> prev = null;
private boolean previnclusive = false;
private int idx = 0;
/**
* Pushes the given expression onto this bucket resolver. Once all buckets have been pushed using this method, call
* {@link #resolve(GroupingExpression)} to retrieve to combined grouping expression.
*
* @param val The expression to push.
* @param inclusive Whether or not the value is inclusive or not.
* @throws IllegalArgumentException Thrown if the expression is incompatible.
*/
public BucketResolver push(ConstantValue<?> val, boolean inclusive) {
if (prev == null) {
prev = val;
} else if (!(prev instanceof InfiniteValue || val instanceof InfiniteValue)
&& !prev.getClass().equals(val.getClass())) {
throw new IllegalArgumentException("Bucket type mismatch, expected '" + prev.getClass().getSimpleName() +
"' got '" + val.getClass().getSimpleName() + "'.");
} else if (prev instanceof InfiniteValue && val instanceof InfiniteValue) {
throw new IllegalArgumentException("Bucket type mismatch, cannot both be infinity.");
}
if ((++idx % 2) == 0) {
ConstantValue<?> begin = previnclusive ? prev : nextValue(prev);
ConstantValue<?> end = inclusive ? nextValue(val) : val;
if (begin instanceof DoubleValue || end instanceof DoubleValue) {
buckets.add(new DoubleBucket(begin, end));
} else if (begin instanceof LongValue || end instanceof LongValue) {
buckets.add(new LongBucket(begin, end));
} else if (begin instanceof StringValue || end instanceof StringValue) {
buckets.add(new StringBucket(begin, end));
} else if (begin instanceof RawValue || end instanceof RawValue) {
buckets.add(new RawBucket(begin, end));
} else {
throw new UnsupportedOperationException("Bucket type '" + val.getClass() + "' not supported.");
}
}
prev = val;
previnclusive = inclusive;
return this;
}
/**
* Resolves and returns the list of grouping expressions that correspond to the previously pushed buckets.
*
* @param exp The expression to assign to the function.
* @return The list corresponding to the pushed buckets.
*/
public PredefinedFunction resolve(GroupingExpression exp) {
if ((idx % 2) == 1) {
throw new IllegalStateException("Missing to-limit of last bucket.");
}
int len = buckets.size();
if (len == 0) {
throw new IllegalStateException("Expected at least one bucket, got none.");
}
ConstantValue<?> begin = buckets.get(0).getFrom();
ConstantValue<?> end = buckets.get(0).getTo();
if (begin instanceof DoubleValue || end instanceof DoubleValue) {
if (len == 1) {
return new DoublePredefined(exp, (DoubleBucket)buckets.get(0));
} else {
return new DoublePredefined(exp, (DoubleBucket)buckets.get(0),
buckets.subList(1, len).toArray(new DoubleBucket[len - 1]));
}
} else if (begin instanceof LongValue || end instanceof LongValue) {
if (len == 1) {
return new LongPredefined(exp, (LongBucket)buckets.get(0));
} else {
return new LongPredefined(exp, (LongBucket)buckets.get(0),
buckets.subList(1, len).toArray(new LongBucket[len - 1]));
}
} else if (begin instanceof StringValue || end instanceof StringValue) {
if (len == 1) {
return new StringPredefined(exp, (StringBucket)buckets.get(0));
} else {
return new StringPredefined(exp, (StringBucket)buckets.get(0),
buckets.subList(1, len).toArray(new StringBucket[len - 1]));
}
} else if (begin instanceof RawValue || end instanceof RawValue) {
if (len == 1) {
return new RawPredefined(exp, (RawBucket)buckets.get(0));
} else {
return new RawPredefined(exp, (RawBucket)buckets.get(0),
buckets.subList(1, len).toArray(new RawBucket[len - 1]));
}
}
throw new UnsupportedOperationException("Bucket type '" + begin.getClass() + "' not supported.");
}
private ConstantValue<?> nextValue(ConstantValue<?> value) {
if (value instanceof LongValue) {
return LongBucket.nextValue((LongValue)value);
} else if (value instanceof DoubleValue) {
return DoubleBucket.nextValue((DoubleValue)value);
} else if (value instanceof StringValue) {
return StringBucket.nextValue((StringValue)value);
} else if (value instanceof RawValue) {
return RawBucket.nextValue((RawValue)value);
}
return value;
}
}
|