Skip to content

Commit 561555a

Browse files
committed
Migrate to the new column API
1 parent f831476 commit 561555a

17 files changed

+332
-551
lines changed

datastore/src/main/java/io/spine/server/storage/datastore/type/package-info.java renamed to datastore/src/main/java/io/spine/server/storage/datastore/ColumnTypeRegistry.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,9 @@
1818
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1919
*/
2020

21-
/**
22-
* This package contains implementations of
23-
* {@link io.spine.server.entity.storage.ColumnType ColumnType} interface used for the GAE
24-
* storage.
25-
*/
21+
package io.spine.server.storage.datastore;
2622

27-
@ParametersAreNonnullByDefault
28-
package io.spine.server.storage.datastore.type;
23+
public interface ColumnTypeRegistry {
2924

30-
import javax.annotation.ParametersAreNonnullByDefault;
25+
<T> PersistenceStrategy<T> persistenceStrategyOf(Class<T> clazz);
26+
}

datastore/src/main/java/io/spine/server/storage/datastore/DatastoreStorageFactory.java

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import io.spine.server.aggregate.AggregateStorage;
3232
import io.spine.server.delivery.InboxStorage;
3333
import io.spine.server.entity.Entity;
34-
import io.spine.server.entity.storage.ColumnTypeRegistry;
3534
import io.spine.server.projection.Projection;
3635
import io.spine.server.projection.ProjectionStorage;
3736
import io.spine.server.storage.RecordStorage;
@@ -42,8 +41,6 @@
4241
import io.spine.server.storage.datastore.tenant.NamespaceSupplier;
4342
import io.spine.server.storage.datastore.tenant.NsConverterFactory;
4443
import io.spine.server.storage.datastore.tenant.PrefixedNsConverterFactory;
45-
import io.spine.server.storage.datastore.type.DatastoreColumnType;
46-
import io.spine.server.storage.datastore.type.DatastoreTypeRegistryFactory;
4744
import io.spine.server.tenant.TenantIndex;
4845

