mirror of
https://github.com/google/nomulus.git
synced 2025-07-22 02:36:03 +02:00
Resurrect symmetric vkeys when possible. (#899)
* Resurrect symmetric vkeys when possible. AbstractVKeyConverter had never been updated to generate symmetric VKeys for simple (i.e. non-composite) VKey types. Update it to default to generating a VKey with a simple Ofy key. With this change, composite VKeys must specify the "compositeKey = true" field in the With*VKey annotations. Doing so creates an asymmetric (SQL only) VKey that can triggers higher-level logic to generate a corrected VKey containing the composite Key.
This commit is contained in:
parent
49a55245ba
commit
1bd1615ca1
11 changed files with 179 additions and 64 deletions
|
@ -18,6 +18,12 @@ plugins {
|
|||
|
||||
dependencies {
|
||||
def deps = rootProject.dependencyMap
|
||||
|
||||
// Custom-built objectify jar at commit ecd5165, included in Nomulus
|
||||
// release.
|
||||
compile files(
|
||||
"${rootDir}/third_party/objectify/v4_1/objectify-4.1.3.jar")
|
||||
|
||||
compile deps['com.google.code.findbugs:jsr305']
|
||||
compile deps['com.google.guava:guava']
|
||||
compile deps['com.squareup:javapoet']
|
||||
|
|
|
@ -27,11 +27,14 @@ import com.squareup.javapoet.TypeSpec;
|
|||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.annotation.processing.AbstractProcessor;
|
||||
import javax.annotation.processing.RoundEnvironment;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
|
@ -47,9 +50,12 @@ import javax.persistence.Converter;
|
|||
public abstract class AbstractVKeyProcessor extends AbstractProcessor {
|
||||
|
||||
private static final String CONVERTER_CLASS_NAME_TEMP = "VKeyConverter_%s";
|
||||
// The method with same name should be defined in StringVKey and LongVKey
|
||||
// The method with same name should be defined in WithStringVKey and WithLongVKey
|
||||
private static final String CLASS_NAME_SUFFIX_KEY = "classNameSuffix";
|
||||
|
||||
// Method in WithStringVKey and WithLongVKey to indicate that this is a composite key.
|
||||
private static final String COMPOSITE_KEY_KEY = "compositeKey";
|
||||
|
||||
abstract Class<?> getSqlColumnType();
|
||||
|
||||
abstract String getAnnotationSimpleName();
|
||||
|
@ -76,18 +82,18 @@ public abstract class AbstractVKeyProcessor extends AbstractProcessor {
|
|||
actualAnnotation.size() == 1,
|
||||
String.format(
|
||||
"type can have only 1 %s annotation", getAnnotationSimpleName()));
|
||||
String converterClassNameSuffix =
|
||||
actualAnnotation.get(0).getElementValues().entrySet().stream()
|
||||
.filter(
|
||||
entry ->
|
||||
entry
|
||||
.getKey()
|
||||
.getSimpleName()
|
||||
.toString()
|
||||
.equals(CLASS_NAME_SUFFIX_KEY))
|
||||
.map(entry -> ((String) entry.getValue().getValue()).trim())
|
||||
.findFirst()
|
||||
.orElse("");
|
||||
String converterClassNameSuffix = "";
|
||||
boolean hasCompositeOfyKey = false;
|
||||
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry :
|
||||
actualAnnotation.get(0).getElementValues().entrySet()) {
|
||||
String keyName = entry.getKey().getSimpleName().toString();
|
||||
Object value = entry.getValue().getValue();
|
||||
if (keyName.equals(CLASS_NAME_SUFFIX_KEY)) {
|
||||
converterClassNameSuffix = ((String) value).trim();
|
||||
} else if (keyName.equals(COMPOSITE_KEY_KEY)) {
|
||||
hasCompositeOfyKey = (Boolean) value;
|
||||
}
|
||||
}
|
||||
if (converterClassNameSuffix.isEmpty()) {
|
||||
converterClassNameSuffix =
|
||||
getTypeUtils().asElement(entityType).getSimpleName().toString();
|
||||
|
@ -97,7 +103,8 @@ public abstract class AbstractVKeyProcessor extends AbstractProcessor {
|
|||
createJavaFile(
|
||||
getPackageName(annotatedTypeElement),
|
||||
String.format(CONVERTER_CLASS_NAME_TEMP, converterClassNameSuffix),
|
||||
entityType)
|
||||
entityType,
|
||||
hasCompositeOfyKey)
|
||||
.writeTo(processingEnv.getFiler());
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
|
@ -108,7 +115,10 @@ public abstract class AbstractVKeyProcessor extends AbstractProcessor {
|
|||
}
|
||||
|
||||
private JavaFile createJavaFile(
|
||||
String packageName, String converterClassName, TypeMirror entityTypeMirror) {
|
||||
String packageName,
|
||||
String converterClassName,
|
||||
TypeMirror entityTypeMirror,
|
||||
boolean hasCompositeOfyKey) {
|
||||
TypeName entityType = ClassName.get(entityTypeMirror);
|
||||
|
||||
ParameterizedTypeName attributeConverter =
|
||||
|
@ -127,7 +137,7 @@ public abstract class AbstractVKeyProcessor extends AbstractProcessor {
|
|||
.addStatement("return $T.class", entityType)
|
||||
.build();
|
||||
|
||||
TypeSpec vKeyConverter =
|
||||
TypeSpec.Builder classBuilder =
|
||||
TypeSpec.classBuilder(converterClassName)
|
||||
.addAnnotation(
|
||||
AnnotationSpec.builder(ClassName.get(Converter.class))
|
||||
|
@ -135,9 +145,24 @@ public abstract class AbstractVKeyProcessor extends AbstractProcessor {
|
|||
.build())
|
||||
.addModifiers(Modifier.FINAL)
|
||||
.superclass(attributeConverter)
|
||||
.addMethod(getAttributeClass)
|
||||
.build();
|
||||
.addMethod(getAttributeClass);
|
||||
|
||||
// If this is a converter for a composite vkey type, generate an override for the default
|
||||
// {@link google.registry.persistence.VKeyConverter.hasCompositeOfyKey()} method, which returns
|
||||
// false.
|
||||
if (hasCompositeOfyKey) {
|
||||
MethodSpec hasCompositeOfyKeyMethod =
|
||||
MethodSpec.methodBuilder("hasCompositeOfyKey")
|
||||
.addAnnotation(Override.class)
|
||||
.addModifiers(Modifier.PROTECTED)
|
||||
.returns(boolean.class)
|
||||
.addStatement("return true", entityType)
|
||||
.build();
|
||||
|
||||
classBuilder.addMethod(hasCompositeOfyKeyMethod);
|
||||
}
|
||||
|
||||
TypeSpec vKeyConverter = classBuilder.build();
|
||||
return JavaFile.builder(packageName, vKeyConverter).build();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue