Skip to content

Commit 112f9d6

Browse files
authored
Support for string value types with single-argument String constructor (#25)
in addition to using the fromString(String)/valueOf(String) static methods
1 parent 33297ee commit 112f9d6

File tree

6 files changed

+74
-15
lines changed

6 files changed

+74
-15
lines changed

repository-test/src/main/java/tech/ydb/yoj/repository/test/ListingTest.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ public void enumParsing() {
213213
@Test
214214
public void embeddedNulls() {
215215
db.tx(() -> db.typeFreaks().insert(
216-
new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null)
216+
new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null)
217217
));
218218
ListResult<TypeFreak> lst = db.tx(() -> db.typeFreaks().list(ListRequest.builder(TypeFreak.class)
219219
.filter(fb -> fb.where("embedded.a.a").eq("myfqdn"))
@@ -226,7 +226,7 @@ public void embeddedNulls() {
226226

227227
@Test
228228
public void flattenedIsNull() {
229-
var tf = new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
229+
var tf = new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
230230
db.tx(() -> db.typeFreaks().insert(tf));
231231

232232
ListResult<TypeFreak> lst = db.tx(() -> db.typeFreaks().list(ListRequest.builder(TypeFreak.class)
@@ -240,7 +240,7 @@ public void flattenedIsNull() {
240240

241241
@Test
242242
public void flattenedIsNotNull() {
243-
var tf = new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new TypeFreak.Embedded(new TypeFreak.A("A"), new TypeFreak.B("B")), null, null, null, null, null, null, null, null, null, null);
243+
var tf = new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new TypeFreak.Embedded(new TypeFreak.A("A"), new TypeFreak.B("B")), null, null, null, null, null, null, null, null, null, null, null);
244244
db.tx(() -> db.typeFreaks().insert(tf));
245245

246246
ListResult<TypeFreak> lst = db.tx(() -> db.typeFreaks().list(ListRequest.builder(TypeFreak.class)
@@ -455,6 +455,7 @@ public void listByNamesWithUnderscores() {
455455
emptyMap(),
456456
emptyMap(),
457457
emptyMap(),
458+
null,
458459
"CUSTOM NAMED COLUMN",
459460
null
460461
);
@@ -474,7 +475,7 @@ public void listByNamesWithUnderscores() {
474475

475476
@Test
476477
public void listStringValuedFilteredByString() {
477-
TypeFreak typeFreak = new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new TypeFreak.Ticket("CLOUD", 100500));
478+
TypeFreak typeFreak = new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new TypeFreak.Ticket("CLOUD", 100500));
478479
db.tx(() -> db.typeFreaks().insert(typeFreak));
479480

480481
db.tx(() -> {
@@ -489,10 +490,27 @@ public void listStringValuedFilteredByString() {
489490
});
490491
}
491492

493+
@Test
494+
public void listStringValuedFilteredByString2() {
495+
TypeFreak typeFreak = new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new TypeFreak.StringValueWrapper("svw 123"), null, null);
496+
db.tx(() -> db.typeFreaks().insert(typeFreak));
497+
498+
db.tx(() -> {
499+
ListResult<TypeFreak> page = listTypeFreak(ListRequest.builder(TypeFreak.class)
500+
.pageSize(100)
501+
.filter(newFilterBuilder(TypeFreak.class)
502+
.where("stringValueWrapper").eq("svw 123")
503+
.build())
504+
.build());
505+
assertThat(page).containsExactly(typeFreak);
506+
assertThat(page.isLastPage()).isTrue();
507+
});
508+
}
509+
492510
@Test
493511
public void listStringValuedFilteredByStruct() {
494512
TypeFreak.Ticket ticket = new TypeFreak.Ticket("CLOUD", 100500);
495-
TypeFreak typeFreak = new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, ticket);
513+
TypeFreak typeFreak = new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, ticket);
496514
db.tx(() -> db.typeFreaks().insert(typeFreak));
497515

498516
db.tx(() -> {

repository-test/src/main/java/tech/ydb/yoj/repository/test/RepositoryTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1486,6 +1486,8 @@ protected TypeFreak newTypeFreak(int n, String a, String b) {
14861486
singletonMap(1, new Embedded(new A("ooo"), new B("ppp"))),
14871487
singletonMap(1, new Embedded(new A("ppp"), new B("qqq"))),
14881488

1489+
new TypeFreak.StringValueWrapper("the string value wrapper"),
1490+
14891491
"hi there",
14901492

14911493
new TypeFreak.Ticket("CLOUD", 25)
@@ -1645,6 +1647,7 @@ public void allTypesNull() {
16451647
singletonMap(1, new Embedded(new A("a"), new B("b"))),
16461648
singletonMap(1, new Embedded(new A("a"), new B("b"))),
16471649
null,
1650+
null,
16481651
null
16491652
);
16501653
db.typeFreaks().save(t);
@@ -1693,6 +1696,7 @@ public void allTypesWithNulls() {
16931696
null,
16941697
null,
16951698
null,
1699+
null,
16961700
"hi",
16971701
null
16981702
);

repository-test/src/main/java/tech/ydb/yoj/repository/test/TableQueryBuilderTest.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ public void enumParsing() {
173173

174174
@Test
175175
public void flattenedIsNull() {
176-
var tf = new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
176+
var tf = new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
177177
db.tx(() -> db.typeFreaks().insert(tf));
178178

179179
List<TypeFreak> lst = db.tx(() -> getQueryBuilder(db.typeFreaks())
@@ -185,7 +185,7 @@ public void flattenedIsNull() {
185185

186186
@Test
187187
public void flattenedIsNotNull() {
188-
var tf = new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new TypeFreak.Embedded(new TypeFreak.A("A"), new TypeFreak.B("B")), null, null, null, null, null, null, null, null, null, null);
188+
var tf = new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new TypeFreak.Embedded(new TypeFreak.A("A"), new TypeFreak.B("B")), null, null, null, null, null, null, null, null, null, null, null);
189189
db.tx(() -> db.typeFreaks().insert(tf));
190190

191191
List<TypeFreak> lst = db.tx(() -> getQueryBuilder(db.typeFreaks())
@@ -197,7 +197,7 @@ public void flattenedIsNotNull() {
197197

198198
@Test
199199
public void filterStringValuedByString() {
200-
TypeFreak typeFreak = new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new TypeFreak.Ticket("CLOUD", 100500));
200+
TypeFreak typeFreak = new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new TypeFreak.Ticket("CLOUD", 100500));
201201
db.tx(() -> db.typeFreaks().insert(typeFreak));
202202
List<TypeFreak> lst = db.tx(() -> getQueryBuilder(db.typeFreaks())
203203
.filter(fb -> fb.where("ticket").eq("CLOUD-100500"))
@@ -210,7 +210,7 @@ public void filterStringValuedByString() {
210210
@Test
211211
public void filterStringValuedByStruct() {
212212
TypeFreak.Ticket ticket = new TypeFreak.Ticket("CLOUD", 100500);
213-
TypeFreak typeFreak = new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, ticket);
213+
TypeFreak typeFreak = new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, ticket);
214214
db.tx(() -> db.typeFreaks().insert(typeFreak));
215215
List<TypeFreak> lst = db.tx(() -> getQueryBuilder(db.typeFreaks())
216216
.filter(newFilterBuilder(TypeFreak.class)
@@ -225,7 +225,7 @@ public void filterStringValuedByStruct() {
225225
@Test
226226
public void embeddedNulls() {
227227
db.tx(() -> db.typeFreaks().insert(
228-
new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null)
228+
new TypeFreak(new TypeFreak.Id("b1p", 1), false, (byte) 0, (byte) 0, (short) 0, 0, 0, 0.0f, 0.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null)
229229
));
230230
List<TypeFreak> lst = db.tx(() -> getQueryBuilder(db.typeFreaks())
231231
.filter(fb -> fb.where("embedded.a.a").eq("myfqdn"))
@@ -427,6 +427,7 @@ public void listByNamesWithUnderscores() {
427427
emptyMap(),
428428
emptyMap(),
429429
emptyMap(),
430+
null,
430431
"CUSTOM NAMED COLUMN",
431432
null
432433
);

repository-test/src/main/java/tech/ydb/yoj/repository/test/entity/TestEntities.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ private TestEntities() {
4343
@SuppressWarnings("unchecked")
4444
public static Repository init(@NonNull Repository repository) {
4545
FieldValueType.registerStringValueType(TypeFreak.Ticket.class);
46+
FieldValueType.registerStringValueType(TypeFreak.StringValueWrapper.class);
4647

4748
repository.createTablespace();
4849
ALL.forEach(entityClass -> repository.schema(entityClass).create());

repository-test/src/main/java/tech/ydb/yoj/repository/test/sample/model/TypeFreak.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.time.Instant;
1212
import java.util.List;
1313
import java.util.Map;
14+
import java.util.Objects;
1415
import java.util.Set;
1516

1617
@Value
@@ -67,6 +68,8 @@ public class TypeFreak implements Entity<TypeFreak> {
6768
@Column(dbType = "JSON_DOCUMENT")
6869
Map<Integer, Embedded> jsonDocumentMap;
6970

71+
StringValueWrapper stringValueWrapper;
72+
7073
@Column(name = "custom_named_column")
7174
String customNamedColumn;
7275

@@ -111,6 +114,29 @@ public static class StringView implements Table.ViewId<TypeFreak> {
111114
String stringEmbedded;
112115
}
113116

117+
public static final class StringValueWrapper {
118+
private final String value;
119+
120+
public StringValueWrapper(String value) {
121+
this.value = Objects.requireNonNull(value);
122+
}
123+
124+
@Override
125+
public boolean equals(Object obj) {
126+
return obj instanceof StringValueWrapper s && s.value.equals(value);
127+
}
128+
129+
@Override
130+
public int hashCode() {
131+
return value.hashCode();
132+
}
133+
134+
@Override
135+
public String toString() {
136+
return value;
137+
}
138+
}
139+
114140
/**
115141
* String-valued type with canonical static factory ({@link #valueOf(String)}) and a matching {@link #toString()}
116142
* instance method.

repository/src/main/java/tech/ydb/yoj/repository/db/common/CommonConverters.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import org.slf4j.LoggerFactory;
77

88
import javax.annotation.ParametersAreNonnullByDefault;
9+
910
import java.lang.reflect.InvocationTargetException;
1011
import java.lang.reflect.Method;
1112
import java.lang.reflect.Type;
@@ -64,10 +65,10 @@ public static <S> ThrowingGetter<S> stringValueGetter(Type type, Function<S, Obj
6465
return rawValueGetter::apply;
6566
}
6667

67-
Method deserializer = getStringValueDeserializerMethod(clazz);
68+
ThrowingGetter<Object> deserializer = getStringValueDeserializerMethod(clazz);
6869
return v -> {
6970
try {
70-
return deserializer.invoke(null, rawValueGetter.apply(v));
71+
return deserializer.throwingGet(rawValueGetter.apply(v));
7172
} catch (InvocationTargetException e) {
7273
// Propagate the real exception thrown by the deserializer method.
7374
// All unhandled getter exceptions are wrapped in ConversionException by the Repository, automatically,
@@ -79,18 +80,26 @@ public static <S> ThrowingGetter<S> stringValueGetter(Type type, Function<S, Obj
7980
};
8081
}
8182

82-
private static Method getStringValueDeserializerMethod(Class<?> clazz) {
83+
private static ThrowingGetter<Object> getStringValueDeserializerMethod(Class<?> clazz) {
8384
for (String methodName : new String[]{"fromString", "valueOf"}) {
8485
try {
8586
Method method = clazz.getMethod(methodName, String.class);
8687
if (isStatic(method.getModifiers())) {
87-
return method;
88+
return s -> method.invoke(null, s);
8889
}
8990
} catch (NoSuchMethodException ignored) {
9091
}
9192
}
93+
94+
try {
95+
return clazz.getConstructor(String.class)::newInstance;
96+
} catch (NoSuchMethodException ignored) {
97+
}
98+
9299
throw new IllegalArgumentException(format(
93-
"Type <%s> does not have a deserializer method: public static fromString(String)/valueOf(String)",
100+
"Type <%s> does not have a deserializer method: public static fromString(String)/valueOf(String) and" +
101+
"doesn't have constructor public %s(String)",
102+
clazz.getTypeName(),
94103
clazz.getTypeName()
95104
));
96105
}

0 commit comments

Comments
 (0)