4946
import java.util.Map;
@@ -86,7 +83,7 @@ public class DatastoreStorageFactory implements StorageFactory {
8683
*/
8784
private final Map<Class<? extends Storage>, DatastoreWrapper> sysWrappers = newConcurrentMap();
8885

89-
private final ColumnTypeRegistry<? extends DatastoreColumnType<?, ?>> typeRegistry;
86+
private final ColumnTypeRegistry typeRegistry;
9087

9188
private final NsConverterFactory converterFactory;
9289

@@ -268,7 +265,7 @@ public static Builder newBuilder() {
268265
public static class Builder {
269266

270267
private Datastore datastore;
271-
private ColumnTypeRegistry<? extends DatastoreColumnType<?, ?>> typeRegistry;
268+
private ColumnTypeRegistry typeRegistry;
272269
private NamespaceConverter namespaceConverter;
273270
private NsConverterFactory converterFactory;
274271

@@ -298,16 +295,14 @@ public Datastore getDatastore() {
298295
/**
299296
* Sets a {@link ColumnTypeRegistry} for handling the Entity Columns.
300297
*
301-
* <p>Default value is {@link DatastoreTypeRegistryFactory#defaultInstance()}.
298+
* <p>Default value is {@link DefaultColumnTypeRegistry}.
302299
*
303300
* @param typeRegistry
304-
* the type registry containing all the required
305-
* {@linkplain io.spine.server.entity.storage.ColumnType column types}
306-
* to handle the existing Entity Columns
301+
* the type registry containing all the supported
302+
* {@linkplain io.spine.server.entity.storage.Column column} types
307303
* @return self for method chaining
308304
*/
309-
public Builder
310-
setTypeRegistry(ColumnTypeRegistry<? extends DatastoreColumnType<?, ?>> typeRegistry) {
305+
public Builder setTypeRegistry(ColumnTypeRegistry typeRegistry) {
311306
this.typeRegistry = checkNotNull(typeRegistry);
312307
return this;
313308
}
@@ -338,7 +333,7 @@ public Builder setNamespaceConverter(NamespaceConverter converter) {
338333
public DatastoreStorageFactory build() {
339334
checkNotNull(datastore);
340335
if (typeRegistry == null) {
341-
typeRegistry = DatastoreTypeRegistryFactory.defaultInstance();
336+
typeRegistry = new DefaultColumnTypeRegistry();
342337
}
343338
if (namespaceConverter == null) {
344339
converterFactory = NsConverterFactory.defaults();
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
/*
2+
* Copyright 2019, TeamDev. All rights reserved.
3+
*
4+
* Redistribution and use in source and/or binary forms, with or without
5+
* modification, must retain the above copyright notice and the following
6+
* disclaimer.
7+
*
8+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
9+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
10+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
11+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
12+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
13+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
14+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
15+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
16+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
17+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
18+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19+
*/
20+
21+
package io.spine.server.storage.datastore;
22+
23+
import com.google.cloud.datastore.BooleanValue;
24+
import com.google.cloud.datastore.DoubleValue;
25+
import com.google.cloud.datastore.LongValue;
26+
import com.google.cloud.datastore.StringValue;
27+
import com.google.cloud.datastore.TimestampValue;
28+
import com.google.cloud.datastore.Value;
29+
import com.google.common.collect.ImmutableSortedMap;
30+
import com.google.protobuf.Message;
31+
import com.google.protobuf.Timestamp;
32+
import io.spine.core.Version;
33+
import io.spine.string.Stringifiers;
34+
35+
import java.io.Serializable;
36+
import java.util.Comparator;
37+
38+
import static com.google.cloud.Timestamp.ofTimeSecondsAndNanos;
39+
import static io.spine.util.Exceptions.newIllegalArgumentException;
40+
41+
final class DefaultColumnTypeRegistry implements ColumnTypeRegistry {
42+
43+
private static final ImmutableSortedMap<Class<?>, PersistenceStrategy<?>> defaultStrategies =
44+
defaultPolicies();
45+
46+
@SuppressWarnings("unchecked") // Ensured by `defaultPolicies` declaration.
47+
@Override
48+
public <T> PersistenceStrategy<T> persistenceStrategyOf(Class<T> clazz) {
49+
PersistenceStrategy<?> strategy = defaultStrategies.get(clazz);
50+
if (strategy == null) {
51+
strategy = searchForSuperclassStrategy(clazz);
52+
}
53+
PersistenceStrategy<T> result = (PersistenceStrategy<T>) strategy;
54+
return result;
55+
}
56+
57+
private static <T> PersistenceStrategy<?> searchForSuperclassStrategy(Class<T> clazz) {
58+
PersistenceStrategy<?> result =
59+
defaultPolicies().keySet()
60+
.stream()
61+
.filter(cls -> cls.isAssignableFrom(clazz))
62+
.map(defaultStrategies::get)
63+
.findFirst()
64+
.orElseThrow(() -> classNotFound(clazz));
65+
return result;
66+
}
67+
68+
private static <T> IllegalArgumentException classNotFound(Class<T> clazz) {
69+
throw newIllegalArgumentException("The class %s is not found among registered types.",
70+
clazz.getCanonicalName());
71+
}
72+
73+
private static ImmutableSortedMap<Class<?>, PersistenceStrategy<?>> defaultPolicies() {
74+
ImmutableSortedMap.Builder<Class<?>, PersistenceStrategy<?>> policies =
75+
ImmutableSortedMap.orderedBy(new SimplisticClassComparator());
76+
77+
policies.put(String.class, new DefaultStringPersistenceStrategy());
78+
policies.put(Integer.class, new DefaultIntegerPersistenceStrategy());
79+
policies.put(Long.class, new DefaultLongPersistenceStrategy());
80+
policies.put(Double.class, new DefaultDoublePersistenceStrategy());
81+
policies.put(Float.class, new DefaultFloatPersistenceStrategy());
82+
policies.put(Boolean.class, new DefaultBooleanPersistenceStrategy());
83+
policies.put(Timestamp.class, new DefaultTimestampPersistenceStrategy());
84+
policies.put(Version.class, new DefaultVersionPersistenceStrategy());
85+
policies.put(Enum.class, new DefaultEnumPersistenceStrategy());
86+
policies.put(Message.class, new DefaultMessagePersistenceStrategy());
87+
88+
return policies.build();
89+
}
90+
91+
/**
92+
* A class comparator for the {@linkplain #defaultStrategies} map.
93+
*
94+
* <p>Compares classes in such a way so the subclasses go <b>before</b> their superclasses.
95+
*
96+
* <p>For the classes without "parent-child" relationship there is no predefined order of
97+
* storing.
98+
*/
99+
private static class SimplisticClassComparator implements Comparator<Class<?>>, Serializable {
100+
101+
private static final long serialVersionUID = 0L;
102+
103+
@Override
104+
public int compare(Class<?> o1, Class<?> o2) {
105+
if (o1.equals(o2)) {
106+
return 0;
107+
}
108+
if (o1.isAssignableFrom(o2)) {
109+
return 1;
110+
}
111+
return -1;
112+
}
113+
}
114+
115+
private static class DefaultStringPersistenceStrategy implements PersistenceStrategy<String> {
116+
117+
@Override
118+
public Value<?> apply(String s) {
119+
return StringValue.of(s);
120+
}
121+
}
122+
123+
private static class DefaultIntegerPersistenceStrategy implements PersistenceStrategy<Integer> {
124+
125+
@Override
126+
public Value<?> apply(Integer integer) {
127+
return LongValue.of(integer);
128+
}
129+
}
130+
131+
private static class DefaultLongPersistenceStrategy implements PersistenceStrategy<Long> {
132+
133+
@Override
134+
public Value<?> apply(Long aLong) {
135+
return LongValue.of(aLong);
136+
}
137+
}
138+
139+
private static class DefaultDoublePersistenceStrategy implements PersistenceStrategy<Double> {
140+
141+
@Override
142+
public Value<?> apply(Double aDouble) {
143+
return DoubleValue.of(aDouble);
144+
}
145+
}
146+
147+
private static class DefaultFloatPersistenceStrategy implements PersistenceStrategy<Float> {
148+
149+
@Override
150+
public Value<?> apply(Float aFloat) {
151+
return DoubleValue.of(aFloat);
152+
}
153+
}
154+
155+
private static class DefaultBooleanPersistenceStrategy
156+
implements PersistenceStrategy<Boolean> {
157+
158+
@Override
159+
public Value<?> apply(Boolean aBoolean) {
160+
return BooleanValue.of(aBoolean);
161+
}
162+
}
163+
164+
private static class DefaultTimestampPersistenceStrategy
165+
implements PersistenceStrategy<Timestamp> {
166+
167+
@Override
168+
public Value<?> apply(Timestamp timestamp) {
169+
return TimestampValue.of(
170+
ofTimeSecondsAndNanos(timestamp.getSeconds(), timestamp.getNanos())
171+
);
172+
}
173+
}
174+
175+
private static class DefaultVersionPersistenceStrategy
176+
implements PersistenceStrategy<Version> {
177+
178+
@Override
179+
public Value<?> apply(Version version) {
180+
int versionNumber = version.getNumber();
181+
return LongValue.of(versionNumber);
182+
}
183+
}
184+
185+
private static class DefaultEnumPersistenceStrategy implements PersistenceStrategy<Enum<?>> {
186+
187+
@Override
188+
public Value<?> apply(Enum<?> anEnum) {
189+
int ordinal = anEnum.ordinal();
190+
return LongValue.of(ordinal);
191+
}
192+
}
193+
194+
private static class DefaultMessagePersistenceStrategy
195+
implements PersistenceStrategy<Message> {
196+
197+
@Override
198+
public Value<?> apply(Message message) {
199+
String messageString = Stringifiers.toString(message);
200+
return StringValue.of(messageString);
201+
}
202+
}
203+
}

datastore/src/main/java/io/spine/server/storage/datastore/DsAggregateStorage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ protected DsAggregateStorage(Class<? extends Aggregate<I, ?, ?>> cls,
116116
@SuppressWarnings("unchecked") // The ID class is ensured by the parameter type.
117117
Class<I> idClass = (Class<I>) modelClass.idClass();
118118
this.idClass = idClass;
119-
this.stateTypeName = modelClass.stateType()
119+
this.stateTypeName = modelClass.stateTypeUrl()
120120
.toTypeName();
121121
}
122122

datastore/src/main/java/io/spine/server/storage/datastore/DsFilters.java

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
import com.google.common.base.Objects;
2727
import com.google.common.collect.ImmutableMultimap;
2828
import io.spine.client.Filter;
29+
import io.spine.server.entity.storage.Column;
2930
import io.spine.server.entity.storage.CompositeQueryParameter;
30-
import io.spine.server.entity.storage.EntityColumn;
3131

3232
import javax.annotation.Nullable;
3333
import java.util.ArrayDeque;
@@ -69,7 +69,7 @@ final class DsFilters {
6969
private static final Predicate<CompositeQueryParameter> isConjunctive =
7070
input -> {
7171
checkNotNull(input);
72-
return input.getOperator() == ALL;
72+
return input.operator() == ALL;
7373
};
7474

7575
/**
@@ -285,9 +285,9 @@ private static FilterNode buildConjunctionTree(
285285
* Converts the given parameter to a {@code Collection} of {@link FilterNode}s.
286286
*/
287287
private static Collection<FilterNode> toFilters(CompositeQueryParameter param) {
288-
ImmutableMultimap<EntityColumn, Filter> srcFilters = param.getFilters();
288+
ImmutableMultimap<Column, Filter> srcFilters = param.filters();
289289
Set<FilterNode> filters = new HashSet<>(srcFilters.size());
290-
for (Map.Entry<EntityColumn, Filter> entry : srcFilters.entries()) {
290+
for (Map.Entry<Column, Filter> entry : srcFilters.entries()) {
291291
filters.add(new FilterNode(entry.getKey(), entry.getValue()));
292292
}
293293
return filters;
@@ -363,12 +363,12 @@ public void walk(Collection<FilterNode> conjunctionGroup) {
363363
*/
364364
private static class FilterNode {
365365

366-
private final EntityColumn column;
366+
private final Column column;
367367
private final Filter columnFilter;
368368

369369
private final Collection<FilterNode> subtrees;
370370

371-
private FilterNode(@Nullable EntityColumn column, @Nullable Filter filter) {
371+
private FilterNode(@Nullable Column column, @Nullable Filter filter) {
372372
this.column = column;
373373
this.columnFilter = filter;
374374
this.subtrees = newLinkedList();
@@ -378,19 +378,20 @@ private FilterNode() {
378378
this(null, null);
379379
}
380380

381-
private EntityColumn getColumn() {
381+
private Column column() {
382382
return column;
383383
}
384384

385-
private Filter getFilter() {
385+
private Filter filter() {
386386
return columnFilter;
387387
}
388388

389389
@SuppressWarnings({"EnumSwitchStatementWhichMissesCases", "MethodOnlyUsedFromInnerClass"})
390390
// Only non-faulty values are used.
391391
private StructuredQuery.Filter toFilter(FilterAdapter adapter) {
392392
Value<?> value = adapter.toValue(column, columnFilter);
393-
String columnName = column.name();
393+
String columnName = column.name()
394+
.value();
394395
switch (columnFilter.getOperator()) {
395396
case EQUAL:
396397
return eq(columnName, value);
@@ -468,13 +469,13 @@ public boolean equals(Object o) {
468469
return false;
469470
}
470471
FilterNode that = (FilterNode) o;
471-
return Objects.equal(getColumn(), that.getColumn()) &&
472-
Objects.equal(getFilter(), that.getFilter());
472+
return Objects.equal(column(), that.column()) &&
473+
Objects.equal(filter(), that.filter());
473474
}
474475

475476
@Override
476477
public int hashCode() {
477-
return Objects.hashCode(getColumn(), getFilter());
478+
return Objects.hashCode(column(), filter());
478479
}
479480

480481
private static Function<FilterNode, StructuredQuery.Filter>

datastore/src/main/java/io/spine/server/storage/datastore/DsProjectionStorage.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.util.Iterator;
3434
import java.util.Optional;
3535

36+
import static io.spine.server.projection.model.ProjectionClass.asProjectionClass;
3637
import static io.spine.validate.Validate.isDefault;
3738

3839
/**
@@ -51,7 +52,7 @@ protected DsProjectionStorage(Class<? extends Projection<I, ?, ?>> projectionCla
5152
DsRecordStorage<I> recordStorage,
5253
DsPropertyStorage propertyStorage,
5354
boolean multitenant) {
54-
super(multitenant);
55+
super(asProjectionClass(projectionClass), multitenant);
5556
this.recordStorage = recordStorage;
5657
this.propertyStorage = propertyStorage;
5758
this.lastTimestampId =

0 commit comments

Comments
 (0)