From f627eb9741fb25e1c26ba33051ce774ca5430d4a Mon Sep 17 00:00:00 2001 From: Albert Shift Date: Fri, 17 Apr 2015 14:26:30 -0700 Subject: [PATCH] test collections and implement collection operations --- pom.xml | 2 +- .../java/com/noorq/casser/core/Query.java | 28 +- .../core/operation/UpdateOperation.java | 1 - .../core/reflect/CasserNamedProperty.java | 101 ++++++ .../core/reflect/CasserPropertyNode.java | 18 +- .../core/reflect/DslInvocationHandler.java | 22 +- .../noorq/casser/core/reflect/ListDsl.java | 184 ++++++++++ .../com/noorq/casser/core/reflect/MapDsl.java | 118 +++++++ .../com/noorq/casser/core/reflect/SetDsl.java | 121 +++++++ .../com/noorq/casser/mapping/MappingUtil.java | 18 + .../build/AbstractEmbeddedCassandraTest.java | 12 +- .../core/collection/CollectionTest.java | 331 ++++++++++++++++++ .../integration/core/collection/Customer.java | 8 +- .../unit/core/dsl/AccountWithCollections.java | 42 +++ .../unit/core/dsl/CollectionsDlsTest.java | 87 +++++ 15 files changed, 1076 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/noorq/casser/core/reflect/CasserNamedProperty.java create mode 100644 src/main/java/com/noorq/casser/core/reflect/ListDsl.java create mode 100644 src/main/java/com/noorq/casser/core/reflect/MapDsl.java create mode 100644 src/main/java/com/noorq/casser/core/reflect/SetDsl.java create mode 100644 src/test/java/com/noorq/casser/test/unit/core/dsl/AccountWithCollections.java create mode 100644 src/test/java/com/noorq/casser/test/unit/core/dsl/CollectionsDlsTest.java diff --git a/pom.xml b/pom.xml index 0d108bd..655ca8c 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,7 @@ 2.0.2.2 2.1.5 - 2.1.2 + 2.1.4 16.0.1 1.3 diff --git a/src/main/java/com/noorq/casser/core/Query.java b/src/main/java/com/noorq/casser/core/Query.java index a4788ab..3fc9278 100644 --- a/src/main/java/com/noorq/casser/core/Query.java +++ b/src/main/java/com/noorq/casser/core/Query.java @@ -17,6 +17,7 @@ package com.noorq.casser.core; import java.util.List; import java.util.Map; +import java.util.Objects; import com.datastax.driver.core.querybuilder.BindMarker; import com.datastax.driver.core.querybuilder.QueryBuilder; @@ -72,12 +73,31 @@ public final class Query { return new Postulate(Operator.IN, vals); } - public static Getter get(Getter> listGetter, int index) { - return null; + public static Getter getIdx(Getter> listGetter, int index) { + Objects.requireNonNull(listGetter, "listGetter is null"); + + return new Getter() { + + @Override + public V get() { + return listGetter.get().get(index); + } + + }; } - public static Getter get(Getter> mapGetter, K k) { - return null; + public static Getter get(Getter> mapGetter, K k) { + Objects.requireNonNull(mapGetter, "mapGetter is null"); + Objects.requireNonNull(k, "key is null"); + + return new Getter() { + + @Override + public V get() { + return mapGetter.get().get(k); + } + + }; } diff --git a/src/main/java/com/noorq/casser/core/operation/UpdateOperation.java b/src/main/java/com/noorq/casser/core/operation/UpdateOperation.java index b7873f1..25ef568 100644 --- a/src/main/java/com/noorq/casser/core/operation/UpdateOperation.java +++ b/src/main/java/com/noorq/casser/core/operation/UpdateOperation.java @@ -309,7 +309,6 @@ public final class UpdateOperation extends AbstractFilterOperation getIndexName() { + return Optional.empty(); + } + + @Override + public Class getJavaType() { + throw new CasserMappingException("will never called"); + } + + @Override + public AbstractDataType getDataType() { + throw new CasserMappingException("will never called"); + } + + @Override + public ColumnType getColumnType() { + return ColumnType.COLUMN; + } + + @Override + public int getOrdinal() { + return 0; + } + + @Override + public OrderingDirection getOrdering() { + return OrderingDirection.ASC; + } + + @Override + public Optional> getReadConverter( + SessionRepository repository) { + return Optional.empty(); + } + + @Override + public Optional> getWriteConverter( + SessionRepository repository) { + return Optional.empty(); + } + +} diff --git a/src/main/java/com/noorq/casser/core/reflect/CasserPropertyNode.java b/src/main/java/com/noorq/casser/core/reflect/CasserPropertyNode.java index 601eb64..c3c199d 100644 --- a/src/main/java/com/noorq/casser/core/reflect/CasserPropertyNode.java +++ b/src/main/java/com/noorq/casser/core/reflect/CasserPropertyNode.java @@ -37,12 +37,28 @@ public final class CasserPropertyNode implements Iterable { public String getColumnName() { if (next.isPresent()) { + List columnNames = new ArrayList(); for (CasserProperty p : this) { columnNames.add(p.getColumnName().toCql(true)); } Collections.reverse(columnNames); - return columnNames.stream().collect(Collectors.joining(".")); + + if (prop instanceof CasserNamedProperty) { + int size = columnNames.size(); + StringBuilder str = new StringBuilder(); + for (int i = 0; i != size -1; ++i) { + if (str.length() != 0) { + str.append("."); + } + str.append(columnNames.get(i)); + } + str.append("[").append(columnNames.get(size-1)).append("]"); + return str.toString(); + } + else { + return columnNames.stream().collect(Collectors.joining(".")); + } } else { return prop.getColumnName().toCql(); diff --git a/src/main/java/com/noorq/casser/core/reflect/DslInvocationHandler.java b/src/main/java/com/noorq/casser/core/reflect/DslInvocationHandler.java index ccd123a..fdf87ae 100644 --- a/src/main/java/com/noorq/casser/core/reflect/DslInvocationHandler.java +++ b/src/main/java/com/noorq/casser/core/reflect/DslInvocationHandler.java @@ -21,6 +21,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Optional; +import com.datastax.driver.core.DataType; import com.datastax.driver.core.TupleType; import com.datastax.driver.core.TupleValue; import com.datastax.driver.core.UDTValue; @@ -114,8 +115,11 @@ public class DslInvocationHandler implements InvocationHandler { if (type instanceof DTDataType) { DTDataType dataType = (DTDataType) type; + DataType dt = dataType.getDataType(); - if (dataType.getDataType() instanceof TupleType) { + switch(dt.getName()) { + + case TUPLE: Object childDsl = tupleMap.get(method); @@ -123,7 +127,23 @@ public class DslInvocationHandler implements InvocationHandler { return childDsl; } + break; + + case SET: + return new SetDsl(new CasserPropertyNode(prop, parent)); + + case LIST: + return new ListDsl(new CasserPropertyNode(prop, parent)); + + case MAP: + return new MapDsl(new CasserPropertyNode(prop, parent)); + + default: + break; + } + + } throw new DslPropertyException(new CasserPropertyNode(prop, parent)); diff --git a/src/main/java/com/noorq/casser/core/reflect/ListDsl.java b/src/main/java/com/noorq/casser/core/reflect/ListDsl.java new file mode 100644 index 0000000..c4ca450 --- /dev/null +++ b/src/main/java/com/noorq/casser/core/reflect/ListDsl.java @@ -0,0 +1,184 @@ +/* + * 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.reflect; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Optional; + +import com.noorq.casser.mapping.CasserProperty; +import com.noorq.casser.support.CasserMappingException; +import com.noorq.casser.support.DslPropertyException; + +public final class ListDsl implements List { + + private final CasserPropertyNode parent; + + public ListDsl(CasserPropertyNode parent) { + this.parent = parent; + } + + public CasserPropertyNode getParent() { + return parent; + } + + @Override + public V get(int index) { + CasserProperty prop = new CasserNamedProperty(Integer.toString(index)); + throw new DslPropertyException(new CasserPropertyNode(prop, Optional.of(parent))); + } + + @Override + public int size() { + throwShouldNeverCall(); + return 0; + } + + @Override + public boolean isEmpty() { + throwShouldNeverCall(); + return false; + } + + @Override + public boolean contains(Object o) { + throwShouldNeverCall(); + return false; + } + + @Override + public Iterator iterator() { + throwShouldNeverCall(); + return null; + } + + @Override + public Object[] toArray() { + throwShouldNeverCall(); + return null; + } + + @Override + public T[] toArray(T[] a) { + throwShouldNeverCall(); + return null; + } + + @Override + public boolean add(V e) { + throwShouldNeverCall(); + return false; + } + + @Override + public boolean remove(Object o) { + throwShouldNeverCall(); + return false; + } + + @Override + public boolean containsAll(Collection c) { + throwShouldNeverCall(); + return false; + } + + @Override + public boolean addAll(Collection c) { + throwShouldNeverCall(); + return false; + } + + @Override + public boolean addAll(int index, Collection c) { + throwShouldNeverCall(); + return false; + } + + @Override + public boolean removeAll(Collection c) { + throwShouldNeverCall(); + return false; + } + + @Override + public boolean retainAll(Collection c) { + throwShouldNeverCall(); + return false; + } + + @Override + public void clear() { + throwShouldNeverCall(); + } + + @Override + public V set(int index, V element) { + throwShouldNeverCall(); + return null; + } + + @Override + public void add(int index, V element) { + throwShouldNeverCall(); + } + + @Override + public V remove(int index) { + throwShouldNeverCall(); + return null; + } + + @Override + public int indexOf(Object o) { + throwShouldNeverCall(); + return 0; + } + + @Override + public int lastIndexOf(Object o) { + throwShouldNeverCall(); + return 0; + } + + @Override + public ListIterator listIterator() { + throwShouldNeverCall(); + return null; + } + + @Override + public ListIterator listIterator(int index) { + throwShouldNeverCall(); + return null; + } + + @Override + public List subList(int fromIndex, int toIndex) { + throwShouldNeverCall(); + return null; + } + + private void throwShouldNeverCall() { + throw new CasserMappingException("should be never called"); + } + + @Override + public String toString() { + return "ListDsl"; + } +} diff --git a/src/main/java/com/noorq/casser/core/reflect/MapDsl.java b/src/main/java/com/noorq/casser/core/reflect/MapDsl.java new file mode 100644 index 0000000..ff1887c --- /dev/null +++ b/src/main/java/com/noorq/casser/core/reflect/MapDsl.java @@ -0,0 +1,118 @@ +/* + * 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.reflect; + +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import com.noorq.casser.mapping.CasserProperty; +import com.noorq.casser.support.CasserMappingException; +import com.noorq.casser.support.DslPropertyException; + +public final class MapDsl implements Map { + + private final CasserPropertyNode parent; + + public MapDsl(CasserPropertyNode parent) { + this.parent = parent; + } + + public CasserPropertyNode getParent() { + return parent; + } + + @Override + public V get(Object key) { + CasserProperty prop = new CasserNamedProperty(key.toString()); + throw new DslPropertyException(new CasserPropertyNode(prop, Optional.of(parent))); + } + + @Override + public int size() { + throwShouldNeverCall(); + return 0; + } + + @Override + public boolean isEmpty() { + throwShouldNeverCall(); + return false; + } + + @Override + public boolean containsKey(Object key) { + throwShouldNeverCall(); + return false; + } + + @Override + public boolean containsValue(Object value) { + throwShouldNeverCall(); + return false; + } + + @Override + public V put(K key, V value) { + throwShouldNeverCall(); + return null; + } + + @Override + public V remove(Object key) { + throwShouldNeverCall(); + return null; + } + + @Override + public void putAll(Map m) { + throwShouldNeverCall(); + } + + @Override + public void clear() { + throwShouldNeverCall(); + } + + @Override + public Set keySet() { + throwShouldNeverCall(); + return null; + } + + @Override + public Collection values() { + throwShouldNeverCall(); + return null; + } + + @Override + public Set> entrySet() { + throwShouldNeverCall(); + return null; + } + + private void throwShouldNeverCall() { + throw new CasserMappingException("should be never called"); + } + + @Override + public String toString() { + return "MapDsl"; + } + +} diff --git a/src/main/java/com/noorq/casser/core/reflect/SetDsl.java b/src/main/java/com/noorq/casser/core/reflect/SetDsl.java new file mode 100644 index 0000000..b755acc --- /dev/null +++ b/src/main/java/com/noorq/casser/core/reflect/SetDsl.java @@ -0,0 +1,121 @@ +/* + * 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.reflect; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; + +import com.noorq.casser.support.CasserMappingException; + +public final class SetDsl implements Set { + + private final CasserPropertyNode parent; + + public SetDsl(CasserPropertyNode parent) { + this.parent = parent; + } + + public CasserPropertyNode getParent() { + return parent; + } + + @Override + public int size() { + throwShouldNeverCall(); + return 0; + } + + @Override + public boolean isEmpty() { + throwShouldNeverCall(); + return false; + } + + @Override + public boolean contains(Object o) { + throwShouldNeverCall(); + return false; + } + + @Override + public Iterator iterator() { + throwShouldNeverCall(); + return null; + } + + @Override + public Object[] toArray() { + throwShouldNeverCall(); + return null; + } + + @Override + public T[] toArray(T[] a) { + throwShouldNeverCall(); + return null; + } + + @Override + public boolean add(V e) { + throwShouldNeverCall(); + return false; + } + + @Override + public boolean remove(Object o) { + throwShouldNeverCall(); + return false; + } + + @Override + public boolean containsAll(Collection c) { + throwShouldNeverCall(); + return false; + } + + @Override + public boolean addAll(Collection c) { + throwShouldNeverCall(); + return false; + } + + @Override + public boolean retainAll(Collection c) { + throwShouldNeverCall(); + return false; + } + + @Override + public boolean removeAll(Collection c) { + throwShouldNeverCall(); + return false; + } + + @Override + public void clear() { + throwShouldNeverCall(); + } + + private void throwShouldNeverCall() { + throw new CasserMappingException("should be never called"); + } + + @Override + public String toString() { + return "SetDsl"; + } +} diff --git a/src/main/java/com/noorq/casser/mapping/MappingUtil.java b/src/main/java/com/noorq/casser/mapping/MappingUtil.java index 8a26694..1c1b4f1 100644 --- a/src/main/java/com/noorq/casser/mapping/MappingUtil.java +++ b/src/main/java/com/noorq/casser/mapping/MappingUtil.java @@ -22,7 +22,10 @@ import com.noorq.casser.core.Casser; import com.noorq.casser.core.Getter; import com.noorq.casser.core.reflect.CasserPropertyNode; import com.noorq.casser.core.reflect.DslExportable; +import com.noorq.casser.core.reflect.ListDsl; +import com.noorq.casser.core.reflect.MapDsl; import com.noorq.casser.core.reflect.MapExportable; +import com.noorq.casser.core.reflect.SetDsl; import com.noorq.casser.mapping.annotation.Index; import com.noorq.casser.mapping.annotation.Table; import com.noorq.casser.mapping.annotation.Tuple; @@ -195,6 +198,21 @@ public final class MappingUtil { return e.getParentDslCasserPropertyNode(); } + else if (childDsl instanceof MapDsl) { + MapDsl mapDsl = (MapDsl) childDsl; + return mapDsl.getParent(); + } + + else if (childDsl instanceof ListDsl) { + ListDsl listDsl = (ListDsl) childDsl; + return listDsl.getParent(); + } + + else if (childDsl instanceof SetDsl) { + SetDsl setDsl = (SetDsl) childDsl; + return setDsl.getParent(); + } + throw new CasserMappingException( "getter must reference to the dsl object " + getter); diff --git a/src/test/java/com/noorq/casser/test/integration/build/AbstractEmbeddedCassandraTest.java b/src/test/java/com/noorq/casser/test/integration/build/AbstractEmbeddedCassandraTest.java index 5c7623c..77df24c 100644 --- a/src/test/java/com/noorq/casser/test/integration/build/AbstractEmbeddedCassandraTest.java +++ b/src/test/java/com/noorq/casser/test/integration/build/AbstractEmbeddedCassandraTest.java @@ -65,9 +65,15 @@ public abstract class AbstractEmbeddedCassandraTest { KeyspaceMetadata kmd = cluster.getMetadata().getKeyspace(keyspace); if (kmd == null) { session = cluster.connect(); - session.execute("CREATE KEYSPACE " + keyspace - + " WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1};"); - session.execute("USE " + keyspace + ";"); + + String cql = "CREATE KEYSPACE " + keyspace + + " WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1};"; + System.out.println(cql + "\n"); + session.execute(cql); + + cql = "USE " + keyspace + ";"; + System.out.println(cql + "\n"); + session.execute(cql); } else { session = cluster.connect(keyspace); } diff --git a/src/test/java/com/noorq/casser/test/integration/core/collection/CollectionTest.java b/src/test/java/com/noorq/casser/test/integration/core/collection/CollectionTest.java index 557be7e..cee2bbe 100644 --- a/src/test/java/com/noorq/casser/test/integration/core/collection/CollectionTest.java +++ b/src/test/java/com/noorq/casser/test/integration/core/collection/CollectionTest.java @@ -15,10 +15,19 @@ */ package com.noorq.casser.test.integration.core.collection; +import static com.noorq.casser.core.Query.eq; +import static com.noorq.casser.core.Query.get; +import static com.noorq.casser.core.Query.getIdx; + +import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -64,6 +73,328 @@ public class CollectionTest extends AbstractEmbeddedCassandraTest { } @Test + public void testPrint() { + System.out.println(customer); + } + + @Test + public void testSetCRUID() { + + UUID id = UUID.randomUUID(); + + Set aliases = new HashSet(); + aliases.add("Alex"); + aliases.add("Albert"); + + // CREATE + + csession.insert() + .value(customer::id, id) + .value(customer::aliases, aliases) + .sync(); + + // READ + + // read full object + + Customer actual = csession.select(Customer.class).where(customer::id, eq(id)).sync().findFirst().get(); + Assert.assertEquals(id, actual.id()); + Assert.assertEquals(aliases, actual.aliases()); + Assert.assertNull(actual.names()); + Assert.assertNull(actual.properties()); + + // read full set + + Set actualSet = csession.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(aliases, actualSet); + + // UPDATE + + Set expected = new HashSet(); + expected.add("unknown"); + + csession.update().set(customer::aliases, expected).where(customer::id, eq(id)).sync(); + + actual = csession.select(Customer.class).where(customer::id, eq(id)).sync().findFirst().get(); + Assert.assertEquals(id, actual.id()); + Assert.assertEquals(expected, actual.aliases()); + + // INSERT + + // add operation + + expected.add("add"); + csession.update().add(customer::aliases, "add").where(customer::id, eq(id)).sync(); + + actualSet = csession.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(expected, actualSet); + + // addAll operation + expected.addAll(aliases); + csession.update().addAll(customer::aliases, aliases).where(customer::id, eq(id)).sync(); + + actualSet = csession.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(expected, actualSet); + + // DELETE + + // remove single value + + expected.remove("add"); + csession.update().remove(customer::aliases, "add").where(customer::id, eq(id)).sync(); + + actualSet = csession.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(expected, actualSet); + + // remove values + + expected.removeAll(aliases); + csession.update().removeAll(customer::aliases, aliases).where(customer::id, eq(id)).sync(); + + actualSet = csession.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(expected, actualSet); + + // remove full list + + csession.update().set(customer::aliases, null).where(customer::id, eq(id)).sync(); + + actualSet = csession.select(customer::aliases).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertNull(actualSet); + + // remove object + + csession.delete().where(customer::id, eq(id)).sync(); + Long cnt = csession.count().where(customer::id, eq(id)).sync(); + Assert.assertEquals(Long.valueOf(0), cnt); + + } + + + @Test + public void testListCRUID() { + + UUID id = UUID.randomUUID(); + + List names = new ArrayList(); + names.add("Alex"); + names.add("Albert"); + + // CREATE + + csession.insert() + .value(customer::id, id) + .value(customer::names, names) + .sync(); + + // READ + + // read full object + + Customer actual = csession.select(Customer.class).where(customer::id, eq(id)).sync().findFirst().get(); + Assert.assertEquals(id, actual.id()); + Assert.assertEquals(names, actual.names()); + Assert.assertNull(actual.aliases()); + Assert.assertNull(actual.properties()); + + // read full list + + List actualList = csession.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(names, actualList); + + // read single value by index + + String cql = csession.select(getIdx(customer::names, 1)) + .where(customer::id, eq(id)).cql(); + + System.out.println("Still not supporting cql = " + cql); + + // UPDATE + + List expected = new ArrayList(); + expected.add("unknown"); + + csession.update().set(customer::names, expected).where(customer::id, eq(id)).sync(); + + actual = csession.select(Customer.class).where(customer::id, eq(id)).sync().findFirst().get(); + Assert.assertEquals(id, actual.id()); + Assert.assertEquals(expected, actual.names()); + + // INSERT + + // prepend operation + + expected.add(0, "prepend"); + csession.update().prepend(customer::names, "prepend").where(customer::id, eq(id)).sync(); + + actualList = csession.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(expected, actualList); + + // append operation + + expected.add("append"); + csession.update().append(customer::names, "append").where(customer::id, eq(id)).sync(); + + actualList = csession.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(expected, actualList); + + // prependAll operation + expected.addAll(0, names); + csession.update().prependAll(customer::names, names).where(customer::id, eq(id)).sync(); + + actualList = csession.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(expected, actualList); + + // appendAll operation + expected.addAll(names); + csession.update().appendAll(customer::names, names).where(customer::id, eq(id)).sync(); + + actualList = csession.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(expected, actualList); + + // set by Index + + expected.set(5, "inserted"); + csession.update().setIdx(customer::names, 5, "inserted").where(customer::id, eq(id)).sync(); + + actualList = csession.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(expected, actualList); + + // DELETE + + // remove single value + + expected.remove("inserted"); + csession.update().discard(customer::names, "inserted").where(customer::id, eq(id)).sync(); + + actualList = csession.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(expected, actualList); + + // remove values + + expected.removeAll(names); + csession.update().discardAll(customer::names, names).where(customer::id, eq(id)).sync(); + + actualList = csession.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(expected, actualList); + + // remove full list + + csession.update().set(customer::names, null).where(customer::id, eq(id)).sync(); + + actualList = csession.select(customer::names).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertNull(actualList); + + // remove object + + csession.delete().where(customer::id, eq(id)).sync(); + Long cnt = csession.count().where(customer::id, eq(id)).sync(); + Assert.assertEquals(Long.valueOf(0), cnt); + + } + + @Test + public void testMapCRUID() { + + UUID id = UUID.randomUUID(); + + Map props = new HashMap(); + props.put("key1", "value1"); + props.put("key2", "value2"); + + // CREATE + + csession.insert() + .value(customer::id, id) + .value(customer::properties, props) + .sync(); + + // READ + + // read full object + + Customer actual = csession.select(Customer.class).where(customer::id, eq(id)).sync().findFirst().get(); + Assert.assertEquals(id, actual.id()); + Assert.assertEquals(props, actual.properties()); + Assert.assertNull(actual.aliases()); + Assert.assertNull(actual.names()); + + // read full map + + Map actualMap = csession.select(customer::properties).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(props, actualMap); + + // read single key-value in map + + String cql = csession.select(get(customer::properties, "key1")) + .where(customer::id, eq(id)).cql(); + + System.out.println("Still not supporting cql = " + cql); + + // UPDATE + + Map expected = new HashMap(); + expected.put("k1", "v1"); + expected.put("k2", "v2"); + + csession.update().set(customer::properties, expected).where(customer::id, eq(id)).sync(); + + actual = csession.select(Customer.class).where(customer::id, eq(id)).sync().findFirst().get(); + Assert.assertEquals(id, actual.id()); + Assert.assertEquals(expected, actual.properties()); + + // INSERT + + // put operation + + expected.put("k3", "v3"); + csession.update().put(customer::properties, "k3", "v3").where(customer::id, eq(id)).sync(); + + actualMap = csession.select(customer::properties).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(expected, actualMap); + + // putAll operation + expected.putAll(props); + csession.update().putAll(customer::properties, props).where(customer::id, eq(id)).sync(); + + actualMap = csession.select(customer::properties).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(expected, actualMap); + + // put existing + + expected.put("k3", "v33"); + csession.update().put(customer::properties, "k3", "v33").where(customer::id, eq(id)).sync(); + + actualMap = csession.select(customer::properties).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(expected, actualMap); + + // DELETE + + // remove single key + + expected.remove("k3"); + csession.update().put(customer::properties, "k3", null).where(customer::id, eq(id)).sync(); + + actualMap = csession.select(customer::properties).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertEquals(expected, actualMap); + + // remove full map + + csession.update().set(customer::properties, null).where(customer::id, eq(id)).sync(); + + actualMap = csession.select(customer::properties).where(customer::id, eq(id)).sync().findFirst().get()._1; + Assert.assertNull(actualMap); + + // remove object + + csession.delete().where(customer::id, eq(id)).sync(); + Long cnt = csession.count().where(customer::id, eq(id)).sync(); + Assert.assertEquals(Long.valueOf(0), cnt); + + + } + + + //@Test public void test() { System.out.println(customer); diff --git a/src/test/java/com/noorq/casser/test/integration/core/collection/Customer.java b/src/test/java/com/noorq/casser/test/integration/core/collection/Customer.java index 96b6b75..12484c4 100644 --- a/src/test/java/com/noorq/casser/test/integration/core/collection/Customer.java +++ b/src/test/java/com/noorq/casser/test/integration/core/collection/Customer.java @@ -21,7 +21,6 @@ import java.util.Set; import java.util.UUID; import com.datastax.driver.core.DataType.Name; -import com.noorq.casser.mapping.annotation.Column; import com.noorq.casser.mapping.annotation.PartitionKey; import com.noorq.casser.mapping.annotation.Table; import com.noorq.casser.mapping.annotation.Types; @@ -29,19 +28,16 @@ import com.noorq.casser.mapping.annotation.Types; @Table public interface Customer { - @PartitionKey(ordinal=0) + @PartitionKey UUID id(); @Types.Set(Name.TEXT) - @Column(ordinal=1) Set aliases(); @Types.List(Name.TEXT) - @Column(ordinal=2) - List name(); + List names(); @Types.Map(key=Name.TEXT, value=Name.TEXT) - @Column(ordinal=3) Map properties(); } diff --git a/src/test/java/com/noorq/casser/test/unit/core/dsl/AccountWithCollections.java b/src/test/java/com/noorq/casser/test/unit/core/dsl/AccountWithCollections.java new file mode 100644 index 0000000..a6c45c0 --- /dev/null +++ b/src/test/java/com/noorq/casser/test/unit/core/dsl/AccountWithCollections.java @@ -0,0 +1,42 @@ +/* + * 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.test.unit.core.dsl; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.datastax.driver.core.DataType.Name; +import com.noorq.casser.mapping.annotation.PartitionKey; +import com.noorq.casser.mapping.annotation.Table; +import com.noorq.casser.mapping.annotation.Types; + +@Table +public interface AccountWithCollections { + + @PartitionKey + long id(); + + @Types.Set(Name.TEXT) + Set aliases(); + + @Types.List(Name.TEXT) + List name(); + + @Types.Map(key=Name.TEXT, value=Name.TEXT) + Map properties(); + +} diff --git a/src/test/java/com/noorq/casser/test/unit/core/dsl/CollectionsDlsTest.java b/src/test/java/com/noorq/casser/test/unit/core/dsl/CollectionsDlsTest.java new file mode 100644 index 0000000..aeb7390 --- /dev/null +++ b/src/test/java/com/noorq/casser/test/unit/core/dsl/CollectionsDlsTest.java @@ -0,0 +1,87 @@ +/* + * 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.test.unit.core.dsl; + + + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.noorq.casser.core.Casser; +import com.noorq.casser.core.Getter; +import com.noorq.casser.core.Query; +import com.noorq.casser.core.reflect.CasserPropertyNode; +import com.noorq.casser.support.DslPropertyException; + +public class CollectionsDlsTest { + + static AccountWithCollections account; + + @BeforeClass + public static void beforeTests() { + account = Casser.dsl(AccountWithCollections.class); + } + + @Test + public void testPrint() { + System.out.println(account); + } + + @Test + public void testMapGet() { + + String columnName = null; + + Getter getter = Query.get(account::properties, "key1"); + + try { + getter.get(); + } + catch(DslPropertyException e) { + + CasserPropertyNode node = e.getPropertyNode(); + columnName = node.getColumnName(); + + } + + Assert.assertEquals("\"properties\"[\"key1\"]", columnName); + + } + + @Test + public void testListGet() { + + String columnName = null; + + Getter getter = Query.getIdx(account::name, 2); + + try { + getter.get(); + } + catch(DslPropertyException e) { + + CasserPropertyNode node = e.getPropertyNode(); + + columnName = node.getColumnName(); + + } + + Assert.assertEquals("\"name\"[\"2\"]", columnName); + + } + +}