This commit is contained in:
Andrea Cavalli 2023-01-21 21:00:40 +01:00
parent 2b3c048e60
commit 68ce3b6d7e
18 changed files with 145 additions and 65 deletions

View File

@ -37,9 +37,7 @@ public final class ClassConfiguration {
return hash; return hash;
} }
@SuppressWarnings("MethodDoesntCallSuperMethod") public ClassConfiguration copy() {
@Override
public ClassConfiguration clone() {
var cc = new ClassConfiguration(); var cc = new ClassConfiguration();
cc.stringRepresenter = stringRepresenter; cc.stringRepresenter = stringRepresenter;
cc.data = new LinkedHashMap<>(data); cc.data = new LinkedHashMap<>(data);

View File

@ -3,6 +3,7 @@ package it.cavallium.data.generator.plugin;
import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeName;
import it.cavallium.data.generator.plugin.ComputedType.VersionedComputedType; import it.cavallium.data.generator.plugin.ComputedType.VersionedComputedType;
import java.util.LinkedHashMap;
import java.util.stream.Stream; import java.util.stream.Stream;
public sealed interface ComputedType permits VersionedComputedType, ComputedTypeArray, ComputedTypeCustom, public sealed interface ComputedType permits VersionedComputedType, ComputedTypeArray, ComputedTypeCustom,
@ -33,7 +34,8 @@ public sealed interface ComputedType permits VersionedComputedType, ComputedType
return !version.isCurrent() && version.getVersion() == this.getVersion().getVersion(); return !version.isCurrent() && version.getVersion() == this.getVersion().getVersion();
} }
ComputedType withChangeAtVersion(ComputedVersion version, VersionChangeChecker versionChangeChecker); ComputedType withChangeAtVersion(ComputedVersion version, VersionChangeChecker versionChangeChecker,
LinkedHashMap<String, VersionedType> data);
} }
/** /**

View File

@ -6,6 +6,7 @@ import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeName;
import it.cavallium.data.generator.nativedata.UpgradeUtil; import it.cavallium.data.generator.nativedata.UpgradeUtil;
import it.cavallium.data.generator.plugin.ComputedType.VersionedComputedType; import it.cavallium.data.generator.plugin.ComputedType.VersionedComputedType;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -32,7 +33,8 @@ public final class ComputedTypeArrayVersioned implements VersionedComputedType,
} }
@Override @Override
public ComputedTypeArrayVersioned withChangeAtVersion(ComputedVersion version, VersionChangeChecker versionChangeChecker) { public ComputedTypeArrayVersioned withChangeAtVersion(ComputedVersion version, VersionChangeChecker versionChangeChecker,
LinkedHashMap<String, VersionedType> data) {
return new ComputedTypeArrayVersioned(baseType.withVersion(version), return new ComputedTypeArrayVersioned(baseType.withVersion(version),
computedTypeSupplier computedTypeSupplier
); );

View File

@ -39,7 +39,8 @@ public final class ComputedTypeBase implements VersionedComputedType {
} }
@Override @Override
public ComputedTypeBase withChangeAtVersion(ComputedVersion version, VersionChangeChecker versionChangeChecker) { public ComputedTypeBase withChangeAtVersion(ComputedVersion version, VersionChangeChecker versionChangeChecker,
LinkedHashMap<String, VersionedType> data) {
var newData = new LinkedHashMap<String, VersionedType>(); var newData = new LinkedHashMap<String, VersionedType>();
data.forEach((k, v) -> newData.put(k, v.withVersionIfChanged(version, versionChangeChecker))); data.forEach((k, v) -> newData.put(k, v.withVersionIfChanged(version, versionChangeChecker)));
return new ComputedTypeBase(type.withVersion(version), return new ComputedTypeBase(type.withVersion(version),

View File

@ -5,6 +5,7 @@ import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeName;
import it.cavallium.data.generator.nativedata.UpgradeUtil; import it.cavallium.data.generator.nativedata.UpgradeUtil;
import it.cavallium.data.generator.plugin.ComputedType.VersionedComputedType; import it.cavallium.data.generator.plugin.ComputedType.VersionedComputedType;
import java.util.LinkedHashMap;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -30,7 +31,8 @@ public final class ComputedTypeNullableVersioned implements ComputedTypeNullable
} }
@Override @Override
public ComputedTypeNullableVersioned withChangeAtVersion(ComputedVersion version, VersionChangeChecker versionChangeChecker) { public ComputedTypeNullableVersioned withChangeAtVersion(ComputedVersion version, VersionChangeChecker versionChangeChecker,
LinkedHashMap<String, VersionedType> data) {
return new ComputedTypeNullableVersioned(baseType.withVersion(version), return new ComputedTypeNullableVersioned(baseType.withVersion(version),
computedTypeSupplier computedTypeSupplier
); );

View File

@ -4,6 +4,7 @@ import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeName;
import it.cavallium.data.generator.plugin.ComputedType.VersionedComputedType; import it.cavallium.data.generator.plugin.ComputedType.VersionedComputedType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -33,7 +34,7 @@ public final class ComputedTypeSuper implements VersionedComputedType {
@Override @Override
public it.cavallium.data.generator.plugin.ComputedTypeSuper withChangeAtVersion(ComputedVersion version, public it.cavallium.data.generator.plugin.ComputedTypeSuper withChangeAtVersion(ComputedVersion version,
VersionChangeChecker versionChangeChecker) { VersionChangeChecker versionChangeChecker, LinkedHashMap<String, VersionedType> data) {
return new it.cavallium.data.generator.plugin.ComputedTypeSuper(type.withVersion(version), return new it.cavallium.data.generator.plugin.ComputedTypeSuper(type.withVersion(version),
subTypes.stream().map(subType -> subType.withVersionIfChanged(version, versionChangeChecker)).toList(), subTypes.stream().map(subType -> subType.withVersionIfChanged(version, versionChangeChecker)).toList(),
computedTypeSupplier computedTypeSupplier

View File

@ -1,8 +1,5 @@
package it.cavallium.data.generator.plugin; package it.cavallium.data.generator.plugin;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import java.util.Objects; import java.util.Objects;
public final class CustomTypesConfiguration { public final class CustomTypesConfiguration {
@ -38,9 +35,7 @@ public final class CustomTypesConfiguration {
return hash; return hash;
} }
@SuppressWarnings("MethodDoesntCallSuperMethod") public CustomTypesConfiguration copy() {
@Override
public CustomTypesConfiguration clone() {
var c = new CustomTypesConfiguration(); var c = new CustomTypesConfiguration();
c.javaClass = this.javaClass; c.javaClass = this.javaClass;
c.serializer = this.serializer; c.serializer = this.serializer;

View File

@ -168,7 +168,12 @@ public class DataModel {
Map<String, ParsedClass> prevVersionConfiguration Map<String, ParsedClass> prevVersionConfiguration
= requireNonNull(computedClassConfig.get(versionIndex - 1)); = requireNonNull(computedClassConfig.get(versionIndex - 1));
Map<String, ParsedClass> newVersionConfiguration = prevVersionConfiguration.entrySet().stream() Map<String, ParsedClass> newVersionConfiguration = prevVersionConfiguration.entrySet().stream()
.map(entry -> Map.entry(entry.getKey(), entry.getValue().clone())) .map(entry -> {
var parsedClass = entry.getValue().copy();
parsedClass.differentThanPrev = null;
parsedClass.differentThanNext = false;
return Map.entry(entry.getKey(), parsedClass);
})
.collect(Collectors.toMap(Entry::getKey, Entry::getValue)); .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
for (VersionTransformation rawTransformation : version.transformations) { for (VersionTransformation rawTransformation : version.transformations) {
@ -284,6 +289,7 @@ public class DataModel {
)); ));
// Compute the types // Compute the types
Object2IntMap<String> currentOrNewerTypeVersion = new Object2IntOpenHashMap<>();
Int2ObjectMap<Map<String, ComputedType>> computedTypes = new Int2ObjectLinkedOpenHashMap<>(); Int2ObjectMap<Map<String, ComputedType>> computedTypes = new Int2ObjectLinkedOpenHashMap<>();
Int2ObjectMap<Map<String, ComputedType>> randomComputedTypes = new Int2ObjectOpenHashMap<>(); Int2ObjectMap<Map<String, ComputedType>> randomComputedTypes = new Int2ObjectOpenHashMap<>();
Int2ObjectMap<Map<String, List<TransformationConfiguration>>> baseTypeDataChanges = new Int2ObjectOpenHashMap<>(); Int2ObjectMap<Map<String, List<TransformationConfiguration>>> baseTypeDataChanges = new Int2ObjectOpenHashMap<>();
@ -369,8 +375,11 @@ public class DataModel {
// Compute native types // Compute native types
versionBaseTypes.addAll(ComputedTypeNative.get(computedTypeSupplier)); versionBaseTypes.addAll(ComputedTypeNative.get(computedTypeSupplier));
randomComputedTypes.put(versionIndexF, var allLatestTypes = versionBaseTypes.stream().distinct().collect(Collectors.toMap(ComputedType::getName, identity()));
versionBaseTypes.stream().distinct().collect(Collectors.toMap(ComputedType::getName, identity())));
allLatestTypes.forEach((typeName, type) -> currentOrNewerTypeVersion.put(typeName, latestVersion));
randomComputedTypes.put(versionIndexF, allLatestTypes);
} else { } else {
Set<String> changedTypes = randomComputedTypes.get(versionIndexF + 1).values().stream() Set<String> changedTypes = randomComputedTypes.get(versionIndexF + 1).values().stream()
.filter(prevType -> prevType instanceof ComputedTypeBase prevBaseType .filter(prevType -> prevType instanceof ComputedTypeBase prevBaseType
@ -391,15 +400,37 @@ public class DataModel {
} while (addedMoreTypes); } while (addedMoreTypes);
} }
for (String changedType : changedTypes) {
currentOrNewerTypeVersion.put(changedType, versionIndexF);
}
Map<String, ComputedType> currentVersionComputedTypes = new HashMap<>(); Map<String, ComputedType> currentVersionComputedTypes = new HashMap<>();
var versionChangeChecker = new VersionChangeChecker(changedTypes, versionIndexF, latestVersion); var versionChangeChecker = new VersionChangeChecker(changedTypes, versionIndexF, latestVersion);
randomComputedTypes.get(versionIndexF + 1).forEach((name, type) -> { randomComputedTypes.get(versionIndexF + 1).forEach((computedTypeName, computedType) -> {
if (!changedTypes.contains(name)) { if (!changedTypes.contains(computedTypeName)) {
currentVersionComputedTypes.put(name, type); currentVersionComputedTypes.put(computedTypeName, computedType);
} else { } else {
if (type instanceof VersionedComputedType versionedComputedType) { if (computedType instanceof VersionedComputedType versionedComputedType) {
ComputedType newType = versionedComputedType.withChangeAtVersion(version, versionChangeChecker); ParsedClass parsedClass = computedClassConfig.get(versionIndexF).get(computedTypeName);
currentVersionComputedTypes.put(name, newType); LinkedHashMap<String, VersionedType> parsedFields;
if (parsedClass != null) {
parsedFields = parsedClass.data
.entrySet()
.stream()
.collect(Collectors.toMap(Entry::getKey, e -> {
var fieldTypeName = e.getValue();
return new VersionedType(fieldTypeName, computedVersions.get(currentOrNewerTypeVersion.getInt(fieldTypeName)));
}, (a, b) -> {
throw new IllegalStateException();
}, LinkedHashMap::new));
} else {
parsedFields = new LinkedHashMap<>();
}
ComputedType olderComputedType = versionedComputedType.withChangeAtVersion(version,
versionChangeChecker,
parsedFields
);
currentVersionComputedTypes.put(computedTypeName, olderComputedType);
} else { } else {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -881,6 +912,10 @@ public class DataModel {
} }
public List<TransformationConfiguration> getChanges(ComputedTypeBase nextType) { public List<TransformationConfiguration> getChanges(ComputedTypeBase nextType) {
return baseTypeDataChanges.get(nextType.getVersion().getVersion()).get(nextType.getName()); var prev = getPrevVersion(nextType);
if (prev == null) {
return List.of();
}
return baseTypeDataChanges.get(prev.getVersion().getVersion() + 1).get(nextType.getName());
} }
} }

View File

@ -41,9 +41,7 @@ public final class MoveDataConfiguration implements TransformationConfiguration
return hash; return hash;
} }
@SuppressWarnings("MethodDoesntCallSuperMethod") public MoveDataConfiguration copy() {
@Override
public MoveDataConfiguration clone() {
var c = new MoveDataConfiguration(); var c = new MoveDataConfiguration();
if (this.transformClass != null) c.transformClass = this.transformClass; if (this.transformClass != null) c.transformClass = this.transformClass;
if (this.from != null) c.from = this.from; if (this.from != null) c.from = this.from;

View File

@ -47,9 +47,7 @@ public class NewDataConfiguration implements TransformationConfiguration {
return hash; return hash;
} }
@SuppressWarnings("MethodDoesntCallSuperMethod") public NewDataConfiguration copy() {
@Override
public NewDataConfiguration clone() {
var c = new NewDataConfiguration(); var c = new NewDataConfiguration();
if (this.transformClass != null) c.transformClass = this.transformClass; if (this.transformClass != null) c.transformClass = this.transformClass;
if (this.initializer != null) c.initializer = this.initializer; if (this.initializer != null) c.initializer = this.initializer;

View File

@ -61,12 +61,12 @@ public final class ParsedClass {
return hash; return hash;
} }
@SuppressWarnings("MethodDoesntCallSuperMethod") public ParsedClass copy() {
@Override
public ParsedClass clone() {
var cc = new ParsedClass(); var cc = new ParsedClass();
if (this.stringRepresenter != null) cc.stringRepresenter = this.stringRepresenter; if (this.stringRepresenter != null) cc.stringRepresenter = this.stringRepresenter;
cc.data = new LinkedHashMap<>(data); cc.data = new LinkedHashMap<>(data);
cc.differentThanNext = differentThanNext;
cc.differentThanPrev = differentThanPrev;
return cc; return cc;
} }

View File

@ -11,7 +11,7 @@ public class ParsedVersion {
public ParsedVersion(VersionConfiguration versionConfiguration) { public ParsedVersion(VersionConfiguration versionConfiguration) {
this.details = versionConfiguration.details; this.details = versionConfiguration.details;
if (versionConfiguration.transformations != null) { if (versionConfiguration.transformations != null) {
this.transformations = versionConfiguration.transformations.stream().map(VersionTransformation::clone).toList(); this.transformations = versionConfiguration.transformations.stream().map(VersionTransformation::copy).toList();
} }
} }

View File

@ -37,9 +37,7 @@ public class RemoveDataConfiguration implements TransformationConfiguration {
return hash; return hash;
} }
@SuppressWarnings("MethodDoesntCallSuperMethod") public RemoveDataConfiguration copy() {
@Override
public RemoveDataConfiguration clone() {
var c = new RemoveDataConfiguration(); var c = new RemoveDataConfiguration();
if (this.transformClass != null) c.transformClass = this.transformClass; if (this.transformClass != null) c.transformClass = this.transformClass;
if (this.from != null) c.from = this.from; if (this.from != null) c.from = this.from;

View File

@ -42,9 +42,7 @@ public class UpgradeDataConfiguration implements TransformationConfiguration {
return hash; return hash;
} }
@SuppressWarnings("MethodDoesntCallSuperMethod") public UpgradeDataConfiguration copy() {
@Override
public UpgradeDataConfiguration clone() {
var c = new UpgradeDataConfiguration(); var c = new UpgradeDataConfiguration();
if (this.transformClass != null) c.transformClass = this.transformClass; if (this.transformClass != null) c.transformClass = this.transformClass;
if (this.from != null) c.from = this.from; if (this.from != null) c.from = this.from;

View File

@ -87,14 +87,12 @@ public final class VersionTransformation {
return hash; return hash;
} }
@SuppressWarnings("MethodDoesntCallSuperMethod") public VersionTransformation copy() {
@Override
public VersionTransformation clone() {
var t = new VersionTransformation(); var t = new VersionTransformation();
if (this.moveData != null) t.moveData = this.moveData.clone(); if (this.moveData != null) t.moveData = this.moveData.copy();
if (this.removeData != null) t.removeData = this.removeData.clone(); if (this.removeData != null) t.removeData = this.removeData.copy();
if (this.upgradeData != null) t.upgradeData = this.upgradeData.clone(); if (this.upgradeData != null) t.upgradeData = this.upgradeData.copy();
if (this.newData != null) t.newData = this.newData.clone(); if (this.newData != null) t.newData = this.newData.copy();
return t; return t;
} }
} }

View File

@ -29,6 +29,7 @@ public class GenCurrentVersion extends ClassGenerator {
@Override @Override
protected Stream<GeneratedClass> generateClasses() { protected Stream<GeneratedClass> generateClasses() {
var currentVersionPackage = dataModel.getCurrentVersion().getPackage(basePackageName);
var currentVersionDataPackage = dataModel.getCurrentVersion().getDataPackage(basePackageName); var currentVersionDataPackage = dataModel.getCurrentVersion().getDataPackage(basePackageName);
var currentVersionClass = TypeSpec.classBuilder("CurrentVersion"); var currentVersionClass = TypeSpec.classBuilder("CurrentVersion");
@ -57,7 +58,7 @@ public class GenCurrentVersion extends ClassGenerator {
.addModifiers(Modifier.FINAL).addModifiers(Modifier.STATIC) .addModifiers(Modifier.FINAL).addModifiers(Modifier.STATIC)
.returns(ParameterizedTypeName.get(ClassName.get(Set.class), .returns(ParameterizedTypeName.get(ClassName.get(Set.class),
ParameterizedTypeName.get(ClassName.get(Class.class), ParameterizedTypeName.get(ClassName.get(Class.class),
WildcardTypeName.subtypeOf(ClassName.get(currentVersionDataPackage, "IType"))))) WildcardTypeName.subtypeOf(ClassName.get(currentVersionPackage, "IType")))))
.addCode("return $T.of(\n", Set.class); .addCode("return $T.of(\n", Set.class);
AtomicBoolean isFirst = new AtomicBoolean(true); AtomicBoolean isFirst = new AtomicBoolean(true);
dataModel.getSuperTypesComputed(dataModel.getCurrentVersion()).forEach(superType -> { dataModel.getSuperTypesComputed(dataModel.getCurrentVersion()).forEach(superType -> {
@ -77,10 +78,10 @@ public class GenCurrentVersion extends ClassGenerator {
.addModifiers(Modifier.FINAL).addModifiers(Modifier.STATIC) .addModifiers(Modifier.FINAL).addModifiers(Modifier.STATIC)
.returns(ParameterizedTypeName.get(ClassName.get(Set.class), .returns(ParameterizedTypeName.get(ClassName.get(Set.class),
ParameterizedTypeName.get(ClassName.get(Class.class), ParameterizedTypeName.get(ClassName.get(Class.class),
WildcardTypeName.subtypeOf(ClassName.get(currentVersionDataPackage, "IBaseType"))))); WildcardTypeName.subtypeOf(ClassName.get(currentVersionPackage, "IBaseType")))));
getSuperTypeSubtypesClasses getSuperTypeSubtypesClasses
.addParameter(ParameterSpec.builder(ParameterizedTypeName.get(ClassName.get(Class.class), .addParameter(ParameterSpec.builder(ParameterizedTypeName.get(ClassName.get(Class.class),
WildcardTypeName.subtypeOf(ClassName.get(currentVersionDataPackage, "IType")) WildcardTypeName.subtypeOf(ClassName.get(currentVersionPackage, "IType"))
), "superTypeClass").build()); ), "superTypeClass").build());
getSuperTypeSubtypesClasses.beginControlFlow("return switch (superTypeClass.getCanonicalName())"); getSuperTypeSubtypesClasses.beginControlFlow("return switch (superTypeClass.getCanonicalName())");
dataModel.getSuperTypesComputed(dataModel.getCurrentVersion()).forEach(superType -> { dataModel.getSuperTypesComputed(dataModel.getCurrentVersion()).forEach(superType -> {
@ -107,7 +108,7 @@ public class GenCurrentVersion extends ClassGenerator {
// UpgradeDataToLatestVersion1 Method // UpgradeDataToLatestVersion1 Method
{ {
var upgradeDataToLatestVersion1MethodBuilder = MethodSpec.methodBuilder("upgradeDataToLatestVersion") var upgradeDataToLatestVersion1MethodBuilder = MethodSpec.methodBuilder("upgradeDataToLatestVersion")
.addTypeVariable(TypeVariableName.get("U", ClassName.get(currentVersionDataPackage, "IBaseType"))) .addTypeVariable(TypeVariableName.get("U", ClassName.get(currentVersionPackage, "IBaseType")))
.addModifiers(Modifier.PUBLIC).addModifiers(Modifier.STATIC).addModifiers(Modifier.FINAL).returns(TypeVariableName.get("U")) .addModifiers(Modifier.PUBLIC).addModifiers(Modifier.STATIC).addModifiers(Modifier.FINAL).returns(TypeVariableName.get("U"))
.addParameter(ParameterSpec.builder(TypeName.INT, "oldVersion").build()).addParameter( .addParameter(ParameterSpec.builder(TypeName.INT, "oldVersion").build()).addParameter(
ParameterSpec.builder(ClassName.get(dataModel.getRootPackage(basePackageName), "BaseType"), "type").build()) ParameterSpec.builder(ClassName.get(dataModel.getRootPackage(basePackageName), "BaseType"), "type").build())
@ -133,7 +134,7 @@ public class GenCurrentVersion extends ClassGenerator {
var versionsClassName = ClassName.get(dataModel.getRootPackage(basePackageName), "Versions"); var versionsClassName = ClassName.get(dataModel.getRootPackage(basePackageName), "Versions");
var upgradeDataToLatestVersion2MethodBuilder = MethodSpec.methodBuilder("upgradeDataToLatestVersion") var upgradeDataToLatestVersion2MethodBuilder = MethodSpec.methodBuilder("upgradeDataToLatestVersion")
.addModifiers(Modifier.PUBLIC).addModifiers(Modifier.STATIC).addModifiers(Modifier.FINAL).addTypeVariable(TypeVariableName.get("T")) .addModifiers(Modifier.PUBLIC).addModifiers(Modifier.STATIC).addModifiers(Modifier.FINAL).addTypeVariable(TypeVariableName.get("T"))
.addTypeVariable(TypeVariableName.get("U", ClassName.get(currentVersionDataPackage, "IBaseType"))) .addTypeVariable(TypeVariableName.get("U", ClassName.get(currentVersionPackage, "IBaseType")))
.returns(TypeVariableName.get("U")) .returns(TypeVariableName.get("U"))
.addParameter(ParameterSpec.builder(TypeName.INT, "oldVersion").build()) .addParameter(ParameterSpec.builder(TypeName.INT, "oldVersion").build())
.addParameter(ParameterSpec.builder(TypeVariableName.get("T"), "oldData").build()) .addParameter(ParameterSpec.builder(TypeVariableName.get("T"), "oldData").build())

View File

@ -24,7 +24,7 @@ public class GenIBaseType extends ClassGenerator {
interfaceBuilder.addModifiers(Modifier.PUBLIC); interfaceBuilder.addModifiers(Modifier.PUBLIC);
var iTypeClassName = ClassName.get(version.getDataPackage(basePackageName), "IType"); var iTypeClassName = ClassName.get(version.getPackage(basePackageName), "IType");
var baseTypeClassName = ClassName.get(dataModel.getRootPackage(basePackageName), "BaseType"); var baseTypeClassName = ClassName.get(dataModel.getRootPackage(basePackageName), "BaseType");
interfaceBuilder.addSuperinterface(iTypeClassName); interfaceBuilder.addSuperinterface(iTypeClassName);

View File

@ -28,6 +28,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.IntStream; import java.util.stream.IntStream;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.lang.model.element.Modifier; import javax.lang.model.element.Modifier;
@ -93,6 +94,8 @@ public class GenUpgraderBaseX extends ClassGenerator {
AtomicInteger nextInitializerStaticFieldId = new AtomicInteger(); AtomicInteger nextInitializerStaticFieldId = new AtomicInteger();
HashMap<String, String> initializerStaticFieldNames = new HashMap<>(); HashMap<String, String> initializerStaticFieldNames = new HashMap<>();
AtomicInteger nextUpgraderStaticFieldId = new AtomicInteger();
HashMap<String, String> upgraderStaticFieldNames = new HashMap<>();
List<TransformationConfiguration> transformations = dataModel.getChanges(nextTypeBase); List<TransformationConfiguration> transformations = dataModel.getChanges(nextTypeBase);
method.addCode("return new $T(\n$>", nextTypeBaseClassName); method.addCode("return new $T(\n$>", nextTypeBaseClassName);
record ResultField(String name, ComputedType type, CodeBlock code) {} record ResultField(String name, ComputedType type, CodeBlock code) {}
@ -116,7 +119,7 @@ public class GenUpgraderBaseX extends ClassGenerator {
.map(e -> { .map(e -> {
var i = e.getKey(); var i = e.getKey();
var newDataConfiguration = e.getValue(); var newDataConfiguration = e.getValue();
var computedTypes = dataModel.getComputedTypes(version); var computedTypes = dataModel.getComputedTypes(nextTypeBase.getVersion());
var newFieldType = Objects.requireNonNull(computedTypes.get(fixType(newDataConfiguration.type))); var newFieldType = Objects.requireNonNull(computedTypes.get(fixType(newDataConfiguration.type)));
var initializerClass = ClassName.bestGuess(newDataConfiguration.initializer); var initializerClass = ClassName.bestGuess(newDataConfiguration.initializer);
@ -126,13 +129,13 @@ public class GenUpgraderBaseX extends ClassGenerator {
initializerClass initializerClass
); );
return new Field(newDataConfiguration.to, newFieldType, CodeBlock.of("$N", initializerName), i); return new Field(newDataConfiguration.to, newFieldType, CodeBlock.of("$N.initialize()", initializerName), i + 1);
}) })
); );
resultFields = fields.<ResultField>mapMulti((field, consumer) -> { resultFields = fields.<ResultField>mapMulti((field, consumer) -> {
String fieldName = field.name(); String fieldName = field.name();
ComputedType fieldType = field.type(); ComputedType fieldType = field.type();
CodeBlock codeBlock = CodeBlock.of("data.$N()", fieldName); CodeBlock codeBlock = field.code();
for (TransformationConfiguration transformation : transformations.subList(field.processFromTx(), for (TransformationConfiguration transformation : transformations.subList(field.processFromTx(),
transformations.size() transformations.size()
)) { )) {
@ -142,11 +145,20 @@ public class GenUpgraderBaseX extends ClassGenerator {
} }
fieldName = moveDataConfiguration.to; fieldName = moveDataConfiguration.to;
} else if (transformation instanceof NewDataConfiguration newDataConfiguration) { } else if (transformation instanceof NewDataConfiguration newDataConfiguration) {
if (newDataConfiguration.to.equals(fieldName)) {
var type = dataModel.getComputedTypes(version).get(fixType(newDataConfiguration.type));
throw new IllegalStateException(
"New field " + typeBase.getName() + "." + fieldName + " of type \"" + type + "\" at version \"" + nextTypeBase.getVersion()
+ "\" conflicts with another field of type \"" + fieldType + "\" with the same name at version \""
+ version + "\"!");
}
continue; continue;
} else if (transformation instanceof RemoveDataConfiguration removeDataConfiguration) { } else if (transformation instanceof RemoveDataConfiguration removeDataConfiguration) {
if (!removeDataConfiguration.from.equals(fieldName)) { if (!removeDataConfiguration.from.equals(fieldName)) {
continue; continue;
} }
fieldName = null;
fieldType = null;
return; return;
} else if (transformation instanceof UpgradeDataConfiguration upgradeDataConfiguration) { } else if (transformation instanceof UpgradeDataConfiguration upgradeDataConfiguration) {
if (!upgradeDataConfiguration.from.equals(fieldName)) { if (!upgradeDataConfiguration.from.equals(fieldName)) {
@ -156,9 +168,16 @@ public class GenUpgraderBaseX extends ClassGenerator {
var cb = CodeBlock.builder(); var cb = CodeBlock.builder();
var newFieldType = Objects var newFieldType = Objects
.requireNonNull(dataModel.getComputedTypes(version).get(fixType(upgradeDataConfiguration.type))); .requireNonNull(dataModel.getComputedTypes(version).get(fixType(upgradeDataConfiguration.type)));
cb.add("($T) $T.upgrade(($T) ",
var upgraderName = createUpgraderStaticField(nextUpgraderStaticFieldId,
upgraderStaticFieldNames,
classBuilder,
upgraderClass
);
cb.add("($T) $N.upgrade(($T) ",
newFieldType.getJTypeName(basePackageName), newFieldType.getJTypeName(basePackageName),
upgraderClass, upgraderName,
fieldType.getJTypeName(basePackageName) fieldType.getJTypeName(basePackageName)
); );
cb.add(codeBlock); cb.add(codeBlock);
@ -169,11 +188,27 @@ public class GenUpgraderBaseX extends ClassGenerator {
throw new UnsupportedOperationException("Unsupported transformation type: " + transformation); throw new UnsupportedOperationException("Unsupported transformation type: " + transformation);
} }
} }
System.out.println();
consumer.accept(new ResultField(fieldName, fieldType, codeBlock)); consumer.accept(new ResultField(fieldName, fieldType, codeBlock));
}).sorted(Comparator.comparingInt(f -> expectedResultFields.indexOf(f.name()))); }).sorted(Comparator.comparingInt(f -> expectedResultFields.indexOf(f.name())));
} }
resultFields AtomicInteger currentField = new AtomicInteger();
.flatMap(e -> Stream.of(CodeBlock.of(",\n"), upgradeFieldToType(e.name(), e.type(), e.code(), nextTypeBase))) var resultFieldsList = resultFields.toList();
resultFieldsList.stream().flatMap(e -> {
var currentFieldIndex = currentField.getAndIncrement();
var currentFieldName = e.name();
var expectedFieldIndex = expectedResultFields.indexOf(currentFieldName);
if (expectedFieldIndex != currentFieldIndex) {
var expectedFieldName = (currentFieldIndex >= 0 && expectedResultFields.size() > currentFieldIndex) ? expectedResultFields.get(currentFieldIndex) : "<?>";
throw new IllegalStateException(
"" + typeBase + " to " + nextTypeBase + ". Index " + currentFieldIndex + ". Expected " + expectedFieldName + ", got " + currentFieldName
+ ".\n\tExpected: " + String.join(", ", expectedResultFields) + "\n\tResult: " + resultFieldsList
.stream()
.map(ResultField::name)
.collect(Collectors.joining(", ")));
}
return Stream.of(CodeBlock.of(",\n"), upgradeFieldToType(e.name(), e.type(), e.code(), nextTypeBase));
})
.skip(1) .skip(1)
.forEach(method::addCode); .forEach(method::addCode);
method.addCode("\n$<);\n"); method.addCode("\n$<);\n");
@ -189,12 +224,34 @@ public class GenUpgraderBaseX extends ClassGenerator {
var initializerName = initializerStaticFieldNames.get(ref); var initializerName = initializerStaticFieldNames.get(ref);
if (initializerName == null) { if (initializerName == null) {
initializerName = "I" + nextInitializerStaticFieldId.getAndIncrement(); initializerName = "I" + nextInitializerStaticFieldId.getAndIncrement();
classBuilder.addField(FieldSpec.builder(initializerClass, initializerName).initializer("new $T()", initializerClass).build()); classBuilder.addField(FieldSpec
.builder(initializerClass, initializerName)
.addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)
.initializer("new $T()", initializerClass)
.build());
initializerStaticFieldNames.put(ref, initializerName); initializerStaticFieldNames.put(ref, initializerName);
} }
return initializerName; return initializerName;
} }
private String createUpgraderStaticField(AtomicInteger nextUpgraderStaticFieldId,
HashMap<String, String> upgraderStaticFieldNames,
Builder classBuilder,
ClassName upgraderClass) {
var ref = upgraderClass.reflectionName();
var upgraderName = upgraderStaticFieldNames.get(ref);
if (upgraderName == null) {
upgraderName = "U" + nextUpgraderStaticFieldId.getAndIncrement();
classBuilder.addField(FieldSpec
.builder(upgraderClass, upgraderName)
.addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)
.initializer("new $T()", upgraderClass)
.build());
upgraderStaticFieldNames.put(ref, upgraderName);
}
return upgraderName;
}
private CodeBlock upgradeFieldToType(String fieldName, private CodeBlock upgradeFieldToType(String fieldName,
ComputedType fieldType, ComputedType fieldType,
CodeBlock codeBlock, CodeBlock codeBlock,
@ -208,8 +265,4 @@ public class GenUpgraderBaseX extends ClassGenerator {
} }
return codeBlock; return codeBlock;
} }
private String getFieldVarName(int totalTransformations, int transformationId) {
return null;
}
} }