Skip to content

Commit

Permalink
Query does not implement Expression
Browse files Browse the repository at this point in the history
  • Loading branch information
asereda-gs committed Jun 19, 2019
1 parent c3cda12 commit f307dd3
Show file tree
Hide file tree
Showing 21 changed files with 63 additions and 129 deletions.
21 changes: 13 additions & 8 deletions criteria/common/src/org/immutables/criteria/Criterias.java
Expand Up @@ -16,8 +16,10 @@

package org.immutables.criteria;

import com.google.common.base.Preconditions;
import org.immutables.criteria.expression.Expression;
import org.immutables.criteria.expression.Expressional;
import org.immutables.criteria.expression.Query;
import org.immutables.criteria.expression.Queryable;

import java.util.Objects;

Expand All @@ -26,19 +28,22 @@ public final class Criterias {
private Criterias() {}

/**
* Extracts {@link Expressional} interface from a criteria. Any criteria implements
* {@code Expressional} interface at runtime.
* Extracts {@link Query} from a criteria. Any criteria implements
* {@code Queryable} interface at runtime.
*/
public static Expressional toExpressional(DocumentCriteria<?> criteria) {
public static Query toQuery(DocumentCriteria<?> criteria) {
Objects.requireNonNull(criteria, "criteria");
return (Expressional) criteria;
Preconditions.checkArgument(criteria instanceof Queryable, "%s should implement %s",
criteria.getClass().getName(), Queryable.class.getName());

return ((Queryable) criteria).query();
}

/**
* Extract directly expression from a criteria
* Extract directly filter from a criteria
*/
public static Expression toExpression(DocumentCriteria<?> criteria) {
return toExpressional(criteria).expression();
public static Expression toFilterExpression(DocumentCriteria<?> criteria) {
return toQuery(criteria).filter().orElseThrow(() -> new IllegalArgumentException("no defined filter for " + criteria));
}

}
Expand Up @@ -50,8 +50,4 @@ public T visit(Path path) {
return mapper.apply(path);
}

@Override
public T visit(Query query) {
return query.filter().map(e -> e.accept(this)).orElseGet(() -> mapper.apply(query));
}
}
Expand Up @@ -61,8 +61,4 @@ public Void visit(Path path) {
return null;
}

@Override
public Void visit(Query query) {
return query.filter().map(e -> e.accept(this)).orElse(null);
}
}
Expand Up @@ -18,7 +18,6 @@

import com.google.common.collect.ImmutableList;

