Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2019 Immutables Authors and Contributors
*
* 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.immutables.criteria.mongo;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.mongodb.client.model.Filters;
import org.bson.BsonArray;
import org.bson.BsonDocument;
import org.bson.BsonNull;
import org.bson.BsonString;
import org.bson.BsonValue;
import org.bson.Document;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.conversions.Bson;
import org.immutables.criteria.backend.PathNaming;
import org.immutables.criteria.expression.AbstractExpressionVisitor;
import org.immutables.criteria.expression.Call;
import org.immutables.criteria.expression.ComparableOperators;
import org.immutables.criteria.expression.Constant;
import org.immutables.criteria.expression.Expression;
import org.immutables.criteria.expression.Expressions;
import org.immutables.criteria.expression.IterableOperators;
import org.immutables.criteria.expression.Operator;
import org.immutables.criteria.expression.Operators;
import org.immutables.criteria.expression.OptionalOperators;
import org.immutables.criteria.expression.Path;
import org.immutables.criteria.expression.StringOperators;
import org.immutables.criteria.expression.Visitors;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* Converts find expression to Mongo BSON format
* @see Query Documents
*/
class FindVisitor extends AbstractExpressionVisitor {
private final PathNaming naming;
private final CodecRegistry codecRegistry;
FindVisitor(PathNaming pathNaming, CodecRegistry codecRegistry) {
super(e -> { throw new UnsupportedOperationException(); });
this.naming = Objects.requireNonNull(pathNaming, "pathNaming");
this.codecRegistry = Objects.requireNonNull(codecRegistry, "codecRegistry");
}
@Override
public Bson visit(Call call) {
final Operator op = call.operator();
final List args = call.arguments();
if (op == OptionalOperators.IS_ABSENT || op == OptionalOperators.IS_PRESENT) {
Preconditions.checkArgument(args.size() == 1, "Size should be 1 for %s but was %s", op, args.size());
final String field = naming.name(Visitors.toPath(args.get(0)));
Bson filter;
if (op == OptionalOperators.IS_PRESENT) {
filter = Filters.and(Filters.exists(field), Filters.ne(field, null));
} else {
// absent fields means null or missing
filter = Filters.or(Filters.exists(field, false), Filters.eq(field, null));
}
return filter;
}
if (op == Operators.AND || op == Operators.OR) {
final List list = call.arguments().stream()
.map(a -> a.accept(this))
.collect(Collectors.toList());
return op == Operators.AND ? Filters.and(list) : Filters.or(list);
}
if (op == Operators.NOT) {
return negate(args.get(0));
}
if (op == IterableOperators.IS_EMPTY || op == IterableOperators.NOT_EMPTY) {
Preconditions.checkArgument(args.size() == 1, "Size should be 1 for %s but was %s", op, args.size());
final String field = naming.name(Visitors.toPath(args.get(0)));
return op == IterableOperators.IS_EMPTY ? Filters.eq(field, Collections.emptyList())
: Filters.and(Filters.exists(field), Filters.ne(field, null), Filters.ne(field, Collections.emptyList()));
}
if (op.arity() == Operator.Arity.BINARY) {
return binaryCall(call);
}
throw new UnsupportedOperationException(String.format("Not yet supported (%s): %s", call.operator(), call));
}
private Bson binaryCall(Call call) {
Preconditions.checkArgument(call.operator().arity() == Operator.Arity.BINARY, "%s is not binary", call.operator());
final Operator op = call.operator();
Expression left = call.arguments().get(0);
Expression right = call.arguments().get(1);
if (!(left instanceof Path && right instanceof Constant)) {
// special case when $expr has to be used
return call.accept(new MongoExpr(naming, codecRegistry)).asDocument();
}
final String field = naming.name(Visitors.toPath(left));
final Object value = Visitors.toConstant(right).value();
if (op == Operators.EQUAL || op == Operators.NOT_EQUAL) {
if ("".equals(value) && op == Operators.NOT_EQUAL) {
// special case for empty string. string != "" should not return missing strings
return Filters.and(Filters.nin(field, value, null), Filters.exists(field));
}
return op == Operators.EQUAL ? Filters.eq(field, value) : Filters.ne(field, value);
}
if (ComparableOperators.isComparable(op)) {
if (op == ComparableOperators.GREATER_THAN) {
return Filters.gt(field, value);
} else if (op == ComparableOperators.GREATER_THAN_OR_EQUAL) {
return Filters.gte(field, value);
} else if (op == ComparableOperators.LESS_THAN) {
return Filters.lt(field, value);
} else if (op == ComparableOperators.LESS_THAN_OR_EQUAL) {
return Filters.lte(field, value);
}
throw new UnsupportedOperationException("Unknown comparison " + call);
}
if (op == Operators.IN || op == Operators.NOT_IN) {
final Collection