diff --git a/README.md b/README.md index 0d257a5..6f95077 100644 --- a/README.md +++ b/README.md @@ -70,8 +70,8 @@ CasserSession session = Casser.init(getSession()).showCql().add(Timeline.class). Select information: ``` session.select(timeline::userId, timeline::timestamp, timeline::text) - .where(timeline::userId, Operator.EQ, userId) - .orderBy(timeline::timestamp, "desc").limit(5).sync() + .where(timeline::userId, eq(userId)) + .orderBy(desc(timeline::timestamp)).limit(5).sync() .forEach(System.out::println); ``` diff --git a/src/main/java/com/noorq/casser/Example.java b/src/main/java/com/noorq/casser/Example.java index a21c971..fa0c727 100644 --- a/src/main/java/com/noorq/casser/Example.java +++ b/src/main/java/com/noorq/casser/Example.java @@ -15,10 +15,11 @@ */ package com.noorq.casser; +import static com.noorq.casser.core.Query.*; + import com.datastax.driver.core.Cluster; import com.noorq.casser.core.Casser; import com.noorq.casser.core.CasserSession; -import com.noorq.casser.core.Filter; import com.noorq.casser.core.Prepared; import com.noorq.casser.core.operation.SelectOperation; import com.noorq.casser.core.tuple.Tuple1; @@ -86,23 +87,23 @@ public class Example { newUser.age = 34; session.upsert(newUser); - String nameAndAge = session.select(user::name, user::age).where(user::id, "==", 100L).sync().findFirst().map(t -> { + String nameAndAge = session.select(user::name, user::age).where(user::id, eq(100L)).sync().findFirst().map(t -> { return t._1 + ":" + t._2; }).get(); - User userTmp = session.select(user::name, user::age).where(user::id, "==", 100L).map(Example::mapUser).sync().findFirst().get(); + User userTmp = session.select(user::name, user::age).where(user::id, eq(100L)).map(Example::mapUser).sync().findFirst().get(); - session.update(user::age, 10).where(user::id, "==", 100L).async(); + session.update(user::age, 10).where(user::id, eq(100L)).async(); - session.delete(User.class).where(user::id, "==", 100L).async(); + session.delete(User.class).where(user::id, eq(100L)).async(); Prepared>> ps = session.select(user::name).where(user::id, "==", null).prepare(); long cnt = ps.bind(100L).sync().count(); - cnt = session.select(user::name).where(user::id, "==", 100L).count().sync(); + cnt = session.select(user::name).where(user::id, eq(100L)).count().sync(); - cnt = session.select(user::name).where(Filter.equal(user::id, 100L)).count().sync(); + cnt = session.select(user::name).where(user::id, eq(100L)).count().sync(); } diff --git a/src/main/java/com/noorq/casser/core/Filter.java b/src/main/java/com/noorq/casser/core/Filter.java index 0e736fd..d2d571d 100644 --- a/src/main/java/com/noorq/casser/core/Filter.java +++ b/src/main/java/com/noorq/casser/core/Filter.java @@ -18,7 +18,6 @@ package com.noorq.casser.core; import java.util.Objects; import com.datastax.driver.core.querybuilder.Clause; -import com.datastax.driver.core.querybuilder.QueryBuilder; import com.noorq.casser.core.reflect.CasserPropertyNode; import com.noorq.casser.mapping.CasserMappingProperty; import com.noorq.casser.mapping.MappingUtil; @@ -28,67 +27,29 @@ import com.noorq.casser.support.CasserMappingException; public final class Filter { private final CasserMappingProperty property; - private final Operator operation; - private final V value; - private final V[] values; + private final Postulate postulate; private Filter(CasserMappingProperty prop, Operator op, V value) { this.property = prop; - this.operation = op; - this.value = value; - this.values = null; + this.postulate = new Postulate(op, value); } private Filter(CasserMappingProperty prop, Operator op, V[] values) { this.property = prop; - this.operation = op; - this.value = null; - this.values = values; + this.postulate = new Postulate(op, values); + } + + private Filter(CasserMappingProperty prop, Postulate postulate) { + this.property = prop; + this.postulate = postulate; } public CasserMappingProperty getProperty() { return property; } - public Operator getOperation() { - return operation; - } - - public V getValue() { - return value; - } - public Clause getClause(ColumnValuePreparer valuePreparer) { - - switch(operation) { - - case EQ: - return QueryBuilder.eq(property.getColumnName(), - valuePreparer.prepareColumnValue(value, property)); - - case IN: - Object[] preparedValues = new Object[values.length]; - for (int i = 0; i != values.length; ++i) { - preparedValues[i] = valuePreparer.prepareColumnValue(values[i], property); - } - return QueryBuilder.in(property.getColumnName(), preparedValues); - - case LT: - return QueryBuilder.lt(property.getColumnName(), valuePreparer.prepareColumnValue(value, property)); - - case LTE: - return QueryBuilder.lte(property.getColumnName(), valuePreparer.prepareColumnValue(value, property)); - - case GT: - return QueryBuilder.gt(property.getColumnName(), valuePreparer.prepareColumnValue(value, property)); - - case GTE: - return QueryBuilder.gte(property.getColumnName(), valuePreparer.prepareColumnValue(value, property)); - - default: - throw new CasserMappingException("unknown filter operation " + operation); - } - + return postulate.getClause(property, valuePreparer); } public static Filter equal(Getter getter, V val) { @@ -112,22 +73,31 @@ public final class Filter { return new Filter(prop.getProperty(), Operator.IN, vals); } - public static Filter greater(Getter getter, V val) { + public static Filter greaterThan(Getter getter, V val) { return create(getter, Operator.GT, val); } - public static Filter less(Getter getter, V val) { + public static Filter lessThan(Getter getter, V val) { return create(getter, Operator.LT, val); } - public static Filter greaterOrEqual(Getter getter, V val) { + public static Filter greaterThanOrEqual(Getter getter, V val) { return create(getter, Operator.GTE, val); } - public static Filter lessOrEqual(Getter getter, V val) { + public static Filter lessThanOrEqual(Getter getter, V val) { return create(getter, Operator.LTE, val); } + public static Filter create(Getter getter, Postulate postulate) { + Objects.requireNonNull(getter, "empty getter"); + Objects.requireNonNull(postulate, "empty operator"); + + CasserPropertyNode prop = MappingUtil.resolveMappingProperty(getter); + + return new Filter(prop.getProperty(), postulate); + } + public static Filter create(Getter getter, String operator, V val) { Objects.requireNonNull(operator, "empty operator"); diff --git a/src/main/java/com/noorq/casser/core/Ordered.java b/src/main/java/com/noorq/casser/core/Ordered.java new file mode 100644 index 0000000..dae237b --- /dev/null +++ b/src/main/java/com/noorq/casser/core/Ordered.java @@ -0,0 +1,46 @@ +package com.noorq.casser.core; + +import java.util.Objects; + +import com.datastax.driver.core.querybuilder.Ordering; +import com.datastax.driver.core.querybuilder.QueryBuilder; +import com.noorq.casser.core.reflect.CasserPropertyNode; +import com.noorq.casser.mapping.MappingUtil; +import com.noorq.casser.mapping.OrderingDirection; +import com.noorq.casser.support.CasserMappingException; + +public final class Ordered { + + private final Getter getter; + private final OrderingDirection direction; + + public Ordered(Getter getter, OrderingDirection direction) { + this.getter = getter; + this.direction = direction; + } + + public Ordering getOrdering() { + + Objects.requireNonNull(getter, "property is null"); + Objects.requireNonNull(direction, "direction is null"); + + CasserPropertyNode propNode = MappingUtil.resolveMappingProperty(getter); + + if (!propNode.getProperty().isClusteringColumn()) { + throw new CasserMappingException("property must be a clustering column " + propNode.getProperty().getPropertyName()); + } + + switch(direction) { + + case ASC: + return QueryBuilder.asc(propNode.getColumnName()); + + case DESC: + return QueryBuilder.desc(propNode.getColumnName()); + + } + + throw new CasserMappingException("invalid direction " + direction); + } + +} diff --git a/src/main/java/com/noorq/casser/core/Postulate.java b/src/main/java/com/noorq/casser/core/Postulate.java new file mode 100644 index 0000000..6efaeed --- /dev/null +++ b/src/main/java/com/noorq/casser/core/Postulate.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2015 Noorq, Inc. + * + * 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 com.noorq.casser.core; + +import com.datastax.driver.core.querybuilder.Clause; +import com.datastax.driver.core.querybuilder.QueryBuilder; +import com.noorq.casser.mapping.CasserMappingProperty; +import com.noorq.casser.mapping.value.ColumnValuePreparer; +import com.noorq.casser.support.CasserMappingException; + +public final class Postulate { + + private final Operator operator; + private final V value; + private final V[] values; + + protected Postulate(Operator op, V value) { + this.operator = op; + this.value = value; + this.values = null; + + if (op == Operator.IN) { + throw new IllegalArgumentException("invalid usage of the 'in' operator"); + } + } + + protected Postulate(Operator op, V[] values) { + this.operator = op; + this.value = null; + this.values = values; + + if (op != Operator.IN) { + throw new IllegalArgumentException("invalid usage of the non 'in' operator"); + } + } + + public Clause getClause(CasserMappingProperty property, ColumnValuePreparer valuePreparer) { + + switch(operator) { + + case EQ: + return QueryBuilder.eq(property.getColumnName(), + valuePreparer.prepareColumnValue(value, property)); + + case IN: + Object[] preparedValues = new Object[values.length]; + for (int i = 0; i != values.length; ++i) { + preparedValues[i] = valuePreparer.prepareColumnValue(values[i], property); + } + return QueryBuilder.in(property.getColumnName(), preparedValues); + + case LT: + return QueryBuilder.lt(property.getColumnName(), valuePreparer.prepareColumnValue(value, property)); + + case LTE: + return QueryBuilder.lte(property.getColumnName(), valuePreparer.prepareColumnValue(value, property)); + + case GT: + return QueryBuilder.gt(property.getColumnName(), valuePreparer.prepareColumnValue(value, property)); + + case GTE: + return QueryBuilder.gte(property.getColumnName(), valuePreparer.prepareColumnValue(value, property)); + + default: + throw new CasserMappingException("unknown filter operation " + operator); + } + + } + +} diff --git a/src/main/java/com/noorq/casser/core/Query.java b/src/main/java/com/noorq/casser/core/Query.java new file mode 100644 index 0000000..1882ebb --- /dev/null +++ b/src/main/java/com/noorq/casser/core/Query.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2015 Noorq, Inc. + * + * 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 com.noorq.casser.core; + +import java.util.List; +import java.util.Map; + +import com.noorq.casser.mapping.OrderingDirection; + +/** + * Sugar methods for the queries + * + */ + +public final class Query { + + private Query() { + } + + public static Ordered asc(Getter getter) { + return new Ordered(getter, OrderingDirection.ASC); + } + + public static Ordered desc(Getter getter) { + return new Ordered(getter, OrderingDirection.DESC); + } + + public static Postulate eq(V val) { + return new Postulate(Operator.EQ, val); + } + + public static Postulate lt(V val) { + return new Postulate(Operator.LT, val); + } + + public static Postulate lte(V val) { + return new Postulate(Operator.LTE, val); + } + + public static Postulate gt(V val) { + return new Postulate(Operator.GT, val); + } + + public static Postulate gte(V val) { + return new Postulate(Operator.GTE, val); + } + + public static Postulate in(Getter getter, V[] vals) { + return new Postulate(Operator.IN, vals); + } + + public static Getter get(Getter> listGetter, int index) { + return null; + } + + public static Getter get(Getter> mapGetter, K k) { + return null; + } + + + +} diff --git a/src/main/java/com/noorq/casser/core/collection/CList.java b/src/main/java/com/noorq/casser/core/collection/CList.java deleted file mode 100644 index a08022a..0000000 --- a/src/main/java/com/noorq/casser/core/collection/CList.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2015 Noorq, Inc. - * - * 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 com.noorq.casser.core.collection; - -import java.util.List; - -import com.noorq.casser.core.Getter; - -public final class CList { - - private CList() { - } - - public static Getter get(Getter> listGetter, int index) { - return null; - } - -} diff --git a/src/main/java/com/noorq/casser/core/collection/CMap.java b/src/main/java/com/noorq/casser/core/collection/CMap.java deleted file mode 100644 index 351c090..0000000 --- a/src/main/java/com/noorq/casser/core/collection/CMap.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2015 Noorq, Inc. - * - * 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 com.noorq.casser.core.collection; - -import java.util.Map; - -import com.noorq.casser.core.Getter; - -public final class CMap { - - private CMap() { - } - - public static Getter get(Getter> mapGetter, K k) { - return null; - } - -} diff --git a/src/main/java/com/noorq/casser/core/collection/CSet.java b/src/main/java/com/noorq/casser/core/collection/CSet.java deleted file mode 100644 index 9780226..0000000 --- a/src/main/java/com/noorq/casser/core/collection/CSet.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2015 Noorq, Inc. - * - * 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 com.noorq.casser.core.collection; - -import java.util.List; - -import com.noorq.casser.core.Getter; - -public final class CSet { - - private CSet() { - } - -} diff --git a/src/main/java/com/noorq/casser/core/operation/AbstractFilterOperation.java b/src/main/java/com/noorq/casser/core/operation/AbstractFilterOperation.java index 2dbe6ed..a2721f8 100644 --- a/src/main/java/com/noorq/casser/core/operation/AbstractFilterOperation.java +++ b/src/main/java/com/noorq/casser/core/operation/AbstractFilterOperation.java @@ -22,6 +22,7 @@ import com.noorq.casser.core.AbstractSessionOperations; import com.noorq.casser.core.Filter; import com.noorq.casser.core.Getter; import com.noorq.casser.core.Operator; +import com.noorq.casser.core.Postulate; public abstract class AbstractFilterOperation> extends AbstractEntityOperation { @@ -31,6 +32,14 @@ public abstract class AbstractFilterOperation O where(Getter getter, Postulate postulate) { + + addFilter(Filter.create(getter, postulate)); + + return (O) this; + } + + public O where(Getter getter, String operator, V val) { addFilter(Filter.create(getter, operator, val)); @@ -52,6 +61,13 @@ public abstract class AbstractFilterOperation O add(Getter getter, Postulate postulate) { + + addFilter(Filter.create(getter, postulate)); + + return (O) this; + } + public O and(Getter getter, String operator, V val) { addFilter(Filter.create(getter, operator, val)); diff --git a/src/main/java/com/noorq/casser/core/operation/AbstractFilterStreamOperation.java b/src/main/java/com/noorq/casser/core/operation/AbstractFilterStreamOperation.java index a5dc5a8..d3454b9 100644 --- a/src/main/java/com/noorq/casser/core/operation/AbstractFilterStreamOperation.java +++ b/src/main/java/com/noorq/casser/core/operation/AbstractFilterStreamOperation.java @@ -22,6 +22,7 @@ import com.noorq.casser.core.AbstractSessionOperations; import com.noorq.casser.core.Filter; import com.noorq.casser.core.Getter; import com.noorq.casser.core.Operator; +import com.noorq.casser.core.Postulate; public abstract class AbstractFilterStreamOperation> extends AbstractStreamOperation { @@ -31,6 +32,13 @@ public abstract class AbstractFilterStreamOperation O where(Getter getter, Postulate postulate) { + + addFilter(Filter.create(getter, postulate)); + + return (O) this; + } + public O where(Getter getter, String operator, V val) { addFilter(Filter.create(getter, operator, val)); @@ -52,6 +60,13 @@ public abstract class AbstractFilterStreamOperation O add(Getter getter, Postulate postulate) { + + addFilter(Filter.create(getter, postulate)); + + return (O) this; + } + public O and(Getter getter, String operator, V val) { addFilter(Filter.create(getter, operator, val)); diff --git a/src/main/java/com/noorq/casser/core/operation/SelectOperation.java b/src/main/java/com/noorq/casser/core/operation/SelectOperation.java index cd06b4b..6227408 100644 --- a/src/main/java/com/noorq/casser/core/operation/SelectOperation.java +++ b/src/main/java/com/noorq/casser/core/operation/SelectOperation.java @@ -35,10 +35,9 @@ import com.datastax.driver.core.querybuilder.Select.Where; import com.noorq.casser.core.AbstractSessionOperations; import com.noorq.casser.core.Filter; import com.noorq.casser.core.Getter; +import com.noorq.casser.core.Ordered; import com.noorq.casser.core.reflect.CasserPropertyNode; import com.noorq.casser.mapping.CasserMappingEntity; -import com.noorq.casser.mapping.CasserMappingProperty; -import com.noorq.casser.mapping.MappingUtil; import com.noorq.casser.mapping.OrderingDirection; import com.noorq.casser.support.CasserMappingException; @@ -87,25 +86,13 @@ public final class SelectOperation extends AbstractFilterStreamOperation orderBy(Getter getter, OrderingDirection direction) { - Objects.requireNonNull(getter, "property is null"); - Objects.requireNonNull(direction, "direction is null"); - - CasserPropertyNode propNode = MappingUtil.resolveMappingProperty(getter); - - if (!propNode.getProperty().isClusteringColumn()) { - throw new CasserMappingException("property must be a clustering column " + propNode.getProperty().getPropertyName()); - } - - switch(direction) { - case ASC: - getOrCreateOrdering().add(QueryBuilder.asc(propNode.getColumnName())); - return this; - case DESC: - getOrCreateOrdering().add(QueryBuilder.desc(propNode.getColumnName())); - return this; - } - - throw new CasserMappingException("unknown ordering direction " + direction); + getOrCreateOrdering().add(new Ordered(getter, direction).getOrdering()); + return this; + } + + public SelectOperation orderBy(Ordered ordered) { + getOrCreateOrdering().add(ordered.getOrdering()); + return this; } public SelectOperation limit(Integer limit) { diff --git a/src/test/java/com/noorq/casser/test/integration/core/compound/CompondKeyTest.java b/src/test/java/com/noorq/casser/test/integration/core/compound/CompondKeyTest.java index 1a2cf59..f982a27 100644 --- a/src/test/java/com/noorq/casser/test/integration/core/compound/CompondKeyTest.java +++ b/src/test/java/com/noorq/casser/test/integration/core/compound/CompondKeyTest.java @@ -24,6 +24,7 @@ import org.junit.Test; import com.noorq.casser.core.Casser; import com.noorq.casser.core.CasserSession; +import static com.noorq.casser.core.Query.*; import com.noorq.casser.support.Mutable; import com.noorq.casser.test.integration.build.AbstractEmbeddedCassandraTest; @@ -89,7 +90,7 @@ public class CompondKeyTest extends AbstractEmbeddedCassandraTest { session.select(timeline::userId, timeline::timestamp, timeline::text) .where(timeline::userId, "==", userId) - .orderBy(timeline::timestamp, "desc").limit(5).sync() + .orderBy(desc(timeline::timestamp)).limit(5).sync() .forEach(t -> { //System.out.println(t);