Skip to content

Commit 2625a6d

Browse files
committed
Support domain mapping using ExternalDomain of Java Array
1 parent 6a62136 commit 2625a6d

25 files changed

+607
-38
lines changed

src/main/java/org/seasar/doma/internal/Constants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ public final class Constants {
2020

2121
public static final String EXTERNAL_DOMAIN_DESC_ROOT_PACKAGE = "__";
2222

23+
public static final String EXTERNAL_DOMAIN_DESC_ARRAY_SUFFIX = "__ARRAY__";
24+
2325
public static final String DESC_NAME_DELIMITER = "__";
2426

2527
public static final String BINARY_NAME_DELIMITER = "$";

src/main/java/org/seasar/doma/internal/apt/Context.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public class Context {
2727

2828
private CtTypes ctTypes;
2929

30+
private Names names;
31+
3032
public Context(ProcessingEnvironment env) {
3133
this.env = env;
3234
}
@@ -43,6 +45,7 @@ public void init() {
4345
annotations = new Annotations(this);
4446
declarations = new Declarations(this);
4547
ctTypes = new CtTypes(this);
48+
names = new Names(this);
4649
initialized = true;
4750
}
4851

@@ -86,6 +89,11 @@ public CtTypes getCtTypes() {
8689
return ctTypes;
8790
}
8891

92+
public Names getNames() {
93+
assertInitialized();
94+
return names;
95+
}
96+
8997
private void assertInitialized() {
9098
if (!initialized) {
9199
throw new AptIllegalStateException("not yet initialized");
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.seasar.doma.internal.apt;
2+
3+
import static org.seasar.doma.internal.Constants.EXTERNAL_DOMAIN_DESC_ARRAY_SUFFIX;
4+
import static org.seasar.doma.internal.util.AssertionUtil.assertNotNull;
5+
6+
import javax.lang.model.element.Name;
7+
import javax.lang.model.element.TypeElement;
8+
import javax.lang.model.type.ArrayType;
9+
import javax.lang.model.type.TypeMirror;
10+
11+
public class Names {
12+
13+
private final Context ctx;
14+
15+
Names(Context ctx) {
16+
assertNotNull(ctx);
17+
this.ctx = ctx;
18+
}
19+
20+
public Name createExternalDomainName(TypeMirror externalDomainType) {
21+
assertNotNull(externalDomainType);
22+
ArrayType arrayType = ctx.getMoreTypes().toArrayType(externalDomainType);
23+
if (arrayType != null) {
24+
TypeMirror componentType = arrayType.getComponentType();
25+
TypeElement componentElement = ctx.getMoreTypes().toTypeElement(componentType);
26+
if (componentElement == null) {
27+
throw new AptIllegalStateException(componentType.toString());
28+
}
29+
Name binaryName = ctx.getMoreElements().getBinaryName(componentElement);
30+
return ctx.getMoreElements().getName(binaryName + EXTERNAL_DOMAIN_DESC_ARRAY_SUFFIX);
31+
}
32+
TypeElement domainElement = ctx.getMoreTypes().toTypeElement(externalDomainType);
33+
if (domainElement == null) {
34+
throw new AptIllegalStateException(externalDomainType.toString());
35+
}
36+
return ctx.getMoreElements().getBinaryName(domainElement);
37+
}
38+
}

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

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.time.LocalDateTime;
2020
import java.time.LocalTime;
2121
import java.util.Arrays;
22+
import java.util.Collections;
2223
import java.util.Iterator;
2324
import java.util.List;
2425
import java.util.Map;
@@ -175,6 +176,21 @@ private ConfigCtType newConfigCtType(TypeMirror type) {
175176

176177
public DomainCtType newDomainCtType(TypeMirror type) {
177178
assertNotNull(type);
179+
180+
if (type.getKind() == TypeKind.ARRAY) {
181+
DomainInfo info = getExternalDomainInfo(type);
182+
if (info == null) {
183+
return null;
184+
}
185+
BasicCtType basicCtType = newBasicCtType(info.valueType);
186+
if (basicCtType == null) {
187+
return null;
188+
}
189+
Name name = ctx.getNames().createExternalDomainName(type);
190+
ClassName descClassName = ClassNames.newExternalDomainDescClassName(name);
191+
return new DomainCtType(ctx, type, basicCtType, Collections.emptyList(), descClassName);
192+
}
193+
178194
TypeElement typeElement = ctx.getMoreTypes().toTypeElement(type);
179195
if (typeElement == null) {
180196
return null;
@@ -199,7 +215,8 @@ public DomainCtType newDomainCtType(TypeMirror type) {
199215
Name binaryName = ctx.getMoreElements().getBinaryName(typeElement);
200216
ClassName descClassName;
201217
if (info.external) {
202-
descClassName = ClassNames.newExternalDomainDescClassName(binaryName);
218+
Name name = ctx.getNames().createExternalDomainName(type);
219+
descClassName = ClassNames.newExternalDomainDescClassName(name);
203220
} else {
204221
descClassName = ClassNames.newDomainDescClassName(binaryName);
205222
}
@@ -211,7 +228,7 @@ private DomainInfo getDomainInfo(TypeElement typeElement) {
211228
if (domain != null) {
212229
return getDomainInfo(domain);
213230
}
214-
return getExternalDomainInfo(typeElement);
231+
return getExternalDomainInfo(typeElement.asType());
215232
}
216233

217234
private DomainInfo getDomainInfo(Domain domain) {
@@ -223,10 +240,9 @@ private DomainInfo getDomainInfo(Domain domain) {
223240
throw new AptIllegalStateException("unreachable.");
224241
}
225242

226-
private DomainInfo getExternalDomainInfo(TypeElement typeElement) {
243+
private DomainInfo getExternalDomainInfo(TypeMirror domainType) {
227244
String csv = ctx.getOptions().getDomainConverters();
228245
if (csv != null) {
229-
TypeMirror domainType = typeElement.asType();
230246
for (String value : csv.split(",")) {
231247
String className = value.trim();
232248
if (className.isEmpty()) {
@@ -497,10 +513,10 @@ public CtType newCtType(TypeMirror type) {
497513

498514
private CtType newCtTypeInternal(
499515
TypeMirror type, CtTypeVisitor<Void, Void, AptException> validator) {
516+
// The newArrayCtType function must be after the newDomainCtType function
500517
List<Function<TypeMirror, CtType>> functions =
501518
Arrays.asList(
502519
this::newIterableCtType,
503-
this::newArrayCtType,
504520
this::newStreamCtType,
505521
this::newEntityCtType,
506522
this::newOptionalCtType,
@@ -519,7 +535,8 @@ private CtType newCtTypeInternal(
519535
this::newPreparedSqlCtType,
520536
this::newConfigCtType,
521537
this::newResultCtType,
522-
this::newBatchResultCtType);
538+
this::newBatchResultCtType,
539+
this::newArrayCtType);
523540
CtType ctType =
524541
functions.stream()
525542
.map(f -> f.apply(type))

src/main/java/org/seasar/doma/internal/apt/generator/ExternalDomainDescGenerator.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@ private void printClass() {
4949
/* 1 */ simpleName,
5050
/* 2 */ AbstractDomainType.class,
5151
/* 3 */ domainMeta.getValueType(),
52-
/* 4 */ domainMeta.getType(),
52+
/* 4 */ domainMeta.asType(),
5353
/* 5 */ domainMeta.getTypeParameters());
5454
} else {
5555
iprint(
5656
"public final class %1$s extends %2$s<%3$s, %4$s> {%n",
5757
/* 1 */ simpleName,
5858
/* 2 */ AbstractDomainType.class,
5959
/* 3 */ domainMeta.getValueType(),
60-
/* 4 */ domainMeta.getType());
60+
/* 4 */ domainMeta.asType());
6161
}
6262
print("%n");
6363
indent();
@@ -102,10 +102,9 @@ private void printNewDomainMethod() {
102102
}
103103
iprint("@Override%n");
104104
iprint(
105-
"protected %1$s newDomain(%2$s value) {%n",
106-
domainMeta.getType(), domainMeta.getValueType());
105+
"protected %1$s newDomain(%2$s value) {%n", domainMeta.asType(), domainMeta.getValueType());
107106
if (domainMeta.isParameterized()) {
108-
iprint(" return (%1$s) converter.fromValueToDomain(value);%n", domainMeta.getType());
107+
iprint(" return (%1$s) converter.fromValueToDomain(value);%n", domainMeta.asType());
109108
} else {
110109
iprint(" return converter.fromValueToDomain(value);%n");
111110
}
@@ -117,7 +116,7 @@ private void printGetBasicValueMethod() {
117116
iprint("@Override%n");
118117
iprint(
119118
"protected %1$s getBasicValue(%2$s domain) {%n",
120-
domainMeta.getValueType(), domainMeta.getType());
119+
domainMeta.getValueType(), domainMeta.asType());
121120
iprint(" if (domain == null) {%n");
122121
iprint(" return null;%n");
123122
iprint(" }%n");
@@ -139,12 +138,16 @@ private void printGetDomainClassMethod() {
139138
iprint("@SuppressWarnings(\"unchecked\")%n");
140139
}
141140
iprint("@Override%n");
142-
iprint("public Class<%1$s> getDomainClass() {%n", domainMeta.getType());
141+
iprint("public Class<%1$s> getDomainClass() {%n", domainMeta.asType());
143142
if (domainMeta.isParameterized()) {
144143
iprint(" Class<?> clazz = %1$s.class;%n", domainMeta.getTypeElement());
145-
iprint(" return (Class<%1$s>) clazz;%n", domainMeta.getType());
144+
iprint(" return (Class<%1$s>) clazz;%n", domainMeta.asType());
146145
} else {
147-
iprint(" return %1$s.class;%n", domainMeta.getTypeElement());
146+
if (domainMeta.getTypeElement() != null) {
147+
iprint(" return %1$s.class;%n", domainMeta.getTypeElement());
148+
} else {
149+
iprint(" return %1$s.class;%n", domainMeta.asType());
150+
}
148151
}
149152
iprint("}%n");
150153
print("%n");

src/main/java/org/seasar/doma/internal/apt/meta/domain/ExternalDomainMeta.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ public class ExternalDomainMeta implements TypeElementMeta {
1919

2020
private TypeElement typeElement;
2121

22+
private TypeMirror type;
23+
2224
private TypeParametersDef typeParametersDef;
2325

2426
public ExternalDomainMeta(TypeElement converterElement) {
@@ -66,12 +68,16 @@ public List<String> getTypeParameters() {
6668
return typeParametersDef.getTypeParameters();
6769
}
6870

69-
public TypeMirror getType() {
70-
return typeElement.asType();
71+
public void setType(TypeMirror type) {
72+
this.type = type;
73+
}
74+
75+
public TypeMirror asType() {
76+
return typeElement != null ? typeElement.asType() : type;
7177
}
7278

7379
public boolean isParameterized() {
74-
return !typeElement.getTypeParameters().isEmpty();
80+
return typeElement != null && !typeElement.getTypeParameters().isEmpty();
7581
}
7682

7783
@Override

src/main/java/org/seasar/doma/internal/apt/meta/domain/ExternalDomainMetaFactory.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import javax.lang.model.element.NestingKind;
1313
import javax.lang.model.element.PackageElement;
1414
import javax.lang.model.element.TypeElement;
15+
import javax.lang.model.type.ArrayType;
1516
import javax.lang.model.type.DeclaredType;
1617
import javax.lang.model.type.TypeKind;
1718
import javax.lang.model.type.TypeMirror;
@@ -87,6 +88,24 @@ private TypeMirror[] getConverterArgTypes(TypeMirror typeMirror) {
8788

8889
private void doDomainType(
8990
TypeElement converterElement, TypeMirror domainType, ExternalDomainMeta meta) {
91+
meta.setType(domainType);
92+
93+
ArrayType arrayType = ctx.getMoreTypes().toArrayType(domainType);
94+
if (arrayType != null) {
95+
TypeMirror componentType = arrayType.getComponentType();
96+
if (componentType.getKind() == TypeKind.ARRAY) {
97+
throw new AptException(Message.DOMA4447, converterElement, new Object[] {});
98+
}
99+
TypeElement componentElement = ctx.getMoreTypes().toTypeElement(componentType);
100+
if (componentElement == null) {
101+
throw new AptIllegalStateException(componentType.toString());
102+
}
103+
if (!componentElement.getTypeParameters().isEmpty()) {
104+
throw new AptException(Message.DOMA4448, converterElement, new Object[] {});
105+
}
106+
return;
107+
}
108+
90109
TypeElement domainElement = ctx.getMoreTypes().toTypeElement(domainType);
91110
if (domainElement == null) {
92111
throw new AptIllegalStateException(domainType.toString());

src/main/java/org/seasar/doma/internal/apt/processor/ExternalDomainProcessor.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,8 @@ protected ExternalDomainMetaFactory createTypeElementMetaFactory() {
3838
@Override
3939
protected ClassName createClassName(TypeElement typeElement, ExternalDomainMeta meta) {
4040
assertNotNull(typeElement, meta);
41-
TypeElement domainElement = meta.getTypeElement();
42-
Name binaryName = ctx.getMoreElements().getBinaryName(domainElement);
43-
return ClassNames.newExternalDomainDescClassName(binaryName);
41+
Name name = ctx.getNames().createExternalDomainName(meta.asType());
42+
return ClassNames.newExternalDomainDescClassName(name);
4443
}
4544

4645
@Override

src/main/java/org/seasar/doma/jdbc/domain/DomainTypeFactory.java

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.seasar.doma.jdbc.domain;
22

3+
import static org.seasar.doma.internal.Constants.EXTERNAL_DOMAIN_DESC_ARRAY_SUFFIX;
4+
35
import java.lang.reflect.Method;
46
import org.seasar.doma.DomaIllegalArgumentException;
57
import org.seasar.doma.DomaNullPointerException;
@@ -99,20 +101,14 @@ public static <BASIC, DOMAIN> DomainType<BASIC, DOMAIN> getExternalDomainType(
99101
if (classHelper == null) {
100102
throw new DomaNullPointerException("classHelper");
101103
}
102-
Class<?> clazz =
103-
ClassUtil.traverse(
104-
domainClass,
105-
c -> {
106-
String domainTypeClassName =
107-
ClassNames.newExternalDomainDescClassName(c.getName()).toString();
108-
try {
109-
return classHelper.forName(domainTypeClassName);
110-
} catch (WrapException e) {
111-
return null;
112-
} catch (Exception e) {
113-
return null;
114-
}
115-
});
104+
Class<?> clazz;
105+
if (domainClass.isArray()) {
106+
String domainName =
107+
domainClass.getComponentType().getName() + EXTERNAL_DOMAIN_DESC_ARRAY_SUFFIX;
108+
clazz = loadExternalDomainDescClass(domainName, classHelper);
109+
} else {
110+
clazz = loadExternalDomainDescClassWithTraversal(domainClass, classHelper);
111+
}
116112
if (clazz == null) {
117113
return null;
118114
}
@@ -125,4 +121,25 @@ public static <BASIC, DOMAIN> DomainType<BASIC, DOMAIN> getExternalDomainType(
125121
return null;
126122
}
127123
}
124+
125+
private static Class<?> loadExternalDomainDescClass(String domainName, ClassHelper classHelper) {
126+
String domainTypeClassName = ClassNames.newExternalDomainDescClassName(domainName).toString();
127+
try {
128+
return classHelper.forName(domainTypeClassName);
129+
} catch (WrapException e) {
130+
return null;
131+
} catch (Exception e) {
132+
return null;
133+
}
134+
}
135+
136+
private static Class<?> loadExternalDomainDescClassWithTraversal(
137+
Class<?> domainClass, ClassHelper classHelper) {
138+
return ClassUtil.traverse(
139+
domainClass,
140+
c -> {
141+
String domainName = c.getName();
142+
return loadExternalDomainDescClass(domainName, classHelper);
143+
});
144+
}
128145
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,8 @@ public enum Message implements MessageResource {
901901
DOMA4444("cannot combine with the annotation \"{0}\"."),
902902
DOMA4445("When the method is annotated with @Sql, the sqlFile element must be \"false\"."),
903903
DOMA4446("cannot annotate the default method."),
904+
DOMA4447("The multidimensional array is not supported as a domain class."),
905+
DOMA4448("The component type of the array must not have any type parameter."),
904906

905907
// other
906908
DOMA5001(

0 commit comments

Comments
 (0)