Browse Source
Refactored to multiple smaller Aggregation Operator classes reflecting the grouping (array operators, string operators,…) predefined by MongoDB. Original pull request: #429.pull/692/head
30 changed files with 9141 additions and 8730 deletions
@ -0,0 +1,149 @@
@@ -0,0 +1,149 @@
|
||||
/* |
||||
* Copyright 2016. the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.mongodb.core.aggregation; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.Collections; |
||||
import java.util.LinkedHashMap; |
||||
import java.util.List; |
||||
|
||||
import org.bson.Document; |
||||
import org.springframework.util.ObjectUtils; |
||||
|
||||
/** |
||||
* @author Christoph Strobl |
||||
* @since 1.10 |
||||
*/ |
||||
abstract class AbstractAggregationExpression implements AggregationExpression { |
||||
|
||||
private final Object value; |
||||
|
||||
protected AbstractAggregationExpression(Object value) { |
||||
this.value = value; |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpression#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) |
||||
*/ |
||||
@Override |
||||
public Document toDocument(AggregationOperationContext context) { |
||||
return toDocument(this.value, context); |
||||
} |
||||
|
||||
public Document toDocument(Object value, AggregationOperationContext context) { |
||||
|
||||
Object valueToUse; |
||||
if (value instanceof List) { |
||||
|
||||
List<Object> arguments = (List<Object>) value; |
||||
List<Object> args = new ArrayList<Object>(arguments.size()); |
||||
|
||||
for (Object val : arguments) { |
||||
args.add(unpack(val, context)); |
||||
} |
||||
valueToUse = args; |
||||
} else if (value instanceof java.util.Map) { |
||||
|
||||
Document dbo = new Document(); |
||||
for (java.util.Map.Entry<String, Object> entry : ((java.util.Map<String, Object>) value).entrySet()) { |
||||
dbo.put(entry.getKey(), unpack(entry.getValue(), context)); |
||||
} |
||||
valueToUse = dbo; |
||||
} else { |
||||
valueToUse = unpack(value, context); |
||||
} |
||||
|
||||
return new Document(getMongoMethod(), valueToUse); |
||||
} |
||||
|
||||
protected static List<Field> asFields(String... fieldRefs) { |
||||
|
||||
if (ObjectUtils.isEmpty(fieldRefs)) { |
||||
return Collections.emptyList(); |
||||
} |
||||
|
||||
return Fields.fields(fieldRefs).asList(); |
||||
} |
||||
|
||||
private Object unpack(Object value, AggregationOperationContext context) { |
||||
|
||||
if (value instanceof AggregationExpression) { |
||||
return ((AggregationExpression) value).toDocument(context); |
||||
} |
||||
|
||||
if (value instanceof Field) { |
||||
return context.getReference((Field) value).toString(); |
||||
} |
||||
|
||||
if (value instanceof List) { |
||||
|
||||
List<Object> sourceList = (List<Object>) value; |
||||
List<Object> mappedList = new ArrayList<Object>(sourceList.size()); |
||||
|
||||
for (Object item : sourceList) { |
||||
mappedList.add(unpack(item, context)); |
||||
} |
||||
return mappedList; |
||||
} |
||||
|
||||
return value; |
||||
} |
||||
|
||||
protected List<Object> append(Object value) { |
||||
|
||||
if (this.value instanceof List) { |
||||
|
||||
List<Object> clone = new ArrayList<Object>((List) this.value); |
||||
|
||||
if (value instanceof List) { |
||||
for (Object val : (List) value) { |
||||
clone.add(val); |
||||
} |
||||
} else { |
||||
clone.add(value); |
||||
} |
||||
return clone; |
||||
} |
||||
|
||||
return Arrays.asList(this.value, value); |
||||
} |
||||
|
||||
protected java.util.Map<String, Object> append(String key, Object value) { |
||||
|
||||
if (!(this.value instanceof java.util.Map)) { |
||||
throw new IllegalArgumentException("o_O"); |
||||
} |
||||
java.util.Map<String, Object> clone = new LinkedHashMap<String, Object>( |
||||
(java.util.Map<String, Object>) this.value); |
||||
clone.put(key, value); |
||||
return clone; |
||||
|
||||
} |
||||
|
||||
protected List<Object> values() { |
||||
|
||||
if (value instanceof List) { |
||||
return new ArrayList<Object>((List) value); |
||||
} |
||||
if (value instanceof java.util.Map) { |
||||
return new ArrayList<Object>(((java.util.Map) value).values()); |
||||
} |
||||
return new ArrayList<Object>(Arrays.asList(value)); |
||||
} |
||||
|
||||
protected abstract String getMongoMethod(); |
||||
} |
||||
@ -0,0 +1,641 @@
@@ -0,0 +1,641 @@
|
||||
/* |
||||
* Copyright 2016. the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.mongodb.core.aggregation; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
import org.bson.Document; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* Gateway to {@literal accumulator} aggregation operations. |
||||
* |
||||
* @author Christoph Strobl |
||||
* @since 1.10 |
||||
* @soundtrack Rage Against The Machine - Killing In The Name |
||||
*/ |
||||
public class AccumulatorOperators { |
||||
|
||||
/** |
||||
* Take the numeric value referenced by given {@literal fieldReference}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static AccumulatorOperatorFactory valueOf(String fieldReference) { |
||||
return new AccumulatorOperatorFactory(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Take the numeric value referenced resulting from given {@link AggregationExpression}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static AccumulatorOperatorFactory valueOf(AggregationExpression expression) { |
||||
return new AccumulatorOperatorFactory(expression); |
||||
} |
||||
|
||||
/** |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class AccumulatorOperatorFactory { |
||||
|
||||
private final String fieldReference; |
||||
private final AggregationExpression expression; |
||||
|
||||
/** |
||||
* Creates new {@link AccumulatorOperatorFactory} for given {@literal fieldReference}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
*/ |
||||
public AccumulatorOperatorFactory(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
this.fieldReference = fieldReference; |
||||
this.expression = null; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link ArrayOperatorFactory} for given {@link AggregationExpression}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
*/ |
||||
public AccumulatorOperatorFactory(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
this.fieldReference = null; |
||||
this.expression = expression; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that takes the associated numeric value expression and calculates and |
||||
* returns the sum. |
||||
* |
||||
* @return |
||||
*/ |
||||
public Sum sum() { |
||||
return usesFieldRef() ? Sum.sumOf(fieldReference) : Sum.sumOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that takes the associated numeric value expression and returns the |
||||
* average value. |
||||
* |
||||
* @return |
||||
*/ |
||||
public Avg avg() { |
||||
return usesFieldRef() ? Avg.avgOf(fieldReference) : Avg.avgOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that takes the associated numeric value expression and returns the |
||||
* maximum value. |
||||
* |
||||
* @return |
||||
*/ |
||||
public Max max() { |
||||
return usesFieldRef() ? Max.maxOf(fieldReference) : Max.maxOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that takes the associated numeric value expression and returns the |
||||
* minimum value. |
||||
* |
||||
* @return |
||||
*/ |
||||
public Min min() { |
||||
return usesFieldRef() ? Min.minOf(fieldReference) : Min.minOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that takes the associated numeric value expression and calculates the |
||||
* population standard deviation of the input values. |
||||
* |
||||
* @return |
||||
*/ |
||||
public StdDevPop stdDevPop() { |
||||
return usesFieldRef() ? StdDevPop.stdDevPopOf(fieldReference) : StdDevPop.stdDevPopOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that takes the associated numeric value expression and calculates the |
||||
* sample standard deviation of the input values. |
||||
* |
||||
* @return |
||||
*/ |
||||
public StdDevSamp stdDevSamp() { |
||||
return usesFieldRef() ? StdDevSamp.stdDevSampOf(fieldReference) : StdDevSamp.stdDevSampOf(expression); |
||||
} |
||||
|
||||
private boolean usesFieldRef() { |
||||
return fieldReference != null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $sum}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Sum extends AbstractAggregationExpression { |
||||
|
||||
private Sum(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$sum"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Sum}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Sum sumOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Sum(asFields(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Sum}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Sum sumOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Sum(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Sum} with all previously added arguments appending the given one. <br /> |
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Sum and(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Sum(append(Fields.field(fieldReference))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Sum} with all previously added arguments appending the given one. <br /> |
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Sum and(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Sum(append(expression)); |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.AbstractAggregationExpression#toDocument(java.lang.Object, org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) |
||||
*/ |
||||
@Override |
||||
public Document toDocument(Object value, AggregationOperationContext context) { |
||||
|
||||
if (value instanceof List) { |
||||
if (((List) value).size() == 1) { |
||||
return super.toDocument(((List<Object>) value).iterator().next(), context); |
||||
} |
||||
} |
||||
|
||||
return super.toDocument(value, context); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $avg}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Avg extends AbstractAggregationExpression { |
||||
|
||||
private Avg(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$avg"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Avg}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Avg avgOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Avg(asFields(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Avg}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Avg avgOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Avg(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Avg} with all previously added arguments appending the given one. <br /> |
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Avg and(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Avg(append(Fields.field(fieldReference))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Avg} with all previously added arguments appending the given one. <br /> |
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Avg and(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Avg(append(expression)); |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.AbstractAggregationExpression#toDocument(java.lang.Object, org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) |
||||
*/ |
||||
@Override |
||||
public Document toDocument(Object value, AggregationOperationContext context) { |
||||
|
||||
if (value instanceof List) { |
||||
if (((List) value).size() == 1) { |
||||
return super.toDocument(((List<Object>) value).iterator().next(), context); |
||||
} |
||||
} |
||||
|
||||
return super.toDocument(value, context); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $max}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Max extends AbstractAggregationExpression { |
||||
|
||||
private Max(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$max"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Max}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Max maxOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Max(asFields(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Max}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Max maxOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Max(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Max} with all previously added arguments appending the given one. <br /> |
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Max and(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Max(append(Fields.field(fieldReference))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Max} with all previously added arguments appending the given one. <br /> |
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Max and(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Max(append(expression)); |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.AbstractAggregationExpression#toDocument(java.lang.Object, org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) |
||||
*/ |
||||
@Override |
||||
public Document toDocument(Object value, AggregationOperationContext context) { |
||||
|
||||
if (value instanceof List) { |
||||
if (((List) value).size() == 1) { |
||||
return super.toDocument(((List<Object>) value).iterator().next(), context); |
||||
} |
||||
} |
||||
|
||||
return super.toDocument(value, context); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $min}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Min extends AbstractAggregationExpression { |
||||
|
||||
private Min(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$min"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Min}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Min minOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Min(asFields(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Min}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Min minOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Min(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Min} with all previously added arguments appending the given one. <br /> |
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Min and(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Min(append(Fields.field(fieldReference))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Min} with all previously added arguments appending the given one. <br /> |
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Min and(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Min(append(expression)); |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.AbstractAggregationExpression#toDocument(java.lang.Object, org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) |
||||
*/ |
||||
@Override |
||||
public Document toDocument(Object value, AggregationOperationContext context) { |
||||
|
||||
if (value instanceof List) { |
||||
if (((List) value).size() == 1) { |
||||
return super.toDocument(((List<Object>) value).iterator().next(), context); |
||||
} |
||||
} |
||||
|
||||
return super.toDocument(value, context); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $stdDevPop}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class StdDevPop extends AbstractAggregationExpression { |
||||
|
||||
private StdDevPop(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$stdDevPop"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link StdDevPop}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static StdDevPop stdDevPopOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new StdDevPop(asFields(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link StdDevPop} with all previously added arguments appending the given one. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static StdDevPop stdDevPopOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new StdDevPop(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link StdDevPop} with all previously added arguments appending the given one. <br/> |
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public StdDevPop and(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new StdDevPop(append(Fields.field(fieldReference))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link StdDevSamp} with all previously added arguments appending the given one. <br /> |
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public StdDevPop and(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new StdDevPop(append(expression)); |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.AbstractAggregationExpression#toDocument(java.lang.Object, org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) |
||||
*/ |
||||
@Override |
||||
public Document toDocument(Object value, AggregationOperationContext context) { |
||||
|
||||
if (value instanceof List) { |
||||
if (((List) value).size() == 1) { |
||||
return super.toDocument(((List<Object>) value).iterator().next(), context); |
||||
} |
||||
} |
||||
|
||||
return super.toDocument(value, context); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $stdDevSamp}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class StdDevSamp extends AbstractAggregationExpression { |
||||
|
||||
private StdDevSamp(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$stdDevSamp"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link StdDevSamp}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static StdDevSamp stdDevSampOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new StdDevSamp(asFields(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link StdDevSamp}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static StdDevSamp stdDevSampOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new StdDevSamp(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link StdDevSamp} with all previously added arguments appending the given one. <br /> |
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public StdDevSamp and(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new StdDevSamp(append(Fields.field(fieldReference))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link StdDevSamp} with all previously added arguments appending the given one. <br /> |
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public StdDevSamp and(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new StdDevSamp(append(expression)); |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.AbstractAggregationExpression#toDocument(java.lang.Object, org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) |
||||
*/ |
||||
@Override |
||||
public Document toDocument(Object value, AggregationOperationContext context) { |
||||
|
||||
if (value instanceof List) { |
||||
if (((List) value).size() == 1) { |
||||
return super.toDocument(((List<Object>) value).iterator().next(), context); |
||||
} |
||||
} |
||||
|
||||
return super.toDocument(value, context); |
||||
} |
||||
} |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,353 @@
@@ -0,0 +1,353 @@
|
||||
/* |
||||
* Copyright 2016. the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.mongodb.core.aggregation; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* Gateway to {@literal boolean expressions} that evaluate their argument expressions as booleans and return a boolean |
||||
* as the result. |
||||
* |
||||
* @author Christoph Strobl |
||||
* @since 1.10 |
||||
*/ |
||||
public class BooleanOperators { |
||||
|
||||
/** |
||||
* Take the array referenced by given {@literal fieldReference}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static BooleanOperatorFactory valueOf(String fieldReference) { |
||||
return new BooleanOperatorFactory(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Take the value resulting of the given {@link AggregationExpression}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static BooleanOperatorFactory valueOf(AggregationExpression fieldReference) { |
||||
return new BooleanOperatorFactory(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that evaluates the boolean value of the referenced field and returns the |
||||
* opposite boolean value. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Not not(String fieldReference) { |
||||
return Not.not(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that evaluates the boolean value of {@link AggregationExpression} result |
||||
* and returns the opposite boolean value. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Not not(AggregationExpression expression) { |
||||
return Not.not(expression); |
||||
} |
||||
|
||||
/** |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class BooleanOperatorFactory { |
||||
|
||||
private final String fieldReference; |
||||
private final AggregationExpression expression; |
||||
|
||||
/** |
||||
* Creates new {@link BooleanOperatorFactory} for given {@literal fieldReference}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
*/ |
||||
public BooleanOperatorFactory(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
this.fieldReference = fieldReference; |
||||
this.expression = null; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link BooleanOperatorFactory} for given {@link AggregationExpression}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
*/ |
||||
public BooleanOperatorFactory(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
this.fieldReference = null; |
||||
this.expression = expression; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that evaluates one or more expressions and returns {@literal true} if |
||||
* all of the expressions are {@literal true}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public And and(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return createAnd().andExpression(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that evaluates one or more expressions and returns {@literal true} if |
||||
* all of the expressions are {@literal true}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public And and(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return createAnd().andField(fieldReference); |
||||
} |
||||
|
||||
private And createAnd() { |
||||
return usesFieldRef() ? And.and(Fields.field(fieldReference)) : And.and(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that evaluates one or more expressions and returns {@literal true} if |
||||
* any of the expressions are {@literal true}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Or or(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return createOr().orExpression(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that evaluates one or more expressions and returns {@literal true} if |
||||
* any of the expressions are {@literal true}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Or or(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return createOr().orField(fieldReference); |
||||
} |
||||
|
||||
private Or createOr() { |
||||
return usesFieldRef() ? Or.or(Fields.field(fieldReference)) : Or.or(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpression} that evaluates a boolean and returns the opposite boolean value. |
||||
* |
||||
* @return |
||||
*/ |
||||
public Not not() { |
||||
return usesFieldRef() ? Not.not(fieldReference) : Not.not(expression); |
||||
} |
||||
|
||||
private boolean usesFieldRef() { |
||||
return this.fieldReference != null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $and}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class And extends AbstractAggregationExpression { |
||||
|
||||
private And(List<?> values) { |
||||
super(values); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$and"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link And} that evaluates one or more expressions and returns {@literal true} if all of the |
||||
* expressions are {@literal true}. |
||||
* |
||||
* @param expressions |
||||
* @return |
||||
*/ |
||||
public static And and(Object... expressions) { |
||||
return new And(Arrays.asList(expressions)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link And} with all previously added arguments appending the given one. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public And andExpression(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new And(append(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link And} with all previously added arguments appending the given one. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public And andField(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new And(append(Fields.field(fieldReference))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link And} with all previously added arguments appending the given one. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public And andValue(Object value) { |
||||
|
||||
Assert.notNull(value, "Value must not be null!"); |
||||
return new And(append(value)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $or}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Or extends AbstractAggregationExpression { |
||||
|
||||
private Or(List<?> values) { |
||||
super(values); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$or"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Or} that evaluates one or more expressions and returns {@literal true} if any of the |
||||
* expressions are {@literal true}. |
||||
* |
||||
* @param expressions must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Or or(Object... expressions) { |
||||
|
||||
Assert.notNull(expressions, "Expressions must not be null!"); |
||||
return new Or(Arrays.asList(expressions)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Or} with all previously added arguments appending the given one. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Or orExpression(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Or(append(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Or} with all previously added arguments appending the given one. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Or orField(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Or(append(Fields.field(fieldReference))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Or} with all previously added arguments appending the given one. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Or orValue(Object value) { |
||||
|
||||
Assert.notNull(value, "Value must not be null!"); |
||||
return new Or(append(value)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $not}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Not extends AbstractAggregationExpression { |
||||
|
||||
private Not(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$not"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Not} that evaluates the boolean value of the referenced field and returns the opposite boolean |
||||
* value. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Not not(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Not(asFields(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Not} that evaluates the resulting boolean value of the given {@link AggregationExpression} and |
||||
* returns the opposite boolean value. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Not not(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Not(Collections.singletonList(expression)); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,879 @@
@@ -0,0 +1,879 @@
|
||||
/* |
||||
* Copyright 2016. the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.mongodb.core.aggregation; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* Gateway to {@literal comparison expressions}. |
||||
* |
||||
* @author Christoph Strobl |
||||
* @since 1.10 |
||||
*/ |
||||
public class ComparisonOperators { |
||||
|
||||
/** |
||||
* Take the field referenced by given {@literal fieldReference}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static ComparisonOperatorFactory valueOf(String fieldReference) { |
||||
return new ComparisonOperatorFactory(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Take the value resulting from the given {@link AggregationExpression}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static ComparisonOperatorFactory valueOf(AggregationExpression expression) { |
||||
return new ComparisonOperatorFactory(expression); |
||||
} |
||||
|
||||
public static class ComparisonOperatorFactory { |
||||
|
||||
private final String fieldReference; |
||||
private final AggregationExpression expression; |
||||
|
||||
/** |
||||
* Creates new {@link ComparisonOperatorFactory} for given {@literal fieldReference}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
*/ |
||||
public ComparisonOperatorFactory(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
this.fieldReference = fieldReference; |
||||
this.expression = null; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link ComparisonOperatorFactory} for given {@link AggregationExpression}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
*/ |
||||
public ComparisonOperatorFactory(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
this.fieldReference = null; |
||||
this.expression = expression; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Cmp compareTo(String fieldReference) { |
||||
return createCmp().compareTo(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Cmp compareTo(AggregationExpression expression) { |
||||
return createCmp().compareTo(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Cmp compareToValue(Object value) { |
||||
return createCmp().compareToValue(value); |
||||
} |
||||
|
||||
private Cmp createCmp() { |
||||
return usesFieldRef() ? Cmp.valueOf(fieldReference) : Cmp.valueOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the first |
||||
* value is equal to the value of the referenced field. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Eq equalTo(String fieldReference) { |
||||
return createEq().equalTo(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the first |
||||
* value is equal to the expression result. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Eq equalTo(AggregationExpression expression) { |
||||
return createEq().equalTo(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the first |
||||
* value is equal to the given value. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Eq equalToValue(Object value) { |
||||
return createEq().equalToValue(value); |
||||
} |
||||
|
||||
private Eq createEq() { |
||||
return usesFieldRef() ? Eq.valueOf(fieldReference) : Eq.valueOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the first |
||||
* value is greater than the value of the referenced field. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Gt greaterThan(String fieldReference) { |
||||
return createGt().greaterThan(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the first |
||||
* value is greater than the expression result. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Gt greaterThan(AggregationExpression expression) { |
||||
return createGt().greaterThan(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the first |
||||
* value is greater than the given value. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Gt greaterThanValue(Object value) { |
||||
return createGt().greaterThanValue(value); |
||||
} |
||||
|
||||
private Gt createGt() { |
||||
return usesFieldRef() ? Gt.valueOf(fieldReference) : Gt.valueOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the first |
||||
* value is greater than or equivalent to the value of the referenced field. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Gte greaterThanEqualTo(String fieldReference) { |
||||
return createGte().greaterThanEqualTo(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the first |
||||
* value is greater than or equivalent to the expression result. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Gte greaterThanEqualTo(AggregationExpression expression) { |
||||
return createGte().greaterThanEqualTo(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the first |
||||
* value is greater than or equivalent to the given value. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Gte greaterThanEqualToValue(Object value) { |
||||
return createGte().greaterThanEqualToValue(value); |
||||
} |
||||
|
||||
private Gte createGte() { |
||||
return usesFieldRef() ? Gte.valueOf(fieldReference) : Gte.valueOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the first |
||||
* value is less than the value of the referenced field. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Lt lessThan(String fieldReference) { |
||||
return createLt().lessThan(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the first |
||||
* value is less than the expression result. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Lt lessThan(AggregationExpression expression) { |
||||
return createLt().lessThan(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the first |
||||
* value is less than to the given value. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Lt lessThanValue(Object value) { |
||||
return createLt().lessThanValue(value); |
||||
} |
||||
|
||||
private Lt createLt() { |
||||
return usesFieldRef() ? Lt.valueOf(fieldReference) : Lt.valueOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the first |
||||
* value is less than or equivalent to the value of the referenced field. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Lte lessThanEqualTo(String fieldReference) { |
||||
return createLte().lessThanEqualTo(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the first |
||||
* value is less than or equivalent to the expression result. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Lte lessThanEqualTo(AggregationExpression expression) { |
||||
return createLte().lessThanEqualTo(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the first |
||||
* value is less than or equivalent to the given value. |
||||
* |
||||
* @param value |
||||
* @return |
||||
*/ |
||||
public Lte lessThanEqualToValue(Object value) { |
||||
return createLte().lessThanEqualToValue(value); |
||||
} |
||||
|
||||
private Lte createLte() { |
||||
return usesFieldRef() ? Lte.valueOf(fieldReference) : Lte.valueOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the values |
||||
* are not equivalent. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Ne notEqualTo(String fieldReference) { |
||||
return createNe().notEqualTo(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the values |
||||
* are not equivalent. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Ne notEqualTo(AggregationExpression expression) { |
||||
return createNe().notEqualTo(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares two values and returns {@literal true} when the values |
||||
* are not equivalent. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Ne notEqualToValue(Object value) { |
||||
return createNe().notEqualToValue(value); |
||||
} |
||||
|
||||
private Ne createNe() { |
||||
return usesFieldRef() ? Ne.valueOf(fieldReference) : Ne.valueOf(expression); |
||||
} |
||||
|
||||
private boolean usesFieldRef() { |
||||
return fieldReference != null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $cmp}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Cmp extends AbstractAggregationExpression { |
||||
|
||||
private Cmp(List<?> value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$cmp"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Cmp}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Cmp valueOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Cmp(asFields(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Cmp}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Cmp valueOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Cmp(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Cmp} with all previously added arguments appending the given one. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Cmp compareTo(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Cmp(append(Fields.field(fieldReference))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Cmp} with all previously added arguments appending the given one. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Cmp compareTo(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Cmp(append(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Cmp} with all previously added arguments appending the given one. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Cmp compareToValue(Object value) { |
||||
|
||||
Assert.notNull(value, "Value must not be null!"); |
||||
return new Cmp(append(value)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $eq}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Eq extends AbstractAggregationExpression { |
||||
|
||||
private Eq(List<?> value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$eq"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Eq}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Eq valueOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Eq(asFields(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Eq}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Eq valueOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Eq(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Eq} with all previously added arguments appending the given one. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Eq equalTo(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Eq(append(Fields.field(fieldReference))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Eq} with all previously added arguments appending the given one. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Eq equalTo(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Eq(append(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Eq} with all previously added arguments appending the given one. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Eq equalToValue(Object value) { |
||||
|
||||
Assert.notNull(value, "Value must not be null!"); |
||||
return new Eq(append(value)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $gt}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Gt extends AbstractAggregationExpression { |
||||
|
||||
private Gt(List<?> value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$gt"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Gt}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Gt valueOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Gt(asFields(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Gt}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Gt valueOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Gt(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Gt} with all previously added arguments appending the given one. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Gt greaterThan(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Gt(append(Fields.field(fieldReference))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Gt} with all previously added arguments appending the given one. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Gt greaterThan(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Gt(append(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Gt} with all previously added arguments appending the given one. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Gt greaterThanValue(Object value) { |
||||
|
||||
Assert.notNull(value, "Value must not be null!"); |
||||
return new Gt(append(value)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $lt}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Lt extends AbstractAggregationExpression { |
||||
|
||||
private Lt(List<?> value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$lt"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Lt}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Lt valueOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Lt(asFields(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Lt}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Lt valueOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Lt(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Lt} with all previously added arguments appending the given one. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Lt lessThan(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Lt(append(Fields.field(fieldReference))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Lt} with all previously added arguments appending the given one. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Lt lessThan(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Lt(append(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Lt} with all previously added arguments appending the given one. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Lt lessThanValue(Object value) { |
||||
|
||||
Assert.notNull(value, "Value must not be null!"); |
||||
return new Lt(append(value)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $gte}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Gte extends AbstractAggregationExpression { |
||||
|
||||
private Gte(List<?> value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$gte"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Gte}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Gte valueOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Gte(asFields(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Gte}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Gte valueOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Gte(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Gte} with all previously added arguments appending the given one. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Gte greaterThanEqualTo(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Gte(append(Fields.field(fieldReference))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Gte} with all previously added arguments appending the given one. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Gte greaterThanEqualTo(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Gte(append(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Gte} with all previously added arguments appending the given one. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Gte greaterThanEqualToValue(Object value) { |
||||
|
||||
Assert.notNull(value, "Value must not be null!"); |
||||
return new Gte(append(value)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $lte}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Lte extends AbstractAggregationExpression { |
||||
|
||||
private Lte(List<?> value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$lte"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Lte}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Lte valueOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Lte(asFields(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Lte}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Lte valueOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Lte(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Lte} with all previously added arguments appending the given one. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Lte lessThanEqualTo(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Lte(append(Fields.field(fieldReference))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Lte} with all previously added arguments appending the given one. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Lte lessThanEqualTo(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Lte(append(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Lte} with all previously added arguments appending the given one. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Lte lessThanEqualToValue(Object value) { |
||||
|
||||
Assert.notNull(value, "Value must not be null!"); |
||||
return new Lte(append(value)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $ne}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Ne extends AbstractAggregationExpression { |
||||
|
||||
private Ne(List<?> value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$ne"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Ne}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Ne valueOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Ne(asFields(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Ne}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Ne valueOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Ne(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Ne} with all previously added arguments appending the given one. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Ne notEqualTo(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Ne(append(Fields.field(fieldReference))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Ne} with all previously added arguments appending the given one. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Ne notEqualTo(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Ne(append(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Eq} with all previously added arguments appending the given one. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public Ne notEqualToValue(Object value) { |
||||
|
||||
Assert.notNull(value, "Value must not be null!"); |
||||
return new Ne(append(value)); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,973 @@
@@ -0,0 +1,973 @@
|
||||
/* |
||||
* Copyright 2016. the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.mongodb.core.aggregation; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
import org.bson.Document; |
||||
import org.springframework.dao.InvalidDataAccessApiUsageException; |
||||
import org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Cond.OtherwiseBuilder; |
||||
import org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Cond.ThenBuilder; |
||||
import org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Switch.CaseOperator; |
||||
import org.springframework.data.mongodb.core.query.CriteriaDefinition; |
||||
import org.springframework.util.Assert; |
||||
import org.springframework.util.ClassUtils; |
||||
|
||||
/** |
||||
* Gateway to {@literal conditional expressions} that evaluate their argument expressions as booleans to a value. |
||||
* |
||||
* @author Mark Paluch |
||||
*/ |
||||
public class ConditionalOperators { |
||||
|
||||
/** |
||||
* Take the field referenced by given {@literal fieldReference}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static ConditionalOperatorFactory when(String fieldReference) { |
||||
return new ConditionalOperatorFactory(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Take the value resulting from the given {@literal expression}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static ConditionalOperatorFactory when(AggregationExpression expression) { |
||||
return new ConditionalOperatorFactory(expression); |
||||
} |
||||
|
||||
/** |
||||
* Take the value resulting from the given {@literal criteriaDefinition}. |
||||
* |
||||
* @param criteriaDefinition must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static ConditionalOperatorFactory when(CriteriaDefinition criteriaDefinition) { |
||||
return new ConditionalOperatorFactory(criteriaDefinition); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that evaluates an expression and returns the value of the expression if |
||||
* the expression evaluates to a non-null value. If the expression evaluates to a {@literal null} value, including |
||||
* instances of undefined values or missing fields, returns the value of the replacement expression. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static IfNull.ThenBuilder ifNull(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return IfNull.ifNull(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that evaluates an expression and returns the value of the expression if |
||||
* the expression evaluates to a non-null value. If the expression evaluates to a {@literal null} value, including |
||||
* instances of undefined values or missing fields, returns the value of the replacement expression. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static IfNull.ThenBuilder ifNull(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return IfNull.ifNull(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpression} that evaluates a series of {@link CaseOperator} expressions. When it |
||||
* finds an expression which evaluates to {@literal true}, {@code $switch} executes a specified expression and breaks |
||||
* out of the control flow. |
||||
* |
||||
* @param conditions must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Switch switchCases(CaseOperator... conditions) { |
||||
return Switch.switchCases(conditions); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpression} that evaluates a series of {@link CaseOperator} expressions. When it |
||||
* finds an expression which evaluates to {@literal true}, {@code $switch} executes a specified expression and breaks |
||||
* out of the control flow. |
||||
* |
||||
* @param conditions must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Switch switchCases(List<CaseOperator> conditions) { |
||||
return Switch.switchCases(conditions); |
||||
} |
||||
|
||||
public static class ConditionalOperatorFactory { |
||||
|
||||
private final String fieldReference; |
||||
private final AggregationExpression expression; |
||||
private final CriteriaDefinition criteriaDefinition; |
||||
|
||||
/** |
||||
* Creates new {@link ConditionalOperatorFactory} for given {@literal fieldReference}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
*/ |
||||
public ConditionalOperatorFactory(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
|
||||
this.fieldReference = fieldReference; |
||||
this.expression = null; |
||||
this.criteriaDefinition = null; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link ConditionalOperatorFactory} for given {@link AggregationExpression}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
*/ |
||||
public ConditionalOperatorFactory(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
|
||||
this.fieldReference = null; |
||||
this.expression = expression; |
||||
this.criteriaDefinition = null; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link ConditionalOperatorFactory} for given {@link CriteriaDefinition}. |
||||
* |
||||
* @param criteriaDefinition must not be {@literal null}. |
||||
*/ |
||||
public ConditionalOperatorFactory(CriteriaDefinition criteriaDefinition) { |
||||
|
||||
Assert.notNull(criteriaDefinition, "CriteriaDefinition must not be null!"); |
||||
|
||||
this.fieldReference = null; |
||||
this.expression = null; |
||||
this.criteriaDefinition = criteriaDefinition; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpression} that evaluates a boolean expression to return one of the two specified |
||||
* return expressions. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public OtherwiseBuilder then(Object value) { |
||||
|
||||
Assert.notNull(value, "Value must not be null!"); |
||||
return createThenBuilder().then(value); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that evaluates a boolean expression to return one of the two specified |
||||
* return expressions. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public OtherwiseBuilder thenValueOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return createThenBuilder().then(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that evaluates a boolean expression to return one of the two specified |
||||
* return expressions. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public OtherwiseBuilder thenValueOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return createThenBuilder().then(fieldReference); |
||||
} |
||||
|
||||
private ThenBuilder createThenBuilder() { |
||||
|
||||
if (usesFieldRef()) { |
||||
return Cond.newBuilder().when(fieldReference); |
||||
} |
||||
|
||||
return usesCriteriaDefinition() ? Cond.newBuilder().when(criteriaDefinition) : Cond.newBuilder().when(expression); |
||||
} |
||||
|
||||
private boolean usesFieldRef() { |
||||
return this.fieldReference != null; |
||||
} |
||||
|
||||
private boolean usesCriteriaDefinition() { |
||||
return this.criteriaDefinition != null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Encapsulates the aggregation framework {@code $ifNull} operator. Replacement values can be either {@link Field |
||||
* field references}, {@link AggregationExpression expressions}, values of simple MongoDB types or values that can be |
||||
* converted to a simple MongoDB type. |
||||
* |
||||
* @see http://docs.mongodb.com/manual/reference/operator/aggregation/ifNull/
|
||||
* @author Mark Paluch |
||||
*/ |
||||
public static class IfNull implements AggregationExpression { |
||||
|
||||
private final Object condition; |
||||
private final Object value; |
||||
|
||||
private IfNull(Object condition, Object value) { |
||||
|
||||
this.condition = condition; |
||||
this.value = value; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link IfNull}. |
||||
* |
||||
* @param fieldReference the field to check for a {@literal null} value, field reference must not be {@literal null} |
||||
* . |
||||
* @return |
||||
*/ |
||||
public static ThenBuilder ifNull(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new IfNullOperatorBuilder().ifNull(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link IfNull}. |
||||
* |
||||
* @param expression the expression to check for a {@literal null} value, field reference must not be |
||||
* {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static ThenBuilder ifNull(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new IfNullOperatorBuilder().ifNull(expression); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpression#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) |
||||
*/ |
||||
@Override |
||||
public Document toDocument(AggregationOperationContext context) { |
||||
|
||||
List<Object> list = new ArrayList<Object>(); |
||||
|
||||
if (condition instanceof Field) { |
||||
list.add(context.getReference((Field) condition).toString()); |
||||
} else if (condition instanceof AggregationExpression) { |
||||
list.add(((AggregationExpression) condition).toDocument(context)); |
||||
} else { |
||||
list.add(condition); |
||||
} |
||||
|
||||
list.add(resolve(value, context)); |
||||
|
||||
return new Document("$ifNull", list); |
||||
} |
||||
|
||||
private Object resolve(Object value, AggregationOperationContext context) { |
||||
|
||||
if (value instanceof Field) { |
||||
return context.getReference((Field) value).toString(); |
||||
} else if (value instanceof AggregationExpression) { |
||||
return ((AggregationExpression) value).toDocument(context); |
||||
} else if (value instanceof Document) { |
||||
return value; |
||||
} |
||||
|
||||
return context.getMappedObject(new Document("$set", value)).get("$set"); |
||||
} |
||||
|
||||
/** |
||||
* @author Mark Paluch |
||||
*/ |
||||
public static interface IfNullBuilder { |
||||
|
||||
/** |
||||
* @param fieldReference the field to check for a {@literal null} value, field reference must not be |
||||
* {@literal null}. |
||||
* @return the {@link ThenBuilder} |
||||
*/ |
||||
ThenBuilder ifNull(String fieldReference); |
||||
|
||||
/** |
||||
* @param expression the expression to check for a {@literal null} value, field name must not be {@literal null} |
||||
* or empty. |
||||
* @return the {@link ThenBuilder} |
||||
*/ |
||||
ThenBuilder ifNull(AggregationExpression expression); |
||||
} |
||||
|
||||
/** |
||||
* @author Mark Paluch |
||||
*/ |
||||
public static interface ThenBuilder { |
||||
|
||||
/** |
||||
* @param value the value to be used if the {@code $ifNull} condition evaluates {@literal true}. Can be a |
||||
* {@link Document}, a value that is supported by MongoDB or a value that can be converted to a MongoDB |
||||
* representation but must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
IfNull then(Object value); |
||||
|
||||
/** |
||||
* @param fieldReference the field holding the replacement value, must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
IfNull thenValueOf(String fieldReference); |
||||
|
||||
/** |
||||
* @param expression the expression yielding to the replacement value, must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public IfNull thenValueOf(AggregationExpression expression); |
||||
} |
||||
|
||||
/** |
||||
* Builder for fluent {@link IfNullOperator} creation. |
||||
* |
||||
* @author Mark Paluch |
||||
*/ |
||||
static final class IfNullOperatorBuilder implements IfNullBuilder, ThenBuilder { |
||||
|
||||
private Object condition; |
||||
|
||||
private IfNullOperatorBuilder() {} |
||||
|
||||
/** |
||||
* Creates a new builder for {@link IfNullOperator}. |
||||
* |
||||
* @return never {@literal null}. |
||||
*/ |
||||
public static IfNullOperatorBuilder newBuilder() { |
||||
return new IfNullOperatorBuilder(); |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.IfNull.IfNullBuilder#ifNull(java.lang.String) |
||||
*/ |
||||
public ThenBuilder ifNull(String fieldReference) { |
||||
|
||||
Assert.hasText(fieldReference, "FieldReference name must not be null or empty!"); |
||||
this.condition = Fields.field(fieldReference); |
||||
return this; |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.IfNull.IfNullBuilder#ifNull(org.springframework.data.mongodb.core.aggregation.AggregationExpression) |
||||
*/ |
||||
@Override |
||||
public ThenBuilder ifNull(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "AggregationExpression name must not be null or empty!"); |
||||
this.condition = expression; |
||||
return this; |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.IfNull.ThenBuilder#then(java.lang.Object) |
||||
*/ |
||||
public IfNull then(Object value) { |
||||
return new IfNull(condition, value); |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.IfNull.ThenBuilder#thenValueOf(java.lang.String) |
||||
*/ |
||||
public IfNull thenValueOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new IfNull(condition, Fields.field(fieldReference)); |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.IfNull.ThenBuilder#thenValueOf(org.springframework.data.mongodb.core.aggregation.AggregationExpression) |
||||
*/ |
||||
public IfNull thenValueOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new IfNull(condition, expression); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $switch}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Switch extends AbstractAggregationExpression { |
||||
|
||||
private Switch(java.util.Map<String, Object> values) { |
||||
super(values); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$switch"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Switch}. |
||||
* |
||||
* @param conditions must not be {@literal null}. |
||||
*/ |
||||
public static Switch switchCases(CaseOperator... conditions) { |
||||
|
||||
Assert.notNull(conditions, "Conditions must not be null!"); |
||||
return switchCases(Arrays.asList(conditions)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Switch}. |
||||
* |
||||
* @param conditions must not be {@literal null}. |
||||
*/ |
||||
public static Switch switchCases(List<CaseOperator> conditions) { |
||||
|
||||
Assert.notNull(conditions, "Conditions must not be null!"); |
||||
return new Switch(Collections.<String, Object> singletonMap("branches", new ArrayList<CaseOperator>(conditions))); |
||||
} |
||||
|
||||
public Switch defaultTo(Object value) { |
||||
return new Switch(append("default", value)); |
||||
} |
||||
|
||||
/** |
||||
* Encapsulates the aggregation framework case document inside a {@code $switch}-operation. |
||||
*/ |
||||
public static class CaseOperator implements AggregationExpression { |
||||
|
||||
private final AggregationExpression when; |
||||
private final Object then; |
||||
|
||||
private CaseOperator(AggregationExpression when, Object then) { |
||||
|
||||
this.when = when; |
||||
this.then = then; |
||||
} |
||||
|
||||
public static ThenBuilder when(final AggregationExpression condition) { |
||||
|
||||
Assert.notNull(condition, "Condition must not be null!"); |
||||
|
||||
return new ThenBuilder() { |
||||
|
||||
@Override |
||||
public CaseOperator then(Object value) { |
||||
|
||||
Assert.notNull(value, "Value must not be null!"); |
||||
return new CaseOperator(condition, value); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpression#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) |
||||
*/ |
||||
@Override |
||||
public Document toDocument(AggregationOperationContext context) { |
||||
|
||||
Document dbo = new Document("case", when.toDocument(context)); |
||||
|
||||
if (then instanceof AggregationExpression) { |
||||
dbo.put("then", ((AggregationExpression) then).toDocument(context)); |
||||
} else if (then instanceof Field) { |
||||
dbo.put("then", context.getReference((Field) then).toString()); |
||||
} else { |
||||
dbo.put("then", then); |
||||
} |
||||
|
||||
return dbo; |
||||
} |
||||
|
||||
/** |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public interface ThenBuilder { |
||||
|
||||
/** |
||||
* Set the then {@literal value}. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
CaseOperator then(Object value); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Encapsulates the aggregation framework {@code $cond} operator. A {@link Cond} allows nested conditions |
||||
* {@code if-then[if-then-else]-else} using {@link Field}, {@link CriteriaDefinition}, {@link AggregationExpression} |
||||
* or a {@link Document custom} condition. Replacement values can be either {@link Field field references}, |
||||
* {@link AggregationExpression expressions}, values of simple MongoDB types or values that can be converted to a |
||||
* simple MongoDB type. |
||||
* |
||||
* @see http://docs.mongodb.com/manual/reference/operator/aggregation/cond/
|
||||
* @author Mark Paluch |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Cond implements AggregationExpression { |
||||
|
||||
private final Object condition; |
||||
private final Object thenValue; |
||||
private final Object otherwiseValue; |
||||
|
||||
/** |
||||
* Creates a new {@link Cond} for a given {@link Field} and {@code then}/{@code otherwise} values. |
||||
* |
||||
* @param condition must not be {@literal null}. |
||||
* @param thenValue must not be {@literal null}. |
||||
* @param otherwiseValue must not be {@literal null}. |
||||
*/ |
||||
private Cond(Field condition, Object thenValue, Object otherwiseValue) { |
||||
this((Object) condition, thenValue, otherwiseValue); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@link Cond} for a given {@link CriteriaDefinition} and {@code then}/{@code otherwise} values. |
||||
* |
||||
* @param condition must not be {@literal null}. |
||||
* @param thenValue must not be {@literal null}. |
||||
* @param otherwiseValue must not be {@literal null}. |
||||
*/ |
||||
private Cond(CriteriaDefinition condition, Object thenValue, Object otherwiseValue) { |
||||
this((Object) condition, thenValue, otherwiseValue); |
||||
} |
||||
|
||||
private Cond(Object condition, Object thenValue, Object otherwiseValue) { |
||||
|
||||
Assert.notNull(condition, "Condition must not be null!"); |
||||
Assert.notNull(thenValue, "Then value must not be null!"); |
||||
Assert.notNull(otherwiseValue, "Otherwise value must not be null!"); |
||||
|
||||
assertNotBuilder(condition, "Condition"); |
||||
assertNotBuilder(thenValue, "Then value"); |
||||
assertNotBuilder(otherwiseValue, "Otherwise value"); |
||||
|
||||
this.condition = condition; |
||||
this.thenValue = thenValue; |
||||
this.otherwiseValue = otherwiseValue; |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpression#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) |
||||
*/ |
||||
@Override |
||||
public Document toDocument(AggregationOperationContext context) { |
||||
|
||||
Document condObject = new Document(); |
||||
|
||||
condObject.append("if", resolveCriteria(context, condition)); |
||||
condObject.append("then", resolveValue(context, thenValue)); |
||||
condObject.append("else", resolveValue(context, otherwiseValue)); |
||||
|
||||
return new Document("$cond", condObject); |
||||
} |
||||
|
||||
private Object resolveValue(AggregationOperationContext context, Object value) { |
||||
|
||||
if (value instanceof Document || value instanceof Field) { |
||||
return resolve(context, value); |
||||
} |
||||
|
||||
if (value instanceof AggregationExpression) { |
||||
return ((AggregationExpression) value).toDocument(context); |
||||
} |
||||
|
||||
return context.getMappedObject(new Document("$set", value)).get("$set"); |
||||
} |
||||
|
||||
private Object resolveCriteria(AggregationOperationContext context, Object value) { |
||||
|
||||
if (value instanceof Document || value instanceof Field) { |
||||
return resolve(context, value); |
||||
} |
||||
|
||||
if (value instanceof AggregationExpression) { |
||||
return ((AggregationExpression) value).toDocument(context); |
||||
} |
||||
|
||||
if (value instanceof CriteriaDefinition) { |
||||
|
||||
Document mappedObject = context.getMappedObject(((CriteriaDefinition) value).getCriteriaObject()); |
||||
List<Object> clauses = new ArrayList<Object>(); |
||||
|
||||
clauses.addAll(getClauses(context, mappedObject)); |
||||
|
||||
return clauses.size() == 1 ? clauses.get(0) : clauses; |
||||
} |
||||
|
||||
throw new InvalidDataAccessApiUsageException( |
||||
String.format("Invalid value in condition. Supported: Document, Field references, Criteria, got: %s", value)); |
||||
} |
||||
|
||||
private List<Object> getClauses(AggregationOperationContext context, Document mappedObject) { |
||||
|
||||
List<Object> clauses = new ArrayList<Object>(); |
||||
|
||||
for (String key : mappedObject.keySet()) { |
||||
|
||||
Object predicate = mappedObject.get(key); |
||||
clauses.addAll(getClauses(context, key, predicate)); |
||||
} |
||||
|
||||
return clauses; |
||||
} |
||||
|
||||
private List<Object> getClauses(AggregationOperationContext context, String key, Object predicate) { |
||||
|
||||
List<Object> clauses = new ArrayList<Object>(); |
||||
|
||||
if (predicate instanceof List) { |
||||
|
||||
List<Object> args = new ArrayList<Object>(); |
||||
for (Object clause : (List<?>) predicate) { |
||||
if (clause instanceof Document) { |
||||
args.addAll(getClauses(context, (Document) clause)); |
||||
} |
||||
} |
||||
|
||||
clauses.add(new Document(key, args)); |
||||
|
||||
} else if (predicate instanceof Document) { |
||||
|
||||
Document nested = (Document) predicate; |
||||
|
||||
for (String s : nested.keySet()) { |
||||
|
||||
if (!isKeyword(s)) { |
||||
continue; |
||||
} |
||||
|
||||
List<Object> args = new ArrayList<Object>(); |
||||
args.add("$" + key); |
||||
args.add(nested.get(s)); |
||||
clauses.add(new Document(s, args)); |
||||
} |
||||
|
||||
} else if (!isKeyword(key)) { |
||||
|
||||
List<Object> args = new ArrayList<Object>(); |
||||
args.add("$" + key); |
||||
args.add(predicate); |
||||
clauses.add(new Document("$eq", args)); |
||||
} |
||||
|
||||
return clauses; |
||||
} |
||||
|
||||
/** |
||||
* Returns whether the given {@link String} is a MongoDB keyword. |
||||
* |
||||
* @param candidate |
||||
* @return |
||||
*/ |
||||
private boolean isKeyword(String candidate) { |
||||
return candidate.startsWith("$"); |
||||
} |
||||
|
||||
private Object resolve(AggregationOperationContext context, Object value) { |
||||
|
||||
if (value instanceof Document) { |
||||
return context.getMappedObject((Document) value); |
||||
} |
||||
|
||||
return context.getReference((Field) value).toString(); |
||||
} |
||||
|
||||
private void assertNotBuilder(Object toCheck, String name) { |
||||
Assert.isTrue(!ClassUtils.isAssignableValue(ConditionalExpressionBuilder.class, toCheck), |
||||
String.format("%s must not be of type %s", name, ConditionalExpressionBuilder.class.getSimpleName())); |
||||
} |
||||
|
||||
/** |
||||
* Get a builder that allows fluent creation of {@link Cond}. |
||||
* |
||||
* @return never {@literal null}. |
||||
*/ |
||||
public static WhenBuilder newBuilder() { |
||||
return ConditionalExpressionBuilder.newBuilder(); |
||||
} |
||||
|
||||
/** |
||||
* Start creating new {@link Cond} by providing the boolean expression used in {@code if}. |
||||
* |
||||
* @param booleanExpression must not be {@literal null}. |
||||
* @return never {@literal null}. |
||||
*/ |
||||
public static ThenBuilder when(Document booleanExpression) { |
||||
return ConditionalExpressionBuilder.newBuilder().when(booleanExpression); |
||||
} |
||||
|
||||
/** |
||||
* Start creating new {@link Cond} by providing the {@link AggregationExpression} used in {@code if}. |
||||
* |
||||
* @param expression expression that yields in a boolean result, must not be {@literal null}. |
||||
* @return never {@literal null}. |
||||
*/ |
||||
public static ThenBuilder when(AggregationExpression expression) { |
||||
return ConditionalExpressionBuilder.newBuilder().when(expression); |
||||
} |
||||
|
||||
/** |
||||
* Start creating new {@link Cond} by providing the field reference used in {@code if}. |
||||
* |
||||
* @param booleanField name of a field holding a boolean value, must not be {@literal null}. |
||||
* @return never {@literal null}. |
||||
*/ |
||||
public static ThenBuilder when(String booleanField) { |
||||
return ConditionalExpressionBuilder.newBuilder().when(booleanField); |
||||
} |
||||
|
||||
/** |
||||
* Start creating new {@link Cond} by providing the {@link CriteriaDefinition} used in {@code if}. |
||||
* |
||||
* @param criteria criteria to evaluate, must not be {@literal null}. |
||||
* @return the {@link ThenBuilder} |
||||
*/ |
||||
public static ThenBuilder when(CriteriaDefinition criteria) { |
||||
return ConditionalExpressionBuilder.newBuilder().when(criteria); |
||||
} |
||||
|
||||
/** |
||||
* @author Mark Paluch |
||||
*/ |
||||
public static interface WhenBuilder { |
||||
|
||||
/** |
||||
* @param booleanExpression expression that yields in a boolean result, must not be {@literal null}. |
||||
* @return the {@link ThenBuilder} |
||||
*/ |
||||
ThenBuilder when(Document booleanExpression); |
||||
|
||||
/** |
||||
* @param expression expression that yields in a boolean result, must not be {@literal null}. |
||||
* @return the {@link ThenBuilder} |
||||
*/ |
||||
ThenBuilder when(AggregationExpression expression); |
||||
|
||||
/** |
||||
* @param booleanField name of a field holding a boolean value, must not be {@literal null}. |
||||
* @return the {@link ThenBuilder} |
||||
*/ |
||||
ThenBuilder when(String booleanField); |
||||
|
||||
/** |
||||
* @param criteria criteria to evaluate, must not be {@literal null}. |
||||
* @return the {@link ThenBuilder} |
||||
*/ |
||||
ThenBuilder when(CriteriaDefinition criteria); |
||||
} |
||||
|
||||
/** |
||||
* @author Mark Paluch |
||||
*/ |
||||
public static interface ThenBuilder { |
||||
|
||||
/** |
||||
* @param value the value to be used if the condition evaluates {@literal true}. Can be a {@link Document}, a |
||||
* value that is supported by MongoDB or a value that can be converted to a MongoDB representation but |
||||
* must not be {@literal null}. |
||||
* @return the {@link OtherwiseBuilder} |
||||
*/ |
||||
OtherwiseBuilder then(Object value); |
||||
|
||||
/** |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return the {@link OtherwiseBuilder} |
||||
*/ |
||||
OtherwiseBuilder thenValueOf(String fieldReference); |
||||
|
||||
/** |
||||
* @param expression must not be {@literal null}. |
||||
* @return the {@link OtherwiseBuilder} |
||||
*/ |
||||
OtherwiseBuilder thenValueOf(AggregationExpression expression); |
||||
} |
||||
|
||||
/** |
||||
* @author Mark Paluch |
||||
*/ |
||||
public static interface OtherwiseBuilder { |
||||
|
||||
/** |
||||
* @param value the value to be used if the condition evaluates {@literal false}. Can be a {@link Document}, a |
||||
* value that is supported by MongoDB or a value that can be converted to a MongoDB representation but |
||||
* must not be {@literal null}. |
||||
* @return the {@link Cond} |
||||
*/ |
||||
Cond otherwise(Object value); |
||||
|
||||
/** |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return the {@link Cond} |
||||
*/ |
||||
Cond otherwiseValueOf(String fieldReference); |
||||
|
||||
/** |
||||
* @param expression must not be {@literal null}. |
||||
* @return the {@link Cond} |
||||
*/ |
||||
Cond otherwiseValueOf(AggregationExpression expression); |
||||
} |
||||
|
||||
/** |
||||
* Builder for fluent {@link Cond} creation. |
||||
* |
||||
* @author Mark Paluch |
||||
*/ |
||||
static class ConditionalExpressionBuilder implements WhenBuilder, ThenBuilder, OtherwiseBuilder { |
||||
|
||||
private Object condition; |
||||
private Object thenValue; |
||||
|
||||
private ConditionalExpressionBuilder() {} |
||||
|
||||
/** |
||||
* Creates a new builder for {@link Cond}. |
||||
* |
||||
* @return never {@literal null}. |
||||
*/ |
||||
public static ConditionalExpressionBuilder newBuilder() { |
||||
return new ConditionalExpressionBuilder(); |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.Cond.WhenBuilder#when(org.bson.Document) |
||||
*/ |
||||
@Override |
||||
public ConditionalExpressionBuilder when(Document booleanExpression) { |
||||
|
||||
Assert.notNull(booleanExpression, "'Boolean expression' must not be null!"); |
||||
|
||||
this.condition = booleanExpression; |
||||
return this; |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.Cond.WhenBuilder#when(org.springframework.data.mongodb.core.query.CriteriaDefinition) |
||||
*/ |
||||
@Override |
||||
public ThenBuilder when(CriteriaDefinition criteria) { |
||||
|
||||
Assert.notNull(criteria, "Criteria must not be null!"); |
||||
this.condition = criteria; |
||||
return this; |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.Cond.WhenBuilder#when(org.springframework.data.mongodb.core.aggregation.AggregationExpression) |
||||
*/ |
||||
@Override |
||||
public ThenBuilder when(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "AggregationExpression field must not be null!"); |
||||
this.condition = expression; |
||||
return this; |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.Cond.WhenBuilder#when(java.lang.String) |
||||
*/ |
||||
@Override |
||||
public ThenBuilder when(String booleanField) { |
||||
|
||||
Assert.hasText(booleanField, "Boolean field name must not be null or empty!"); |
||||
this.condition = Fields.field(booleanField); |
||||
return this; |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.Cond.ThenBuilder#then(java.lang.Object) |
||||
*/ |
||||
@Override |
||||
public OtherwiseBuilder then(Object thenValue) { |
||||
|
||||
Assert.notNull(thenValue, "Then-value must not be null!"); |
||||
this.thenValue = thenValue; |
||||
return this; |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.Cond.ThenBuilder#thenValueOf(java.lang.String) |
||||
*/ |
||||
@Override |
||||
public OtherwiseBuilder thenValueOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
this.thenValue = Fields.field(fieldReference); |
||||
return this; |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.Cond.ThenBuilder#thenValueOf(org.springframework.data.mongodb.core.aggregation.AggregationExpression) |
||||
*/ |
||||
@Override |
||||
public OtherwiseBuilder thenValueOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "AggregationExpression must not be null!"); |
||||
this.thenValue = expression; |
||||
return this; |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.Cond.OtherwiseBuilder#otherwise(java.lang.Object) |
||||
*/ |
||||
@Override |
||||
public Cond otherwise(Object otherwiseValue) { |
||||
|
||||
Assert.notNull(otherwiseValue, "Value must not be null!"); |
||||
return new Cond(condition, thenValue, otherwiseValue); |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.Cond.OtherwiseBuilder#otherwiseValueOf(java.lang.String) |
||||
*/ |
||||
@Override |
||||
public Cond otherwiseValueOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Cond(condition, thenValue, Fields.field(fieldReference)); |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpressions.Cond.OtherwiseBuilder#otherwiseValueOf(org.springframework.data.mongodb.core.aggregation.AggregationExpression) |
||||
*/ |
||||
@Override |
||||
public Cond otherwiseValueOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "AggregationExpression must not be null!"); |
||||
return new Cond(condition, thenValue, expression); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
/* |
||||
* Copyright 2016. the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.mongodb.core.aggregation; |
||||
|
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* Gateway to {@literal data type} expressions. |
||||
* |
||||
* @author Christoph Strobl |
||||
* @since 1.10 |
||||
* @soundtrack Clawfinger - Catch Me |
||||
*/ |
||||
public class DataTypeOperators { |
||||
|
||||
/** |
||||
* Return the BSON data type of the given {@literal field}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Type typeOf(String fieldReference) { |
||||
return Type.typeOf(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $type}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Type extends AbstractAggregationExpression { |
||||
|
||||
private Type(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$type"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Type}. |
||||
* |
||||
* @param field must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Type typeOf(String field) { |
||||
|
||||
Assert.notNull(field, "Field must not be null!"); |
||||
return new Type(Fields.field(field)); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,838 @@
@@ -0,0 +1,838 @@
|
||||
/* |
||||
* Copyright 2016. the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.mongodb.core.aggregation; |
||||
|
||||
import java.util.LinkedHashMap; |
||||
|
||||
import org.springframework.data.mongodb.core.aggregation.ArithmeticOperators.ArithmeticOperatorFactory; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* Gateway to {@literal Date} aggregation operations. |
||||
* |
||||
* @author Christoph Strobl |
||||
* @since 1.10 |
||||
*/ |
||||
public class DateOperators { |
||||
|
||||
/** |
||||
* Take the date referenced by given {@literal fieldReference}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static DateOperatorFactory dateOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new DateOperatorFactory(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Take the date resulting from the given {@link AggregationExpression}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static DateOperatorFactory dateOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new DateOperatorFactory(expression); |
||||
} |
||||
|
||||
/** |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class DateOperatorFactory { |
||||
|
||||
private final String fieldReference; |
||||
private final AggregationExpression expression; |
||||
|
||||
/** |
||||
* Creates new {@link ArithmeticOperatorFactory} for given {@literal fieldReference}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
*/ |
||||
public DateOperatorFactory(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
this.fieldReference = fieldReference; |
||||
this.expression = null; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link ArithmeticOperatorFactory} for given {@link AggregationExpression}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
*/ |
||||
public DateOperatorFactory(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
this.fieldReference = null; |
||||
this.expression = expression; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that returns the day of the year for a date as a number between 1 and |
||||
* 366. |
||||
* |
||||
* @return |
||||
*/ |
||||
public DayOfYear dayOfYear() { |
||||
return usesFieldRef() ? DayOfYear.dayOfYear(fieldReference) : DayOfYear.dayOfYear(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that returns the day of the month for a date as a number between 1 and |
||||
* 31. |
||||
* |
||||
* @return |
||||
*/ |
||||
public DayOfMonth dayOfMonth() { |
||||
return usesFieldRef() ? DayOfMonth.dayOfMonth(fieldReference) : DayOfMonth.dayOfMonth(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that returns the day of the week for a date as a number between 1 |
||||
* (Sunday) and 7 (Saturday). |
||||
* |
||||
* @return |
||||
*/ |
||||
public DayOfWeek dayOfWeek() { |
||||
return usesFieldRef() ? DayOfWeek.dayOfWeek(fieldReference) : DayOfWeek.dayOfWeek(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that returns the year portion of a date. |
||||
* |
||||
* @return |
||||
*/ |
||||
public Year year() { |
||||
return usesFieldRef() ? Year.yearOf(fieldReference) : Year.yearOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that returns the month of a date as a number between 1 and 12. |
||||
* |
||||
* @return |
||||
*/ |
||||
public Month month() { |
||||
return usesFieldRef() ? Month.monthOf(fieldReference) : Month.monthOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that returns the week of the year for a date as a number between 0 and |
||||
* 53. |
||||
* |
||||
* @return |
||||
*/ |
||||
public Week week() { |
||||
return usesFieldRef() ? Week.weekOf(fieldReference) : Week.weekOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that returns the hour portion of a date as a number between 0 and 23. |
||||
* |
||||
* @return |
||||
*/ |
||||
public Hour hour() { |
||||
return usesFieldRef() ? Hour.hourOf(fieldReference) : Hour.hourOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that returns the minute portion of a date as a number between 0 and |
||||
* 59. |
||||
* |
||||
* @return |
||||
*/ |
||||
public Minute minute() { |
||||
return usesFieldRef() ? Minute.minuteOf(fieldReference) : Minute.minuteOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that returns the second portion of a date as a number between 0 and |
||||
* 59, but can be 60 to account for leap seconds. |
||||
* |
||||
* @return |
||||
*/ |
||||
public Second second() { |
||||
return usesFieldRef() ? Second.secondOf(fieldReference) : Second.secondOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that returns the millisecond portion of a date as an integer between 0 |
||||
* and 999. |
||||
* |
||||
* @return |
||||
*/ |
||||
public Millisecond millisecond() { |
||||
return usesFieldRef() ? Millisecond.millisecondOf(fieldReference) : Millisecond.millisecondOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that converts a date object to a string according to a user-specified |
||||
* {@literal format}. |
||||
* |
||||
* @param format must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public DateToString toString(String format) { |
||||
return (usesFieldRef() ? DateToString.dateOf(fieldReference) : DateToString.dateOf(expression)).toString(format); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that returns the weekday number in ISO 8601 format, ranging from 1 |
||||
* (for Monday) to 7 (for Sunday). |
||||
* |
||||
* @return |
||||
*/ |
||||
public IsoDayOfWeek isoDayOfWeek() { |
||||
return usesFieldRef() ? IsoDayOfWeek.isoDayOfWeek(fieldReference) : IsoDayOfWeek.isoDayOfWeek(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that returns the week number in ISO 8601 format, ranging from 1 to 53. |
||||
* |
||||
* @return |
||||
*/ |
||||
public IsoWeek isoWeek() { |
||||
return usesFieldRef() ? IsoWeek.isoWeekOf(fieldReference) : IsoWeek.isoWeekOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that returns the year number in ISO 8601 format. |
||||
* |
||||
* @return |
||||
*/ |
||||
public IsoWeekYear isoWeekYear() { |
||||
return usesFieldRef() ? IsoWeekYear.isoWeekYearOf(fieldReference) : IsoWeekYear.isoWeekYearOf(expression); |
||||
} |
||||
|
||||
private boolean usesFieldRef() { |
||||
return fieldReference != null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $dayOfYear}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class DayOfYear extends AbstractAggregationExpression { |
||||
|
||||
private DayOfYear(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$dayOfYear"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link DayOfYear}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static DayOfYear dayOfYear(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new DayOfYear(Fields.field(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link DayOfYear}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static DayOfYear dayOfYear(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new DayOfYear(expression); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $dayOfMonth}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class DayOfMonth extends AbstractAggregationExpression { |
||||
|
||||
private DayOfMonth(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$dayOfMonth"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link DayOfMonth}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static DayOfMonth dayOfMonth(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new DayOfMonth(Fields.field(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link DayOfMonth}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static DayOfMonth dayOfMonth(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new DayOfMonth(expression); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $dayOfWeek}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class DayOfWeek extends AbstractAggregationExpression { |
||||
|
||||
private DayOfWeek(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$dayOfWeek"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link DayOfWeek}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static DayOfWeek dayOfWeek(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new DayOfWeek(Fields.field(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link DayOfWeek}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static DayOfWeek dayOfWeek(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new DayOfWeek(expression); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $year}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Year extends AbstractAggregationExpression { |
||||
|
||||
private Year(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$year"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Year}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Year yearOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Year(Fields.field(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Year}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Year yearOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Year(expression); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $month}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Month extends AbstractAggregationExpression { |
||||
|
||||
private Month(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$month"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Month}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Month monthOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Month(Fields.field(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Month}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Month monthOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Month(expression); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $week}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Week extends AbstractAggregationExpression { |
||||
|
||||
private Week(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$week"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Week}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Week weekOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Week(Fields.field(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Week}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Week weekOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Week(expression); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $hour}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Hour extends AbstractAggregationExpression { |
||||
|
||||
private Hour(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$hour"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Hour}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Hour hourOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Hour(Fields.field(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Hour}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Hour hourOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Hour(expression); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $minute}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Minute extends AbstractAggregationExpression { |
||||
|
||||
private Minute(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$minute"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Minute}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Minute minuteOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Minute(Fields.field(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Minute}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Minute minuteOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Minute(expression); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $second}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Second extends AbstractAggregationExpression { |
||||
|
||||
private Second(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$second"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Second}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Second secondOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Second(Fields.field(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Second}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Second secondOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Second(expression); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $millisecond}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Millisecond extends AbstractAggregationExpression { |
||||
|
||||
private Millisecond(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$millisecond"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Millisecond}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Millisecond millisecondOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new Millisecond(Fields.field(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Millisecond}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Millisecond millisecondOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Millisecond(expression); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $dateToString}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class DateToString extends AbstractAggregationExpression { |
||||
|
||||
private DateToString(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$dateToString"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link FormatBuilder} allowing to define the date format to apply. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static FormatBuilder dateOf(final String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
|
||||
return new FormatBuilder() { |
||||
|
||||
@Override |
||||
public DateToString toString(String format) { |
||||
|
||||
Assert.notNull(format, "Format must not be null!"); |
||||
return new DateToString(argumentMap(Fields.field(fieldReference), format)); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link FormatBuilder} allowing to define the date format to apply. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static FormatBuilder dateOf(final AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
|
||||
return new FormatBuilder() { |
||||
|
||||
@Override |
||||
public DateToString toString(String format) { |
||||
|
||||
Assert.notNull(format, "Format must not be null!"); |
||||
return new DateToString(argumentMap(expression, format)); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
private static java.util.Map<String, Object> argumentMap(Object date, String format) { |
||||
|
||||
java.util.Map<String, Object> args = new LinkedHashMap<String, Object>(2); |
||||
args.put("format", format); |
||||
args.put("date", date); |
||||
return args; |
||||
} |
||||
|
||||
public interface FormatBuilder { |
||||
|
||||
/** |
||||
* Creates new {@link DateToString} with all previously added arguments appending the given one. |
||||
* |
||||
* @param format must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
DateToString toString(String format); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $isoDayOfWeek}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class IsoDayOfWeek extends AbstractAggregationExpression { |
||||
|
||||
private IsoDayOfWeek(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$isoDayOfWeek"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link IsoDayOfWeek}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static IsoDayOfWeek isoDayOfWeek(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new IsoDayOfWeek(Fields.field(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link IsoDayOfWeek}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static IsoDayOfWeek isoDayOfWeek(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new IsoDayOfWeek(expression); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $isoWeek}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class IsoWeek extends AbstractAggregationExpression { |
||||
|
||||
private IsoWeek(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$isoWeek"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link IsoWeek}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static IsoWeek isoWeekOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new IsoWeek(Fields.field(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link IsoWeek}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static IsoWeek isoWeekOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new IsoWeek(expression); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $isoWeekYear}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class IsoWeekYear extends AbstractAggregationExpression { |
||||
|
||||
private IsoWeekYear(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$isoWeekYear"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link IsoWeekYear}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static IsoWeekYear isoWeekYearOf(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
return new IsoWeekYear(Fields.field(fieldReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Millisecond}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static IsoWeekYear isoWeekYearOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new IsoWeekYear(expression); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,96 @@
@@ -0,0 +1,96 @@
|
||||
/* |
||||
* Copyright 2016. the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.mongodb.core.aggregation; |
||||
|
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* Gateway to {@literal literal} aggregation operations. |
||||
* |
||||
* @author Christoph Strobl |
||||
* @since 1.10 |
||||
*/ |
||||
public class LiteralOperators { |
||||
|
||||
/** |
||||
* Take the value referenced by given {@literal value}. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static LiteralOperatorFactory valueOf(Object value) { |
||||
|
||||
Assert.notNull(value, "Value must not be null!"); |
||||
return new LiteralOperatorFactory(value); |
||||
} |
||||
|
||||
/** |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class LiteralOperatorFactory { |
||||
|
||||
private final Object value; |
||||
|
||||
/** |
||||
* Creates new {@link LiteralOperatorFactory} for given {@literal value}. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
*/ |
||||
public LiteralOperatorFactory(Object value) { |
||||
|
||||
Assert.notNull(value, "Value must not be null!"); |
||||
this.value = value; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that returns the associated value without parsing. |
||||
* |
||||
* @return |
||||
*/ |
||||
public Literal asLiteral() { |
||||
return Literal.asLiteral(value); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $literal}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class Literal extends AbstractAggregationExpression { |
||||
|
||||
private Literal(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$literal"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Literal}. |
||||
* |
||||
* @param value must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Literal asLiteral(Object value) { |
||||
|
||||
Assert.notNull(value, "Value must not be null!"); |
||||
return new Literal(value); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,666 @@
@@ -0,0 +1,666 @@
|
||||
/* |
||||
* Copyright 2016. the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.mongodb.core.aggregation; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
import org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.Sum; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* Gateway to {@literal Set expressions} which perform {@literal set} operation on arrays, treating arrays as sets. |
||||
* |
||||
* @author Christoph Strobl |
||||
* @since 1.10 |
||||
*/ |
||||
public class SetOperators { |
||||
|
||||
/** |
||||
* Take the array referenced by given {@literal fieldReference}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static SetOperatorFactory arrayAsSet(String fieldReference) { |
||||
return new SetOperatorFactory(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Take the array resulting from the given {@link AggregationExpression}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static SetOperatorFactory arrayAsSet(AggregationExpression expression) { |
||||
return new SetOperatorFactory(expression); |
||||
} |
||||
|
||||
/** |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class SetOperatorFactory { |
||||
|
||||
private final String fieldReference; |
||||
private final AggregationExpression expression; |
||||
|
||||
/** |
||||
* Creates new {@link SetOperatorFactory} for given {@literal fieldReference}. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
*/ |
||||
public SetOperatorFactory(String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
this.fieldReference = fieldReference; |
||||
this.expression = null; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link SetOperatorFactory} for given {@link AggregationExpression}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
*/ |
||||
public SetOperatorFactory(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
this.fieldReference = null; |
||||
this.expression = expression; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares the previously mentioned field to one or more arrays and |
||||
* returns {@literal true} if they have the same distinct elements and {@literal false} otherwise. |
||||
* |
||||
* @param arrayReferences must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetEquals isEqualTo(String... arrayReferences) { |
||||
return createSetEquals().isEqualTo(arrayReferences); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that compares the previously mentioned field to one or more arrays and |
||||
* returns {@literal true} if they have the same distinct elements and {@literal false} otherwise. |
||||
* |
||||
* @param expressions must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetEquals isEqualTo(AggregationExpression... expressions) { |
||||
return createSetEquals().isEqualTo(expressions); |
||||
} |
||||
|
||||
private SetEquals createSetEquals() { |
||||
return usesFieldRef() ? SetEquals.arrayAsSet(fieldReference) : SetEquals.arrayAsSet(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that takes array of the previously mentioned field and one or more |
||||
* arrays and returns an array that contains the elements that appear in every of those. |
||||
* |
||||
* @param arrayReferences must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetIntersection intersects(String... arrayReferences) { |
||||
return createSetIntersection().intersects(arrayReferences); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that takes array of the previously mentioned field and one or more |
||||
* arrays and returns an array that contains the elements that appear in every of those. |
||||
* |
||||
* @param expressions must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetIntersection intersects(AggregationExpression... expressions) { |
||||
return createSetIntersection().intersects(expressions); |
||||
} |
||||
|
||||
private SetIntersection createSetIntersection() { |
||||
return usesFieldRef() ? SetIntersection.arrayAsSet(fieldReference) : SetIntersection.arrayAsSet(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that takes array of the previously mentioned field and one or more |
||||
* arrays and returns an array that contains the elements that appear in any of those. |
||||
* |
||||
* @param arrayReferences must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetUnion union(String... arrayReferences) { |
||||
return createSetUnion().union(arrayReferences); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that takes array of the previously mentioned field and one or more |
||||
* arrays and returns an array that contains the elements that appear in any of those. |
||||
* |
||||
* @param expressions must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetUnion union(AggregationExpression... expressions) { |
||||
return createSetUnion().union(expressions); |
||||
} |
||||
|
||||
private SetUnion createSetUnion() { |
||||
return usesFieldRef() ? SetUnion.arrayAsSet(fieldReference) : SetUnion.arrayAsSet(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that takes array of the previously mentioned field and returns an |
||||
* array containing the elements that do not exist in the given {@literal arrayReference}. |
||||
* |
||||
* @param arrayReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetDifference differenceTo(String arrayReference) { |
||||
return createSetDifference().differenceTo(arrayReference); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that takes array of the previously mentioned field and returns an |
||||
* array containing the elements that do not exist in the given {@link AggregationExpression}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetDifference differenceTo(AggregationExpression expression) { |
||||
return createSetDifference().differenceTo(expression); |
||||
} |
||||
|
||||
private SetDifference createSetDifference() { |
||||
return usesFieldRef() ? SetDifference.arrayAsSet(fieldReference) : SetDifference.arrayAsSet(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that takes array of the previously mentioned field and returns |
||||
* {@literal true} if it is a subset of the given {@literal arrayReference}. |
||||
* |
||||
* @param arrayReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetIsSubset isSubsetOf(String arrayReference) { |
||||
return createSetIsSubset().isSubsetOf(arrayReference); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that takes array of the previously mentioned field and returns |
||||
* {@literal true} if it is a subset of the given {@link AggregationExpression}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetIsSubset isSubsetOf(AggregationExpression expression) { |
||||
return createSetIsSubset().isSubsetOf(expression); |
||||
} |
||||
|
||||
private SetIsSubset createSetIsSubset() { |
||||
return usesFieldRef() ? SetIsSubset.arrayAsSet(fieldReference) : SetIsSubset.arrayAsSet(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that takes array of the previously mentioned field and returns |
||||
* {@literal true} if any of the elements are {@literal true} and {@literal false} otherwise. |
||||
* |
||||
* @return |
||||
*/ |
||||
public AnyElementTrue anyElementTrue() { |
||||
return usesFieldRef() ? AnyElementTrue.arrayAsSet(fieldReference) : AnyElementTrue.arrayAsSet(expression); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AggregationExpressions} that tkes array of the previously mentioned field and returns |
||||
* {@literal true} if no elements is {@literal false}. |
||||
* |
||||
* @return |
||||
*/ |
||||
public AllElementsTrue allElementsTrue() { |
||||
return usesFieldRef() ? AllElementsTrue.arrayAsSet(fieldReference) : AllElementsTrue.arrayAsSet(expression); |
||||
} |
||||
|
||||
private boolean usesFieldRef() { |
||||
return this.fieldReference != null; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $setEquals}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class SetEquals extends AbstractAggregationExpression { |
||||
|
||||
private SetEquals(List<?> arrays) { |
||||
super(arrays); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$setEquals"; |
||||
} |
||||
|
||||
/** |
||||
* Create new {@link SetEquals}. |
||||
* |
||||
* @param arrayReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static SetEquals arrayAsSet(String arrayReference) { |
||||
|
||||
Assert.notNull(arrayReference, "ArrayReference must not be null!"); |
||||
return new SetEquals(asFields(arrayReference)); |
||||
} |
||||
|
||||
/** |
||||
* Create new {@link SetEquals}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static SetEquals arrayAsSet(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new SetEquals(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link java.util.Set} with all previously added arguments appending the given one. |
||||
* |
||||
* @param arrayReferences must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetEquals isEqualTo(String... arrayReferences) { |
||||
|
||||
Assert.notNull(arrayReferences, "ArrayReferences must not be null!"); |
||||
return new SetEquals(append(Fields.fields(arrayReferences).asList())); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Sum} with all previously added arguments appending the given one. |
||||
* |
||||
* @param expressions must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetEquals isEqualTo(AggregationExpression... expressions) { |
||||
|
||||
Assert.notNull(expressions, "Expressions must not be null!"); |
||||
return new SetEquals(append(Arrays.asList(expressions))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link Sum} with all previously added arguments appending the given one. |
||||
* |
||||
* @param array must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetEquals isEqualTo(Object[] array) { |
||||
|
||||
Assert.notNull(array, "Array must not be null!"); |
||||
return new SetEquals(append(array)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $setIntersection}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class SetIntersection extends AbstractAggregationExpression { |
||||
|
||||
private SetIntersection(List<?> arrays) { |
||||
super(arrays); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$setIntersection"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link SetIntersection} |
||||
* |
||||
* @param arrayReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static SetIntersection arrayAsSet(String arrayReference) { |
||||
|
||||
Assert.notNull(arrayReference, "ArrayReference must not be null!"); |
||||
return new SetIntersection(asFields(arrayReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link SetIntersection}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static SetIntersection arrayAsSet(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new SetIntersection(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link SetIntersection} with all previously added arguments appending the given one. |
||||
* |
||||
* @param arrayReferences must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetIntersection intersects(String... arrayReferences) { |
||||
|
||||
Assert.notNull(arrayReferences, "ArrayReferences must not be null!"); |
||||
return new SetIntersection(append(asFields(arrayReferences))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link SetIntersection} with all previously added arguments appending the given one. |
||||
* |
||||
* @param expressions must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetIntersection intersects(AggregationExpression... expressions) { |
||||
|
||||
Assert.notNull(expressions, "Expressions must not be null!"); |
||||
return new SetIntersection(append(Arrays.asList(expressions))); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $setUnion}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class SetUnion extends AbstractAggregationExpression { |
||||
|
||||
private SetUnion(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$setUnion"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link SetUnion}. |
||||
* |
||||
* @param arrayReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static SetUnion arrayAsSet(String arrayReference) { |
||||
|
||||
Assert.notNull(arrayReference, "ArrayReference must not be null!"); |
||||
return new SetUnion(asFields(arrayReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link SetUnion}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static SetUnion arrayAsSet(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new SetUnion(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link SetUnion} with all previously added arguments appending the given one. |
||||
* |
||||
* @param arrayReferences must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetUnion union(String... arrayReferences) { |
||||
|
||||
Assert.notNull(arrayReferences, "ArrayReferences must not be null!"); |
||||
return new SetUnion(append(asFields(arrayReferences))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link SetUnion} with all previously added arguments appending the given one. |
||||
* |
||||
* @param expressions must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetUnion union(AggregationExpression... expressions) { |
||||
|
||||
Assert.notNull(expressions, "Expressions must not be null!"); |
||||
return new SetUnion(append(Arrays.asList(expressions))); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $setDifference}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class SetDifference extends AbstractAggregationExpression { |
||||
|
||||
private SetDifference(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$setDifference"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link SetDifference}. |
||||
* |
||||
* @param arrayReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static SetDifference arrayAsSet(String arrayReference) { |
||||
|
||||
Assert.notNull(arrayReference, "ArrayReference must not be null!"); |
||||
return new SetDifference(asFields(arrayReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link SetDifference}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static SetDifference arrayAsSet(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new SetDifference(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link SetDifference} with all previously added arguments appending the given one. |
||||
* |
||||
* @param arrayReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetDifference differenceTo(String arrayReference) { |
||||
|
||||
Assert.notNull(arrayReference, "ArrayReference must not be null!"); |
||||
return new SetDifference(append(Fields.field(arrayReference))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link SetDifference} with all previously added arguments appending the given one. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetDifference differenceTo(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new SetDifference(append(expression)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $setIsSubset}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class SetIsSubset extends AbstractAggregationExpression { |
||||
|
||||
private SetIsSubset(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$setIsSubset"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link SetIsSubset}. |
||||
* |
||||
* @param arrayReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static SetIsSubset arrayAsSet(String arrayReference) { |
||||
|
||||
Assert.notNull(arrayReference, "ArrayReference must not be null!"); |
||||
return new SetIsSubset(asFields(arrayReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link SetIsSubset}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static SetIsSubset arrayAsSet(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new SetIsSubset(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link SetIsSubset} with all previously added arguments appending the given one. |
||||
* |
||||
* @param arrayReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetIsSubset isSubsetOf(String arrayReference) { |
||||
|
||||
Assert.notNull(arrayReference, "ArrayReference must not be null!"); |
||||
return new SetIsSubset(append(Fields.field(arrayReference))); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link SetIsSubset} with all previously added arguments appending the given one. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public SetIsSubset isSubsetOf(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new SetIsSubset(append(expression)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $anyElementTrue}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class AnyElementTrue extends AbstractAggregationExpression { |
||||
|
||||
private AnyElementTrue(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$anyElementTrue"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AnyElementTrue}. |
||||
* |
||||
* @param arrayReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static AnyElementTrue arrayAsSet(String arrayReference) { |
||||
|
||||
Assert.notNull(arrayReference, "ArrayReference must not be null!"); |
||||
return new AnyElementTrue(asFields(arrayReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AnyElementTrue}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static AnyElementTrue arrayAsSet(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new AnyElementTrue(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
public AnyElementTrue anyElementTrue() { |
||||
return this; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $allElementsTrue}. |
||||
* |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class AllElementsTrue extends AbstractAggregationExpression { |
||||
|
||||
private AllElementsTrue(Object value) { |
||||
super(value); |
||||
} |
||||
|
||||
@Override |
||||
protected String getMongoMethod() { |
||||
return "$allElementsTrue"; |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AllElementsTrue}. |
||||
* |
||||
* @param arrayReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static AllElementsTrue arrayAsSet(String arrayReference) { |
||||
|
||||
Assert.notNull(arrayReference, "ArrayReference must not be null!"); |
||||
return new AllElementsTrue(asFields(arrayReference)); |
||||
} |
||||
|
||||
/** |
||||
* Creates new {@link AllElementsTrue}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static AllElementsTrue arrayAsSet(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new AllElementsTrue(Collections.singletonList(expression)); |
||||
} |
||||
|
||||
public AllElementsTrue allElementsTrue() { |
||||
return this; |
||||
} |
||||
} |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,389 @@
@@ -0,0 +1,389 @@
|
||||
/* |
||||
* Copyright 2016. the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.mongodb.core.aggregation; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
|
||||
import org.bson.Document; |
||||
import org.springframework.data.mongodb.core.aggregation.VariableOperators.Let.ExpressionVariable; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* Gateway to {@literal variable} aggregation operations. |
||||
* |
||||
* @author Christoph Strobl |
||||
* @author Mark Paluch |
||||
* @since 1.10 |
||||
*/ |
||||
public class VariableOperators { |
||||
|
||||
/** |
||||
* Starts building new {@link Map} that applies an {@link AggregationExpression} to each item of a referenced array |
||||
* and returns an array with the applied results. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Map.AsBuilder mapItemsOf(String fieldReference) { |
||||
return Map.itemsOf(fieldReference); |
||||
} |
||||
|
||||
/** |
||||
* Starts building new {@link Map} that applies an {@link AggregationExpression} to each item of a referenced array |
||||
* and returns an array with the applied results. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Map.AsBuilder mapItemsOf(AggregationExpression expression) { |
||||
return Map.itemsOf(expression); |
||||
} |
||||
|
||||
/** |
||||
* Start creating new {@link Let} that allows definition of {@link ExpressionVariable} that can be used within a |
||||
* nested {@link AggregationExpression}. |
||||
* |
||||
* @param variables must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Let.LetBuilder define(ExpressionVariable... variables) { |
||||
return Let.define(variables); |
||||
} |
||||
|
||||
/** |
||||
* Start creating new {@link Let} that allows definition of {@link ExpressionVariable} that can be used within a |
||||
* nested {@link AggregationExpression}. |
||||
* |
||||
* @param variables must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static Let.LetBuilder define(Collection<ExpressionVariable> variables) { |
||||
return Let.define(variables); |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $map}. |
||||
*/ |
||||
public static class Map implements AggregationExpression { |
||||
|
||||
private Object sourceArray; |
||||
private String itemVariableName; |
||||
private AggregationExpression functionToApply; |
||||
|
||||
private Map(Object sourceArray, String itemVariableName, AggregationExpression functionToApply) { |
||||
|
||||
Assert.notNull(sourceArray, "SourceArray must not be null!"); |
||||
Assert.notNull(itemVariableName, "ItemVariableName must not be null!"); |
||||
Assert.notNull(functionToApply, "FunctionToApply must not be null!"); |
||||
|
||||
this.sourceArray = sourceArray; |
||||
this.itemVariableName = itemVariableName; |
||||
this.functionToApply = functionToApply; |
||||
} |
||||
|
||||
/** |
||||
* Starts building new {@link Map} that applies an {@link AggregationExpression} to each item of a referenced array |
||||
* and returns an array with the applied results. |
||||
* |
||||
* @param fieldReference must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static AsBuilder itemsOf(final String fieldReference) { |
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!"); |
||||
|
||||
return new AsBuilder() { |
||||
|
||||
@Override |
||||
public FunctionBuilder as(final String variableName) { |
||||
|
||||
Assert.notNull(variableName, "VariableName must not be null!"); |
||||
|
||||
return new FunctionBuilder() { |
||||
|
||||
@Override |
||||
public Map andApply(final AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "AggregationExpression must not be null!"); |
||||
return new Map(Fields.field(fieldReference), variableName, expression); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
}; |
||||
}; |
||||
|
||||
/** |
||||
* Starts building new {@link Map} that applies an {@link AggregationExpression} to each item of a referenced array |
||||
* and returns an array with the applied results. |
||||
* |
||||
* @param source must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static AsBuilder itemsOf(final AggregationExpression source) { |
||||
|
||||
Assert.notNull(source, "AggregationExpression must not be null!"); |
||||
|
||||
return new AsBuilder() { |
||||
|
||||
@Override |
||||
public FunctionBuilder as(final String variableName) { |
||||
|
||||
Assert.notNull(variableName, "VariableName must not be null!"); |
||||
|
||||
return new FunctionBuilder() { |
||||
|
||||
@Override |
||||
public Map andApply(final AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "AggregationExpression must not be null!"); |
||||
return new Map(source, variableName, expression); |
||||
} |
||||
}; |
||||
} |
||||
}; |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpression#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) |
||||
*/ |
||||
@Override |
||||
public Document toDocument(final AggregationOperationContext context) { |
||||
return toMap(ExposedFields.synthetic(Fields.fields(itemVariableName)), context); |
||||
} |
||||
|
||||
private Document toMap(ExposedFields exposedFields, AggregationOperationContext context) { |
||||
|
||||
Document map = new Document(); |
||||
InheritingExposedFieldsAggregationOperationContext operationContext = new InheritingExposedFieldsAggregationOperationContext( |
||||
exposedFields, context); |
||||
|
||||
Document input; |
||||
if (sourceArray instanceof Field) { |
||||
input = new Document("input", context.getReference((Field) sourceArray).toString()); |
||||
} else { |
||||
input = new Document("input", ((AggregationExpression) sourceArray).toDocument(context)); |
||||
} |
||||
|
||||
map.putAll(context.getMappedObject(input)); |
||||
map.put("as", itemVariableName); |
||||
map.put("in", |
||||
functionToApply.toDocument(new NestedDelegatingExpressionAggregationOperationContext(operationContext))); |
||||
|
||||
return new Document("$map", map); |
||||
} |
||||
|
||||
public interface AsBuilder { |
||||
|
||||
/** |
||||
* Define the {@literal variableName} for addressing items within the array. |
||||
* |
||||
* @param variableName must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
FunctionBuilder as(String variableName); |
||||
} |
||||
|
||||
public interface FunctionBuilder { |
||||
|
||||
/** |
||||
* Creates new {@link Map} that applies the given {@link AggregationExpression} to each item of the referenced |
||||
* array and returns an array with the applied results. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
Map andApply(AggregationExpression expression); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* {@link AggregationExpression} for {@code $let} that binds {@link AggregationExpression} to variables for use in the |
||||
* specified {@code in} expression, and returns the result of the expression. |
||||
* |
||||
* @author Christoph Strobl |
||||
* @since 1.10 |
||||
*/ |
||||
public static class Let implements AggregationExpression { |
||||
|
||||
private final List<ExpressionVariable> vars; |
||||
private final AggregationExpression expression; |
||||
|
||||
private Let(List<ExpressionVariable> vars, AggregationExpression expression) { |
||||
|
||||
this.vars = vars; |
||||
this.expression = expression; |
||||
} |
||||
|
||||
/** |
||||
* Start creating new {@link Let} by defining the variables for {@code $vars}. |
||||
* |
||||
* @param variables must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static LetBuilder define(final Collection<ExpressionVariable> variables) { |
||||
|
||||
Assert.notNull(variables, "Variables must not be null!"); |
||||
|
||||
return new LetBuilder() { |
||||
|
||||
@Override |
||||
public Let andApply(final AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Let(new ArrayList<ExpressionVariable>(variables), expression); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* Start creating new {@link Let} by defining the variables for {@code $vars}. |
||||
* |
||||
* @param variables must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
public static LetBuilder define(final ExpressionVariable... variables) { |
||||
|
||||
Assert.notNull(variables, "Variables must not be null!"); |
||||
|
||||
return new LetBuilder() { |
||||
|
||||
@Override |
||||
public Let andApply(final AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new Let(Arrays.asList(variables), expression); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
public interface LetBuilder { |
||||
|
||||
/** |
||||
* Define the {@link AggregationExpression} to evaluate. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
Let andApply(AggregationExpression expression); |
||||
} |
||||
|
||||
/* (non-Javadoc) |
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationExpression#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext) |
||||
*/ |
||||
@Override |
||||
public Document toDocument(final AggregationOperationContext context) { |
||||
return toLet(ExposedFields.synthetic(Fields.fields(getVariableNames())), context); |
||||
} |
||||
|
||||
private String[] getVariableNames() { |
||||
|
||||
String[] varNames = new String[this.vars.size()]; |
||||
for (int i = 0; i < this.vars.size(); i++) { |
||||
varNames[i] = this.vars.get(i).variableName; |
||||
} |
||||
|
||||
return varNames; |
||||
} |
||||
|
||||
private Document toLet(ExposedFields exposedFields, AggregationOperationContext context) { |
||||
|
||||
Document letExpression = new Document(); |
||||
Document mappedVars = new Document(); |
||||
InheritingExposedFieldsAggregationOperationContext operationContext = new InheritingExposedFieldsAggregationOperationContext( |
||||
exposedFields, context); |
||||
|
||||
for (ExpressionVariable var : this.vars) { |
||||
mappedVars.putAll(getMappedVariable(var, context)); |
||||
} |
||||
|
||||
letExpression.put("vars", mappedVars); |
||||
letExpression.put("in", getMappedIn(operationContext)); |
||||
|
||||
return new Document("$let", letExpression); |
||||
} |
||||
|
||||
private Document getMappedVariable(ExpressionVariable var, AggregationOperationContext context) { |
||||
|
||||
return new Document(var.variableName, var.expression instanceof AggregationExpression |
||||
? ((AggregationExpression) var.expression).toDocument(context) : var.expression); |
||||
} |
||||
|
||||
private Object getMappedIn(AggregationOperationContext context) { |
||||
return expression.toDocument(new NestedDelegatingExpressionAggregationOperationContext(context)); |
||||
} |
||||
|
||||
/** |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public static class ExpressionVariable { |
||||
|
||||
private final String variableName; |
||||
private final Object expression; |
||||
|
||||
/** |
||||
* Creates new {@link ExpressionVariable}. |
||||
* |
||||
* @param variableName can be {@literal null}. |
||||
* @param expression can be {@literal null}. |
||||
*/ |
||||
private ExpressionVariable(String variableName, Object expression) { |
||||
|
||||
this.variableName = variableName; |
||||
this.expression = expression; |
||||
} |
||||
|
||||
/** |
||||
* Create a new {@link ExpressionVariable} with given name. |
||||
* |
||||
* @param variableName must not be {@literal null}. |
||||
* @return never {@literal null}. |
||||
*/ |
||||
public static ExpressionVariable newVariable(String variableName) { |
||||
|
||||
Assert.notNull(variableName, "VariableName must not be null!"); |
||||
return new ExpressionVariable(variableName, null); |
||||
} |
||||
|
||||
/** |
||||
* Create a new {@link ExpressionVariable} with current name and given {@literal expression}. |
||||
* |
||||
* @param expression must not be {@literal null}. |
||||
* @return never {@literal null}. |
||||
*/ |
||||
public ExpressionVariable forExpression(AggregationExpression expression) { |
||||
|
||||
Assert.notNull(expression, "Expression must not be null!"); |
||||
return new ExpressionVariable(variableName, expression); |
||||
} |
||||
|
||||
/** |
||||
* Create a new {@link ExpressionVariable} with current name and given {@literal expressionObject}. |
||||
* |
||||
* @param expressionObject must not be {@literal null}. |
||||
* @return never {@literal null}. |
||||
*/ |
||||
public ExpressionVariable forExpression(Document expressionObject) { |
||||
|
||||
Assert.notNull(expressionObject, "Expression must not be null!"); |
||||
return new ExpressionVariable(variableName, expressionObject); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue