Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Scope features #643

Merged
merged 31 commits into from
Jan 24, 2021
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
29cad76
Add scope parameter to Metamodel.
orekyuu Jan 4, 2021
2c7a4be
Scopeのテストを用意
orekyuu Jan 9, 2021
fdcfc49
ScopeClassを追加
orekyuu Jan 10, 2021
646de71
ScopeClassにscopeメソッドを追加
orekyuu Jan 10, 2021
2a4eed9
生成されたmetamodelの情報をテストできるようにする
orekyuu Jan 10, 2021
e662cf5
scope fieldの生成
orekyuu Jan 10, 2021
5e70174
scope methodの生成
orekyuu Jan 10, 2021
2ce2949
nullチェックを追加
orekyuu Jan 11, 2021
c6259a3
改行位置を変えてテストを落ちなくする
orekyuu Jan 11, 2021
d226d7e
引数ありscopeメソッドのテストを追加
orekyuu Jan 11, 2021
d9ee7d3
可変長引数のテストを追加
orekyuu Jan 11, 2021
3ec7dc7
MethodDeclarationに引数を返すメソッドと可変長引数があるかを返すメソッドを用意
orekyuu Jan 11, 2021
af8420d
引数付きメソッドを生成する
orekyuu Jan 11, 2021
b8e2feb
不要な引数を削除
orekyuu Jan 11, 2021
91b1107
scope methodの抽出方法をかえる
orekyuu Jan 11, 2021
f0f2a76
複数のパラメータを受け付けるテスト
orekyuu Jan 11, 2021
b742f25
複数のScopeを受け取るテスト
orekyuu Jan 11, 2021
7f6a85c
reformat
orekyuu Jan 11, 2021
eb3ff18
reformat
orekyuu Jan 11, 2021
e2a23ca
TODOコメントを削除
orekyuu Jan 12, 2021
2df6008
EntityMetaFactoryでScopeClassを処理する
orekyuu Jan 18, 2021
3ba142f
printScopeField -> printScopeFields
orekyuu Jan 18, 2021
45f0ad2
_scope_ -> __scope__
orekyuu Jan 18, 2021
30a461e
不要になったクラスを削除
orekyuu Jan 18, 2021
22e732d
scopeのフィールド名を完全修飾名にする
orekyuu Jan 18, 2021
e771131
新しいMetamodelのコードに追従
orekyuu Jan 18, 2021
c581150
Reformat
orekyuu Jan 19, 2021
bbed38e
newMetamodelAnnotするときにMethodの一覧を調べておく
orekyuu Jan 19, 2021
2ae744b
TypeDeclarationをもとに戻す
orekyuu Jan 19, 2021
e5f9b92
spotlessApply
orekyuu Jan 19, 2021
616995e
nullチェックを追加
orekyuu Jan 19, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions doma-core/src/main/java/org/seasar/doma/Metamodel.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,7 @@

/** @return the suffix for the metamodel class */
String suffix() default "";

/** @return the scope class array */
Class<?>[] scope() default {};
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

import static org.seasar.doma.internal.util.AssertionUtil.assertNonNullValue;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.type.TypeMirror;
import org.seasar.doma.internal.apt.AptIllegalStateException;
import org.seasar.doma.internal.apt.util.AnnotationValueUtil;

Expand All @@ -14,14 +17,19 @@ public class MetamodelAnnot extends AbstractAnnot {

private static final String SUFFIX = "suffix";

private static final String SCOPE = "scope";

private final AnnotationValue prefix;

private final AnnotationValue suffix;

private final AnnotationValue scopeClasses;

MetamodelAnnot(AnnotationMirror annotationMirror, Map<String, AnnotationValue> values) {
super(annotationMirror);
this.prefix = assertNonNullValue(values, PREFIX);
this.suffix = assertNonNullValue(values, SUFFIX);
this.scopeClasses = assertNonNullValue(values, SCOPE);
}

public AnnotationValue getPrefix() {
Expand All @@ -47,4 +55,9 @@ public String getSuffixValue() {
}
return value;
}

public List<ScopeClass> getScopeValue() {
List<TypeMirror> type = AnnotationValueUtil.toTypeList(scopeClasses);
return type.stream().map(ScopeClass::new).collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.seasar.doma.internal.apt.annot;

import javax.lang.model.type.TypeMirror;
import org.seasar.doma.internal.ClassName;
import org.seasar.doma.internal.ClassNames;

public class ScopeClass {
final TypeMirror type;

public ScopeClass(TypeMirror type) {
this.type = type;
}

public ClassName className() {
String binaryName = ClassNames.normalizeBinaryName(type.toString());
return new ClassName(binaryName);
}

public TypeMirror asType() {
return type;
}

@Override
public String toString() {
return className().toString();
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package org.seasar.doma.internal.apt.decl;

import static org.seasar.doma.internal.util.AssertionUtil.*;
import static org.seasar.doma.internal.util.AssertionUtil.assertNotNull;

import java.util.List;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.VariableElement;

public class MethodDeclaration {

Expand All @@ -28,4 +30,16 @@ public TypeDeclaration getReturnTypeDeclaration() {
public boolean isStatic() {
return element.getModifiers().contains(Modifier.STATIC);
}

public String name() {
return element.getSimpleName().toString();
}

public List<? extends VariableElement> parameters() {
return element.getParameters();
}

public boolean isVarArgs() {
return element.isVarArgs();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,15 @@

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.*;
import java.util.function.Predicate;
import javax.lang.model.element.*;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.seasar.doma.internal.ClassName;
import org.seasar.doma.internal.apt.Context;
import org.seasar.doma.internal.apt.MoreTypes;
import org.seasar.doma.internal.apt.cttype.ArrayCtType;
import org.seasar.doma.internal.apt.cttype.BasicCtType;
import org.seasar.doma.internal.apt.cttype.CtType;
import org.seasar.doma.internal.apt.cttype.DomainCtType;
import org.seasar.doma.internal.apt.cttype.IterableCtType;
import org.seasar.doma.internal.apt.cttype.SimpleCtTypeVisitor;
import org.seasar.doma.internal.apt.cttype.*;
import org.seasar.doma.internal.util.Pair;
import org.seasar.doma.internal.util.Zip;

Expand Down Expand Up @@ -226,6 +216,32 @@ private void removeHiddenFieldDeclarations(List<FieldDeclaration> candidates) {
}
}

public List<MethodDeclaration> getScopeMethods(ClassName metamodel) {
nakamura-to marked this conversation as resolved.
Show resolved Hide resolved
return getMethods(m -> isScopeMethod(m, metamodel));
}

public boolean isScopeMethod(ExecutableElement m, ClassName metamodel) {
if (m.getModifiers().contains(Modifier.STATIC)) {
return false;
}

if (!m.getModifiers().contains(Modifier.PUBLIC)) {
return false;
}

if (m.getReturnType().getKind() == TypeKind.VOID) {
return false;
}

if (m.getParameters().size() < 1) {
return false;
}

VariableElement firstParameter = m.getParameters().get(0);
// Note; Here, type checking cannot be performed correctly because it is before the Metamodel is generated.
return firstParameter.asType().toString().equals(metamodel.getSimpleName());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, type checking cannot be performed correctly because it is before the Metamodel is generated.
Do you have a good idea?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea.
But I think it's OK.

}

public Optional<MethodDeclaration> getMethodDeclaration(
String name, List<TypeDeclaration> parameterTypeDeclarations) {
return getMethodDeclarationInternal(name, parameterTypeDeclarations, false);
Expand All @@ -247,19 +263,25 @@ private Optional<MethodDeclaration> getMethodDeclarationInternal(

private List<MethodDeclaration> getCandidateMethodDeclarations(
String name, List<TypeDeclaration> parameterTypeDeclarations, boolean statik) {
return getMethods(
m ->
(!statik || m.getModifiers().contains(Modifier.STATIC))
&& m.getModifiers().contains(Modifier.PUBLIC)
&& m.getSimpleName().contentEquals(name)
&& m.getReturnType().getKind() != TypeKind.VOID
&& m.getParameters().size() == parameterTypeDeclarations.size()
&& isAssignable(parameterTypeDeclarations, m.getParameters()));
}

private List<MethodDeclaration> getMethods(Predicate<ExecutableElement> predicate) {
return typeParameterDeclarationsMap.entrySet().stream()
.map(e -> new Pair<>(e.getKey(), e.getValue()))
.map(p -> new Pair<>(ctx.getMoreElements().getTypeElement(p.fst), p.snd))
.filter(p -> Objects.nonNull(p.fst))
.flatMap(
p ->
methodsIn(p.fst.getEnclosedElements()).stream()
.filter(m -> !statik || m.getModifiers().contains(Modifier.STATIC))
.filter(m -> m.getModifiers().contains(Modifier.PUBLIC))
.filter(m -> m.getSimpleName().contentEquals(name))
.filter(m -> m.getReturnType().getKind() != TypeKind.VOID)
.filter(m -> m.getParameters().size() == parameterTypeDeclarations.size())
.filter(m -> isAssignable(parameterTypeDeclarations, m.getParameters()))
.filter(predicate)
.map(m -> ctx.getDeclarations().newMethodDeclaration(m, p.snd)))
.collect(toList());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,23 @@

import static org.seasar.doma.internal.util.AssertionUtil.assertNotNull;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.TypeMirror;
import org.seasar.doma.internal.ClassName;
import org.seasar.doma.internal.ClassNames;
import org.seasar.doma.internal.apt.AptIllegalStateException;
import org.seasar.doma.internal.apt.Context;
import org.seasar.doma.internal.apt.cttype.CtType;
import org.seasar.doma.internal.apt.decl.MethodDeclaration;
import org.seasar.doma.internal.apt.decl.TypeDeclaration;
import org.seasar.doma.internal.apt.meta.entity.EntityMeta;
import org.seasar.doma.internal.apt.meta.entity.EntityMetaScope;
import org.seasar.doma.internal.apt.meta.entity.EntityPropertyMeta;
import org.seasar.doma.internal.util.Pair;
import org.seasar.doma.jdbc.criteria.metamodel.DefaultPropertyMetamodel;
Expand Down Expand Up @@ -70,6 +78,7 @@ private void printFields() {
printEntityTypeField();
printAllPropertyMetamodelsFields();
printPropertyMetamodelFields();
printScopeField();
}

private void printEntityTypeField() {
Expand All @@ -89,6 +98,14 @@ private void printQualifiedTableNameField() {
print("%n");
}

private void printScopeField() {
nakamura-to marked this conversation as resolved.
Show resolved Hide resolved
List<EntityMetaScope> scopes = entityMeta.getAllMetaScope();
for (EntityMetaScope scope : scopes) {
iprint("private final %1$s %2$s = new %1$s();%n", scope.scopeClass(), scope.scopeField());
print("%n");
}
}

private void printConstructors() {
printNoArgsConstructor();
printOneArgConstructor();
Expand Down Expand Up @@ -157,6 +174,7 @@ private ClassName createEmbeddableTypeClassName(EntityPropertyMeta p) {
private void printMethods() {
printAsTypeMethod();
printAllPropertyMetamodelsMethod();
printScopeMethods();
}

private void printAsTypeMethod() {
Expand All @@ -180,4 +198,56 @@ private void printAllPropertyMetamodelsMethod() {
iprint("}%n");
print("%n");
}

private void printScopeMethods() {
for (EntityMetaScope scope : entityMeta.getAllMetaScope()) {
TypeDeclaration declaration =
nakamura-to marked this conversation as resolved.
Show resolved Hide resolved
ctx.getDeclarations().newTypeDeclaration(scope.scopeClass().asType());
printScopeMethods(scope, declaration);
}
}

private void printScopeMethods(EntityMetaScope scope, TypeDeclaration scopeDeclaration) {
for (MethodDeclaration method : scopeDeclaration.getScopeMethods(className)) {
List<? extends VariableElement> parameters = new ArrayList<>(method.parameters());
parameters.remove(0);

iprint(
"public %1$s %2$s(%3$s) {%n",
method.getReturnTypeDeclaration(),
method.name(),
generateParameterList(method, parameters));
indent();

String params =
parameters.stream().map(VariableElement::getSimpleName).collect(Collectors.joining(", "));
if (!params.isEmpty()) {
params = ", " + params;
}
iprint("return %1$s.%2$s(this%3$s);%n", scope.scopeField(), method.name(), params);
unindent();
iprint("}%n");
print("%n");
}
}

private String generateParameterList(
MethodDeclaration method, List<? extends VariableElement> parameters) {
List<String> params = new ArrayList<>();
for (int i = 0; i < parameters.size(); i++) {
VariableElement variable = parameters.get(i);
boolean isLast = (parameters.size() - 1) == i;
String type = variable.asType().toString();

if (isLast && method.isVarArgs()) {
// build varargs parameter
ArrayType arrayType = (ArrayType) variable.asType();
type = arrayType.getComponentType().toString() + "...";
}

params.add(type + " " + variable.getSimpleName());
}

return String.join(", ", params);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
import static org.seasar.doma.internal.util.AssertionUtil.assertNotNull;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import org.seasar.doma.internal.apt.annot.EntityAnnot;
import org.seasar.doma.internal.apt.annot.MetamodelAnnot;
import org.seasar.doma.internal.apt.annot.ScopeClass;
import org.seasar.doma.internal.apt.annot.TableAnnot;
import org.seasar.doma.internal.apt.meta.TypeElementMeta;
import org.seasar.doma.jdbc.entity.NamingType;
Expand Down Expand Up @@ -116,6 +120,15 @@ public List<EntityPropertyMeta> getIdPropertyMetas() {
return idPropertyMetas;
}

public List<EntityMetaScope> getAllMetaScope() {
MetamodelAnnot metamodelValue = getEntityAnnot().getMetamodelValue();
if (metamodelValue == null) {
return Collections.emptyList();
}
List<ScopeClass> scopeClasses = metamodelValue.getScopeValue();
return scopeClasses.stream().map(EntityMetaScope::new).collect(Collectors.toList());
}

public boolean hasVersionPropertyMeta() {
return versionPropertyMeta != null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.seasar.doma.internal.apt.meta.entity;

import org.seasar.doma.internal.apt.annot.ScopeClass;

public class EntityMetaScope {
nakamura-to marked this conversation as resolved.
Show resolved Hide resolved
final ScopeClass scopeClass;

public EntityMetaScope(ScopeClass scopeClass) {
this.scopeClass = scopeClass;
}

public ScopeClass scopeClass() {
return scopeClass;
}

public String scopeField() {
String name = scopeClass().className().getSimpleName();
nakamura-to marked this conversation as resolved.
Show resolved Hide resolved
return "_scope_" + name;
nakamura-to marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package org.seasar.doma.internal.apt;

import java.io.IOException;
import java.io.*;
import java.net.URL;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.processing.Processor;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
Expand Down Expand Up @@ -40,6 +41,17 @@ protected void addCompilationUnit(final Class<?> clazz) {
compiler.addCompilationUnit(clazz);
}

protected void addResourceFileCompilationUnit(final String fqn) {
String fileName = fqn.replace(".", "/") + ".java";
try (InputStream in = getClass().getClassLoader().getResourceAsStream(fileName);
BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
String source = reader.lines().collect(Collectors.joining("\n"));
compiler.addCompilationUnit(fqn, source);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

protected void compile() throws IOException {
compiler.compile();
}
Expand Down
Loading