Skip to content

Commit faeebad

Browse files
authored
Add BiConsumer support in AssociationLinker (#1327)
2 parents a86223c + f5aad91 commit faeebad

File tree

16 files changed

+275
-50
lines changed

16 files changed

+275
-50
lines changed

doma-core/src/main/java/org/seasar/doma/message/Message.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -955,9 +955,9 @@ public enum Message implements MessageResource {
955955
DOMA4462("The property \"{0}\" is not found in the entity class \"{1}\"."),
956956
DOMA4463("'{'\"execTimeMillis\": {0}, \"annotation\": \"{1}\", \"element\": \"{2}\"'}'"),
957957
DOMA4464("Fields annotated with AssociationLinker must be static."),
958-
DOMA4465("Fields annotated with AssociationLinker must be java.util.function.BiFunction."),
958+
DOMA4465("Fields annotated with AssociationLinker must be BiFunction or BiConsumer."),
959959
DOMA4466("The {0} type parameter of BiFunction must be an entity class."),
960-
DOMA4467("The first and third type parameters of java.util.function.BiFunction must be the same"),
960+
DOMA4467("The first and third type parameters of BiFunction must be the same"),
961961
DOMA4468("The tableAlias must not be blank."),
962962
DOMA4469("No field annotated with @AssociationLinker was found in the class \"{0}\"."),
963963
DOMA4470("Fields annotated with AssociationLinker must be public."),
@@ -971,9 +971,9 @@ public enum Message implements MessageResource {
971971
+ "or a `List` of `Optional` containing elements of the entity class."),
972972
DOMA4474("The field \"{0}\" could not be found in the class \"{1}\"."),
973973
DOMA4475(
974-
"The first type parameter of java.util.function.BiFunction differs from the type resolved by the propertyPath. type parameter=\"{0}\", resolved type=\"{1}\"."),
974+
"The first type parameter of BiFunction or BiConsumer differs from the type resolved by the propertyPath. type parameter=\"{0}\", resolved type=\"{1}\"."),
975975
DOMA4476(
976-
"The second type parameter of java.util.function.BiFunction differs from the type resolved by the propertyPath. type parameter=\"{0}\", resolved type=\"{1}\"."),
976+
"The second type parameter of BiFunction or BiConsumer differs from the type resolved by the propertyPath. type parameter=\"{0}\", resolved type=\"{1}\"."),
977977
DOMA4477(
978978
"The type of field \"{0}\" in class \"{1}\" must be one of the following: "
979979
+ "the entity class, "
@@ -1012,6 +1012,7 @@ public enum Message implements MessageResource {
10121012
"When \"returning = @Returning\" is specified, the return type must be the same as the parameter type or an Optional whose element is the parameter type."),
10131013
DOMA4496(
10141014
"When \"returning = @Returning\" is specified, the return type must be a List of the entity class \"{0}\"."),
1015+
DOMA4497("The {0} type parameter of BiConsumer must be an entity class."),
10151016

10161017
// other
10171018
DOMA5001(
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright Doma Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.seasar.doma.internal.apt.cttype;
17+
18+
import static org.seasar.doma.internal.util.AssertionUtil.assertNotNull;
19+
20+
import javax.lang.model.type.TypeMirror;
21+
import org.seasar.doma.internal.apt.RoundContext;
22+
23+
public class BiConsumerCtType extends AbstractCtType {
24+
25+
private final CtType firstArgCtType;
26+
27+
private final CtType secondArgCtType;
28+
29+
BiConsumerCtType(
30+
RoundContext ctx, TypeMirror type, CtType firstArgCtType, CtType secondArgCtType) {
31+
super(ctx, type);
32+
assertNotNull(firstArgCtType, secondArgCtType);
33+
this.firstArgCtType = firstArgCtType;
34+
this.secondArgCtType = secondArgCtType;
35+
}
36+
37+
public CtType getFirstArgCtType() {
38+
return firstArgCtType;
39+
}
40+
41+
public CtType getSecondArgCtType() {
42+
return secondArgCtType;
43+
}
44+
45+
public boolean isRaw() {
46+
return firstArgCtType.isNone() || secondArgCtType.isNone();
47+
}
48+
49+
public boolean hasWildcard() {
50+
return firstArgCtType.isWildcard() || secondArgCtType.isWildcard();
51+
}
52+
53+
@Override
54+
public <R, P, TH extends Throwable> R accept(CtTypeVisitor<R, P, TH> visitor, P p) throws TH {
55+
return visitor.visitBiConsumerCtType(this, p);
56+
}
57+
}

doma-processor/src/main/java/org/seasar/doma/internal/apt/cttype/CtTypeVisitor.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ public interface CtTypeVisitor<R, P, TH extends Throwable> {
6161

6262
R visitBiFunctionCtType(BiFunctionCtType ctType, P p) throws TH;
6363

64+
R visitBiConsumerCtType(BiConsumerCtType ctType, P p) throws TH;
65+
6466
R visitConfigCtType(ConfigCtType ctType, P p) throws TH;
6567

6668
R visitPreparedSqlCtType(PreparedSqlCtType ctType, P p) throws TH;

doma-processor/src/main/java/org/seasar/doma/internal/apt/cttype/CtTypes.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import java.util.OptionalDouble;
4444
import java.util.OptionalInt;
4545
import java.util.OptionalLong;
46+
import java.util.function.BiConsumer;
4647
import java.util.function.BiFunction;
4748
import java.util.function.Function;
4849
import java.util.stream.Collector;
@@ -197,6 +198,17 @@ public BiFunctionCtType newBiFunctionCtType(TypeMirror type) {
197198
return new BiFunctionCtType(ctx, type, firstArgCtType, secondArgCtType, resultCtType);
198199
}
199200

201+
public BiConsumerCtType newBiConsumerCtType(TypeMirror type) {
202+
DeclaredType declaredType = getSuperDeclaredType(type, BiConsumer.class);
203+
if (declaredType == null) {
204+
return null;
205+
}
206+
Iterator<? extends TypeMirror> typeArgs = declaredType.getTypeArguments().iterator();
207+
CtType firstArgCtType = typeArgs.hasNext() ? newCtType(typeArgs.next()) : newNoneCtType();
208+
CtType secondArgCtType = typeArgs.hasNext() ? newCtType(typeArgs.next()) : newNoneCtType();
209+
return new BiConsumerCtType(ctx, type, firstArgCtType, secondArgCtType);
210+
}
211+
200212
private CollectorCtType newCollectorCtType(TypeMirror type) {
201213
DeclaredType declaredType = getSuperDeclaredType(type, Collector.class);
202214
if (declaredType == null) {
@@ -670,6 +682,7 @@ private CtType newCtTypeInternal(
670682
this::newCollectorCtType,
671683
this::newReferenceCtType,
672684
this::newBiFunctionCtType,
685+
this::newBiConsumerCtType,
673686
this::newPreparedSqlCtType,
674687
this::newConfigCtType,
675688
this::newResultCtType,

doma-processor/src/main/java/org/seasar/doma/internal/apt/cttype/SimpleCtTypeVisitor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ public R visitBiFunctionCtType(BiFunctionCtType ctType, P p) throws TH {
139139
return defaultAction(ctType, p);
140140
}
141141

142+
@Override
143+
public R visitBiConsumerCtType(BiConsumerCtType ctType, P p) throws TH {
144+
return defaultAction(ctType, p);
145+
}
146+
142147
@Override
143148
public R visitConfigCtType(ConfigCtType ctType, P p) throws TH {
144149
return defaultAction(ctType, p);

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

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,18 +85,18 @@ private void printConstructor() {
8585
indent();
8686
Iterator<AssociationLinkerMeta> iter = strategyMeta.associationLinkerMetas().iterator();
8787
while (iter.hasNext()) {
88-
AssociationLinkerMeta linkerMeta = iter.next();
88+
var linkerMeta = iter.next();
89+
var linkerExpression = createLinkerExpression(linkerMeta);
8990
iprint(
90-
"%1$s.of(\"%2$s\", \"%3$s\", %4$s, \"%5$s\", %6$s, %7$s, %8$s.%9$s)",
91+
"%1$s.of(\"%2$s\", \"%3$s\", %4$s, \"%5$s\", %6$s, %7$s, %8$s)",
9192
/* 1 */ AssociationLinkerType.class,
9293
/* 2 */ linkerMeta.ancestorPath(),
9394
/* 3 */ linkerMeta.propertyPath(),
9495
/* 4 */ linkerMeta.propertyPathDepth(),
9596
/* 5 */ linkerMeta.tableAlias(),
9697
/* 6 */ linkerMeta.source().getTypeCode(),
9798
/* 7 */ linkerMeta.target().getTypeCode(),
98-
/* 8 */ linkerMeta.classElement(),
99-
/* 9 */ linkerMeta.filedElement());
99+
/* 8 */ linkerExpression);
100100
if (iter.hasNext()) {
101101
print(",");
102102
}
@@ -122,4 +122,14 @@ private void printGetSingletonInternalMethod() {
122122
iprint("}%n");
123123
print("%n");
124124
}
125+
126+
private String createLinkerExpression(AssociationLinkerMeta linkerMeta) {
127+
var expression =
128+
String.format("%1$s.%2$s", linkerMeta.classElement(), linkerMeta.filedElement());
129+
return switch (linkerMeta.linkerKind()) {
130+
case BI_FUNCTION -> expression;
131+
case BI_CONSUMER ->
132+
String.format("(a, b) -> { %1$s.accept(a, b); return null; }", expression);
133+
};
134+
}
125135
}

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

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
import java.util.Iterator;
2222
import java.util.List;
23-
import java.util.Objects;
2423
import java.util.function.Function;
2524
import javax.lang.model.type.TypeKind;
2625
import javax.lang.model.type.TypeMirror;
@@ -46,8 +45,6 @@
4645
import org.seasar.doma.internal.apt.cttype.OptionalLongCtType;
4746
import org.seasar.doma.internal.apt.cttype.SimpleCtTypeVisitor;
4847
import org.seasar.doma.internal.apt.cttype.StreamCtType;
49-
import org.seasar.doma.internal.apt.meta.aggregate.AggregateStrategyMeta;
50-
import org.seasar.doma.internal.apt.meta.aggregate.AssociationLinkerMeta;
5148
import org.seasar.doma.internal.apt.meta.dao.DaoMeta;
5249
import org.seasar.doma.internal.apt.meta.parameter.BasicInOutParameterMeta;
5350
import org.seasar.doma.internal.apt.meta.parameter.BasicInParameterMeta;
@@ -209,7 +206,6 @@
209206
import org.seasar.doma.internal.jdbc.sql.OptionalLongResultListParameter;
210207
import org.seasar.doma.internal.jdbc.sql.OptionalLongSingleResultParameter;
211208
import org.seasar.doma.jdbc.aggregate.AggregateCommand;
212-
import org.seasar.doma.jdbc.aggregate.AssociationLinkerType;
213209
import org.seasar.doma.jdbc.aggregate.ToListReducer;
214210
import org.seasar.doma.jdbc.aggregate.ToOptionalReducer;
215211
import org.seasar.doma.jdbc.aggregate.ToSingleReducer;
@@ -355,32 +351,6 @@ public Void visitSqlFileSelectQueryMeta(final SqlFileSelectQueryMeta m) {
355351
return null;
356352
}
357353

358-
private void printAssociationLinkerTypes(AggregateStrategyMeta aggregateStrategyMeta) {
359-
Objects.requireNonNull(aggregateStrategyMeta);
360-
print("java.util.List.of(%n");
361-
indent();
362-
Iterator<AssociationLinkerMeta> iter =
363-
aggregateStrategyMeta.associationLinkerMetas().iterator();
364-
while (iter.hasNext()) {
365-
AssociationLinkerMeta linkerMeta = iter.next();
366-
iprint(
367-
"%1$s.of(\"%2$s\", \"%3$s\", %4$s, %5$s, %6$s.%7$s)",
368-
AssociationLinkerType.class,
369-
linkerMeta.propertyPath(),
370-
linkerMeta.tableAlias(),
371-
linkerMeta.source().getTypeCode(),
372-
linkerMeta.target().getTypeCode(),
373-
linkerMeta.classElement(),
374-
linkerMeta.filedElement());
375-
if (iter.hasNext()) {
376-
print(",");
377-
}
378-
print("%n");
379-
}
380-
unindent();
381-
iprint(");%n");
382-
}
383-
384354
@Override
385355
public Void visitSqlFileScriptQueryMeta(SqlFileScriptQueryMeta m) {
386356
printEnteringStatements(m);

doma-processor/src/main/java/org/seasar/doma/internal/apt/meta/aggregate/AggregateStrategyMetaFactory.java

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.seasar.doma.internal.apt.RoundContext;
4141
import org.seasar.doma.internal.apt.annot.AggregateStrategyAnnot;
4242
import org.seasar.doma.internal.apt.annot.AssociationLinkerAnnot;
43+
import org.seasar.doma.internal.apt.cttype.BiConsumerCtType;
4344
import org.seasar.doma.internal.apt.cttype.BiFunctionCtType;
4445
import org.seasar.doma.internal.apt.cttype.CtType;
4546
import org.seasar.doma.internal.apt.cttype.CtTypeVisitor;
@@ -308,17 +309,29 @@ private AssociationLinkerMeta createAssociationLinkerMeta(
308309
propertyPathSegments,
309310
propertyPathDepth,
310311
associationLinkerAnnot.getTableAliasValue(),
312+
linkMeta.kind,
311313
linkMeta.source,
312314
linkMeta.target,
313315
aggregateStrategyElement,
314316
fieldElement);
315317
}
316318

317319
private LinkMeta createLinkMeta(VariableElement linkerElement) {
318-
BiFunctionCtType ctType = ctx.getCtTypes().newBiFunctionCtType(linkerElement.asType());
319-
if (ctType == null) {
320-
throw new AptException(Message.DOMA4465, linkerElement, new Object[] {});
320+
BiFunctionCtType biFunctionCtType =
321+
ctx.getCtTypes().newBiFunctionCtType(linkerElement.asType());
322+
if (biFunctionCtType != null) {
323+
return createLinkMetaForBiFunction(linkerElement, biFunctionCtType);
321324
}
325+
BiConsumerCtType biConsumerCtType =
326+
ctx.getCtTypes().newBiConsumerCtType(linkerElement.asType());
327+
if (biConsumerCtType != null) {
328+
return createLinkMetaForBiConsumer(linkerElement, biConsumerCtType);
329+
}
330+
throw new AptException(Message.DOMA4465, linkerElement, new Object[] {});
331+
}
332+
333+
private LinkMeta createLinkMetaForBiFunction(
334+
VariableElement linkerElement, BiFunctionCtType ctType) {
322335
CtTypeVisitor<EntityCtType, String, RuntimeException> entityCtTypeVisitor =
323336
new SimpleCtTypeVisitor<>() {
324337
@Override
@@ -342,8 +355,31 @@ public EntityCtType visitEntityCtType(EntityCtType ctType, String ordinalNumber)
342355
throw new AptException(Message.DOMA4467, linkerElement, new Object[] {});
343356
}
344357

345-
return new LinkMeta(source, target);
358+
return new LinkMeta(AssociationLinkerKind.BI_FUNCTION, source, target);
359+
}
360+
361+
private LinkMeta createLinkMetaForBiConsumer(
362+
VariableElement linkerElement, BiConsumerCtType ctType) {
363+
CtTypeVisitor<EntityCtType, String, RuntimeException> entityCtTypeVisitor =
364+
new SimpleCtTypeVisitor<>() {
365+
@Override
366+
protected EntityCtType defaultAction(CtType ctType, String ordinalNumber)
367+
throws RuntimeException {
368+
throw new AptException(Message.DOMA4497, linkerElement, new Object[] {ordinalNumber});
369+
}
370+
371+
@Override
372+
public EntityCtType visitEntityCtType(EntityCtType ctType, String ordinalNumber)
373+
throws RuntimeException {
374+
return ctType;
375+
}
376+
};
377+
378+
EntityCtType source = ctType.getFirstArgCtType().accept(entityCtTypeVisitor, "first");
379+
EntityCtType target = ctType.getSecondArgCtType().accept(entityCtTypeVisitor, "second");
380+
381+
return new LinkMeta(AssociationLinkerKind.BI_CONSUMER, source, target);
346382
}
347383

348-
private record LinkMeta(EntityCtType source, EntityCtType target) {}
384+
private record LinkMeta(AssociationLinkerKind kind, EntityCtType source, EntityCtType target) {}
349385
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright Doma Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.seasar.doma.internal.apt.meta.aggregate;
17+
18+
public enum AssociationLinkerKind {
19+
BI_FUNCTION,
20+
BI_CONSUMER,
21+
}

doma-processor/src/main/java/org/seasar/doma/internal/apt/meta/aggregate/AssociationLinkerMeta.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public record AssociationLinkerMeta(
2929
List<String> propertyPathSegments,
3030
int propertyPathDepth,
3131
String tableAlias,
32+
AssociationLinkerKind linkerKind,
3233
EntityCtType source,
3334
EntityCtType target,
3435
TypeElement classElement,
@@ -39,6 +40,7 @@ public record AssociationLinkerMeta(
3940
Objects.requireNonNull(propertyPath);
4041
Objects.requireNonNull(propertyPathSegments);
4142
Objects.requireNonNull(tableAlias);
43+
Objects.requireNonNull(linkerKind);
4244
Objects.requireNonNull(source);
4345
Objects.requireNonNull(target);
4446
Objects.requireNonNull(classElement);

0 commit comments

Comments
 (0)