import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand All @@ -30,7 +29,7 @@
*
* <p>Example: {@code (A and B or C and D or E)}
*/
public class DnfExpression implements Expressional, Expression {
public class DnfExpression implements Queryable {

private final Query root;
private final List<Expression> conjunctions;
Expand All @@ -46,18 +45,12 @@ public static DnfExpression create(Query root) {
return new DnfExpression(root, Collections.emptyList(), Collections.emptyList());
}

@Nullable
@Override
public <R, C> R accept(ExpressionBiVisitor<R, C> visitor, @Nullable C context) {
return expression().accept(visitor, context);
}

@Override
public Expression expression() {
public Query query() {
return simplify();
}

private Expression simplify() {
private Query simplify() {
final List<Expression> expressions = new ArrayList<>(disjunctions);
if (!conjunctions.isEmpty()) {
expressions.add(Expressions.and(conjunctions));
Expand Down
Expand Up @@ -32,6 +32,4 @@ public interface ExpressionBiVisitor<V, C> {

V visit(Path path, @Nullable C context);

V visit(Query root, @Nullable C context);

}
Expand Up @@ -31,6 +31,4 @@ public interface ExpressionVisitor<V> {

V visit(Path path);

V visit(Query query);

}
Expand Up @@ -22,7 +22,6 @@
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
* A set of predefined utilities and factories for expressions like {@link Constant} or {@link Call}
Expand Down Expand Up @@ -87,25 +86,10 @@ public V visit(Path path, @Nullable Void context) {
return visitor.visit(path);
}

@Override
public V visit(Query root, @Nullable Void context) {
return visitor.visit(root);
}
};
}

public static Optional<Expression> extractPredicate(Expression expression) {
if (expression instanceof Query) {
return ((Query) expression).filter();
}

return Optional.of(expression);
}

public static Expression not(Expression call) {
if (call instanceof Query) {
return ((Query) call).transform(e -> call(Operators.NOT, e));
}
return Expressions.call(Operators.NOT, call);
}

Expand Down
Expand Up @@ -16,15 +16,14 @@

package org.immutables.criteria.expression;

import javax.annotation.Nullable;
import java.util.Objects;
import java.util.Optional;
import java.util.function.UnaryOperator;

/**
* Query which is composed of predicates, projections, group by and order by expressions.
*/
public final class Query implements Expression {
public final class Query {

private final EntityPath entityPath;
private final Expression filter;
Expand All @@ -34,16 +33,10 @@ private Query(EntityPath entityPath, Expression filter) {
this.filter = filter;
}

@Nullable
@Override
public <R, C> R accept(ExpressionBiVisitor<R, C> visitor, @Nullable C context) {
return visitor.visit(this, context);
}

public EntityPath entityPath() {
return this.entityPath;
}

public Optional<Expression> filter() {
return Optional.ofNullable(filter);
}
Expand Down
Expand Up @@ -18,13 +18,13 @@


/**
* Means an object can be expressed as Abstract Syntax Tree (AST).
* Allows to expose current query
*/
public interface Expressional {
public interface Queryable {

/**
* Expose expression used by an object.
*/
Expression expression();
Query query();

}
Expand Up @@ -20,11 +20,12 @@
import com.google.common.collect.ImmutableList;
import org.immutables.criteria.expression.DnfExpression;
import org.immutables.criteria.expression.Expression;
import org.immutables.criteria.expression.Expressional;
import org.immutables.criteria.expression.Expressions;
import org.immutables.criteria.expression.Operator;
import org.immutables.criteria.expression.Operators;
import org.immutables.criteria.expression.Path;
import org.immutables.criteria.expression.Query;
import org.immutables.criteria.expression.Queryable;

import java.lang.reflect.Member;
import java.util.List;
Expand All @@ -35,7 +36,7 @@
* Link between front-end (Criteria DSL) and <a href="https://cs.lmu.edu/~ray/notes/ir/">Intermediate Representation</a>
* (internally known as {@link Expression}).
*/
public final class CriteriaContext implements Expressional {
public final class CriteriaContext implements Queryable {

private final List<CriteriaCreator<?>> creators;
private final DnfExpression expression;
Expand Down Expand Up @@ -159,8 +160,8 @@ public CriteriaContext or() {
}

@Override
public Expression expression() {
return this.expression.expression();
public Query query() {
return this.expression.query();
}

public CriteriaContext withOperator(UnaryOperator<Expression> operator) {
Expand Down
Expand Up @@ -139,7 +139,7 @@ private static <T> T createWithReflection(Class<T> type, CriteriaContext context

/**
* Hacky (and temporary) reflection until we define proper sub-classes for criterias
* (to hide Expressional implementation).
* (to hide Queryable implementation).
*/
static CriteriaContext extract(Object object) {
Objects.requireNonNull(object, "object");
Expand All @@ -156,7 +156,7 @@ static <C> UnaryOperator<Expression> toExpressionOperator(Supplier<C> supplier,
return expression -> {
final C initial = supplier.get();
final C changed = expr.apply(initial);
return Matchers.extract(changed).expression();
return Matchers.extract(changed).query().filter().orElseThrow(() -> new IllegalStateException("filter should be set"));
};
}

Expand All @@ -168,7 +168,7 @@ static <C> UnaryOperator<Expression> toExpressionOperator3(CriteriaContext conte
final CriteriaCreator.TriFactory<?, ?, C> factory = context.factory3();
final C initial = (C) context.withCreators(factory.creator3(), factory.creator2(), factory.creator3()).factory3().create3();
final C changed = expr.apply(initial);
return Matchers.extract(changed).expression();
return Matchers.extract(changed).query().filter().orElseThrow(() -> new IllegalStateException("filter should be set"));
};
}

Expand Down
Expand Up @@ -69,7 +69,7 @@ public void not() {

private static void assertExpressional(DocumentCriteria<?> crit, String ... expectedLines) {
final StringWriter out = new StringWriter();
Criterias.toExpressional(crit).expression().accept(new DebugExpressionVisitor<>(new PrintWriter(out)));
Criterias.toFilterExpression(crit).accept(new DebugExpressionVisitor<>(new PrintWriter(out)));
final String expected = Arrays.stream(expectedLines).collect(Collectors.joining(System.lineSeparator()));
Assert.assertEquals(expected, out.toString().trim());
}
Expand Down
Expand Up @@ -18,12 +18,9 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.immutables.criteria.expression.Expression;
import org.immutables.criteria.expression.ExpressionConverter;
import org.immutables.criteria.expression.Expressions;

import java.util.Objects;
import java.util.Optional;

final class Elasticsearch {

Expand All @@ -33,15 +30,9 @@ static ExpressionConverter<ObjectNode> converter(ObjectMapper mapper) {
Objects.requireNonNull(mapper, "expression");

return expression -> {
Optional<Expression> predicate = Expressions.extractPredicate(expression);

if (!predicate.isPresent()) {
return mapper.createObjectNode();
}

final ObjectNode query = mapper.createObjectNode();
final ElasticsearchQueryVisitor visitor = new ElasticsearchQueryVisitor();
final QueryBuilders.QueryBuilder builder = predicate.get().accept(visitor);
final QueryBuilders.QueryBuilder builder = expression.accept(visitor);
query.set("query", QueryBuilders.constantScoreQuery(builder).toJson(mapper));
return query;
};
Expand Down
Expand Up @@ -30,6 +30,7 @@
import org.immutables.criteria.adapter.Backend;
import org.immutables.criteria.adapter.Operations;
import org.immutables.criteria.expression.Expression;
import org.immutables.criteria.expression.Query;
import org.reactivestreams.Publisher;

import java.io.IOException;
Expand Down Expand Up @@ -68,12 +69,12 @@ public <T> Publisher<T> execute(Operation<T> query) {
return queryInternal((Operations.Query<T>) query);
}

private <T> Flowable<T> queryInternal(Operations.Query<T> query) {
private <T> Flowable<T> queryInternal(Operations.Query<T> op) {
final Request request = new Request("POST", String.format("/%s/_search", index));
final Expression expression = Criterias.toExpression(query.criteria());
final ObjectNode json = Elasticsearch.converter(mapper).convert(expression);
query.limit().ifPresent(limit -> json.put("size", limit));
query.offset().ifPresent(offset -> json.put("start", offset));
final Query query = Criterias.toQuery(op.criteria());
final ObjectNode json = query.filter().map(f -> Elasticsearch.converter(mapper).convert(f)).orElseGet(mapper::createObjectNode);
op.limit().ifPresent(limit -> json.put("size", limit));
op.offset().ifPresent(offset -> json.put("start", offset));
request.setEntity(new StringEntity(json.toString(), ContentType.APPLICATION_JSON));
return Flowable.fromPublisher(new AsyncRestPublisher(restClient, request))
.map(r -> converter((Class<T>) type).apply(r))
Expand Down
23 changes: 11 additions & 12 deletions criteria/geode/src/org/immutables/criteria/geode/GeodeBackend.java
Expand Up @@ -25,6 +25,7 @@
import org.immutables.criteria.Repository;
import org.immutables.criteria.adapter.Backend;
import org.immutables.criteria.adapter.Operations;
import org.immutables.criteria.expression.Query;
import org.reactivestreams.Publisher;

import java.util.Collection;
Expand All @@ -33,7 +34,7 @@
import java.util.Optional;

/**
* Backend for
* Backend for <a href="https://geode.apache.org/">Apache Geode</a>
*/
public class GeodeBackend implements Backend {

Expand All @@ -58,19 +59,17 @@ public <T> Publisher<T> execute(Operation<T> operation) {
}

private <T> Flowable<T> query(Operations.Query<T> op) {
final StringBuilder query = new StringBuilder();
final StringBuilder oql = new StringBuilder();
final Query query = Criterias.toQuery(op.criteria());

query.append("SELECT * FROM ").append(region.getFullPath());
oql.append("SELECT * FROM ").append(region.getFullPath());

final String predicate = Geodes.converter().convert(Criterias.toExpression(op.criteria()));
if (!predicate.isEmpty()) {
query.append(" WHERE ").append(predicate);
}
query.filter().ifPresent(e -> oql.append(" WHERE ").append(Geodes.converter().convert(e)));

op.limit().ifPresent(limit -> query.append(" LIMIT ").append(limit));
op.offset().ifPresent(offset -> query.append(" OFFSET ").append(offset));
op.limit().ifPresent(limit -> oql.append(" LIMIT ").append(limit));
op.offset().ifPresent(offset -> oql.append(" OFFSET ").append(offset));

return Flowable.<Collection<T>>fromCallable(() -> region.query(query.toString()))
return Flowable.<Collection<T>>fromCallable(() -> region.query(oql.toString()))
.flatMapIterable(x -> x);
}

Expand All @@ -89,7 +88,7 @@ private <T> Flowable<Repository.Success> insert(Operations.Insert<T> op) {
}

private <T> Flowable<Repository.Success> delete(Operations.Delete op) {
if (!Geodes.hasPredicate(op.criteria())) {
if (!Criterias.toQuery(op.criteria()).filter().isPresent()) {
// means delete all (ie clear whole region)
return Completable.fromRunnable(region::clear)
.toSingleDefault(Repository.Success.SUCCESS)
Expand All @@ -106,7 +105,7 @@ private <T> Flowable<Repository.Success> delete(Operations.Delete op) {
}


final String predicate = Criterias.toExpression(op.criteria())
final String predicate = Criterias.toFilterExpression(op.criteria())
.accept(new GeodeQueryVisitor(path -> String.format("e.value.%s", path.toStringPath())));

final String query = String.format("select distinct e.key from %s.entries e where %s", region.getFullPath(), predicate);
Expand Down

0 comments on commit f307dd3

Please sign in to comment.