Skip to content

Commit e855d79

Browse files
committed
@Embeddable をサポート
1 parent 944ef9e commit e855d79

File tree

75 files changed

+2974
-227
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+2974
-227
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright 2004-2010 the Seasar Foundation and the Others.
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+
* http://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,
13+
* either express or implied. See the License for the specific language
14+
* governing permissions and limitations under the License.
15+
*/
16+
package org.seasar.doma;
17+
18+
import java.lang.annotation.ElementType;
19+
import java.lang.annotation.Retention;
20+
import java.lang.annotation.RetentionPolicy;
21+
import java.lang.annotation.Target;
22+
23+
/**
24+
* エンベッダブルクラスを示します。エンベッダブルクラスはエンティティに組み込み可能で複数のプロパティをまとめる役割を担います。
25+
* <p>
26+
* エンベッダブルクラスにはすべてのプロパティをパラメータに含んだ非privateなコンストラクタが必要です。
27+
*
28+
* <pre>
29+
* &#064;Embeddable
30+
* public class Address {
31+
*
32+
* &#064;Column(name = &quot;CITY&quot;)
33+
* private final String city;
34+
*
35+
* &#064;Column(name = &quot;STREET&quot;)
36+
* private final String street;
37+
*
38+
* public Address(String city, String street) {
39+
* this.city = city;
40+
* this.street = street;
41+
* }
42+
* ...
43+
* }
44+
* </pre>
45+
*
46+
* <pre>
47+
* &#064;Entity
48+
* public class Employee {
49+
*
50+
* &#064;Id
51+
* &#064;Column(name = &quot;ID&quot;)
52+
* Integer id;
53+
*
54+
* Address address;
55+
*
56+
* &#064;Version
57+
* &#064;Column(name = &quot;VERSION&quot;)
58+
* int version;
59+
*
60+
* ...
61+
* }
62+
* </pre>
63+
*
64+
* <p>
65+
* 注釈されたインタフェースの実装はスレッドセーフであることを要求されません。
66+
* <p>
67+
*
68+
* @author nakamura-to
69+
* @since 2.10.0
70+
*/
71+
@Target(ElementType.TYPE)
72+
@Retention(RetentionPolicy.RUNTIME)
73+
public @interface Embeddable {
74+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright 2004-2010 the Seasar Foundation and the Others.
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+
* http://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,
13+
* either express or implied. See the License for the specific language
14+
* governing permissions and limitations under the License.
15+
*/
16+
package org.seasar.doma.internal.apt;
17+
18+
import static org.seasar.doma.internal.util.AssertionUtil.assertNotNull;
19+
20+
import java.io.IOException;
21+
22+
import javax.annotation.processing.SupportedAnnotationTypes;
23+
import javax.annotation.processing.SupportedOptions;
24+
import javax.lang.model.element.TypeElement;
25+
26+
import org.seasar.doma.Embeddable;
27+
import org.seasar.doma.internal.apt.meta.EmbeddableMeta;
28+
import org.seasar.doma.internal.apt.meta.EmbeddableMetaFactory;
29+
import org.seasar.doma.internal.apt.meta.EmbeddablePropertyMetaFactory;
30+
31+
/**
32+
* @author nakamura-to
33+
*
34+
*/
35+
@SupportedAnnotationTypes({ "org.seasar.doma.Embeddable" })
36+
@SupportedOptions({ Options.VERSION_VALIDATION, Options.TEST, Options.DEBUG })
37+
public class EmbeddableProcessor extends
38+
AbstractGeneratingProcessor<EmbeddableMeta> {
39+
40+
public EmbeddableProcessor() {
41+
super(Embeddable.class);
42+
}
43+
44+
@Override
45+
protected EmbeddableMetaFactory createTypeElementMetaFactory() {
46+
EmbeddablePropertyMetaFactory propertyMetaFactory = createEmbeddablePropertyMetaFactory();
47+
return new EmbeddableMetaFactory(processingEnv, propertyMetaFactory);
48+
}
49+
50+
protected EmbeddablePropertyMetaFactory createEmbeddablePropertyMetaFactory() {
51+
return new EmbeddablePropertyMetaFactory(processingEnv);
52+
}
53+
54+
@Override
55+
protected Generator createGenerator(TypeElement typeElement,
56+
EmbeddableMeta meta) throws IOException {
57+
assertNotNull(typeElement, meta);
58+
return new EmbeddableTypeGenerator(processingEnv, typeElement, meta);
59+
}
60+
61+
}
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
/*
2+
* Copyright 2004-2010 the Seasar Foundation and the Others.
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+
* http://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,
13+
* either express or implied. See the License for the specific language
14+
* governing permissions and limitations under the License.
15+
*/
16+
package org.seasar.doma.internal.apt;
17+
18+
import static org.seasar.doma.internal.util.AssertionUtil.assertNotNull;
19+
20+
import java.io.IOException;
21+
import java.util.Arrays;
22+
import java.util.Iterator;
23+
import java.util.List;
24+
import java.util.Map;
25+
26+
import javax.annotation.processing.ProcessingEnvironment;
27+
import javax.lang.model.element.TypeElement;
28+
29+
import org.seasar.doma.internal.Constants;
30+
import org.seasar.doma.internal.apt.cttype.BasicCtType;
31+
import org.seasar.doma.internal.apt.cttype.CtType;
32+
import org.seasar.doma.internal.apt.cttype.DomainCtType;
33+
import org.seasar.doma.internal.apt.cttype.OptionalCtType;
34+
import org.seasar.doma.internal.apt.cttype.OptionalDoubleCtType;
35+
import org.seasar.doma.internal.apt.cttype.OptionalIntCtType;
36+
import org.seasar.doma.internal.apt.cttype.OptionalLongCtType;
37+
import org.seasar.doma.internal.apt.cttype.SimpleCtTypeVisitor;
38+
import org.seasar.doma.internal.apt.cttype.WrapperCtType;
39+
import org.seasar.doma.internal.apt.meta.EmbeddableMeta;
40+
import org.seasar.doma.internal.apt.meta.EmbeddablePropertyMeta;
41+
import org.seasar.doma.internal.apt.util.TypeMirrorUtil;
42+
import org.seasar.doma.jdbc.entity.DefaultPropertyType;
43+
import org.seasar.doma.jdbc.entity.EmbeddableType;
44+
import org.seasar.doma.jdbc.entity.EntityPropertyType;
45+
import org.seasar.doma.jdbc.entity.NamingType;
46+
import org.seasar.doma.jdbc.entity.Property;
47+
48+
/**
49+
* @author nakamura-to
50+
*
51+
*/
52+
public class EmbeddableTypeGenerator extends AbstractGenerator {
53+
54+
protected final EmbeddableMeta embeddableMeta;
55+
56+
public EmbeddableTypeGenerator(ProcessingEnvironment env,
57+
TypeElement entityElement, EmbeddableMeta embeddableMeta)
58+
throws IOException {
59+
super(env, entityElement, null, null, Constants.METATYPE_PREFIX, "");
60+
assertNotNull(embeddableMeta);
61+
this.embeddableMeta = embeddableMeta;
62+
}
63+
64+
@Override
65+
public void generate() {
66+
printPackage();
67+
printClass();
68+
}
69+
70+
protected void printPackage() {
71+
if (!packageName.isEmpty()) {
72+
iprint("package %1$s;%n", packageName);
73+
iprint("%n");
74+
}
75+
}
76+
77+
protected void printClass() {
78+
iprint("/** */%n");
79+
printGenerated();
80+
iprint("public final class %1$s implements %2$s<%3$s> {%n",
81+
/* 1 */simpleName,
82+
/* 2 */EmbeddableType.class.getName(),
83+
/* 3 */embeddableMeta.getEmbeddableElement().getQualifiedName());
84+
print("%n");
85+
indent();
86+
printValidateVersionStaticInitializer();
87+
printFields();
88+
printMethods();
89+
unindent();
90+
iprint("}%n");
91+
}
92+
93+
protected void printFields() {
94+
printSingletonField();
95+
}
96+
97+
protected void printSingletonField() {
98+
iprint("private static final %1$s __singleton = new %1$s();%n",
99+
simpleName);
100+
print("%n");
101+
}
102+
103+
protected void printMethods() {
104+
printGetEmbeddablePropertyTypesMethod();
105+
printNewEmbeddableMethod();
106+
printGetSingletonInternalMethod();
107+
}
108+
109+
protected void printGetEmbeddablePropertyTypesMethod() {
110+
iprint("@Override%n");
111+
iprint("public <ENTITY> %1$s<%2$s<ENTITY, ?>> getEmbeddablePropertyTypes(String embeddedPropertyName, Class<ENTITY> entityClass, %3$s namingType) {%n",
112+
List.class.getName(), EntityPropertyType.class.getName(),
113+
NamingType.class.getName());
114+
iprint(" return %1$s.asList(%n", Arrays.class.getName());
115+
for (Iterator<EmbeddablePropertyMeta> it = embeddableMeta
116+
.getEmbeddablePropertyMetas().iterator(); it.hasNext();) {
117+
EmbeddablePropertyMeta pm = it.next();
118+
EmbeddablePropertyCtTypeVisitor visitor = new EmbeddablePropertyCtTypeVisitor();
119+
pm.getCtType().accept(visitor, null);
120+
BasicCtType basicCtType = visitor.basicCtType;
121+
WrapperCtType wrapperCtType = visitor.wrapperCtType;
122+
DomainCtType domainCtType = visitor.domainCtType;
123+
124+
String newWrapperExpr;
125+
if (basicCtType.isEnum()) {
126+
newWrapperExpr = String.format("new %s(%s.class)",
127+
wrapperCtType.getTypeName(),
128+
basicCtType.getBoxedTypeName());
129+
} else {
130+
newWrapperExpr = String.format("new %s()",
131+
wrapperCtType.getTypeName());
132+
}
133+
String parentEntityPropertyType = "null";
134+
String parentEntityBoxedTypeName = Object.class.getName();
135+
String domainType = "null";
136+
String domainTypeName = "Object";
137+
if (domainCtType != null) {
138+
domainType = domainCtType.getInstantiationCommand();
139+
domainTypeName = domainCtType.getTypeName();
140+
}
141+
iprint(" new %1$s<Object, ENTITY, %3$s, %16$s>(entityClass, %15$s.class, %3$s.class, () -> %9$s, null, %10$s, embeddedPropertyName + \".%4$s\", \"%5$s\", namingType, %6$s, %7$s, %17$s)",
142+
/* 1 */DefaultPropertyType.class.getName(),
143+
/* 2 */null,
144+
/* 3 */basicCtType.getBoxedTypeName(),
145+
/* 4 */pm.getName(),
146+
/* 5 */pm.getColumnName(),
147+
/* 6 */pm.isColumnInsertable(),
148+
/* 7 */pm.isColumnUpdatable(),
149+
/* 8 */null,
150+
/* 9 */newWrapperExpr,
151+
/* 10 */domainType,
152+
/* 11 */pm.getBoxedTypeName(),
153+
/* 12 */parentEntityPropertyType,
154+
/* 13 */parentEntityBoxedTypeName,
155+
/* 14 */null,
156+
/* 15 */pm.getBoxedClassName(),
157+
/* 16 */domainTypeName,
158+
/* 17 */pm.isColumnQuoteRequired());
159+
print(it.hasNext() ? "," : ");");
160+
print("%n");
161+
}
162+
iprint("}%n");
163+
print("%n");
164+
}
165+
166+
protected void printNewEmbeddableMethod() {
167+
iprint("@Override%n");
168+
iprint("public <ENTITY> %1$s newEmbeddable(String embeddedPropertyName, %2$s<String, %3$s<ENTITY, ?>> __args) {%n",
169+
embeddableMeta.getEmbeddableElement().getQualifiedName(),
170+
Map.class.getName(), Property.class.getName());
171+
if (embeddableMeta.isAbstract()) {
172+
iprint(" return null;%n");
173+
} else {
174+
iprint(" return new %1$s(%n", embeddableMeta
175+
.getEmbeddableElement().getQualifiedName());
176+
for (Iterator<EmbeddablePropertyMeta> it = embeddableMeta
177+
.getEmbeddablePropertyMetas().iterator(); it.hasNext();) {
178+
EmbeddablePropertyMeta propertyMeta = it.next();
179+
iprint(" (%1$s)(__args.get(embeddedPropertyName + \".%2$s\") != null ? __args.get(embeddedPropertyName + \".%2$s\").get() : null)",
180+
TypeMirrorUtil.boxIfPrimitive(propertyMeta.getType(),
181+
env), propertyMeta.getName());
182+
if (it.hasNext()) {
183+
print(",%n");
184+
}
185+
}
186+
print(");%n");
187+
}
188+
iprint("}%n");
189+
print("%n");
190+
}
191+
192+
protected void printGetSingletonInternalMethod() {
193+
iprint("/**%n");
194+
iprint(" * @return the singleton%n");
195+
iprint(" */%n");
196+
iprint("public static %1$s getSingletonInternal() {%n", simpleName);
197+
iprint(" return __singleton;%n");
198+
iprint("}%n");
199+
print("%n");
200+
}
201+
202+
protected class EmbeddablePropertyCtTypeVisitor extends
203+
SimpleCtTypeVisitor<Void, Void, RuntimeException> {
204+
205+
protected BasicCtType basicCtType;
206+
207+
protected WrapperCtType wrapperCtType;
208+
209+
protected DomainCtType domainCtType;
210+
211+
@Override
212+
protected Void defaultAction(CtType ctType, Void p)
213+
throws RuntimeException {
214+
assertNotNull(basicCtType);
215+
assertNotNull(wrapperCtType);
216+
return null;
217+
}
218+
219+
@Override
220+
public Void visitOptionalCtType(OptionalCtType ctType, Void p)
221+
throws RuntimeException {
222+
return ctType.getElementCtType().accept(this, p);
223+
}
224+
225+
@Override
226+
public Void visitOptionalIntCtType(OptionalIntCtType ctType, Void p)
227+
throws RuntimeException {
228+
return ctType.getElementCtType().accept(this, p);
229+
}
230+
231+
@Override
232+
public Void visitOptionalLongCtType(OptionalLongCtType ctType, Void p)
233+
throws RuntimeException {
234+
return ctType.getElementCtType().accept(this, p);
235+
}
236+
237+
@Override
238+
public Void visitOptionalDoubleCtType(OptionalDoubleCtType ctType,
239+
Void p) throws RuntimeException {
240+
return ctType.getElementCtType().accept(this, p);
241+
}
242+
243+
@Override
244+
public Void visitBasicCtType(BasicCtType basicCtType, Void p)
245+
throws RuntimeException {
246+
this.basicCtType = basicCtType;
247+
this.wrapperCtType = basicCtType.getWrapperCtType();
248+
return defaultAction(basicCtType, p);
249+
}
250+
251+
@Override
252+
public Void visitDomainCtType(DomainCtType domainCtType, Void p)
253+
throws RuntimeException {
254+
this.domainCtType = domainCtType;
255+
return visitBasicCtType(domainCtType.getBasicCtType(), p);
256+
}
257+
}
258+
259+
}

0 commit comments

Comments
 (0)