Skip to content

Commit

Permalink
Made section reader even more flexible and added projections
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim203 committed Jun 20, 2024
1 parent 109f236 commit 7ea8686
Show file tree
Hide file tree
Showing 40 changed files with 1,775 additions and 510 deletions.
8 changes: 3 additions & 5 deletions ap/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@ dependencies {
tasks.withType<Test>().configureEach {
doFirst {
// See: https://github.com/google/compile-testing/issues/222
jvmArgs(
"--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED"
)
jvmArgs("--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED")
jvmArgs("--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED")
jvmArgs("--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ EntityInfo processEntity(TypeElement type) {
indexes.add(new IndexInfo("", keys.toArray(new CharSequence[0]), true));
}

var entityInfo = new EntityInfo(tableName, type.getQualifiedName(), columns, indexes, keys);
var entityInfo = new EntityInfo(tableName, type, columns, indexes, keys);
entityInfoByClassName.put(type.getQualifiedName(), entityInfo);
return entityInfo;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
Expand Down Expand Up @@ -102,7 +101,7 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
for (int i = 0; i < result.size(); i++) {
results.get(i).add(result.get(i));
}
} catch (InvalidRepositoryException exception) {
} catch (InvalidRepositoryException | IllegalStateException exception) {
error(exception.getMessage());
errorOccurred = true;
}
Expand Down Expand Up @@ -195,27 +194,16 @@ private List<RepositoryGenerator> processRepository(TypeElement repository) {
continue;
}

TypeElement returnType;
boolean async = false;
if (MoreTypes.isTypeOf(CompletableFuture.class, element.getReturnType())) {
async = true;
returnType = typeUtils.toBoxedTypeElement(MoreTypes.asDeclared(element.getReturnType())
.getTypeArguments()
.get(0));
} else {
returnType = typeUtils.toBoxedTypeElement(element.getReturnType());
}

var name = element.getSimpleName().toString();

var result = new KeywordsReader(name, entity).read();
var action = ActionRegistry.actionMatching(result);
if (action == null) {
throw new InvalidRepositoryException("No available actions for %s", name);
}
var queryInfo = new QueryInfoCreator(result, element, entity, typeUtils).create();
var queryInfo = new QueryInfoCreator(action, result, element, entity, typeUtils).create();

action.addTo(generators, queryInfo, returnType, async, typeUtils);
action.addTo(generators, queryInfo);
}

return generators;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,94 +27,117 @@
import com.squareup.javapoet.MethodSpec;
import java.util.Collection;
import java.util.List;
import javax.lang.model.element.TypeElement;
import java.util.function.Consumer;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import org.geysermc.databaseutils.processor.info.EntityInfo;
import org.geysermc.databaseutils.processor.query.QueryInfo;
import org.geysermc.databaseutils.processor.query.section.projection.ProjectionKeywordCategory;
import org.geysermc.databaseutils.processor.type.RepositoryGenerator;
import org.geysermc.databaseutils.processor.util.InvalidRepositoryException;
import org.geysermc.databaseutils.processor.util.TypeUtils;

public abstract class Action {
private final String actionType;
private final boolean allowSelfCollectionArgument;
private final boolean supportsFilter;
private final List<ProjectionKeywordCategory> supportedProjectionCategories;

protected Action(String actionType) {
this(actionType, true);
}

protected Action(String actionType, boolean supportsFilter) {
protected Action(
String actionType,
boolean allowSelfCollectionArgument,
boolean supportsFilter,
ProjectionKeywordCategory... supportedProjectionCategories) {
this.actionType = actionType;
this.allowSelfCollectionArgument = allowSelfCollectionArgument;
this.supportsFilter = supportsFilter;
this.supportedProjectionCategories = List.of(supportedProjectionCategories);
}

public String actionType() {
return actionType;
}

public boolean allowSelfCollectionArgument() {
return allowSelfCollectionArgument;
}

public boolean supportsFilter() {
return supportsFilter;
}

protected abstract void addToSingle(
RepositoryGenerator generator,
QueryInfo info,
MethodSpec.Builder spec,
TypeElement returnType,
boolean async);
public List<ProjectionKeywordCategory> unsupportedProjectionCategories() {
return supportedProjectionCategories;
}

protected abstract void addToSingle(RepositoryGenerator generator, QueryInfo info, MethodSpec.Builder spec);

protected boolean validateSingle(QueryInfo info, TypeElement returnType, TypeUtils typeUtils) {
return TypeUtils.isType(Void.class, returnType) || TypeUtils.isWholeNumberType(returnType);
protected boolean validateSingle(
EntityInfo info, CharSequence methodName, TypeMirror returnType, TypeUtils typeUtils) {
return typeUtils.isType(Void.class, returnType) || typeUtils.isWholeNumberType(returnType);
}

protected boolean validateCollection(QueryInfo info, TypeElement elementType, TypeUtils typeUtils) {
return false;
protected boolean validateCollection(
EntityInfo info, CharSequence methodName, TypeMirror returnType, TypeUtils typeUtils) {
throw new InvalidRepositoryException(
"Collection return type (%s) is not supported for %s", returnType, actionType());
}

protected boolean validateEither(QueryInfo info, TypeElement elementType, boolean collection, TypeUtils typeUtils) {
protected boolean validateEither(
EntityInfo info, CharSequence methodName, TypeMirror returnType, boolean collection, TypeUtils typeUtils) {
return false;
}

protected void validate(QueryInfo info, TypeElement returnType, TypeUtils typeUtils) {
var elementType = returnType;
if (typeUtils.isAssignable(Collection.class, returnType.asType())) {
elementType = (TypeElement) returnType.getTypeParameters().get(0);
public void validate(
EntityInfo info,
CharSequence methodName,
TypeMirror returnType,
TypeUtils typeUtils,
Consumer<TypeMirror> customValidation) {
var passedCustomValidation = false;
if (typeUtils.isAssignable(returnType, Collection.class)) {
returnType = ((DeclaredType) returnType).getTypeArguments().get(0);

if (!supportsFilter) {
throw new InvalidRepositoryException("%s does not support a By section", actionType);
}

if (validateCollection(info, elementType, typeUtils)
|| validateEither(info, elementType, true, typeUtils)) {
if (customValidation != null) {
customValidation.accept(returnType);
passedCustomValidation = true;
}

if (validateCollection(info, methodName, returnType, typeUtils)
|| validateEither(info, methodName, returnType, true, typeUtils)) {
return;
}
} else {
if (validateEither(info, elementType, false, typeUtils)) {
if (customValidation != null) {
customValidation.accept(returnType);
passedCustomValidation = true;
}

if (validateEither(info, methodName, returnType, false, typeUtils)) {
return;
}
if (validateSingle(info, returnType, typeUtils)) {
if (validateSingle(info, methodName, returnType, typeUtils)) {
return;
}
}

if (!typeUtils.isAssignable(info.entityType(), elementType.asType())) {
throw new InvalidRepositoryException(
"Unsupported return type %s for %s",
returnType.getSimpleName(), info.element().getSimpleName());
if (!passedCustomValidation) {
throw new InvalidRepositoryException("Unsupported return type %s for %s", returnType, methodName);
}
}

public void addTo(
List<RepositoryGenerator> generators,
QueryInfo info,
TypeElement returnType,
boolean async,
TypeUtils typeUtils) {
if (!info.hasBySection() && info.element().getParameters().size() != 1) {
throw new InvalidRepositoryException("Expected one parameter with type %s", info.entityType());
public void addTo(List<RepositoryGenerator> generators, QueryInfo info) {
if (!info.hasBySection() && !info.parametersInfo().isNoneOrAnySelf()) {
throw new InvalidRepositoryException("Expected at most one parameter, with type %s", info.entityType());
}
validate(info, returnType, typeUtils);

for (RepositoryGenerator generator : generators) {
addToSingle(generator, info, MethodSpec.overriding(info.element()), returnType, async);
addToSingle(
generator, info, MethodSpec.overriding(info.parametersInfo().element()));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,30 @@
package org.geysermc.databaseutils.processor.action;

import com.squareup.javapoet.MethodSpec;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import org.geysermc.databaseutils.processor.info.EntityInfo;
import org.geysermc.databaseutils.processor.query.QueryInfo;
import org.geysermc.databaseutils.processor.type.RepositoryGenerator;
import org.geysermc.databaseutils.processor.util.InvalidRepositoryException;
import org.geysermc.databaseutils.processor.util.TypeUtils;

final class DeleteAction extends Action {
DeleteAction() {
super("delete");
super("delete", true, true);
}

@Override
protected boolean validateSingle(QueryInfo info, TypeElement returnType, TypeUtils typeUtils) {
// todo does it also support saying how many items were deleted?
if (!TypeUtils.isType(Void.class, returnType)) {
throw new InvalidRepositoryException(
"Expected Void as return type for %s, got %s",
info.element().getSimpleName(), returnType);
}
return true;
protected void addToSingle(RepositoryGenerator generator, QueryInfo info, MethodSpec.Builder spec) {
generator.addDelete(info, spec);
}

@Override
protected void addToSingle(
RepositoryGenerator generator,
QueryInfo info,
MethodSpec.Builder spec,
TypeElement returnType,
boolean async) {
generator.addDelete(info, spec, returnType, async);
protected boolean validateSingle(
EntityInfo info, CharSequence methodName, TypeMirror returnType, TypeUtils typeUtils) {
// todo does it also support saying how many items were deleted?
if (!typeUtils.isType(Void.class, returnType)) {
throw new InvalidRepositoryException("Expected Void as return type for %s, got %s", methodName, returnType);
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,31 @@
package org.geysermc.databaseutils.processor.action;

import com.squareup.javapoet.MethodSpec;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import org.geysermc.databaseutils.processor.info.EntityInfo;
import org.geysermc.databaseutils.processor.query.QueryInfo;
import org.geysermc.databaseutils.processor.query.section.projection.ProjectionKeywordCategory;
import org.geysermc.databaseutils.processor.type.RepositoryGenerator;
import org.geysermc.databaseutils.processor.util.InvalidRepositoryException;
import org.geysermc.databaseutils.processor.util.TypeUtils;

final class ExistsAction extends Action {
ExistsAction() {
super("exists");
super("exists", false, true, ProjectionKeywordCategory.UNIQUE);
}

@Override
protected boolean validateSingle(QueryInfo info, TypeElement returnType, TypeUtils typeUtils) {
if (!TypeUtils.isType(Boolean.class, returnType)) {
protected boolean validateSingle(
EntityInfo info, CharSequence methodName, TypeMirror returnType, TypeUtils typeUtils) {
if (!typeUtils.isType(Boolean.class, returnType)) {
throw new InvalidRepositoryException(
"Expected Boolean as return type for %s, got %s",
info.element().getSimpleName(), returnType);
"Expected Boolean as return type for %s, got %s", methodName, returnType);
}
return true;
}

@Override
public void addToSingle(
RepositoryGenerator generator,
QueryInfo info,
MethodSpec.Builder spec,
TypeElement returnType,
boolean async) {
generator.addExists(info, spec, returnType, async);
public void addToSingle(RepositoryGenerator generator, QueryInfo info, MethodSpec.Builder spec) {
generator.addExists(info, spec);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,43 @@
package org.geysermc.databaseutils.processor.action;

import com.squareup.javapoet.MethodSpec;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import org.geysermc.databaseutils.processor.info.EntityInfo;
import org.geysermc.databaseutils.processor.query.QueryInfo;
import org.geysermc.databaseutils.processor.query.section.projection.ProjectionKeywordCategory;
import org.geysermc.databaseutils.processor.type.RepositoryGenerator;
import org.geysermc.databaseutils.processor.util.InvalidRepositoryException;
import org.geysermc.databaseutils.processor.util.TypeUtils;

final class FindAction extends Action {
FindAction() {
super("find");
super(
"find",
true,
true,
ProjectionKeywordCategory.UNIQUE,
ProjectionKeywordCategory.SUMMARY,
ProjectionKeywordCategory.LIMIT);
}

@Override
protected boolean validateEither(QueryInfo info, TypeElement returnType, boolean collection, TypeUtils typeUtils) {
if (!TypeUtils.isType(info.entityType(), returnType)) {
protected boolean validateEither(
EntityInfo info, CharSequence methodName, TypeMirror returnType, boolean collection, TypeUtils typeUtils) {
if (!typeUtils.isType(info.type().asType(), returnType)) {
throw new InvalidRepositoryException(
"Expected %s as return type for %s, got %s",
info.entityType(), info.element().getSimpleName(), returnType);
"Expected %s as return type for %s, got %s", info.typeName(), methodName, returnType);
}
return true;
}

@Override
public void addToSingle(
RepositoryGenerator generator,
QueryInfo info,
MethodSpec.Builder spec,
TypeElement returnType,
boolean async) {
generator.addFind(info, spec, returnType, async);
protected boolean validateCollection(
EntityInfo info, CharSequence methodName, TypeMirror returnType, TypeUtils typeUtils) {
return false;
}

@Override
public void addToSingle(RepositoryGenerator generator, QueryInfo info, MethodSpec.Builder spec) {
generator.addFind(info, spec);
}
}
Loading

0 comments on commit 7ea8686

Please sign in to comment.