Skip to content

Commit c826182

Browse files
authored
feat: Add support for optional embeddable null handling (#1410)
2 parents 8b949f6 + dcf3da5 commit c826182

File tree

15 files changed

+144
-51
lines changed

15 files changed

+144
-51
lines changed

doma-core/src/main/java/org/seasar/doma/jdbc/entity/EmbeddableType.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ public interface EmbeddableType<EMBEDDABLE> {
118118
* @param __args a map of property names to property values for initializing the embeddable
119119
* @return a new instance of the embeddable object
120120
*/
121+
@Deprecated
122+
default <ENTITY> EMBEDDABLE newEmbeddable(
123+
String embeddedPropertyName, Map<String, Property<ENTITY, ?>> __args) {
124+
return newEmbeddable(embeddedPropertyName, __args, false);
125+
}
126+
121127
<ENTITY> EMBEDDABLE newEmbeddable(
122-
String embeddedPropertyName, Map<String, Property<ENTITY, ?>> __args);
128+
String embeddedPropertyName, Map<String, Property<ENTITY, ?>> __args, boolean optional);
123129
}

doma-processor/src/main/java/org/seasar/doma/internal/apt/generator/EmbeddableTypeGenerator.java

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -181,40 +181,53 @@ private void printNewEmbeddableMethod() {
181181
}
182182
iprint("@Override%n");
183183
iprint(
184-
"public <ENTITY> %1$s newEmbeddable(String embeddedPropertyName, %2$s<String, %3$s<ENTITY, ?>> __args) {%n",
184+
"public <ENTITY> %1$s newEmbeddable(String embeddedPropertyName, %2$s<String, %3$s<ENTITY, ?>> __args, boolean optional) {%n",
185185
embeddableMeta.getType(), Map.class, Property.class);
186186
if (embeddableMeta.isAbstract()) {
187187
iprint(" return null;%n");
188188
} else {
189-
iprint(" return new %1$s(%n", embeddableMeta.getType());
190-
for (Iterator<EmbeddableFieldMeta> it = embeddableMeta.getEmbeddableFieldMetas().iterator();
191-
it.hasNext(); ) {
192-
EmbeddableFieldMeta fieldMeta = it.next();
189+
int i = 0;
190+
for (EmbeddableFieldMeta fieldMeta : embeddableMeta.getEmbeddableFieldMetas()) {
191+
iprint(" var __p%s = ", i++);
193192
if (fieldMeta instanceof EmbeddedMeta embeddedMeta) {
194193
if (embeddedMeta.optional()) {
195-
iprint(
196-
" java.util.Optional.ofNullable((%1$s)%2$s.newEmbeddable(embeddedPropertyName + \".%3$s\", __args))",
194+
print(
195+
"java.util.Optional.ofNullable((%1$s)%2$s.newEmbeddable(embeddedPropertyName + \".%3$s\", __args, true))",
197196
/* 1 */ embeddedMeta.embeddableMeta().getType(),
198197
/* 2 */ embeddedMeta.embeddableCtType().getTypeCode(),
199198
/* 3 */ embeddedMeta.name());
200199
} else {
201-
iprint(
202-
" (%1$s)%2$s.newEmbeddable(embeddedPropertyName + \".%3$s\", __args)",
200+
print(
201+
"(%1$s)%2$s.newEmbeddable(embeddedPropertyName + \".%3$s\", __args, false)",
203202
/* 1 */ embeddedMeta.embeddableMeta().getType(),
204203
/* 2 */ embeddedMeta.embeddableCtType().getTypeCode(),
205204
/* 3 */ embeddedMeta.name());
206205
}
207206
} else if (fieldMeta instanceof EmbeddablePropertyMeta propertyMeta) {
208-
iprint(
209-
" (%1$s)(__args.get(embeddedPropertyName + \".%2$s\") "
207+
print(
208+
"(%1$s)(__args.get(embeddedPropertyName + \".%2$s\") "
210209
+ "!= null ? __args.get(embeddedPropertyName + \".%2$s\").get() : null)",
211210
propertyMeta.getBoxedType(), propertyMeta.getName());
212211
} else {
213212
throw new AptIllegalStateException(fieldMeta.toString());
214213
}
215-
if (it.hasNext()) {
216-
print(",%n");
217-
}
214+
print(";%n");
215+
}
216+
iprint(" if (optional) {%n");
217+
iprint(" var __stream = java.util.stream.Stream.<Object>of(");
218+
for (int j = 0; j < i; j++) {
219+
print("__p%s%s", j, j == i - 1 ? "" : ", ");
220+
}
221+
print(
222+
").map(it -> (it instanceof java.util.Optional<?> o) ? o.orElse(null) : it).filter(java.util.Objects::nonNull);;%n",
223+
i);
224+
iprint(" if (__stream.findAny().isEmpty()) {%n");
225+
iprint(" return null;%n");
226+
iprint(" }%n");
227+
iprint(" }%n");
228+
iprint(" return new %1$s(", embeddableMeta.getType());
229+
for (int j = 0; j < i; j++) {
230+
print("__p%s%s", j, j == i - 1 ? "" : ", ");
218231
}
219232
print(");%n");
220233
}

doma-processor/src/main/java/org/seasar/doma/internal/apt/generator/EntityTypeGenerator.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -652,11 +652,11 @@ private void printNewEntityMethod() {
652652
if (fieldMeta instanceof EmbeddedMeta embeddedMeta) {
653653
if (embeddedMeta.optional()) {
654654
iprint(
655-
" java.util.Optional.ofNullable(%1$s.newEmbeddable(\"%2$s\", __args))",
655+
" java.util.Optional.ofNullable(%1$s.newEmbeddable(\"%2$s\", __args, true))",
656656
embeddedMeta.embeddableCtType().getTypeCode(), fieldMeta.getName());
657657
} else {
658658
iprint(
659-
" %1$s.newEmbeddable(\"%2$s\", __args)",
659+
" %1$s.newEmbeddable(\"%2$s\", __args, false)",
660660
embeddedMeta.embeddableCtType().getTypeCode(), fieldMeta.getName());
661661
}
662662
} else if (fieldMeta instanceof EntityPropertyMeta propertyMeta) {
@@ -676,13 +676,14 @@ private void printNewEntityMethod() {
676676
for (EntityFieldMeta fieldMeta : entityMeta.getAllFieldMetas()) {
677677
if (fieldMeta instanceof EmbeddedMeta embeddedMeta) {
678678
iprint(
679-
" ((%4$s<%5$s, %6$s>)__embeddedPropertyTypeMap.get(\"%1$s\")).save(entity, %2$s.newEmbeddable(\"%3$s\", __args));%n",
679+
" ((%4$s<%5$s, %6$s>)__embeddedPropertyTypeMap.get(\"%1$s\")).save(entity, %2$s.newEmbeddable(\"%3$s\", __args, %7$s));%n",
680680
/* 1 */ fieldMeta.getName(),
681681
/* 2 */ embeddedMeta.embeddableCtType().getTypeCode(),
682682
/* 3 */ fieldMeta.getName(),
683683
/* 4 */ EmbeddedPropertyType.class,
684684
/* 5 */ entityMeta.getType(),
685-
/* 6 */ embeddedMeta.embeddableCtType().getType());
685+
/* 6 */ embeddedMeta.embeddableCtType().getType(),
686+
/* 7 */ embeddedMeta.optional());
686687

687688
} else if (fieldMeta instanceof EntityPropertyMeta propertyMeta) {
688689
iprint(

doma-processor/src/test/resources/org/seasar/doma/internal/apt/processor/embeddable/EmbeddableProcessorTest_AbstractEmbeddable.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public final class _AbstractEmbeddable implements org.seasar.doma.jdbc.entity.Em
1919
}
2020

2121
@Override
22-
public <ENTITY> org.seasar.doma.internal.apt.processor.embeddable.AbstractEmbeddable newEmbeddable(String embeddedPropertyName, java.util.Map<String, org.seasar.doma.jdbc.entity.Property<ENTITY, ?>> __args) {
22+
public <ENTITY> org.seasar.doma.internal.apt.processor.embeddable.AbstractEmbeddable newEmbeddable(String embeddedPropertyName, java.util.Map<String, org.seasar.doma.jdbc.entity.Property<ENTITY, ?>> __args, boolean optional) {
2323
return null;
2424
}
2525

doma-processor/src/test/resources/org/seasar/doma/internal/apt/processor/embeddable/EmbeddableProcessorTest_Address.txt

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,16 @@ public final class _Address implements org.seasar.doma.jdbc.entity.EmbeddableTyp
2020
}
2121

2222
@Override
23-
public <ENTITY> org.seasar.doma.internal.apt.processor.embeddable.Address newEmbeddable(String embeddedPropertyName, java.util.Map<String, org.seasar.doma.jdbc.entity.Property<ENTITY, ?>> __args) {
24-
return new org.seasar.doma.internal.apt.processor.embeddable.Address(
25-
(java.lang.String)(__args.get(embeddedPropertyName + ".city") != null ? __args.get(embeddedPropertyName + ".city").get() : null),
26-
(java.lang.String)(__args.get(embeddedPropertyName + ".street") != null ? __args.get(embeddedPropertyName + ".street").get() : null));
23+
public <ENTITY> org.seasar.doma.internal.apt.processor.embeddable.Address newEmbeddable(String embeddedPropertyName, java.util.Map<String, org.seasar.doma.jdbc.entity.Property<ENTITY, ?>> __args, boolean optional) {
24+
var __p0 = (java.lang.String)(__args.get(embeddedPropertyName + ".city") != null ? __args.get(embeddedPropertyName + ".city").get() : null);
25+
var __p1 = (java.lang.String)(__args.get(embeddedPropertyName + ".street") != null ? __args.get(embeddedPropertyName + ".street").get() : null);
26+
if (optional) {
27+
var __stream = java.util.stream.Stream.<Object>of(__p0, __p1).map(it -> (it instanceof java.util.Optional<?> o) ? o.orElse(null) : it).filter(java.util.Objects::nonNull);;
28+
if (__stream.findAny().isEmpty()) {
29+
return null;
30+
}
31+
}
32+
return new org.seasar.doma.internal.apt.processor.embeddable.Address(__p0, __p1);
2733
}
2834

2935
/**

doma-processor/src/test/resources/org/seasar/doma/internal/apt/processor/embeddable/EmbeddableProcessorTest_Derived.txt

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,16 @@ public final class _Derived implements org.seasar.doma.jdbc.entity.EmbeddableTyp
2020
}
2121

2222
@Override
23-
public <ENTITY> org.seasar.doma.internal.apt.processor.embeddable.Derived newEmbeddable(String embeddedPropertyName, java.util.Map<String, org.seasar.doma.jdbc.entity.Property<ENTITY, ?>> __args) {
24-
return new org.seasar.doma.internal.apt.processor.embeddable.Derived(
25-
(java.lang.String)(__args.get(embeddedPropertyName + ".aaa") != null ? __args.get(embeddedPropertyName + ".aaa").get() : null),
26-
(java.lang.String)(__args.get(embeddedPropertyName + ".bbb") != null ? __args.get(embeddedPropertyName + ".bbb").get() : null));
23+
public <ENTITY> org.seasar.doma.internal.apt.processor.embeddable.Derived newEmbeddable(String embeddedPropertyName, java.util.Map<String, org.seasar.doma.jdbc.entity.Property<ENTITY, ?>> __args, boolean optional) {
24+
var __p0 = (java.lang.String)(__args.get(embeddedPropertyName + ".aaa") != null ? __args.get(embeddedPropertyName + ".aaa").get() : null);
25+
var __p1 = (java.lang.String)(__args.get(embeddedPropertyName + ".bbb") != null ? __args.get(embeddedPropertyName + ".bbb").get() : null);
26+
if (optional) {
27+
var __stream = java.util.stream.Stream.<Object>of(__p0, __p1).map(it -> (it instanceof java.util.Optional<?> o) ? o.orElse(null) : it).filter(java.util.Objects::nonNull);;
28+
if (__stream.findAny().isEmpty()) {
29+
return null;
30+
}
31+
}
32+
return new org.seasar.doma.internal.apt.processor.embeddable.Derived(__p0, __p1);
2733
}
2834

2935
/**

doma-processor/src/test/resources/org/seasar/doma/internal/apt/processor/embeddable/EmbeddableProcessorTest_LombokAllArgsConstructor.txt

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,16 @@ public final class _LombokAllArgsConstructor implements org.seasar.doma.jdbc.ent
2020
}
2121

2222
@Override
23-
public <ENTITY> org.seasar.doma.internal.apt.processor.embeddable.LombokAllArgsConstructor newEmbeddable(String embeddedPropertyName, java.util.Map<String, org.seasar.doma.jdbc.entity.Property<ENTITY, ?>> __args) {
24-
return new org.seasar.doma.internal.apt.processor.embeddable.LombokAllArgsConstructor(
25-
(java.lang.String)(__args.get(embeddedPropertyName + ".street") != null ? __args.get(embeddedPropertyName + ".street").get() : null),
26-
(java.lang.String)(__args.get(embeddedPropertyName + ".city") != null ? __args.get(embeddedPropertyName + ".city").get() : null));
23+
public <ENTITY> org.seasar.doma.internal.apt.processor.embeddable.LombokAllArgsConstructor newEmbeddable(String embeddedPropertyName, java.util.Map<String, org.seasar.doma.jdbc.entity.Property<ENTITY, ?>> __args, boolean optional) {
24+
var __p0 = (java.lang.String)(__args.get(embeddedPropertyName + ".street") != null ? __args.get(embeddedPropertyName + ".street").get() : null);
25+
var __p1 = (java.lang.String)(__args.get(embeddedPropertyName + ".city") != null ? __args.get(embeddedPropertyName + ".city").get() : null);
26+
if (optional) {
27+
var __stream = java.util.stream.Stream.<Object>of(__p0, __p1).map(it -> (it instanceof java.util.Optional<?> o) ? o.orElse(null) : it).filter(java.util.Objects::nonNull);;
28+
if (__stream.findAny().isEmpty()) {
29+
return null;
30+
}
31+
}
32+
return new org.seasar.doma.internal.apt.processor.embeddable.LombokAllArgsConstructor(__p0, __p1);
2733
}
2834

2935
/**

doma-processor/src/test/resources/org/seasar/doma/internal/apt/processor/embeddable/EmbeddableProcessorTest_LombokValue.txt

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,16 @@ public final class _LombokValue implements org.seasar.doma.jdbc.entity.Embeddabl
2020
}
2121

2222
@Override
23-
public <ENTITY> org.seasar.doma.internal.apt.processor.embeddable.LombokValue newEmbeddable(String embeddedPropertyName, java.util.Map<String, org.seasar.doma.jdbc.entity.Property<ENTITY, ?>> __args) {
24-
return new org.seasar.doma.internal.apt.processor.embeddable.LombokValue(
25-
(java.lang.String)(__args.get(embeddedPropertyName + ".street") != null ? __args.get(embeddedPropertyName + ".street").get() : null),
26-
(java.lang.String)(__args.get(embeddedPropertyName + ".city") != null ? __args.get(embeddedPropertyName + ".city").get() : null));
23+
public <ENTITY> org.seasar.doma.internal.apt.processor.embeddable.LombokValue newEmbeddable(String embeddedPropertyName, java.util.Map<String, org.seasar.doma.jdbc.entity.Property<ENTITY, ?>> __args, boolean optional) {
24+
var __p0 = (java.lang.String)(__args.get(embeddedPropertyName + ".street") != null ? __args.get(embeddedPropertyName + ".street").get() : null);
25+
var __p1 = (java.lang.String)(__args.get(embeddedPropertyName + ".city") != null ? __args.get(embeddedPropertyName + ".city").get() : null);
26+
if (optional) {
27+
var __stream = java.util.stream.Stream.<Object>of(__p0, __p1).map(it -> (it instanceof java.util.Optional<?> o) ? o.orElse(null) : it).filter(java.util.Objects::nonNull);;
28+
if (__stream.findAny().isEmpty()) {
29+
return null;
30+
}
31+
}
32+
return new org.seasar.doma.internal.apt.processor.embeddable.LombokValue(__p0, __p1);
2733
}
2834

2935
/**

doma-processor/src/test/resources/org/seasar/doma/internal/apt/processor/embeddable/EmbeddableProcessorTest_NestedEmbeddable1.txt

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,16 @@ public final class _NestedEmbeddable1 implements org.seasar.doma.jdbc.entity.Emb
2121

2222
@SuppressWarnings("unchecked")
2323
@Override
24-
public <ENTITY> org.seasar.doma.internal.apt.processor.embeddable.NestedEmbeddable1 newEmbeddable(String embeddedPropertyName, java.util.Map<String, org.seasar.doma.jdbc.entity.Property<ENTITY, ?>> __args) {
25-
return new org.seasar.doma.internal.apt.processor.embeddable.NestedEmbeddable1(
26-
(org.seasar.doma.internal.apt.processor.embeddable.NestedEmbeddable2)org.seasar.doma.internal.apt.processor.embeddable._NestedEmbeddable2.getSingletonInternal().newEmbeddable(embeddedPropertyName + ".nestedEmbeddable2", __args),
27-
java.util.Optional.ofNullable((org.seasar.doma.internal.apt.processor.embeddable.NestedEmbeddable2)org.seasar.doma.internal.apt.processor.embeddable._NestedEmbeddable2.getSingletonInternal().newEmbeddable(embeddedPropertyName + ".optionalNestedEmbeddable2", __args)));
24+
public <ENTITY> org.seasar.doma.internal.apt.processor.embeddable.NestedEmbeddable1 newEmbeddable(String embeddedPropertyName, java.util.Map<String, org.seasar.doma.jdbc.entity.Property<ENTITY, ?>> __args, boolean optional) {
25+
var __p0 = (org.seasar.doma.internal.apt.processor.embeddable.NestedEmbeddable2)org.seasar.doma.internal.apt.processor.embeddable._NestedEmbeddable2.getSingletonInternal().newEmbeddable(embeddedPropertyName + ".nestedEmbeddable2", __args, false);
26+
var __p1 = java.util.Optional.ofNullable((org.seasar.doma.internal.apt.processor.embeddable.NestedEmbeddable2)org.seasar.doma.internal.apt.processor.embeddable._NestedEmbeddable2.getSingletonInternal().newEmbeddable(embeddedPropertyName + ".optionalNestedEmbeddable2", __args, true));
27+
if (optional) {
28+
var __stream = java.util.stream.Stream.<Object>of(__p0, __p1).map(it -> (it instanceof java.util.Optional<?> o) ? o.orElse(null) : it).filter(java.util.Objects::nonNull);;
29+
if (__stream.findAny().isEmpty()) {
30+
return null;
31+
}
32+
}
33+
return new org.seasar.doma.internal.apt.processor.embeddable.NestedEmbeddable1(__p0, __p1);
2834
}
2935

3036
/**

doma-processor/src/test/resources/org/seasar/doma/internal/apt/processor/embeddable/EmbeddableProcessorTest_NotTopLevel.txt

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,16 @@ public final class _NotTopLevel__Address implements org.seasar.doma.jdbc.entity.
2020
}
2121

2222
@Override
23-
public <ENTITY> org.seasar.doma.internal.apt.processor.embeddable.NotTopLevel.Address newEmbeddable(String embeddedPropertyName, java.util.Map<String, org.seasar.doma.jdbc.entity.Property<ENTITY, ?>> __args) {
24-
return new org.seasar.doma.internal.apt.processor.embeddable.NotTopLevel.Address(
25-
(java.lang.String)(__args.get(embeddedPropertyName + ".city") != null ? __args.get(embeddedPropertyName + ".city").get() : null),
26-
(java.lang.String)(__args.get(embeddedPropertyName + ".street") != null ? __args.get(embeddedPropertyName + ".street").get() : null));
23+
public <ENTITY> org.seasar.doma.internal.apt.processor.embeddable.NotTopLevel.Address newEmbeddable(String embeddedPropertyName, java.util.Map<String, org.seasar.doma.jdbc.entity.Property<ENTITY, ?>> __args, boolean optional) {
24+
var __p0 = (java.lang.String)(__args.get(embeddedPropertyName + ".city") != null ? __args.get(embeddedPropertyName + ".city").get() : null);
25+
var __p1 = (java.lang.String)(__args.get(embeddedPropertyName + ".street") != null ? __args.get(embeddedPropertyName + ".street").get() : null);
26+
if (optional) {
27+
var __stream = java.util.stream.Stream.<Object>of(__p0, __p1).map(it -> (it instanceof java.util.Optional<?> o) ? o.orElse(null) : it).filter(java.util.Objects::nonNull);;
28+
if (__stream.findAny().isEmpty()) {
29+
return null;
30+
}
31+
}
32+
return new org.seasar.doma.internal.apt.processor.embeddable.NotTopLevel.Address(__p0, __p1);
2733
}
2834

2935
/**

0 commit comments

Comments
 (0)