Skip to content

Commit f4f53e4

Browse files
authored
Merge pull request #81 from eclipse/couchbase_map
Optimizes map structure
2 parents 81522c3 + 12b78ef commit f4f53e4

File tree

4 files changed

+150
-22
lines changed

4 files changed

+150
-22
lines changed

couchbase-driver/src/main/java/org/jnosql/diana/couchbase/key/CouchbaseMap.java

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,18 @@
1515
package org.jnosql.diana.couchbase.key;
1616

1717
import com.couchbase.client.java.Bucket;
18+
import com.couchbase.client.java.document.json.JsonObject;
1819
import org.jnosql.diana.api.Value;
1920

2021
import javax.json.bind.Jsonb;
2122
import javax.json.bind.JsonbBuilder;
23+
import java.util.ArrayList;
2224
import java.util.Collection;
2325
import java.util.HashMap;
2426
import java.util.Map;
2527
import java.util.Objects;
2628
import java.util.Set;
2729

28-
import static java.util.stream.Collectors.toList;
2930
import static java.util.stream.Collectors.toSet;
3031

3132

@@ -47,7 +48,7 @@ class CouchbaseMap<K, V> implements Map<K, V> {
4748
private final String bucketName;
4849
private final Class<K> keyClass;
4950
private final Class<V> valueClass;
50-
private final com.couchbase.client.java.datastructures.collections.CouchbaseMap<String> map;
51+
private final com.couchbase.client.java.datastructures.collections.CouchbaseMap<JsonObject> map;
5152

5253
CouchbaseMap(Bucket bucket, String bucketName, Class<K> keyClass, Class<V> valueClass) {
5354
this.bucketName = bucketName + ":map";
@@ -69,9 +70,9 @@ public boolean isEmpty() {
6970
@Override
7071
public V get(Object key) {
7172
Objects.requireNonNull(key, "key is required");
72-
String json = map.get(key.toString());
73+
JsonObject json = map.get(key.toString());
7374
if (Objects.nonNull(json)) {
74-
return JSONB.fromJson(json, valueClass);
75+
return JSONB.fromJson(json.toString(), valueClass);
7576
}
7677
return null;
7778
}
@@ -80,19 +81,19 @@ public V get(Object key) {
8081
public V put(K key, V value) {
8182
Objects.requireNonNull(key, "key is required");
8283
Objects.requireNonNull(value, "value is required");
83-
String json = map.put(key.toString(), JSONB.toJson(value));
84+
JsonObject json = map.put(key.toString(), JsonObjectCouchbaseUtil.toJson(JSONB, value));
8485
if (Objects.nonNull(json)) {
85-
return JSONB.fromJson(json, valueClass);
86+
return JSONB.fromJson(json.toString(), valueClass);
8687
}
8788
return null;
8889
}
8990

9091
@Override
9192
public V remove(Object key) {
9293
Objects.requireNonNull(key, "key is required");
93-
String json = map.remove(key.toString());
94+
JsonObject json = map.remove(key.toString());
9495
if (Objects.nonNull(json)) {
95-
return JSONB.fromJson(json, valueClass);
96+
return JSONB.fromJson(json.toString(), valueClass);
9697
}
9798
return null;
9899
}
@@ -119,7 +120,7 @@ public boolean containsKey(Object key) {
119120
@Override
120121
public boolean containsValue(Object value) {
121122
Objects.requireNonNull(value, "key is required");
122-
return map.containsValue(JSONB.toJson(value));
123+
return values().stream().anyMatch(value::equals);
123124
}
124125

125126
@Override
@@ -131,20 +132,34 @@ public Set<K> keySet() {
131132

132133
@Override
133134
public Collection<V> values() {
134-
return map.values().stream()
135-
.map(s -> JSONB.fromJson(s, valueClass))
136-
.collect(toList());
135+
136+
Collection<V> values = new ArrayList<>();
137+
138+
for (Object object : map.values()) {
139+
values.add(convertValue(object));
140+
}
141+
return values;
137142
}
138143

139144
@Override
140145
public Set<Entry<K, V>> entrySet() {
141146
Map<K, V> copy = new HashMap<>();
142147

143-
for (Entry<String, String> entry : map.entrySet()) {
148+
for (Entry<String, JsonObject> entry : map.entrySet()) {
144149
String key = entry.getKey();
145-
String value = entry.getValue();
146-
copy.put(JSONB.fromJson(key, keyClass), JSONB.fromJson(value, valueClass));
150+
V value = convertValue(entry.getValue());
151+
copy.put((K) key, value);
147152
}
148153
return copy.entrySet();
149154
}
155+
156+
private V convertValue(Object value) {
157+
if(value instanceof Map) {
158+
return JSONB.fromJson(JsonObject.from(Map.class.cast(value)).toString(), valueClass);
159+
} else if(value instanceof JsonObject) {
160+
return JSONB.fromJson(JsonObject.class.cast(value).toString(), valueClass);
161+
}
162+
163+
throw new IllegalStateException("Couchbase does not support the structure value " + value.getClass().getName());
164+
}
150165
}

couchbase-driver/src/main/java/org/jnosql/diana/couchbase/key/DefaultCouchbaseBucketManagerFactory.java

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.couchbase.client.java.CouchbaseCluster;
1919
import com.couchbase.client.java.datastructures.collections.CouchbaseArrayList;
2020
import com.couchbase.client.java.datastructures.collections.CouchbaseArraySet;
21+
import com.couchbase.client.java.document.json.JsonValue;
2122
import org.jnosql.diana.couchbase.util.CouchbaseClusterUtil;
2223

2324
import java.util.List;
@@ -66,7 +67,19 @@ public <K, V> Map<K, V> getMap(String bucketName, Class<K> keyValue, Class<V> va
6667
requireNonNull(bucketName, "bucketName is required");
6768
requireNonNull(valueValue, "valueValue is required");
6869
requireNonNull(keyValue, "keyValue is required");
69-
return new CouchbaseMap<>(getBucket(bucketName), bucketName, keyValue, valueValue);
70+
71+
if(!String.class.isAssignableFrom(keyValue)) {
72+
throw new UnsupportedOperationException("Couchbase Map does not support a not String key instead of: "
73+
+ keyValue);
74+
}
75+
if (JsonValueCheck.checkType(valueValue)) {
76+
return (Map<K, V>)
77+
new com.couchbase.client.java.datastructures.collections.
78+
CouchbaseMap<V>(bucketName + ":map", getBucket(bucketName));
79+
} else {
80+
return new CouchbaseMap<>(getBucket(bucketName), bucketName, keyValue, valueValue);
81+
}
82+
7083
}
7184

7285
@Override
@@ -76,6 +89,17 @@ public <K, V> Map<K, V> getMap(String bucketName, String key, Class<K> keyValue,
7689
requireNonNull(key, "key is required");
7790
requireNonNull(valueValue, "valueValue is required");
7891
requireNonNull(keyValue, "keyValue is required");
92+
93+
if(!String.class.isAssignableFrom(keyValue)) {
94+
throw new UnsupportedOperationException("Couchbase Map does not support a not String key instead of: "
95+
+ keyValue);
96+
}
97+
98+
if (JsonValueCheck.checkType(valueValue)) {
99+
return (Map<K, V>)
100+
new com.couchbase.client.java.datastructures.collections.CouchbaseMap<V>(key, getBucket(bucketName));
101+
}
102+
79103
return new CouchbaseMap<>(getBucket(bucketName), key, keyValue, valueValue);
80104
}
81105

@@ -96,7 +120,7 @@ public <T> Queue<T> getQueue(String bucketName, Class<T> clazz) {
96120
public <T> Set<T> getSet(String bucketName, Class<T> clazz) {
97121
requireNonNull(bucketName, "bucketName is required");
98122
requireNonNull(clazz, "valueValue is required");
99-
if (JsonValueCheck.checkType(clazz)) {
123+
if (JsonValueCheck.checkType(clazz) && !JsonValue.class.isAssignableFrom(clazz)) {
100124
return new CouchbaseArraySet<>(bucketName + SET, getBucket(bucketName));
101125
} else {
102126
return new CouchbaseSet<>(getBucket(bucketName), bucketName, clazz);
@@ -120,7 +144,7 @@ public <T> Queue<T> getQueue(String bucketName, String key, Class<T> clazz) {
120144
requireNonNull(clazz, "valueValue is required");
121145
requireNonNull(key, "key is required");
122146
if (JsonValueCheck.checkType(clazz)) {
123-
return new com.couchbase.client.java.datastructures.collections.CouchbaseQueue<>(bucketName + QUEUE,
147+
return new com.couchbase.client.java.datastructures.collections.CouchbaseQueue<>(key + QUEUE,
124148
getBucket(bucketName));
125149
} else {
126150
return new CouchbaseQueue<>(getBucket(bucketName), key, clazz);
@@ -133,8 +157,8 @@ public <T> Set<T> getSet(String bucketName, String key, Class<T> clazz) {
133157
requireNonNull(bucketName, "bucketName is required");
134158
requireNonNull(clazz, "valueValue is required");
135159
requireNonNull(key, "key is required");
136-
if (JsonValueCheck.checkType(clazz)) {
137-
return new CouchbaseArraySet<>(bucketName + SET, getBucket(key));
160+
if (JsonValueCheck.checkType(clazz) && !JsonValue.class.isAssignableFrom(clazz)) {
161+
return new CouchbaseArraySet<>(key + SET, getBucket(key));
138162
} else {
139163
return new CouchbaseSet<>(getBucket(key), bucketName, clazz);
140164
}
@@ -147,7 +171,7 @@ public <T> List<T> getList(String bucketName, String key, Class<T> clazz) {
147171
requireNonNull(clazz, "valueValue is required");
148172
requireNonNull(key, "key is required");
149173
if (JsonValueCheck.checkType(clazz)) {
150-
return new CouchbaseArrayList<>(bucketName + LIST, getBucket(key));
174+
return new CouchbaseArrayList<>(key + LIST, getBucket(key));
151175
} else {
152176
return new CouchbaseList<>(getBucket(bucketName), key, clazz);
153177
}

couchbase-driver/src/test/java/org/jnosql/diana/couchbase/key/CouchbaseMapTest.java

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,24 @@
1414
*/
1515
package org.jnosql.diana.couchbase.key;
1616

17+
import org.hamcrest.Matchers;
1718
import org.jnosql.diana.api.key.BucketManager;
1819
import org.jnosql.diana.api.key.BucketManagerFactory;
1920
import org.jnosql.diana.couchbase.CouchbaseUtil;
2021
import org.junit.jupiter.api.AfterAll;
2122
import org.junit.jupiter.api.BeforeEach;
2223
import org.junit.jupiter.api.Test;
2324

25+
import java.util.Collections;
2426
import java.util.Map;
27+
import java.util.Set;
2528

26-
import static org.junit.jupiter.api.Assertions.*;
29+
import static org.junit.jupiter.api.Assertions.assertEquals;
30+
import static org.junit.jupiter.api.Assertions.assertFalse;
31+
import static org.junit.jupiter.api.Assertions.assertNotNull;
32+
import static org.junit.jupiter.api.Assertions.assertNull;
33+
import static org.junit.jupiter.api.Assertions.assertTrue;
34+
import static org.hamcrest.MatcherAssert.assertThat;
2735

2836
public class CouchbaseMapTest {
2937
private BucketManagerFactory entityManagerFactory;
@@ -71,4 +79,45 @@ public void shouldVerifyExist() {
7179
}
7280

7381

82+
@Test
83+
public void shouldRemove() {
84+
Map<String, User> vertebrates = entityManagerFactory.getMap(CouchbaseUtil.BUCKET_NAME, String.class, User.class);
85+
vertebrates.put("mammals", mammals);
86+
assertNotNull(vertebrates.remove("mammals"));
87+
assertNull(vertebrates.remove("mammals"));
88+
}
89+
90+
@Test
91+
public void shouldPutAll() {
92+
Map<String, User> vertebrates = entityManagerFactory.getMap(CouchbaseUtil.BUCKET_NAME, String.class, User.class);
93+
Map<String, User> map = Collections.singletonMap("mammals", mammals);
94+
vertebrates.putAll(map);
95+
96+
assertFalse(vertebrates.isEmpty());
97+
assertTrue(vertebrates.containsKey("mammals"));
98+
}
99+
100+
@Test
101+
public void shouldKeySet() {
102+
Map<String, User> vertebrates = entityManagerFactory.getMap(CouchbaseUtil.BUCKET_NAME, String.class, User.class);
103+
vertebrates.put("mammals", mammals);
104+
105+
Set<String> keys = vertebrates.keySet();
106+
assertFalse(keys.isEmpty());
107+
assertTrue(keys.stream().anyMatch(String.class::isInstance));
108+
}
109+
110+
@Test
111+
public void shouldEntrySet() {
112+
Map<String, User> vertebrates = entityManagerFactory.getMap(CouchbaseUtil.BUCKET_NAME, String.class, User.class);
113+
vertebrates.put("mammals", mammals);
114+
115+
Set<Map.Entry<String, User>> entries = vertebrates.entrySet();
116+
assertFalse(entries.isEmpty());
117+
assertEquals(1, entries.size());
118+
Map.Entry<String, User> entry = entries.stream().findFirst().get();
119+
assertEquals("mammals", entry.getKey());
120+
assertEquals(mammals, entry.getValue());
121+
}
122+
74123
}

couchbase-driver/src/test/java/org/jnosql/diana/couchbase/key/DefaultCouchbaseBucketManagerFactoryTest.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,16 @@
1414
*/
1515
package org.jnosql.diana.couchbase.key;
1616

17+
import com.couchbase.client.java.datastructures.collections.CouchbaseArrayList;
18+
import com.couchbase.client.java.datastructures.collections.CouchbaseArraySet;
1719
import org.jnosql.diana.api.key.BucketManager;
1820
import org.jnosql.diana.couchbase.CouchbaseUtil;
1921
import org.junit.jupiter.api.BeforeEach;
2022
import org.junit.jupiter.api.Test;
2123

2224
import static org.junit.jupiter.api.Assertions.assertNotNull;
2325
import static org.junit.jupiter.api.Assertions.assertThrows;
26+
import static org.junit.jupiter.api.Assertions.assertTrue;
2427

2528
public class DefaultCouchbaseBucketManagerFactoryTest {
2629

@@ -42,4 +45,41 @@ public void shouldReturnManager() {
4245
public void shouldReturnError() {
4346
assertThrows(NullPointerException.class, () -> factory.getBucketManager(null));
4447
}
48+
49+
50+
@Test
51+
public void shouldReturnList() {
52+
assertTrue(factory.getList("jnosql", String.class) instanceof CouchbaseArrayList);
53+
assertTrue(factory.getList("jnosql", User.class) instanceof CouchbaseList);
54+
assertTrue(factory.getList("jnosql", "jnosql", User.class) instanceof CouchbaseList);
55+
assertTrue(factory.getList("jnosql", "jnosql", String.class) instanceof CouchbaseArrayList);
56+
}
57+
58+
@Test
59+
public void shouldReturnSet() {
60+
assertTrue(factory.getSet("jnosql", String.class) instanceof CouchbaseArraySet);
61+
assertTrue(factory.getSet("jnosql", User.class) instanceof CouchbaseSet);
62+
assertTrue(factory.getSet("jnosql", "jnosql", User.class) instanceof CouchbaseSet);
63+
assertTrue(factory.getSet("jnosql", "jnosql", String.class) instanceof CouchbaseArraySet);
64+
}
65+
66+
@Test
67+
public void shouldReturnQueue() {
68+
assertTrue(factory.getQueue("jnosql", String.class) instanceof
69+
com.couchbase.client.java.datastructures.collections.CouchbaseQueue);
70+
assertTrue(factory.getQueue("jnosql", User.class) instanceof CouchbaseQueue);
71+
assertTrue(factory.getQueue("jnosql", "jnosql", User.class) instanceof CouchbaseQueue);
72+
assertTrue(factory.getQueue("jnosql", "jnosql", String.class) instanceof
73+
com.couchbase.client.java.datastructures.collections.CouchbaseQueue);
74+
}
75+
76+
@Test
77+
public void shouldReturnMap() {
78+
assertTrue(factory.getMap("jnosql", String.class, String.class) instanceof
79+
com.couchbase.client.java.datastructures.collections.CouchbaseMap);
80+
assertTrue(factory.getMap("jnosql", String.class, User.class) instanceof CouchbaseMap);
81+
assertTrue(factory.getMap("jnosql", "jnosql", String.class, String.class) instanceof
82+
com.couchbase.client.java.datastructures.collections.CouchbaseMap);
83+
assertTrue(factory.getMap("jnosql", "jnosql", String.class, User.class) instanceof CouchbaseMap);
84+
}
4585
}

0 commit comments

Comments
 (0)