Skip to content

Commit 6610aab

Browse files
committed
#157: Deprecate reflection-heavy EntityIdSchema.SORT_ENTITY_BY_ID in favor of EntitySchema.defaultOrder() Comparator
1 parent 7c28079 commit 6610aab

File tree

6 files changed

+105
-14
lines changed

6 files changed

+105
-14
lines changed

repository-inmemory/src/main/java/tech/ydb/yoj/repository/test/inmemory/InMemoryTable.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public List<T> find(
110110
@Nullable Long offset
111111
) {
112112
// NOTE: InMemoryTable doesn't handle index.
113-
return InMemoryQueries.find(() -> findAll().stream(), filter, orderBy, limit, offset);
113+
return TableQueryImpl.find(() -> findAll().stream(), schema, filter, orderBy, limit, offset);
114114
}
115115

116116
@Override
@@ -192,7 +192,7 @@ public T find(Entity.Id<T> id) {
192192

193193
@Override
194194
public <ID extends Entity.Id<T>> List<T> find(Set<ID> ids) {
195-
return TableQueryImpl.find(this, getFirstLevelCache(), ids);
195+
return TableQueryImpl.find(this, schema, getFirstLevelCache(), ids);
196196
}
197197

198198
@Override
@@ -218,7 +218,7 @@ public <ID extends Entity.Id<T>> List<T> find(Range<ID> range) {
218218
transaction.getWatcher().markRangeRead(tableDescriptor, range);
219219
return findAll0().stream()
220220
.filter(e -> range.contains((ID) e.getId()))
221-
.sorted(EntityIdSchema.SORT_ENTITY_BY_ID)
221+
.sorted(schema.defaultOrder())
222222
.collect(toList());
223223
}
224224

@@ -239,7 +239,7 @@ public <V extends View, ID extends Entity.Id<T>> List<V> find(Class<V> viewType,
239239

240240
@Override
241241
public <V extends View, ID extends Entity.Id<T>> List<V> find(Class<V> viewType, Set<ID> ids) {
242-
return find(viewType, ids, null, EntityExpressions.defaultOrder(getType()), null);
242+
return find(viewType, ids, null, EntityExpressions.defaultOrder(schema), null);
243243
}
244244

245245
@Override
@@ -542,7 +542,7 @@ private <ID extends Entity.Id<T>> Stream<T> readTableStream(ReadTableParams<ID>
542542
.stream()
543543
.filter(e -> readTableFilter(e, params));
544544
if (params.isOrdered()) {
545-
stream = stream.sorted(EntityIdSchema.SORT_ENTITY_BY_ID);
545+
stream = stream.sorted(schema.defaultOrder());
546546
}
547547
if (params.getRowLimit() > 0) {
548548
stream = stream.limit(params.getRowLimit());

repository-ydb-v2/src/main/java/tech/ydb/yoj/repository/ydb/table/YdbTable.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ public T find(Entity.Id<T> id) {
273273

274274
@Override
275275
public <ID extends Entity.Id<T>> List<T> find(Set<ID> ids) {
276-
return TableQueryImpl.find(this, getFirstLevelCache(), ids);
276+
return TableQueryImpl.find(this, schema, getFirstLevelCache(), ids);
277277
}
278278

279279
@Override

repository/src/main/java/tech/ydb/yoj/repository/db/EntityIdSchema.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.google.common.base.Preconditions;
44
import com.google.common.reflect.TypeToken;
55
import lombok.NonNull;
6+
import tech.ydb.yoj.DeprecationWarnings;
67
import tech.ydb.yoj.databind.CustomValueTypes;
78
import tech.ydb.yoj.databind.FieldValueType;
89
import tech.ydb.yoj.databind.schema.Schema;
@@ -42,11 +43,33 @@ public final class EntityIdSchema<ID extends Entity.Id<?>> extends Schema<ID> im
4243
private static final String ID_SUBFIELD_PATH_PREFIX = ID_FIELD_NAME + PATH_DELIMITER;
4344
private static final String ID_SUBFIELD_NAME_PREFIX = ID_FIELD_NAME + NAME_DELIMITER;
4445

46+
/**
47+
* @deprecated This constant will be removed in YOJ 2.7.0.
48+
* <p>If you need a {@link Comparator} to manually sort entities by ID ascending,
49+
* use {@link EntitySchema#defaultOrder()} if you have an entity schema,
50+
* or {@code Comparator.comparing(Entity::getId, idSchema)} if you have an entity ID schema.
51+
* <p>To obtain entity schema or entity ID schema, see {@code EntitySchema.of()},
52+
* {@link EntitySchema#getIdSchema()} and {@code EntityIdSchema.{of, from, ofEntity}()}.
53+
*/
54+
@Deprecated(forRemoval = true)
4555
public static final Comparator<Entity<?>> SORT_ENTITY_BY_ID = Comparator.comparing(
46-
Entity::getId, (a, b) -> EntityIdSchema.ofEntity(a.getType()).compare(a, b)
56+
Entity::getId, (a, b) -> {
57+
DeprecationWarnings.warnOnce("EntityIdSchema[" + a.getClass().getName() + "].SORT_ENTITY_BY_ID",
58+
"EntityIdSchema.SORT_ENTITY_BY_ID constant will be removed in YOJ 2.7.0. "
59+
+ "Please use EntitySchema.defaultOrder() if you have an entity schema, or "
60+
+ "Comparator.comparing(Entity::getId, idSchema) if you have an entity ID schema.");
61+
return EntityIdSchema.ofEntity(a.getType()).compare(a, b);
62+
}
4763
);
4864

65+
/**
66+
* @deprecated This method serves no useful purpose and will be removed in YOJ 2.7.0.
67+
* <p>If you need a {@link Comparator} for entity IDs, use the {@code EntityIdSchema} instance as it already implements {@code Comparator<ID>}.
68+
*/
69+
@Deprecated(forRemoval = true)
4970
public static <T extends Entity<T>> Comparator<Entity.Id<T>> getIdComparator(Class<T> type) {
71+
DeprecationWarnings.warnOnce("EntityIdSchema.getIdComparator(" + type.getName() + ")",
72+
"EntityIdSchema.getIdComparator(Class) method will be removed in YOJ 2.7.0. Please use the EntityIdSchema itself as the comparator");
5073
return Comparator.comparing(
5174
id -> id, (a, b) -> EntityIdSchema.ofEntity(type).compare(a, b)
5275
);

repository/src/main/java/tech/ydb/yoj/repository/db/EntitySchema.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import tech.ydb.yoj.databind.schema.reflect.Reflector;
1111

1212
import java.lang.reflect.Type;
13+
import java.util.Comparator;
1314
import java.util.List;
1415
import java.util.Map;
1516

@@ -117,4 +118,12 @@ public Map<String, Object> flattenId(Entity.Id<T> idValue) {
117118
public <V extends Table.View> ViewSchema<V> getViewSchema(Class<V> viewClass) {
118119
return ViewSchema.of(getRegistry(), viewClass, getNamingStrategy());
119120
}
121+
122+
/**
123+
* @return a comparator for sorting entities by ID ascending
124+
* @since 2.6.24
125+
*/
126+
public Comparator<T> defaultOrder() {
127+
return Comparator.comparing(Entity::getId, getIdSchema());
128+
}
120129
}

repository/src/main/java/tech/ydb/yoj/repository/db/TableQueryImpl.java

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
package tech.ydb.yoj.repository.db;
22

33
import com.google.common.collect.Sets;
4+
import lombok.NonNull;
45
import tech.ydb.yoj.InternalApi;
6+
import tech.ydb.yoj.databind.expression.FilterExpression;
7+
import tech.ydb.yoj.databind.expression.OrderExpression;
58
import tech.ydb.yoj.repository.db.cache.FirstLevelCache;
9+
import tech.ydb.yoj.repository.db.list.InMemoryQueries;
610
import tech.ydb.yoj.repository.db.list.ListRequest;
11+
import tech.ydb.yoj.util.function.StreamSupplier;
712

13+
import javax.annotation.Nullable;
814
import java.util.HashMap;
915
import java.util.HashSet;
1016
import java.util.List;
1117
import java.util.Optional;
1218
import java.util.Set;
1319
import java.util.function.Function;
1420
import java.util.stream.Collectors;
21+
import java.util.stream.Stream;
1522

23+
import static java.util.stream.Collectors.toList;
1624
import static java.util.stream.Collectors.toSet;
1725

1826
/**
@@ -25,14 +33,16 @@ public final class TableQueryImpl {
2533
private TableQueryImpl() {
2634
}
2735

36+
@NonNull
2837
public static <E extends Entity<E>, ID extends Entity.Id<E>> List<E> find(
29-
Table<E> table, FirstLevelCache<E> cache, Set<ID> ids
38+
@NonNull Table<E> table, @NonNull EntitySchema<E> schema, @NonNull FirstLevelCache<E> cache,
39+
@NonNull Set<ID> ids
3040
) {
3141
if (ids.isEmpty()) {
3242
return List.of();
3343
}
3444

35-
var orderBy = EntityExpressions.defaultOrder(table.getType());
45+
var orderBy = EntityExpressions.defaultOrder(schema);
3646
var isPartialIdMode = ids.iterator().next().isPartial();
3747

3848
var foundInCache = ids.stream()
@@ -71,15 +81,49 @@ public static <E extends Entity<E>, ID extends Entity.Id<E>> List<E> find(
7181
Sets.difference(Sets.difference(ids, foundInDbIds), foundInCacheIds).forEach(cache::putEmpty);
7282
}
7383

74-
return merged.values().stream().sorted(EntityIdSchema.SORT_ENTITY_BY_ID).collect(Collectors.toList());
84+
return merged.values().stream()
85+
.sorted(schema.defaultOrder())
86+
.collect(toList());
7587
}
7688

77-
public static <E extends Entity<E>> TableQueryBuilder<E> toQueryBuilder(Table<E> table, ListRequest<E> request) {
89+
@NonNull
90+
public static <E extends Entity<E>> TableQueryBuilder<E> toQueryBuilder(@NonNull Table<E> table, @NonNull ListRequest<E> request) {
7891
return table.query()
7992
.index(request.getIndex())
8093
.filter(request.getFilter())
8194
.orderBy(request.getOrderBy())
8295
.offset(request.getOffset())
8396
.limit(request.getPageSize() + 1);
8497
}
98+
99+
public static <T extends Entity<T>> List<T> find(@NonNull StreamSupplier<T> streamSupplier,
100+
@NonNull EntitySchema<T> schema,
101+
@Nullable FilterExpression<T> filter,
102+
@Nullable OrderExpression<T> orderBy,
103+
@Nullable Integer limit,
104+
@Nullable Long offset) {
105+
if (limit == null && offset != null && offset > 0) {
106+
throw new IllegalArgumentException("offset > 0 with limit=null is not supported");
107+
}
108+
109+
try (Stream<T> stream = streamSupplier.stream()) {
110+
Stream<T> foundStream = stream;
111+
if (filter != null) {
112+
foundStream = foundStream.filter(InMemoryQueries.toPredicate(filter));
113+
}
114+
if (orderBy != null) {
115+
foundStream = foundStream.sorted(InMemoryQueries.toComparator(orderBy));
116+
} else {
117+
foundStream = foundStream.sorted(schema.defaultOrder());
118+
}
119+
120+
foundStream = foundStream.skip(offset == null ? 0L : offset);
121+
122+
if (limit != null) {
123+
foundStream = foundStream.limit(limit);
124+
}
125+
126+
return foundStream.collect(toList());
127+
}
128+
}
85129
}

repository/src/main/java/tech/ydb/yoj/repository/db/list/InMemoryQueries.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
import tech.ydb.yoj.databind.schema.Schema;
1414
import tech.ydb.yoj.databind.schema.Schema.JavaField;
1515
import tech.ydb.yoj.repository.db.Entity;
16+
import tech.ydb.yoj.repository.db.EntityIdSchema;
17+
import tech.ydb.yoj.repository.db.EntitySchema;
18+
import tech.ydb.yoj.repository.db.TableQueryImpl;
1619
import tech.ydb.yoj.util.function.StreamSupplier;
1720

1821
import javax.annotation.Nullable;
@@ -29,18 +32,26 @@
2932
import static java.util.function.Predicate.not;
3033
import static java.util.stream.Collectors.toList;
3134
import static tech.ydb.yoj.databind.expression.OrderExpression.SortOrder.ASCENDING;
32-
import static tech.ydb.yoj.repository.db.EntityIdSchema.SORT_ENTITY_BY_ID;
3335

3436
/**
3537
* Utilities for in-memory filtering and sorting objects that have a {@link Schema} (mostly {@link Entity entities}).
3638
*/
3739
public final class InMemoryQueries {
40+
@Deprecated(forRemoval = true)
41+
private static final Comparator<Entity<?>> ENTITY_DEFAULT_ORDER_VIA_REFLECTION = Comparator.comparing(
42+
Entity::getId, (a, b) -> EntityIdSchema.ofEntity(a.getType()).compare(a, b)
43+
);
44+
3845
public static <T extends Entity<T>> ListResult<T> list(@NonNull StreamSupplier<T> streamSupplier,
3946
@NonNull ListRequest<T> request) {
47+
if (!(request.getSchema() instanceof EntitySchema<T> entitySchema)) {
48+
throw new IllegalArgumentException("Expected ListRequest for an entity, but got a non-entity schema: " + request.getSchema());
49+
}
4050
return ListResult.forPage(
4151
request,
42-
find(
52+
TableQueryImpl.find(
4353
streamSupplier,
54+
entitySchema,
4455
request.getFilter(),
4556
request.getOrderBy(),
4657
request.getPageSize() + 1,
@@ -49,6 +60,10 @@ public static <T extends Entity<T>> ListResult<T> list(@NonNull StreamSupplier<T
4960
);
5061
}
5162

63+
/**
64+
* @deprecated This method is an implementation detail leaked into the public YOJ API. It will be removed in YOJ 2.7.0.
65+
*/
66+
@Deprecated(forRemoval = true)
5267
public static <T extends Entity<T>> List<T> find(@NonNull StreamSupplier<T> streamSupplier,
5368
@Nullable FilterExpression<T> filter,
5469
@Nullable OrderExpression<T> orderBy,
@@ -66,7 +81,7 @@ public static <T extends Entity<T>> List<T> find(@NonNull StreamSupplier<T> stre
6681
if (orderBy != null) {
6782
foundStream = foundStream.sorted(toComparator(orderBy));
6883
} else {
69-
foundStream = foundStream.sorted(SORT_ENTITY_BY_ID);
84+
foundStream = foundStream.sorted(ENTITY_DEFAULT_ORDER_VIA_REFLECTION);
7085
}
7186

7287
foundStream = foundStream.skip(offset == null ? 0L : offset);

0 commit comments

Comments
 (0)