Skip to content

Commit 1416b2a

Browse files
committed
インターフェースにも@Domainで注釈できるようにしました。
これは、例えば定義済みの値はenumで表し、未定義の値はクラスで表したい場合 などに利点があります。 色をドメインクラスで表す例を記載します。 @Domain(valueType = String.class, factoryMethod = "of") public interface Color { String getValue(); static Color of(String value) { return Arrays.<Color> stream(DefinedColor.values()) .filter(c -> value.equals(c.getValue())) .findFirst() .orElseGet(() -> new ColorImpl(value)); } //定義済みの色はenumで表す public enum DefinedColor implements Color { RED, BLUE, GREEN; public String getValue() { return name(); } } //未定義の色はクラスで表す public static class ColorImpl implements Color { private final String value; //例えば #f90c76 のような16進数表現を受け取る事を想定 public ColorImpl(String value) { this.value = value; } public String getValue() { return value; } } } インターフェースをドメインクラスにすることで上記のような表現が可能になり ます。 なお、これまでも外部ドメインを利用すればインターフェースをドメインクラス にする事は可能でしたが、今回のコミットにより内部ドメインでも実現可能とな ります。
1 parent b32fea9 commit 1416b2a

File tree

8 files changed

+176
-1
lines changed

8 files changed

+176
-1
lines changed

src/main/java/org/seasar/doma/internal/apt/meta/DomainMetaFactory.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,13 @@ protected void validateClass(TypeElement classElement, DomainMeta domainMeta) {
105105
if (classElement.getNestingKind().isNested()) {
106106
throw new AptException(Message.DOMA4179, env, classElement);
107107
}
108+
} else if (classElement.getKind() == ElementKind.INTERFACE) {
109+
if (domainMeta.providesConstructor()) {
110+
throw new AptException(Message.DOMA4268, env, classElement);
111+
}
112+
if (classElement.getNestingKind().isNested()) {
113+
throw new AptException(Message.DOMA4269, env, classElement);
114+
}
108115
} else {
109116
DomainMirror domainMirror = domainMeta.getDomainMirror();
110117
throw new AptException(Message.DOMA4105, env, classElement,

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ public enum Message implements MessageResource {
264264
DOMA4102("型[{0}]は永続対象としてサポートされていません。"),
265265
DOMA4103("型[{0}]をパラメータにもつ非privateなコンストラクタが見つかりません。コンストラクタを定義するか、ファクトリメソッドを利用したい場合は@DomainのfactoryMethod属性にメソッド名を指定してください。"),
266266
DOMA4104("アクセッサメソッド[{0}]が見つかりません。アクセッサメソッドは、型[{1}]を戻り値とする非privateで引数なしのインスタンスメソッドでなければいけません。"),
267-
DOMA4105("クラスまたは列挙型以外には注釈できません"),
267+
DOMA4105("クラスまたはインタフェースまたは列挙型以外には注釈できません"),
268268
DOMA4106("ファクトリメソッド[{0}]が見つかりません。ファクトリメソッドは、型[{1}]を戻り値とし型[{2}]をパラメータにもつ、非privateなstaticメソッドでなければいけません。また、メソッドの型パラメータはクラスの型パラメータと同一でなければいけません。ファクトリメソッドを定義するか、ファクトリメソッドが不要な場合は@DomainのfactoryMethodに\"new\"と指定しコンストラクタを定義してください。"),
269269
DOMA4107("@Domainを注釈したクラスには型パラメータを定義できません。"),
270270
DOMA4108("Referenceには実型引数が必須です。"),
@@ -407,6 +407,8 @@ public enum Message implements MessageResource {
407407
DOMA4265("戻り値の型[{0}]とCollectorの3番目の実型引数の型[{1}]が一致していません。"),
408408
DOMA4266("@Selectのstrategy要素にSelectStrategyType.COLLECTを設定した場合、Collector型のパラメータが必要です。"),
409409
DOMA4267("java.util.List内のjava.util.Optionalに対する実型引数の型[{0}]はサポートされていません。サポートされている型は次のものです。基本型、ドメインクラス。"),
410+
DOMA4268("インターフェースに@Domainを注釈する場合、factoryMethod属性に\"new\"は指定できません(\"new\"はコンストラクタで生成することを示します)。staticで非privateなファクトリメソッドの名前を指定してください。"),
411+
DOMA4269("@Domainが注釈されたインターフェースはトップレベルのインターフェースでなければいけません。"),
410412

411413
DOMA4300("型[{0}]の処理中に例外が発生しました。注釈処理とは直接関係ない場所でコンパイルエラーがありませんか?"),
412414

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.seasar.doma.internal.apt.domain;
2+
3+
import org.seasar.doma.Domain;
4+
5+
@Domain(valueType = Integer.class, factoryMethod = "of")
6+
public @interface AnnotationDomain {
7+
8+
String getValue();
9+
}

src/test/java/org/seasar/doma/internal/apt/domain/DomainProcessorTest.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,4 +273,41 @@ public void testObjectDomain() throws Exception {
273273
assertTrue(getCompiledResult());
274274
}
275275

276+
public void testInterface() throws Exception {
277+
Class<?> target = InterfaceDomain.class;
278+
DomainProcessor processor = new DomainProcessor();
279+
addProcessor(processor);
280+
addCompilationUnit(target);
281+
compile();
282+
assertGeneratedSource(target);
283+
assertTrue(getCompiledResult());
284+
}
285+
286+
public void testInterfaceFactoryOfAttributeMustNotBeNew() throws Exception {
287+
DomainProcessor processor = new DomainProcessor();
288+
addProcessor(processor);
289+
addCompilationUnit(InterfaceNew.class);
290+
compile();
291+
assertFalse(getCompiledResult());
292+
assertMessage(Message.DOMA4268);
293+
}
294+
295+
public void testInterfaceMustNotBeInner() throws Exception {
296+
DomainProcessor processor = new DomainProcessor();
297+
addProcessor(processor);
298+
addCompilationUnit(InterfaceOuter.class);
299+
compile();
300+
assertFalse(getCompiledResult());
301+
assertMessage(Message.DOMA4269);
302+
}
303+
304+
public void testAnnotationMustNotBeDomainClass() throws Exception {
305+
DomainProcessor processor = new DomainProcessor();
306+
addProcessor(processor);
307+
addCompilationUnit(AnnotationDomain.class);
308+
compile();
309+
assertFalse(getCompiledResult());
310+
assertMessage(Message.DOMA4105);
311+
}
312+
276313
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package org.seasar.doma.internal.apt.domain;
2+
3+
import java.util.Arrays;
4+
5+
import org.seasar.doma.Domain;
6+
7+
@Domain(valueType = String.class, factoryMethod = "of")
8+
public interface InterfaceDomain {
9+
10+
String getValue();
11+
12+
static InterfaceDomain of(String value) {
13+
return Arrays.<InterfaceDomain> stream(DefinedColor.values())
14+
.filter(a -> a.getValue().equals(value)).findFirst()
15+
.orElseGet(() -> new Color(value));
16+
}
17+
18+
public enum DefinedColor implements InterfaceDomain {
19+
RED, BLUE, GREEN;
20+
21+
@Override
22+
public String getValue() {
23+
return name();
24+
}
25+
}
26+
27+
public static class Color implements InterfaceDomain {
28+
29+
private final String value;
30+
31+
public Color(String value) {
32+
this.value = value;
33+
}
34+
35+
@Override
36+
public String getValue() {
37+
return value;
38+
}
39+
}
40+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.seasar.doma.internal.apt.domain;
2+
3+
import org.seasar.doma.Domain;
4+
5+
@Domain(valueType = String.class)
6+
public interface InterfaceNew {
7+
8+
String getValue();
9+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.seasar.doma.internal.apt.domain;
2+
3+
import java.math.BigDecimal;
4+
5+
import org.seasar.doma.Domain;
6+
7+
public class InterfaceOuter {
8+
9+
@Domain(valueType = BigDecimal.class, factoryMethod = "of")
10+
public interface Inner {
11+
12+
default BigDecimal getValue() {
13+
return BigDecimal.ZERO;
14+
}
15+
16+
static Inner of(BigDecimal value) {
17+
return new Inner() {
18+
};
19+
}
20+
}
21+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package org.seasar.doma.internal.apt.domain;
2+
3+
/** */
4+
@javax.annotation.Generated(value = { "Doma", "@VERSION@" }, date = "1970-01-01T09:00:00.000+0900")
5+
public final class _InterfaceDomain extends org.seasar.doma.jdbc.domain.AbstractDomainType<java.lang.String, org.seasar.doma.internal.apt.domain.InterfaceDomain> {
6+
7+
static {
8+
org.seasar.doma.internal.Artifact.validateVersion("@VERSION@");
9+
}
10+
11+
private static final _InterfaceDomain singleton = new _InterfaceDomain();
12+
13+
private _InterfaceDomain() {
14+
super(() -> new org.seasar.doma.wrapper.StringWrapper());
15+
}
16+
17+
@Override
18+
protected org.seasar.doma.internal.apt.domain.InterfaceDomain newDomain(java.lang.String value) {
19+
if (value == null) {
20+
return null;
21+
}
22+
return org.seasar.doma.internal.apt.domain.InterfaceDomain.of(value);
23+
}
24+
25+
@Override
26+
protected java.lang.String getBasicValue(org.seasar.doma.internal.apt.domain.InterfaceDomain domain) {
27+
if (domain == null) {
28+
return null;
29+
}
30+
return domain.getValue();
31+
}
32+
33+
@Override
34+
public Class<?> getBasicClass() {
35+
return java.lang.String.class;
36+
}
37+
38+
@Override
39+
public Class<org.seasar.doma.internal.apt.domain.InterfaceDomain> getDomainClass() {
40+
return org.seasar.doma.internal.apt.domain.InterfaceDomain.class;
41+
}
42+
43+
/**
44+
* @return the singleton
45+
*/
46+
public static _InterfaceDomain getSingletonInternal() {
47+
return singleton;
48+
}
49+
50+
}

0 commit comments

Comments
 (0)