Partial new generator
This commit is contained in:
parent
b446dd682b
commit
8ab50ddefb
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,3 +9,4 @@
|
|||||||
|
|
||||||
.flattened-pom.xml
|
.flattened-pom.xml
|
||||||
/.idea/
|
/.idea/
|
||||||
|
/data-generator-plugin/src/test/java/it/test/
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
package it.cavallium.data.generator.plugin;
|
||||||
|
|
||||||
|
import static java.nio.file.StandardOpenOption.CREATE;
|
||||||
|
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
|
||||||
|
import static java.nio.file.StandardOpenOption.WRITE;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.JavaFile;
|
||||||
|
import com.squareup.javapoet.TypeSpec;
|
||||||
|
import com.squareup.javapoet.TypeSpec.Builder;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public abstract class ClassGenerator {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
private final HashSet<Path> generatedFilesToDelete;
|
||||||
|
protected final DataModel dataModel;
|
||||||
|
protected final String basePackageName;
|
||||||
|
private final Path outPath;
|
||||||
|
protected final boolean deepCheckBeforeCreatingNewEqualInstances;
|
||||||
|
|
||||||
|
public ClassGenerator(ClassGeneratorParams params) {
|
||||||
|
this.generatedFilesToDelete = params.generatedFilesToDelete;
|
||||||
|
this.dataModel = params.dataModel;
|
||||||
|
this.basePackageName = params.basePackageName;
|
||||||
|
this.outPath = params.outPath;
|
||||||
|
this.deepCheckBeforeCreatingNewEqualInstances = params.deepCheckBeforeCreatingNewEqualInstances;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() throws IOException {
|
||||||
|
for (GeneratedClass generatedClass : generateClasses().toList()) {
|
||||||
|
writeClass(generatedClass.packageName, generatedClass.content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeClass(String classPackage, Builder versionsClass) throws IOException {
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
var typeSpec = versionsClass.build();
|
||||||
|
var outJavaFile = outPath;
|
||||||
|
for (String part : classPackage.split("\\.")) {
|
||||||
|
outJavaFile = outJavaFile.resolve(part);
|
||||||
|
}
|
||||||
|
if (Files.notExists(outJavaFile)) {
|
||||||
|
Files.createDirectories(outJavaFile);
|
||||||
|
}
|
||||||
|
outJavaFile = outJavaFile.resolve(typeSpec.name + ".java");
|
||||||
|
JavaFile.builder(classPackage, typeSpec).build().writeTo(sb);
|
||||||
|
String newFile = sb.toString();
|
||||||
|
boolean mustWrite;
|
||||||
|
if (Files.isRegularFile(outJavaFile) && Files.isReadable(outJavaFile)) {
|
||||||
|
String oldFile = Files.readString(outJavaFile, StandardCharsets.UTF_8);
|
||||||
|
mustWrite = !oldFile.equals(newFile);
|
||||||
|
} else {
|
||||||
|
mustWrite = true;
|
||||||
|
}
|
||||||
|
if (mustWrite) {
|
||||||
|
logger.debug("File {} changed", outJavaFile);
|
||||||
|
Files.writeString(outJavaFile, newFile, StandardCharsets.UTF_8, TRUNCATE_EXISTING, CREATE, WRITE);
|
||||||
|
} else {
|
||||||
|
logger.debug("File {} is the same, unchanged", outJavaFile);
|
||||||
|
}
|
||||||
|
markFileAsCreated(generatedFilesToDelete, outPath, outJavaFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void markFileAsCreated(Set<Path> generatedFilesToDelete, Path basePath, Path filePath) {
|
||||||
|
generatedFilesToDelete.remove(basePath.relativize(filePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Stream<GeneratedClass> generateClasses();
|
||||||
|
|
||||||
|
public record GeneratedClass(String packageName, TypeSpec.Builder content) {}
|
||||||
|
|
||||||
|
public record ClassGeneratorParams(HashSet<Path> generatedFilesToDelete,
|
||||||
|
DataModel dataModel,
|
||||||
|
String basePackageName,
|
||||||
|
Path outPath,
|
||||||
|
boolean deepCheckBeforeCreatingNewEqualInstances) {}
|
||||||
|
}
|
@ -1,20 +1,34 @@
|
|||||||
package it.cavallium.data.generator.plugin;
|
package it.cavallium.data.generator.plugin;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import com.squareup.javapoet.TypeName;
|
||||||
import java.util.LinkedHashMap;
|
import it.cavallium.data.generator.plugin.ComputedType.VersionedComputedType;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public sealed interface ComputedType {
|
public sealed interface ComputedType permits VersionedComputedType, ComputedTypeArray, ComputedTypeCustom,
|
||||||
|
ComputedTypeNative, ComputedTypeNullable {
|
||||||
|
|
||||||
String getName();
|
String getName();
|
||||||
|
|
||||||
sealed interface VersionedComputedType extends ComputedType {
|
TypeName getJTypeName(String basePackageName);
|
||||||
|
|
||||||
int getVersion();
|
TypeName getJSerializerName(String basePackageName);
|
||||||
|
|
||||||
ComputedType withChangeAtVersion(int version, VersionChangeChecker versionChangeChecker);
|
FieldLocation getJSerializerInstance(String basePackageName);
|
||||||
|
|
||||||
|
TypeName getJUpgraderName(String basePackageName);
|
||||||
|
|
||||||
|
FieldLocation getJUpgraderInstance(String basePackageName);
|
||||||
|
|
||||||
|
sealed interface VersionedComputedType extends ComputedType permits ComputedTypeArrayVersioned, ComputedTypeBase,
|
||||||
|
ComputedTypeNullableVersioned, ComputedTypeSuper {
|
||||||
|
|
||||||
|
ComputedVersion getVersion();
|
||||||
|
|
||||||
|
default boolean shouldUpgradeAfter(ComputedVersion version) {
|
||||||
|
return !version.isCurrent() && version.getVersion() == this.getVersion().getVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
ComputedType withChangeAtVersion(ComputedVersion version, VersionChangeChecker versionChangeChecker);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,461 +41,4 @@ public sealed interface ComputedType {
|
|||||||
*/
|
*/
|
||||||
Stream<ComputedType> getDependents();
|
Stream<ComputedType> getDependents();
|
||||||
|
|
||||||
final class ComputedBaseType implements VersionedComputedType {
|
|
||||||
|
|
||||||
private final VersionedType type;
|
|
||||||
private final String stringRepresenter;
|
|
||||||
|
|
||||||
private final LinkedHashMap<String, VersionedType> data;
|
|
||||||
private LinkedHashMap<String, ComputedType> computedData;
|
|
||||||
private final ComputedTypeSupplier computedTypeSupplier;
|
|
||||||
|
|
||||||
public ComputedBaseType(VersionedType type,
|
|
||||||
String stringRepresenter,
|
|
||||||
LinkedHashMap<String, VersionedType> data,
|
|
||||||
ComputedTypeSupplier computedTypeSupplier) {
|
|
||||||
this.type = type;
|
|
||||||
if (type.type().startsWith("~") || type.type().startsWith("-")) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
this.computedTypeSupplier = computedTypeSupplier;
|
|
||||||
this.stringRepresenter = stringRepresenter;
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getType() {
|
|
||||||
return type.type();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getVersion() {
|
|
||||||
return type.version();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ComputedBaseType withChangeAtVersion(int version, VersionChangeChecker versionChangeChecker) {
|
|
||||||
var newData = new LinkedHashMap<String, VersionedType>();
|
|
||||||
data.forEach((k, v) -> newData.put(k, v.withVersionIfChanged(version, versionChangeChecker)));
|
|
||||||
return new ComputedBaseType(type.withVersion(version), stringRepresenter, newData, computedTypeSupplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStringRepresenter() {
|
|
||||||
return stringRepresenter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LinkedHashMap<String, ComputedType> getData() {
|
|
||||||
synchronized (this) {
|
|
||||||
if (computedData == null) {
|
|
||||||
computedData = new LinkedHashMap<>();
|
|
||||||
data.forEach((k, v) -> computedData.put(k, computedTypeSupplier.get(v)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return computedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ComputedBaseType that = (ComputedBaseType) o;
|
|
||||||
|
|
||||||
if (!Objects.equals(type, that.type)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!Objects.equals(stringRepresenter, that.stringRepresenter)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return Objects.equals(data, that.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = type != null ? type.hashCode() : 0;
|
|
||||||
result = 31 * result + (stringRepresenter != null ? stringRepresenter.hashCode() : 0);
|
|
||||||
result = 31 * result + (data != null ? data.hashCode() : 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return type.type();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<ComputedType> getDependencies() {
|
|
||||||
return this.data.values().stream().map(computedTypeSupplier::get);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<ComputedType> getDependents() {
|
|
||||||
return computedTypeSupplier.getDependents(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class ComputedCustomType implements ComputedType {
|
|
||||||
|
|
||||||
private final String type;
|
|
||||||
private final String javaClass;
|
|
||||||
private final String serializer;
|
|
||||||
private final ComputedTypeSupplier computedTypeSupplier;
|
|
||||||
|
|
||||||
public ComputedCustomType(String type, String javaClass, String serializer, ComputedTypeSupplier computedTypeSupplier) {
|
|
||||||
this.type = type;
|
|
||||||
this.javaClass = javaClass;
|
|
||||||
this.serializer = serializer;
|
|
||||||
this.computedTypeSupplier = computedTypeSupplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getJavaClass() {
|
|
||||||
return javaClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSerializer() {
|
|
||||||
return serializer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ComputedCustomType that = (ComputedCustomType) o;
|
|
||||||
|
|
||||||
if (!Objects.equals(type, that.type)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!Objects.equals(javaClass, that.javaClass)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return Objects.equals(serializer, that.serializer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = type != null ? type.hashCode() : 0;
|
|
||||||
result = 31 * result + (javaClass != null ? javaClass.hashCode() : 0);
|
|
||||||
result = 31 * result + (serializer != null ? serializer.hashCode() : 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<ComputedType> getDependencies() {
|
|
||||||
return Stream.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<ComputedType> getDependents() {
|
|
||||||
return computedTypeSupplier.getDependents(new VersionedType(type, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class ComputedNullableType implements VersionedComputedType {
|
|
||||||
|
|
||||||
private final VersionedType baseType;
|
|
||||||
|
|
||||||
private ComputedType computedChild;
|
|
||||||
private final ComputedTypeSupplier computedTypeSupplier;
|
|
||||||
|
|
||||||
public ComputedNullableType(VersionedType baseType, ComputedTypeSupplier computedTypeSupplier) {
|
|
||||||
this.baseType = baseType;
|
|
||||||
this.computedTypeSupplier = computedTypeSupplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getBaseType() {
|
|
||||||
return baseType.type();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getVersion() {
|
|
||||||
return baseType.version();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ComputedNullableType withChangeAtVersion(int version, VersionChangeChecker versionChangeChecker) {
|
|
||||||
return new ComputedNullableType(baseType.withVersion(version), computedTypeSupplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ComputedType child() {
|
|
||||||
synchronized (this) {
|
|
||||||
if (computedChild == null) {
|
|
||||||
computedChild = computedTypeSupplier.get(baseType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (computedChild instanceof ComputedNullableType) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
} else if (computedChild instanceof ComputedArrayType) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
return computedChild;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ComputedNullableType that = (ComputedNullableType) o;
|
|
||||||
|
|
||||||
return Objects.equals(baseType, that.baseType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return baseType != null ? baseType.hashCode() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "-" + baseType.type();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<ComputedType> getDependencies() {
|
|
||||||
return Stream.of(child());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<ComputedType> getDependents() {
|
|
||||||
return computedTypeSupplier.getDependents(new VersionedType(getName(), 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class ComputedSuperType implements VersionedComputedType {
|
|
||||||
|
|
||||||
private final VersionedType type;
|
|
||||||
private final List<VersionedType> subTypes;
|
|
||||||
|
|
||||||
private List<ComputedType> computedSubTypes;
|
|
||||||
private final ComputedTypeSupplier computedTypeSupplier;
|
|
||||||
|
|
||||||
public ComputedSuperType(VersionedType type,
|
|
||||||
List<VersionedType> subType,
|
|
||||||
ComputedTypeSupplier computedTypeSupplier) {
|
|
||||||
this.type = type;
|
|
||||||
this.subTypes = subType;
|
|
||||||
this.computedTypeSupplier = computedTypeSupplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getType() {
|
|
||||||
return type.type();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getVersion() {
|
|
||||||
return type.version();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ComputedSuperType withChangeAtVersion(int version, VersionChangeChecker versionChangeChecker) {
|
|
||||||
return new ComputedSuperType(type.withVersion(version),
|
|
||||||
subTypes.stream().map(subType -> subType.withVersionIfChanged(version, versionChangeChecker)).toList(),
|
|
||||||
computedTypeSupplier
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ComputedType> subTypes() {
|
|
||||||
synchronized (this) {
|
|
||||||
if (computedSubTypes == null) {
|
|
||||||
computedSubTypes = new ArrayList<>();
|
|
||||||
for (VersionedType subType : subTypes) {
|
|
||||||
computedSubTypes.add(computedTypeSupplier.get(subType));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return computedSubTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ComputedSuperType that = (ComputedSuperType) o;
|
|
||||||
|
|
||||||
if (!Objects.equals(type, that.type)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return Objects.equals(subTypes, that.subTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = type != null ? type.hashCode() : 0;
|
|
||||||
result = 31 * result + (subTypes != null ? subTypes.hashCode() : 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<ComputedType> getDependencies() {
|
|
||||||
return subTypes().stream();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<ComputedType> getDependents() {
|
|
||||||
return computedTypeSupplier.getDependents(new VersionedType(getName(), 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return type.type();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class ComputedArrayType implements VersionedComputedType {
|
|
||||||
|
|
||||||
private final VersionedType baseType;
|
|
||||||
|
|
||||||
private ComputedType computedChild;
|
|
||||||
private final ComputedTypeSupplier computedTypeSupplier;
|
|
||||||
|
|
||||||
public ComputedArrayType(VersionedType baseType, ComputedTypeSupplier computedTypeSupplier) {
|
|
||||||
this.baseType = baseType;
|
|
||||||
this.computedTypeSupplier = computedTypeSupplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getBaseType() {
|
|
||||||
return baseType.type();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getVersion() {
|
|
||||||
return baseType.version();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ComputedArrayType withChangeAtVersion(int version, VersionChangeChecker versionChangeChecker) {
|
|
||||||
return new ComputedArrayType(baseType.withVersion(version), computedTypeSupplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ComputedType child() {
|
|
||||||
synchronized (this) {
|
|
||||||
if (computedChild == null) {
|
|
||||||
computedChild = computedTypeSupplier.get(baseType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (computedChild instanceof ComputedNullableType) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
} else if (computedChild instanceof ComputedArrayType) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
return computedChild;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ComputedArrayType that = (ComputedArrayType) o;
|
|
||||||
|
|
||||||
return Objects.equals(baseType, that.baseType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return baseType != null ? baseType.hashCode() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "§" + baseType.type();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<ComputedType> getDependencies() {
|
|
||||||
return Stream.of(child());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<ComputedType> getDependents() {
|
|
||||||
return computedTypeSupplier.getDependents(new VersionedType(getName(), 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class ComputedNativeType implements ComputedType {
|
|
||||||
|
|
||||||
private final String type;
|
|
||||||
private final ComputedTypeSupplier computedTypeSupplier;
|
|
||||||
|
|
||||||
public ComputedNativeType(String type, ComputedTypeSupplier computedTypeSupplier) {
|
|
||||||
this.type = type;
|
|
||||||
this.computedTypeSupplier = computedTypeSupplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ComputedNativeType that = (ComputedNativeType) o;
|
|
||||||
|
|
||||||
return Objects.equals(type, that.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return type != null ? type.hashCode() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<ComputedType> getDependencies() {
|
|
||||||
return Stream.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<ComputedType> getDependents() {
|
|
||||||
return computedTypeSupplier.getDependents(new VersionedType(getName(), 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<ComputedNativeType> get(ComputedTypeSupplier computedTypeSupplier) {
|
|
||||||
return Stream.of("String",
|
|
||||||
"boolean",
|
|
||||||
"short",
|
|
||||||
"char",
|
|
||||||
"int",
|
|
||||||
"long",
|
|
||||||
"float",
|
|
||||||
"double",
|
|
||||||
"byte",
|
|
||||||
"Int52").map(name -> new ComputedNativeType(name, computedTypeSupplier)).toList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
package it.cavallium.data.generator.plugin;
|
||||||
|
|
||||||
|
public sealed interface ComputedTypeArray extends ComputedType permits ComputedTypeArrayNative,
|
||||||
|
ComputedTypeArrayVersioned {
|
||||||
|
|
||||||
|
ComputedType getBase();
|
||||||
|
}
|
@ -0,0 +1,147 @@
|
|||||||
|
package it.cavallium.data.generator.plugin;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.ParameterizedTypeName;
|
||||||
|
import com.squareup.javapoet.TypeName;
|
||||||
|
import it.cavallium.data.generator.nativedata.ArrayInt52Serializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.ArrayStringSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.ArraybooleanSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.ArraybyteSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.ArraycharSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.ArraydoubleSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.ArrayfloatSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.ArrayintSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.ArraylongSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.ArrayshortSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.Serializers;
|
||||||
|
import it.unimi.dsi.fastutil.booleans.BooleanList;
|
||||||
|
import it.unimi.dsi.fastutil.bytes.ByteList;
|
||||||
|
import it.unimi.dsi.fastutil.chars.CharList;
|
||||||
|
import it.unimi.dsi.fastutil.doubles.DoubleList;
|
||||||
|
import it.unimi.dsi.fastutil.floats.FloatList;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntList;
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongList;
|
||||||
|
import it.unimi.dsi.fastutil.shorts.ShortList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public final class ComputedTypeArrayNative implements ComputedTypeArray {
|
||||||
|
|
||||||
|
private final String baseType;
|
||||||
|
|
||||||
|
private ComputedTypeNative computedChild;
|
||||||
|
private final ComputedTypeSupplier computedTypeSupplier;
|
||||||
|
|
||||||
|
public ComputedTypeArrayNative(String baseType, ComputedTypeSupplier computedTypeSupplier) {
|
||||||
|
this.baseType = baseType;
|
||||||
|
this.computedTypeSupplier = computedTypeSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComputedType getBase() {
|
||||||
|
return child();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComputedTypeNative child() {
|
||||||
|
synchronized (this) {
|
||||||
|
if (computedChild == null) {
|
||||||
|
var computedChild = computedTypeSupplier.get(baseType);
|
||||||
|
if (computedChild instanceof ComputedTypeNative computedTypeNative) {
|
||||||
|
this.computedChild = computedTypeNative;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return computedChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComputedTypeArrayNative that = (ComputedTypeArrayNative) o;
|
||||||
|
|
||||||
|
return Objects.equals(baseType, that.baseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return baseType != null ? baseType.hashCode() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "§" + baseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJTypeName(String basePackageName) {
|
||||||
|
return switch (baseType) {
|
||||||
|
case "boolean" -> ClassName.get(BooleanList.class);
|
||||||
|
case "byte" -> ClassName.get(ByteList.class);
|
||||||
|
case "short" -> ClassName.get(ShortList.class);
|
||||||
|
case "char" -> ClassName.get(CharList.class);
|
||||||
|
case "int" -> ClassName.get(IntList.class);
|
||||||
|
case "long" -> ClassName.get(LongList.class);
|
||||||
|
case "float" -> ClassName.get(FloatList.class);
|
||||||
|
case "double" -> ClassName.get(DoubleList.class);
|
||||||
|
default -> ParameterizedTypeName.get(ClassName.get(List.class),
|
||||||
|
computedTypeSupplier.get(baseType).getJTypeName(basePackageName));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassName getJSerializerName(String basePackageName) {
|
||||||
|
return switch (baseType) {
|
||||||
|
case "boolean" -> ClassName.get(ArraybooleanSerializer.class);
|
||||||
|
case "byte" -> ClassName.get(ArraybyteSerializer.class);
|
||||||
|
case "short" -> ClassName.get(ArrayshortSerializer.class);
|
||||||
|
case "char" -> ClassName.get(ArraycharSerializer.class);
|
||||||
|
case "int" -> ClassName.get(ArrayintSerializer.class);
|
||||||
|
case "long" -> ClassName.get(ArraylongSerializer.class);
|
||||||
|
case "float" -> ClassName.get(ArrayfloatSerializer.class);
|
||||||
|
case "double" -> ClassName.get(ArraydoubleSerializer.class);
|
||||||
|
case "String" -> ClassName.get(ArrayStringSerializer.class);
|
||||||
|
case "Int52" -> ClassName.get(ArrayInt52Serializer.class);
|
||||||
|
default -> throw new UnsupportedOperationException();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldLocation getJSerializerInstance(String basePackageName) {
|
||||||
|
var className = ClassName.get(Serializers.class);
|
||||||
|
var serializerFieldName = "Array" + baseType + "SerializerInstance";
|
||||||
|
return new FieldLocation(className, serializerFieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJUpgraderName(String basePackageName) {
|
||||||
|
throw new UnsupportedOperationException("Not upgradable");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldLocation getJUpgraderInstance(String basePackageName) {
|
||||||
|
throw new UnsupportedOperationException("Not upgradable");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<ComputedType> getDependencies() {
|
||||||
|
return Stream.of(child());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<ComputedType> getDependents() {
|
||||||
|
return computedTypeSupplier.getDependents(getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return baseType + "[]";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,126 @@
|
|||||||
|
package it.cavallium.data.generator.plugin;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.ParameterizedTypeName;
|
||||||
|
import com.squareup.javapoet.TypeName;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedType.VersionedComputedType;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public final class ComputedTypeArrayVersioned implements VersionedComputedType, ComputedTypeArray {
|
||||||
|
|
||||||
|
private final VersionedType baseType;
|
||||||
|
|
||||||
|
private VersionedComputedType computedChild;
|
||||||
|
private final ComputedTypeSupplier computedTypeSupplier;
|
||||||
|
|
||||||
|
public ComputedTypeArrayVersioned(VersionedType baseType, ComputedTypeSupplier computedTypeSupplier) {
|
||||||
|
this.baseType = baseType;
|
||||||
|
this.computedTypeSupplier = computedTypeSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VersionedComputedType getBase() {
|
||||||
|
return child();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComputedVersion getVersion() {
|
||||||
|
return baseType.version();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComputedTypeArrayVersioned withChangeAtVersion(ComputedVersion version,
|
||||||
|
VersionChangeChecker versionChangeChecker) {
|
||||||
|
return new ComputedTypeArrayVersioned(baseType.withVersion(version),
|
||||||
|
computedTypeSupplier
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VersionedComputedType child() {
|
||||||
|
synchronized (this) {
|
||||||
|
if (computedChild == null) {
|
||||||
|
var computedChild = computedTypeSupplier.get(baseType);
|
||||||
|
if (computedChild instanceof ComputedTypeNullableVersioned) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
} else if (computedChild instanceof ComputedTypeArrayVersioned) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
} else if (computedChild instanceof VersionedComputedType versionedComputedType) {
|
||||||
|
this.computedChild = versionedComputedType;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return computedChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComputedTypeArrayVersioned that = (ComputedTypeArrayVersioned) o;
|
||||||
|
|
||||||
|
return Objects.equals(baseType, that.baseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return baseType != null ? baseType.hashCode() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "§" + baseType.type();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJTypeName(String basePackageName) {
|
||||||
|
return ParameterizedTypeName.get(ClassName.get(List.class),
|
||||||
|
computedTypeSupplier.get(baseType).getJTypeName(basePackageName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassName getJSerializerName(String basePackageName) {
|
||||||
|
return ClassName.get(baseType.version().getSerializersPackage(basePackageName), "Array" + baseType.type() + "Serializer");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldLocation getJSerializerInstance(String basePackageName) {
|
||||||
|
var className = ClassName.get(baseType.version().getPackage(basePackageName), "Version");
|
||||||
|
var serializerFieldName = "Array" + baseType.type() + "SerializerInstance";
|
||||||
|
return new FieldLocation(className, serializerFieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJUpgraderName(String basePackageName) {
|
||||||
|
return ClassName.get(baseType.version().getUpgradersPackage(basePackageName), "Array" + baseType.type() + "Upgrader");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldLocation getJUpgraderInstance(String basePackageName) {
|
||||||
|
var className = ClassName.get(baseType.version().getPackage(basePackageName), "Version");
|
||||||
|
var upgraderFieldName = "Array" + baseType.type() + "UpgraderInstance";
|
||||||
|
return new FieldLocation(className, upgraderFieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<ComputedType> getDependencies() {
|
||||||
|
return Stream.of(child());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<ComputedType> getDependents() {
|
||||||
|
return computedTypeSupplier.getDependents(getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return baseType.type() + "[] (v" + getVersion() + ")";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,146 @@
|
|||||||
|
package it.cavallium.data.generator.plugin;
|
||||||
|
|
||||||
|
import static it.cavallium.data.generator.plugin.DataModel.joinPackage;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.TypeName;
|
||||||
|
import it.cavallium.data.generator.nativedata.Serializers;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedType.VersionedComputedType;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public final class ComputedTypeBase implements VersionedComputedType {
|
||||||
|
|
||||||
|
private final VersionedType type;
|
||||||
|
private final String stringRepresenter;
|
||||||
|
|
||||||
|
private final LinkedHashMap<String, VersionedType> data;
|
||||||
|
private LinkedHashMap<String, ComputedType> computedData;
|
||||||
|
private final ComputedTypeSupplier computedTypeSupplier;
|
||||||
|
|
||||||
|
public ComputedTypeBase(VersionedType type,
|
||||||
|
String stringRepresenter,
|
||||||
|
LinkedHashMap<String, VersionedType> data,
|
||||||
|
ComputedTypeSupplier computedTypeSupplier) {
|
||||||
|
this.type = type;
|
||||||
|
if (type.type().startsWith("~") || type.type().startsWith("-")) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
this.computedTypeSupplier = computedTypeSupplier;
|
||||||
|
this.stringRepresenter = stringRepresenter;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type.type();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComputedVersion getVersion() {
|
||||||
|
return type.version();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComputedTypeBase withChangeAtVersion(ComputedVersion version,
|
||||||
|
VersionChangeChecker versionChangeChecker) {
|
||||||
|
var newData = new LinkedHashMap<String, VersionedType>();
|
||||||
|
data.forEach((k, v) -> newData.put(k, v.withVersionIfChanged(version, versionChangeChecker)));
|
||||||
|
return new ComputedTypeBase(type.withVersion(version),
|
||||||
|
stringRepresenter,
|
||||||
|
newData,
|
||||||
|
computedTypeSupplier
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStringRepresenter() {
|
||||||
|
return stringRepresenter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LinkedHashMap<String, ComputedType> getData() {
|
||||||
|
synchronized (this) {
|
||||||
|
if (computedData == null) {
|
||||||
|
computedData = new LinkedHashMap<>();
|
||||||
|
data.forEach((k, v) -> computedData.put(k, computedTypeSupplier.get(v)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return computedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComputedTypeBase that = (ComputedTypeBase) o;
|
||||||
|
|
||||||
|
if (!Objects.equals(type, that.type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(stringRepresenter, that.stringRepresenter)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Objects.equals(data, that.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = type != null ? type.hashCode() : 0;
|
||||||
|
result = 31 * result + (stringRepresenter != null ? stringRepresenter.hashCode() : 0);
|
||||||
|
result = 31 * result + (data != null ? data.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return type.type();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJTypeName(String basePackageName) {
|
||||||
|
return ClassName.get(getVersion().getDataPackage(basePackageName), type.type());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassName getJSerializerName(String basePackageName) {
|
||||||
|
return ClassName.get(type.version().getSerializersPackage(basePackageName), type.type() + "Serializer");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldLocation getJSerializerInstance(String basePackageName) {
|
||||||
|
var className = ClassName.get(type.version().getPackage(basePackageName), "Version");
|
||||||
|
var serializerFieldName = type.type() + "SerializerInstance";
|
||||||
|
return new FieldLocation(className, serializerFieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJUpgraderName(String basePackageName) {
|
||||||
|
return ClassName.get(type.version().getUpgradersPackage(basePackageName), type.type() + "Upgrader");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldLocation getJUpgraderInstance(String basePackageName) {
|
||||||
|
var className = ClassName.get(type.version().getPackage(basePackageName), "Version");
|
||||||
|
var upgraderFieldName = type.type() + "UpgraderInstance";
|
||||||
|
return new FieldLocation(className, upgraderFieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<ComputedType> getDependencies() {
|
||||||
|
return this.data.values().stream().map(computedTypeSupplier::get);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<ComputedType> getDependents() {
|
||||||
|
return computedTypeSupplier.getDependents(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return type.type() + " (base, v" + getVersion() + ")";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,130 @@
|
|||||||
|
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.stream.Stream;
|
||||||
|
|
||||||
|
public final class ComputedTypeCustom implements ComputedType {
|
||||||
|
|
||||||
|
private final String type;
|
||||||
|
private final ComputedVersion latestVersion;
|
||||||
|
private final String javaClass;
|
||||||
|
private final String serializer;
|
||||||
|
private final ComputedTypeSupplier computedTypeSupplier;
|
||||||
|
private final TypeName typeName;
|
||||||
|
|
||||||
|
public ComputedTypeCustom(String type,
|
||||||
|
String javaClass,
|
||||||
|
String serializer,
|
||||||
|
ComputedTypeSupplier computedTypeSupplier,
|
||||||
|
ComputedVersion latestVersion) {
|
||||||
|
this.type = type;
|
||||||
|
this.latestVersion = latestVersion;
|
||||||
|
this.javaClass = javaClass;
|
||||||
|
this.serializer = serializer;
|
||||||
|
this.computedTypeSupplier = computedTypeSupplier;
|
||||||
|
{
|
||||||
|
int indexOfGeneric;
|
||||||
|
if ((indexOfGeneric = javaClass.indexOf("<")) == -1) {
|
||||||
|
this.typeName = ClassName.bestGuess(javaClass.trim());
|
||||||
|
} else {
|
||||||
|
var rawTypesArray = javaClass.substring(indexOfGeneric + 1, javaClass.length() - 1).split(",");
|
||||||
|
var genericsResult = new TypeName[rawTypesArray.length];
|
||||||
|
int i = 0;
|
||||||
|
for (String rawType : rawTypesArray) {
|
||||||
|
genericsResult[i] = ClassName.bestGuess(rawType.trim());
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
var base = ClassName.bestGuess(javaClass.substring(0, indexOfGeneric).trim());
|
||||||
|
this.typeName = ParameterizedTypeName.get(base, genericsResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJavaClass() {
|
||||||
|
return javaClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSerializer() {
|
||||||
|
return serializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
it.cavallium.data.generator.plugin.ComputedTypeCustom that = (it.cavallium.data.generator.plugin.ComputedTypeCustom) o;
|
||||||
|
|
||||||
|
if (!Objects.equals(type, that.type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Objects.equals(javaClass, that.javaClass)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Objects.equals(serializer, that.serializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = type != null ? type.hashCode() : 0;
|
||||||
|
result = 31 * result + (javaClass != null ? javaClass.hashCode() : 0);
|
||||||
|
result = 31 * result + (serializer != null ? serializer.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJTypeName(String basePackageName) {
|
||||||
|
return typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJSerializerName(String basePackageName) {
|
||||||
|
return ClassName.bestGuess(serializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldLocation getJSerializerInstance(String basePackageName) {
|
||||||
|
return new FieldLocation(ClassName.get(latestVersion.getPackage(basePackageName), "Version"), type + "SerializerInstance");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJUpgraderName(String basePackageName) {
|
||||||
|
throw new UnsupportedOperationException("Not upgradable");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldLocation getJUpgraderInstance(String basePackageName) {
|
||||||
|
throw new UnsupportedOperationException("Not upgradable");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<ComputedType> getDependencies() {
|
||||||
|
return Stream.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<ComputedType> getDependents() {
|
||||||
|
return computedTypeSupplier.getDependents(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return type + " (custom)";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
package it.cavallium.data.generator.plugin;
|
||||||
|
|
||||||
|
import static it.cavallium.data.generator.plugin.DataModel.joinPackage;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.TypeName;
|
||||||
|
import it.cavallium.data.generator.nativedata.Int52Serializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.Serializers;
|
||||||
|
import it.cavallium.data.generator.nativedata.StringSerializer;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public final class ComputedTypeNative implements ComputedType {
|
||||||
|
|
||||||
|
private final String type;
|
||||||
|
private final ComputedTypeSupplier computedTypeSupplier;
|
||||||
|
|
||||||
|
public ComputedTypeNative(String type, ComputedTypeSupplier computedTypeSupplier) {
|
||||||
|
this.type = type;
|
||||||
|
this.computedTypeSupplier = computedTypeSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJTypeName(String basePackageName) {
|
||||||
|
return switch (type) {
|
||||||
|
case "String" -> ClassName.get(String.class);
|
||||||
|
case "boolean" -> TypeName.BOOLEAN;
|
||||||
|
case "short" -> TypeName.SHORT;
|
||||||
|
case "char" -> TypeName.CHAR;
|
||||||
|
case "int" -> TypeName.INT;
|
||||||
|
case "long" -> TypeName.LONG;
|
||||||
|
case "float" -> TypeName.FLOAT;
|
||||||
|
case "double" -> TypeName.DOUBLE;
|
||||||
|
case "byte" -> TypeName.BYTE;
|
||||||
|
case "Int52" -> ClassName.get(it.cavallium.data.generator.nativedata.Int52.class);
|
||||||
|
default -> throw new UnsupportedOperationException(type + " is not a known native type");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJSerializerName(String basePackageName) {
|
||||||
|
return switch (type) {
|
||||||
|
case "String" -> ClassName.get(StringSerializer.class);
|
||||||
|
case "boolean", "byte", "short", "char", "int", "long", "float", "double" ->
|
||||||
|
throw new UnsupportedOperationException("Type " + type
|
||||||
|
+ " is a native type, so it doesn't have a serializer");
|
||||||
|
case "Int52" -> ClassName.get(Int52Serializer.class);
|
||||||
|
default -> throw new UnsupportedOperationException(type + " is not a known native type");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldLocation getJSerializerInstance(String basePackageName) {
|
||||||
|
return new FieldLocation(ClassName.get(Serializers.class), type + "SerializerInstance");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJUpgraderName(String basePackageName) {
|
||||||
|
throw new UnsupportedOperationException("Type " + type + " is a native type, so it doesn't have a upgrader");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldLocation getJUpgraderInstance(String basePackageName) {
|
||||||
|
throw new UnsupportedOperationException("Type " + type + " is a native type, so it doesn't have a upgrader");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
it.cavallium.data.generator.plugin.ComputedTypeNative that = (it.cavallium.data.generator.plugin.ComputedTypeNative) o;
|
||||||
|
|
||||||
|
return Objects.equals(type, that.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return type != null ? type.hashCode() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<ComputedType> getDependencies() {
|
||||||
|
return Stream.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<ComputedType> getDependents() {
|
||||||
|
return computedTypeSupplier.getDependents(getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<it.cavallium.data.generator.plugin.ComputedTypeNative> get(ComputedTypeSupplier computedTypeSupplier) {
|
||||||
|
return Stream
|
||||||
|
.of("String", "boolean", "short", "char", "int", "long", "float", "double", "byte", "Int52")
|
||||||
|
.map(name -> new it.cavallium.data.generator.plugin.ComputedTypeNative(name, computedTypeSupplier))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return type + " (native)";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package it.cavallium.data.generator.plugin;
|
||||||
|
|
||||||
|
public sealed interface ComputedTypeNullable extends ComputedType permits ComputedTypeNullableNative,
|
||||||
|
ComputedTypeNullableVersioned {
|
||||||
|
|
||||||
|
ComputedType getBase();
|
||||||
|
}
|
@ -0,0 +1,154 @@
|
|||||||
|
package it.cavallium.data.generator.plugin;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.TypeName;
|
||||||
|
import it.cavallium.data.generator.nativedata.NullableInt52;
|
||||||
|
import it.cavallium.data.generator.nativedata.NullableInt52Serializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.NullableString;
|
||||||
|
import it.cavallium.data.generator.nativedata.NullableStringSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.Nullableboolean;
|
||||||
|
import it.cavallium.data.generator.nativedata.NullablebooleanSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.Nullablebyte;
|
||||||
|
import it.cavallium.data.generator.nativedata.NullablebyteSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.Nullablechar;
|
||||||
|
import it.cavallium.data.generator.nativedata.NullablecharSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.Nullabledouble;
|
||||||
|
import it.cavallium.data.generator.nativedata.NullabledoubleSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.Nullablefloat;
|
||||||
|
import it.cavallium.data.generator.nativedata.NullablefloatSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.Nullableint;
|
||||||
|
import it.cavallium.data.generator.nativedata.NullableintSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.Nullablelong;
|
||||||
|
import it.cavallium.data.generator.nativedata.NullablelongSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.Nullableshort;
|
||||||
|
import it.cavallium.data.generator.nativedata.NullableshortSerializer;
|
||||||
|
import it.cavallium.data.generator.nativedata.Serializers;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public final class ComputedTypeNullableNative implements ComputedTypeNullable {
|
||||||
|
|
||||||
|
private final String baseType;
|
||||||
|
private final ComputedVersion latestVersion;
|
||||||
|
|
||||||
|
private ComputedTypeNative computedChild;
|
||||||
|
private final ComputedTypeSupplier computedTypeSupplier;
|
||||||
|
|
||||||
|
public ComputedTypeNullableNative(String baseType, ComputedVersion latestVersion, ComputedTypeSupplier computedTypeSupplier) {
|
||||||
|
this.baseType = baseType;
|
||||||
|
this.latestVersion = latestVersion;
|
||||||
|
this.computedTypeSupplier = computedTypeSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComputedTypeNative getBase() {
|
||||||
|
return child();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComputedTypeNative child() {
|
||||||
|
synchronized (this) {
|
||||||
|
if (computedChild == null) {
|
||||||
|
var computedChild = computedTypeSupplier.get(baseType);
|
||||||
|
if (computedChild instanceof ComputedTypeNative computedTypeNative) {
|
||||||
|
this.computedChild = computedTypeNative;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return computedChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComputedTypeNullableNative that = (ComputedTypeNullableNative) o;
|
||||||
|
|
||||||
|
return Objects.equals(baseType, that.baseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return baseType != null ? baseType.hashCode() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "-" + baseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJTypeName(String basePackageName) {
|
||||||
|
return switch (baseType) {
|
||||||
|
case "boolean" -> ClassName.get(Nullableboolean.class);
|
||||||
|
case "byte" -> ClassName.get(Nullablebyte.class);
|
||||||
|
case "short" -> ClassName.get(Nullableshort.class);
|
||||||
|
case "char" -> ClassName.get(Nullablechar.class);
|
||||||
|
case "int" -> ClassName.get(Nullableint.class);
|
||||||
|
case "long" -> ClassName.get(Nullablelong.class);
|
||||||
|
case "float" -> ClassName.get(Nullablefloat.class);
|
||||||
|
case "double" -> ClassName.get(Nullabledouble.class);
|
||||||
|
case "String" -> ClassName.get(NullableString.class);
|
||||||
|
case "Int52" -> ClassName.get(NullableInt52.class);
|
||||||
|
default -> ClassName.get(latestVersion.getDataNullablesPackage(basePackageName), "Nullable" + baseType);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassName getJSerializerName(String basePackageName) {
|
||||||
|
return switch (baseType) {
|
||||||
|
case "boolean" -> ClassName.get(NullablebooleanSerializer.class);
|
||||||
|
case "byte" -> ClassName.get(NullablebyteSerializer.class);
|
||||||
|
case "short" -> ClassName.get(NullableshortSerializer.class);
|
||||||
|
case "char" -> ClassName.get(NullablecharSerializer.class);
|
||||||
|
case "int" -> ClassName.get(NullableintSerializer.class);
|
||||||
|
case "long" -> ClassName.get(NullablelongSerializer.class);
|
||||||
|
case "float" -> ClassName.get(NullablefloatSerializer.class);
|
||||||
|
case "double" -> ClassName.get(NullabledoubleSerializer.class);
|
||||||
|
case "String" -> ClassName.get(NullableStringSerializer.class);
|
||||||
|
case "Int52" -> ClassName.get(NullableInt52Serializer.class);
|
||||||
|
default -> throw new UnsupportedOperationException();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldLocation getJSerializerInstance(String basePackageName) {
|
||||||
|
var className = switch (baseType) {
|
||||||
|
case "boolean", "byte", "short", "char", "int", "long", "float", "double", "String", "Int52" ->
|
||||||
|
ClassName.get(Serializers.class);
|
||||||
|
default -> throw new UnsupportedOperationException();
|
||||||
|
};
|
||||||
|
var serializerFieldName = "Nullable" + baseType + "SerializerInstance";
|
||||||
|
return new FieldLocation(className, serializerFieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJUpgraderName(String basePackageName) {
|
||||||
|
throw new UnsupportedOperationException("Type " + baseType + " is a native type, so it doesn't have a upgrader");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldLocation getJUpgraderInstance(String basePackageName) {
|
||||||
|
throw new UnsupportedOperationException("Type " + baseType + " is a native type, so it doesn't have a upgrader");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<ComputedType> getDependencies() {
|
||||||
|
return Stream.of(child());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<ComputedType> getDependents() {
|
||||||
|
return computedTypeSupplier.getDependents(getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "-" + baseType;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,122 @@
|
|||||||
|
package it.cavallium.data.generator.plugin;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.TypeName;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedType.VersionedComputedType;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public final class ComputedTypeNullableVersioned implements ComputedTypeNullable, VersionedComputedType {
|
||||||
|
|
||||||
|
private final VersionedType baseType;
|
||||||
|
|
||||||
|
private ComputedType computedChild;
|
||||||
|
private final ComputedTypeSupplier computedTypeSupplier;
|
||||||
|
|
||||||
|
public ComputedTypeNullableVersioned(VersionedType baseType, ComputedTypeSupplier computedTypeSupplier) {
|
||||||
|
this.baseType = baseType;
|
||||||
|
this.computedTypeSupplier = computedTypeSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VersionedComputedType getBase() {
|
||||||
|
return (VersionedComputedType) computedTypeSupplier.get(baseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComputedVersion getVersion() {
|
||||||
|
return baseType.version();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComputedTypeNullableVersioned withChangeAtVersion(ComputedVersion version,
|
||||||
|
VersionChangeChecker versionChangeChecker) {
|
||||||
|
return new ComputedTypeNullableVersioned(baseType.withVersion(version),
|
||||||
|
computedTypeSupplier
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComputedType child() {
|
||||||
|
synchronized (this) {
|
||||||
|
if (computedChild == null) {
|
||||||
|
computedChild = computedTypeSupplier.get(baseType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (computedChild instanceof ComputedTypeNullableVersioned) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
} else if (computedChild instanceof ComputedTypeArrayVersioned) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
return computedChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComputedTypeNullableVersioned that = (ComputedTypeNullableVersioned) o;
|
||||||
|
|
||||||
|
return Objects.equals(baseType, that.baseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return baseType != null ? baseType.hashCode() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "-" + baseType.type();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJTypeName(String basePackageName) {
|
||||||
|
return ClassName.get(baseType.version().getDataNullablesPackage(basePackageName),
|
||||||
|
"Nullable" + baseType.type());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassName getJSerializerName(String basePackageName) {
|
||||||
|
return ClassName.get(baseType.version().getSerializersPackage(basePackageName),
|
||||||
|
"Nullable" + baseType.type() + "Serializer");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldLocation getJSerializerInstance(String basePackageName) {
|
||||||
|
var className = ClassName.get(baseType.version().getPackage(basePackageName), "Version");
|
||||||
|
var serializerFieldName = "Nullable" + baseType.type() + "SerializerInstance";
|
||||||
|
return new FieldLocation(className, serializerFieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJUpgraderName(String basePackageName) {
|
||||||
|
return ClassName.get(baseType.version().getSerializersPackage(basePackageName),
|
||||||
|
"Nullable" + baseType.type() + "Upgrader");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldLocation getJUpgraderInstance(String basePackageName) {
|
||||||
|
var className = ClassName.get(baseType.version().getPackage(basePackageName), "Version");
|
||||||
|
var upgraderFieldName = "Nullable" + baseType.type() + "UpgraderInstance";
|
||||||
|
return new FieldLocation(className, upgraderFieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<ComputedType> getDependencies() {
|
||||||
|
return Stream.of(child());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<ComputedType> getDependents() {
|
||||||
|
return computedTypeSupplier.getDependents(getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "-" + baseType.type() + " (v" + getVersion() + ")";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,129 @@
|
|||||||
|
package it.cavallium.data.generator.plugin;
|
||||||
|
|
||||||
|
import static it.cavallium.data.generator.plugin.DataModel.joinPackage;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.TypeName;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedType.VersionedComputedType;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public final class ComputedTypeSuper implements VersionedComputedType {
|
||||||
|
|
||||||
|
private final VersionedType type;
|
||||||
|
private final List<VersionedType> subTypes;
|
||||||
|
|
||||||
|
private List<ComputedType> computedSubTypes;
|
||||||
|
private final ComputedTypeSupplier computedTypeSupplier;
|
||||||
|
|
||||||
|
public ComputedTypeSuper(VersionedType type, List<VersionedType> subType, ComputedTypeSupplier computedTypeSupplier) {
|
||||||
|
this.type = type;
|
||||||
|
this.subTypes = subType;
|
||||||
|
this.computedTypeSupplier = computedTypeSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type.type();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComputedVersion getVersion() {
|
||||||
|
return type.version();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public it.cavallium.data.generator.plugin.ComputedTypeSuper withChangeAtVersion(ComputedVersion version,
|
||||||
|
VersionChangeChecker versionChangeChecker) {
|
||||||
|
return new it.cavallium.data.generator.plugin.ComputedTypeSuper(type.withVersion(version),
|
||||||
|
subTypes.stream().map(subType -> subType.withVersionIfChanged(version, versionChangeChecker)).toList(),
|
||||||
|
computedTypeSupplier
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ComputedType> subTypes() {
|
||||||
|
synchronized (this) {
|
||||||
|
if (computedSubTypes == null) {
|
||||||
|
computedSubTypes = new ArrayList<>();
|
||||||
|
for (VersionedType subType : subTypes) {
|
||||||
|
computedSubTypes.add(computedTypeSupplier.get(subType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return computedSubTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
it.cavallium.data.generator.plugin.ComputedTypeSuper that = (it.cavallium.data.generator.plugin.ComputedTypeSuper) o;
|
||||||
|
|
||||||
|
if (!Objects.equals(type, that.type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Objects.equals(subTypes, that.subTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = type != null ? type.hashCode() : 0;
|
||||||
|
result = 31 * result + (subTypes != null ? subTypes.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<ComputedType> getDependencies() {
|
||||||
|
return subTypes().stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<ComputedType> getDependents() {
|
||||||
|
return computedTypeSupplier.getDependents(getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return type.type();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJTypeName(String basePackageName) {
|
||||||
|
return ClassName.get(getVersion().getDataPackage(basePackageName), type.type());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassName getJSerializerName(String basePackageName) {
|
||||||
|
return ClassName.get(type.version().getSerializersPackage(basePackageName), type.type() + "Serializer");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldLocation getJSerializerInstance(String basePackageName) {
|
||||||
|
var className = ClassName.get(type.version().getPackage(basePackageName), "Version");
|
||||||
|
var serializerFieldName = type.type() + "SerializerInstance";
|
||||||
|
return new FieldLocation(className, serializerFieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeName getJUpgraderName(String basePackageName) {
|
||||||
|
return ClassName.get(type.version().getSerializersPackage(basePackageName), type.type() + "Upgrader");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldLocation getJUpgraderInstance(String basePackageName) {
|
||||||
|
var className = ClassName.get(type.version().getPackage(basePackageName), "Version");
|
||||||
|
var upgraderFieldName = type.type() + "UpgraderInstance";
|
||||||
|
return new FieldLocation(className, upgraderFieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return type.type() + " (super, v" + getVersion() + ")";
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ package it.cavallium.data.generator.plugin;
|
|||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -12,31 +13,45 @@ public class ComputedTypeSupplier {
|
|||||||
|
|
||||||
private final Int2ObjectMap<Map<String, ComputedType>> computedTypeMap;
|
private final Int2ObjectMap<Map<String, ComputedType>> computedTypeMap;
|
||||||
private final Int2ObjectMap<Map<String, List<ComputedType>>> computedTypeDependentsCacheMap = new Int2ObjectOpenHashMap<>();
|
private final Int2ObjectMap<Map<String, List<ComputedType>>> computedTypeDependentsCacheMap = new Int2ObjectOpenHashMap<>();
|
||||||
|
private final ComputedVersion currentVersion;
|
||||||
|
|
||||||
public ComputedTypeSupplier(Int2ObjectMap<Map<String, ComputedType>> computedTypeMap) {
|
public ComputedTypeSupplier(Int2ObjectMap<Map<String, ComputedType>> computedTypeMap, ComputedVersion currentVersion) {
|
||||||
this.computedTypeMap = computedTypeMap;
|
this.computedTypeMap = computedTypeMap;
|
||||||
|
this.currentVersion = currentVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComputedType get(VersionedType type) {
|
public ComputedType get(VersionedType type) {
|
||||||
var computedType = computedTypeMap.get(type.version()).get(type.type());
|
var computedType = computedTypeMap.get(type.version().getVersion()).get(type.type());
|
||||||
if (computedType == null) {
|
if (computedType == null) {
|
||||||
throw new IllegalStateException("Type " + type + " does not exist");
|
throw new IllegalStateException("Type " + type + " does not exist");
|
||||||
}
|
}
|
||||||
return computedType;
|
return computedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ComputedType get(String type) {
|
||||||
|
return get(new VersionedType(type, currentVersion));
|
||||||
|
}
|
||||||
|
|
||||||
public Stream<ComputedType> getDependencies(VersionedType type) {
|
public Stream<ComputedType> getDependencies(VersionedType type) {
|
||||||
return computedTypeMap.get(type.version()).get(type.type()).getDependencies();
|
return computedTypeMap.get(type.version().getVersion()).get(type.type()).getDependencies();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream<ComputedType> getDependents(VersionedType type) {
|
public Stream<ComputedType> getDependents(VersionedType type) {
|
||||||
synchronized (computedTypeDependentsCacheMap) {
|
synchronized (computedTypeDependentsCacheMap) {
|
||||||
return computedTypeDependentsCacheMap
|
return computedTypeDependentsCacheMap
|
||||||
.computeIfAbsent(type.version(), x -> new HashMap<>())
|
.computeIfAbsent(type.version().getVersion(), x -> new HashMap<>())
|
||||||
.computeIfAbsent(type.type(),
|
.computeIfAbsent(type.type(),
|
||||||
typeName -> computedTypeMap.get(type.version()).values().stream().filter(computedType ->
|
typeName -> Objects.requireNonNull(computedTypeMap.get(type.version().getVersion()), () -> "Version " + type.version() + " does not exist")
|
||||||
computedType.getDependencies().anyMatch(y -> Objects.equals(y.getName(), typeName))).toList())
|
.values().stream().filter(computedType ->
|
||||||
|
computedType.getDependencies().anyMatch(y -> Objects.equals(y.getName(), typeName))).toList())
|
||||||
.stream();
|
.stream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get dependents from the current version
|
||||||
|
*/
|
||||||
|
public Stream<ComputedType> getDependents(String type) {
|
||||||
|
return getDependents(new VersionedType(type, currentVersion));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,27 @@
|
|||||||
package it.cavallium.data.generator.plugin;
|
package it.cavallium.data.generator.plugin;
|
||||||
|
|
||||||
|
import static it.cavallium.data.generator.plugin.DataModel.joinPackage;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.StringJoiner;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class ComputedVersion {
|
public class ComputedVersion implements Comparable<ComputedVersion> {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final Map<String, ParsedClass> classMap;
|
|
||||||
private final int version;
|
private final int version;
|
||||||
private final boolean current;
|
private final boolean current;
|
||||||
public DetailsConfiguration details;
|
public DetailsConfiguration details;
|
||||||
public List<VersionTransformation> transformations;
|
public List<VersionTransformation> transformations;
|
||||||
|
|
||||||
public ComputedVersion(ParsedVersion value, int version, boolean current, String versionName, Map<String, ParsedClass> classMap) {
|
public ComputedVersion(ParsedVersion value, int version, boolean current, String versionName) {
|
||||||
this.details = value.details;
|
this.details = value.details;
|
||||||
this.transformations = value.transformations;
|
this.transformations = value.transformations;
|
||||||
|
this.name = versionName;
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.current = current;
|
this.current = current;
|
||||||
this.name = versionName;
|
|
||||||
this.classMap = classMap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getVersion() {
|
public int getVersion() {
|
||||||
@ -30,10 +32,6 @@ public class ComputedVersion {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, ParsedClass> getClassMap() {
|
|
||||||
return classMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) {
|
if (this == o) {
|
||||||
@ -43,46 +41,65 @@ public class ComputedVersion {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ComputedVersion that = (ComputedVersion) o;
|
ComputedVersion that = (ComputedVersion) o;
|
||||||
return Objects.equals(details, that.details)
|
return Objects.equals(version, that.version);
|
||||||
&& Objects.equals(transformations, that.transformations);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int hash = 0;
|
return ConfigUtils.hashCode(version);
|
||||||
hash += ConfigUtils.hashCode(details);
|
|
||||||
hash += ConfigUtils.hashCode(transformations);
|
|
||||||
return hash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPackage(String basePackageName) {
|
public String getPackage(String basePackageName) {
|
||||||
if (current) {
|
if (current) {
|
||||||
return joinPackage(basePackageName, "current");
|
return joinPackage(basePackageName, "current");
|
||||||
} else {
|
} else {
|
||||||
return joinPackage(basePackageName, "v" + getVersionCompleteInt());
|
return joinPackage(basePackageName, "v" + version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDataPackage(String basePackageName) {
|
||||||
|
return joinPackage(getPackage(basePackageName), "data");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUpgradersPackage(String basePackageName) {
|
||||||
|
return joinPackage(getPackage(basePackageName), "upgraders");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSerializersPackage(String basePackageName) {
|
||||||
|
return joinPackage(getPackage(basePackageName), "serializers");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataNullablesPackage(String basePackageName) {
|
||||||
|
return joinPackage(getDataPackage(basePackageName), "nullables");
|
||||||
|
}
|
||||||
|
|
||||||
public String getVersionVarName() {
|
public String getVersionVarName() {
|
||||||
return "V" + version;
|
return "V" + version;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getVersionCompleteInt() {
|
public String getVersionShortInt() {
|
||||||
return Integer.toString(version);
|
return Integer.toString(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String joinPackage(String basePackageName, String packageName) {
|
|
||||||
if (basePackageName.isBlank()) {
|
|
||||||
basePackageName = "org.generated";
|
|
||||||
}
|
|
||||||
if (packageName.isBlank()) {
|
|
||||||
return basePackageName;
|
|
||||||
} else {
|
|
||||||
return basePackageName + "." + packageName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCurrent() {
|
public boolean isCurrent() {
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(@NotNull ComputedVersion o) {
|
||||||
|
return Integer.compare(version, o.version);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(version);
|
||||||
|
sb.append(" (");
|
||||||
|
sb.append(name);
|
||||||
|
if (current) {
|
||||||
|
sb.append(", current");
|
||||||
|
}
|
||||||
|
sb.append(")");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,23 +14,6 @@ public final class CustomTypesConfiguration {
|
|||||||
this.javaClass = javaClass;
|
this.javaClass = javaClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeName getJavaClassType() {
|
|
||||||
int indexOfGeneric;
|
|
||||||
if ((indexOfGeneric = javaClass.indexOf("<")) == -1) {
|
|
||||||
return ClassName.bestGuess(javaClass.trim());
|
|
||||||
} else {
|
|
||||||
var rawTypesArray = javaClass.substring(indexOfGeneric + 1, javaClass.length() - 1).split(",");
|
|
||||||
var genericsResult = new TypeName[rawTypesArray.length];
|
|
||||||
int i = 0;
|
|
||||||
for (String rawType : rawTypesArray) {
|
|
||||||
genericsResult[i] = ClassName.bestGuess(rawType.trim());
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
var base = ClassName.bestGuess(javaClass.substring(0, indexOfGeneric).trim());
|
|
||||||
return ParameterizedTypeName.get(base, genericsResult);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getJavaClassString() {
|
public String getJavaClassString() {
|
||||||
return javaClass;
|
return javaClass;
|
||||||
}
|
}
|
||||||
|
@ -3,20 +3,14 @@ package it.cavallium.data.generator.plugin;
|
|||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
import static java.util.function.Function.identity;
|
import static java.util.function.Function.identity;
|
||||||
|
|
||||||
import it.cavallium.data.generator.plugin.ComputedType.ComputedArrayType;
|
|
||||||
import it.cavallium.data.generator.plugin.ComputedType.ComputedBaseType;
|
|
||||||
import it.cavallium.data.generator.plugin.ComputedType.ComputedCustomType;
|
|
||||||
import it.cavallium.data.generator.plugin.ComputedType.ComputedNativeType;
|
|
||||||
import it.cavallium.data.generator.plugin.ComputedType.ComputedNullableType;
|
|
||||||
import it.cavallium.data.generator.plugin.ComputedType.ComputedSuperType;
|
|
||||||
import it.cavallium.data.generator.plugin.ComputedType.VersionedComputedType;
|
import it.cavallium.data.generator.plugin.ComputedType.VersionedComputedType;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@ -30,6 +24,7 @@ import java.util.concurrent.atomic.LongAdder;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collector;
|
import java.util.stream.Collector;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@ -47,7 +42,7 @@ public class DataModel {
|
|||||||
"Int52"
|
"Int52"
|
||||||
);
|
);
|
||||||
|
|
||||||
private final int currentVersion;
|
private final ComputedVersion currentVersion;
|
||||||
private final int hash;
|
private final int hash;
|
||||||
private final Map<String, ParsedInterface> interfacesData;
|
private final Map<String, ParsedInterface> interfacesData;
|
||||||
private final Int2ObjectMap<ComputedVersion> versions;
|
private final Int2ObjectMap<ComputedVersion> versions;
|
||||||
@ -107,7 +102,6 @@ public class DataModel {
|
|||||||
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
|
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
|
||||||
|
|
||||||
// Build versions sequence
|
// Build versions sequence
|
||||||
List<String> rawVersionsSequence = new ArrayList<>();
|
|
||||||
int versionsCount = 0;
|
int versionsCount = 0;
|
||||||
Int2ObjectMap<String> versionToName = new Int2ObjectLinkedOpenHashMap<>();
|
Int2ObjectMap<String> versionToName = new Int2ObjectLinkedOpenHashMap<>();
|
||||||
Object2IntMap<String> nameToVersion = new Object2IntOpenHashMap<>();
|
Object2IntMap<String> nameToVersion = new Object2IntOpenHashMap<>();
|
||||||
@ -115,7 +109,6 @@ public class DataModel {
|
|||||||
String lastVersion = null;
|
String lastVersion = null;
|
||||||
String nextVersion = rootVersion;
|
String nextVersion = rootVersion;
|
||||||
while (nextVersion != null) {
|
while (nextVersion != null) {
|
||||||
rawVersionsSequence.add(nextVersion);
|
|
||||||
lastVersion = nextVersion;
|
lastVersion = nextVersion;
|
||||||
versionToName.put(versionsCount, nextVersion);
|
versionToName.put(versionsCount, nextVersion);
|
||||||
nameToVersion.put(nextVersion, versionsCount);
|
nameToVersion.put(nextVersion, versionsCount);
|
||||||
@ -157,8 +150,8 @@ public class DataModel {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Compute the numeric versions map
|
// Compute the numeric versions map
|
||||||
Int2ObjectMap<ParsedVersion> versions = new Int2ObjectLinkedOpenHashMap<>();
|
Int2ObjectMap<ParsedVersion> parsedVersions = new Int2ObjectLinkedOpenHashMap<>();
|
||||||
rawVersions.forEach((k, v) -> versions.put(nameToVersion.getInt(k), new ParsedVersion(v)));
|
rawVersions.forEach((k, v) -> parsedVersions.put(nameToVersion.getInt(k), new ParsedVersion(v)));
|
||||||
|
|
||||||
Int2ObjectMap<Map<String, ParsedClass>> computedClassConfig = new Int2ObjectLinkedOpenHashMap<>();
|
Int2ObjectMap<Map<String, ParsedClass>> computedClassConfig = new Int2ObjectLinkedOpenHashMap<>();
|
||||||
for (int versionIndex = 0; versionIndex < versionsCount; versionIndex++) {
|
for (int versionIndex = 0; versionIndex < versionsCount; versionIndex++) {
|
||||||
@ -168,7 +161,7 @@ public class DataModel {
|
|||||||
.collect(Collectors.toMap(Entry::getKey, Entry::getValue))
|
.collect(Collectors.toMap(Entry::getKey, Entry::getValue))
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
var version = versions.get(versionIndex);
|
var version = parsedVersions.get(versionIndex);
|
||||||
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()
|
||||||
@ -194,7 +187,7 @@ public class DataModel {
|
|||||||
throw new IllegalArgumentException(transformCoordinate + " refers to an unknown type: "
|
throw new IllegalArgumentException(transformCoordinate + " refers to an unknown type: "
|
||||||
+ t.transformClass);
|
+ t.transformClass);
|
||||||
}
|
}
|
||||||
transformClass.changed = true;
|
transformClass.differentThanPrev = true;
|
||||||
var definition = removeAndGetIndex(transformClass.data, t.from);
|
var definition = removeAndGetIndex(transformClass.data, t.from);
|
||||||
if (definition.isEmpty()) {
|
if (definition.isEmpty()) {
|
||||||
throw new IllegalArgumentException(transformCoordinate + " refers to an unknown field: " + t.from);
|
throw new IllegalArgumentException(transformCoordinate + " refers to an unknown field: " + t.from);
|
||||||
@ -217,7 +210,7 @@ public class DataModel {
|
|||||||
throw new IllegalArgumentException(transformCoordinate + " refers to an unknown type: "
|
throw new IllegalArgumentException(transformCoordinate + " refers to an unknown type: "
|
||||||
+ t.transformClass);
|
+ t.transformClass);
|
||||||
}
|
}
|
||||||
transformClass.changed = true;
|
transformClass.differentThanPrev = true;
|
||||||
if (!allTypes.contains(extractTypeName(t.type))) {
|
if (!allTypes.contains(extractTypeName(t.type))) {
|
||||||
throw new IllegalArgumentException(transformCoordinate + " refers to an unknown type: " + t.type);
|
throw new IllegalArgumentException(transformCoordinate + " refers to an unknown type: " + t.type);
|
||||||
}
|
}
|
||||||
@ -240,7 +233,7 @@ public class DataModel {
|
|||||||
throw new IllegalArgumentException(transformCoordinate + " refers to an unknown type: "
|
throw new IllegalArgumentException(transformCoordinate + " refers to an unknown type: "
|
||||||
+ t.transformClass);
|
+ t.transformClass);
|
||||||
}
|
}
|
||||||
transformClass.changed = true;
|
transformClass.differentThanPrev = true;
|
||||||
var prevDef = transformClass.data.remove(t.from);
|
var prevDef = transformClass.data.remove(t.from);
|
||||||
if (prevDef == null) {
|
if (prevDef == null) {
|
||||||
throw new IllegalArgumentException(transformCoordinate + " tries to remove the nonexistent field \""
|
throw new IllegalArgumentException(transformCoordinate + " tries to remove the nonexistent field \""
|
||||||
@ -254,7 +247,7 @@ public class DataModel {
|
|||||||
throw new IllegalArgumentException(transformCoordinate + " refers to an unknown type: "
|
throw new IllegalArgumentException(transformCoordinate + " refers to an unknown type: "
|
||||||
+ t.transformClass);
|
+ t.transformClass);
|
||||||
}
|
}
|
||||||
transformClass.changed = true;
|
transformClass.differentThanPrev = true;
|
||||||
if (!allTypes.contains(extractTypeName(t.type))) {
|
if (!allTypes.contains(extractTypeName(t.type))) {
|
||||||
throw new IllegalArgumentException(transformCoordinate + " refers to an unknown type: " + t.type);
|
throw new IllegalArgumentException(transformCoordinate + " refers to an unknown type: " + t.type);
|
||||||
}
|
}
|
||||||
@ -271,84 +264,141 @@ public class DataModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compute the versions
|
||||||
|
var computedVersions = parsedVersions
|
||||||
|
.int2ObjectEntrySet()
|
||||||
|
.stream()
|
||||||
|
.collect(Collectors.toMap(Int2ObjectMap.Entry::getIntKey,
|
||||||
|
e -> new ComputedVersion(e.getValue(),
|
||||||
|
e.getIntKey(),
|
||||||
|
e.getIntKey() == latestVersion,
|
||||||
|
versionToName.get(e.getIntKey())
|
||||||
|
),
|
||||||
|
(a, b) -> {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
},
|
||||||
|
Int2ObjectLinkedOpenHashMap::new
|
||||||
|
));
|
||||||
|
|
||||||
// Compute the types
|
// Compute the types
|
||||||
Int2ObjectMap<Map<String, ComputedType>> computedTypes = new Int2ObjectLinkedOpenHashMap<>();
|
Int2ObjectMap<Map<String, ComputedType>> computedTypes = new Int2ObjectLinkedOpenHashMap<>();
|
||||||
ComputedTypeSupplier computedTypeSupplier = new ComputedTypeSupplier(computedTypes);
|
Int2ObjectMap<Map<String, ComputedType>> randomComputedTypes = new Int2ObjectOpenHashMap<>();
|
||||||
for (int versionIndex = 0; versionIndex < versionsCount; versionIndex++) {
|
ComputedTypeSupplier computedTypeSupplier = new ComputedTypeSupplier(randomComputedTypes, computedVersions.get(latestVersion));
|
||||||
int versionIndexF = versionIndex;
|
{
|
||||||
if (versionIndexF == 0) {
|
for (int versionNumber = latestVersion - 1; versionNumber >= 0; versionNumber--) {
|
||||||
// Compute base types
|
var version = computedClassConfig.get(versionNumber);
|
||||||
List<ComputedType> versionBaseTypes = computedClassConfig.get(versionIndexF).entrySet().stream()
|
computedClassConfig.get(versionNumber + 1).forEach((type, typeConfig) -> {
|
||||||
.map(e -> {
|
if (typeConfig.differentThanPrev) {
|
||||||
var data = new LinkedHashMap<String, VersionedType>();
|
version.get(type).differentThanNext = true;
|
||||||
e.getValue().getData().forEach((key, value) -> data.put(key, new VersionedType(value, versionIndexF)));
|
|
||||||
return new ComputedBaseType(new VersionedType(e.getKey(), versionIndexF),
|
|
||||||
e.getValue().stringRepresenter, data, computedTypeSupplier);
|
|
||||||
}).collect(Collectors.toList());
|
|
||||||
// Compute custom types
|
|
||||||
customTypesData.forEach((name, data) -> versionBaseTypes.add(new ComputedCustomType(name,
|
|
||||||
data.getJavaClassString(), data.serializer, computedTypeSupplier)));
|
|
||||||
// Compute super types
|
|
||||||
superTypesData.forEach((key, data) -> {
|
|
||||||
List<VersionedType> subTypes = data.stream().map(x -> new VersionedType(x, versionIndexF)).toList();
|
|
||||||
versionBaseTypes.add(new ComputedSuperType(new VersionedType(key, versionIndexF), subTypes, computedTypeSupplier));
|
|
||||||
});
|
|
||||||
// Compute nullable types
|
|
||||||
computedClassConfig.values().stream()
|
|
||||||
.flatMap(x -> x.values().stream())
|
|
||||||
.flatMap(x -> x.getData().values().stream())
|
|
||||||
.filter(x -> x.startsWith("-"))
|
|
||||||
.map(nullableName -> new VersionedType(nullableName.substring(1), versionIndexF))
|
|
||||||
.map(baseType -> new ComputedNullableType(baseType, computedTypeSupplier))
|
|
||||||
.forEach(versionBaseTypes::add);
|
|
||||||
// Compute array types
|
|
||||||
computedClassConfig.values().stream()
|
|
||||||
.flatMap(x -> x.values().stream())
|
|
||||||
.flatMap(x -> x.getData().values().stream())
|
|
||||||
.filter(x -> x.startsWith("§"))
|
|
||||||
.map(nullableName -> new VersionedType(nullableName.substring(1), versionIndexF))
|
|
||||||
.map(baseType -> new ComputedArrayType(baseType, computedTypeSupplier))
|
|
||||||
.forEach(versionBaseTypes::add);
|
|
||||||
// Compute native types
|
|
||||||
versionBaseTypes.addAll(ComputedNativeType.get(computedTypeSupplier));
|
|
||||||
|
|
||||||
computedTypes.put(versionIndexF,
|
|
||||||
versionBaseTypes.stream().distinct().collect(Collectors.toMap(ComputedType::getName, identity())));
|
|
||||||
} else {
|
|
||||||
Set<String> changedTypes = computedTypes.get(versionIndexF - 1).values().stream()
|
|
||||||
.filter(prevType -> prevType instanceof ComputedBaseType prevBaseType
|
|
||||||
&& computedClassConfig.get(versionIndexF).get(prevBaseType.getName()).changed)
|
|
||||||
.map(ComputedType::getName)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
|
|
||||||
{
|
|
||||||
boolean addedMoreTypes;
|
|
||||||
do {
|
|
||||||
var newChangedTypes = changedTypes
|
|
||||||
.parallelStream()
|
|
||||||
.flatMap(changedType -> computedTypes.get(versionIndexF - 1).get(changedType).getDependents())
|
|
||||||
.map(ComputedType::getName)
|
|
||||||
.distinct()
|
|
||||||
.toList();
|
|
||||||
addedMoreTypes = changedTypes.addAll(newChangedTypes);
|
|
||||||
} while (addedMoreTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, ComputedType> currentVersionComputedTypes = new HashMap<>();
|
|
||||||
var versionChangeChecker = new VersionChangeChecker(changedTypes);
|
|
||||||
computedTypes.get(versionIndexF - 1).forEach((name, type) -> {
|
|
||||||
if (!changedTypes.contains(name)) {
|
|
||||||
currentVersionComputedTypes.put(name, type);
|
|
||||||
} else {
|
|
||||||
if (type instanceof VersionedComputedType versionedComputedType) {
|
|
||||||
ComputedType newType = versionedComputedType.withChangeAtVersion(versionIndexF, versionChangeChecker);
|
|
||||||
currentVersionComputedTypes.put(name, newType);
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
computedTypes.put(versionIndexF, currentVersionComputedTypes);
|
}
|
||||||
|
for (int versionIndex = latestVersion; versionIndex >= 0; versionIndex--) {
|
||||||
|
int versionIndexF = versionIndex;
|
||||||
|
var version = computedVersions.get(versionIndexF);
|
||||||
|
if (versionIndexF == latestVersion) {
|
||||||
|
// Compute base types
|
||||||
|
List<ComputedType> versionBaseTypes = computedClassConfig.get(versionIndexF).entrySet().stream()
|
||||||
|
.map(e -> {
|
||||||
|
var data = new LinkedHashMap<String, VersionedType>();
|
||||||
|
e.getValue().getData().forEach((key, value) -> data.put(key, new VersionedType(value, version)));
|
||||||
|
return new ComputedTypeBase(new VersionedType(e.getKey(), version),
|
||||||
|
e.getValue().stringRepresenter, data, computedTypeSupplier);
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
// Compute custom types
|
||||||
|
customTypesData.forEach((name, data) -> versionBaseTypes.add(new ComputedTypeCustom(name,
|
||||||
|
data.getJavaClassString(), data.serializer, computedTypeSupplier, computedVersions.get(latestVersion))));
|
||||||
|
// Compute super types
|
||||||
|
superTypesData.forEach((key, data) -> {
|
||||||
|
List<VersionedType> subTypes = data.stream().map(x -> new VersionedType(x, version)).toList();
|
||||||
|
versionBaseTypes.add(new ComputedTypeSuper(new VersionedType(key, version), subTypes, computedTypeSupplier));
|
||||||
|
});
|
||||||
|
// Compute nullable types
|
||||||
|
{
|
||||||
|
var nullableRawTypes = computedClassConfig.values().stream()
|
||||||
|
.flatMap(x -> x.values().stream())
|
||||||
|
.flatMap(x -> x.getData().values().stream())
|
||||||
|
.filter(x -> x.startsWith("-"))
|
||||||
|
.map(nullableName -> nullableName.substring(1))
|
||||||
|
.toList();
|
||||||
|
// Compute nullable base types
|
||||||
|
nullableRawTypes.stream()
|
||||||
|
.filter(nullableName -> !NATIVE_TYPES.contains(nullableName))
|
||||||
|
.map(nullableName -> new VersionedType(nullableName, version))
|
||||||
|
.map(baseType -> new ComputedTypeNullableVersioned(baseType, computedTypeSupplier))
|
||||||
|
.forEach(versionBaseTypes::add);
|
||||||
|
// Compute nullable native types
|
||||||
|
nullableRawTypes.stream()
|
||||||
|
.filter(NATIVE_TYPES::contains)
|
||||||
|
.map(baseType ->
|
||||||
|
new ComputedTypeNullableNative(baseType, computedVersions.get(latestVersion), computedTypeSupplier))
|
||||||
|
.forEach(versionBaseTypes::add);
|
||||||
|
}
|
||||||
|
// Compute array types
|
||||||
|
{
|
||||||
|
var arrayRawTypes = computedClassConfig.values().stream()
|
||||||
|
.flatMap(x -> x.values().stream())
|
||||||
|
.flatMap(x -> x.getData().values().stream())
|
||||||
|
.filter(x -> x.startsWith("§"))
|
||||||
|
.map(nullableName -> nullableName.substring(1))
|
||||||
|
.toList();
|
||||||
|
// Compute array base types
|
||||||
|
arrayRawTypes.stream()
|
||||||
|
.filter(nullableName -> !NATIVE_TYPES.contains(nullableName))
|
||||||
|
.map(nullableName -> new VersionedType(nullableName, version))
|
||||||
|
.map(baseType -> new ComputedTypeArrayVersioned(baseType, computedTypeSupplier))
|
||||||
|
.forEach(versionBaseTypes::add);
|
||||||
|
// Compute array native types
|
||||||
|
arrayRawTypes.stream()
|
||||||
|
.filter(NATIVE_TYPES::contains)
|
||||||
|
.map(baseType ->
|
||||||
|
new ComputedTypeArrayNative(baseType, computedTypeSupplier))
|
||||||
|
.forEach(versionBaseTypes::add);
|
||||||
|
}
|
||||||
|
// Compute native types
|
||||||
|
versionBaseTypes.addAll(ComputedTypeNative.get(computedTypeSupplier));
|
||||||
|
|
||||||
|
randomComputedTypes.put(versionIndexF,
|
||||||
|
versionBaseTypes.stream().distinct().collect(Collectors.toMap(ComputedType::getName, identity())));
|
||||||
|
} else {
|
||||||
|
Set<String> changedTypes = randomComputedTypes.get(versionIndexF + 1).values().stream()
|
||||||
|
.filter(prevType -> prevType instanceof ComputedTypeBase prevBaseType
|
||||||
|
&& computedClassConfig.get(versionIndexF).get(prevBaseType.getName()).differentThanNext)
|
||||||
|
.map(ComputedType::getName)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
{
|
||||||
|
boolean addedMoreTypes;
|
||||||
|
do {
|
||||||
|
var newChangedTypes = changedTypes
|
||||||
|
.parallelStream()
|
||||||
|
.flatMap(changedType -> randomComputedTypes.get(versionIndexF + 1).get(changedType).getDependents())
|
||||||
|
.map(ComputedType::getName)
|
||||||
|
.distinct()
|
||||||
|
.toList();
|
||||||
|
addedMoreTypes = changedTypes.addAll(newChangedTypes);
|
||||||
|
} while (addedMoreTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, ComputedType> currentVersionComputedTypes = new HashMap<>();
|
||||||
|
var versionChangeChecker = new VersionChangeChecker(changedTypes, versionIndexF, latestVersion);
|
||||||
|
randomComputedTypes.get(versionIndexF + 1).forEach((name, type) -> {
|
||||||
|
if (!changedTypes.contains(name)) {
|
||||||
|
currentVersionComputedTypes.put(name, type);
|
||||||
|
} else {
|
||||||
|
if (type instanceof VersionedComputedType versionedComputedType) {
|
||||||
|
ComputedType newType = versionedComputedType.withChangeAtVersion(version, versionChangeChecker);
|
||||||
|
currentVersionComputedTypes.put(name, newType);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
randomComputedTypes.put(versionIndexF, currentVersionComputedTypes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < versionsCount; i++) {
|
||||||
|
computedTypes.put(i, Objects.requireNonNull(randomComputedTypes.get(i)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// All types, including arrays, nullables, primitives, etc
|
// All types, including arrays, nullables, primitives, etc
|
||||||
@ -366,7 +416,7 @@ public class DataModel {
|
|||||||
.collect(Collectors.toMap(Entry::getKey, e -> e
|
.collect(Collectors.toMap(Entry::getKey, e -> e
|
||||||
.getValue()
|
.getValue()
|
||||||
.stream()
|
.stream()
|
||||||
.sorted(Comparator.comparingInt(VersionedComputedType::getVersion))
|
.sorted(Comparator.comparingInt(x -> x.getVersion().getVersion()))
|
||||||
.map(x -> new VersionedType(e.getKey(), x.getVersion()))
|
.map(x -> new VersionedType(e.getKey(), x.getVersion()))
|
||||||
.toList()));
|
.toList()));
|
||||||
versionedTypeVersions.forEach((type, versionsList) -> {
|
versionedTypeVersions.forEach((type, versionsList) -> {
|
||||||
@ -434,43 +484,31 @@ public class DataModel {
|
|||||||
|__BaseGroupId v1
|
|__BaseGroupId v1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
this.versions = computedVersions;
|
||||||
this.interfacesData = interfacesData.entrySet().stream()
|
this.interfacesData = interfacesData.entrySet().stream()
|
||||||
.map(e -> Map.entry(e.getKey(), new ParsedInterface(e.getValue())))
|
.map(e -> Map.entry(e.getKey(), new ParsedInterface(e.getValue())))
|
||||||
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
|
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
|
||||||
this.versions = versions
|
|
||||||
.int2ObjectEntrySet()
|
|
||||||
.stream()
|
|
||||||
.collect(Collectors.toMap(Int2ObjectMap.Entry::getIntKey,
|
|
||||||
e -> new ComputedVersion(e.getValue(),
|
|
||||||
e.getIntKey(),
|
|
||||||
e.getIntKey() == latestVersion,
|
|
||||||
versionToName.get(e.getIntKey()),
|
|
||||||
computedClassConfig.get(e.getIntKey())
|
|
||||||
),
|
|
||||||
(a, b) -> {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
},
|
|
||||||
Int2ObjectLinkedOpenHashMap::new
|
|
||||||
));
|
|
||||||
LongAdder unchangedTot = new LongAdder();
|
LongAdder unchangedTot = new LongAdder();
|
||||||
LongAdder changedTot = new LongAdder();
|
LongAdder changedTot = new LongAdder();
|
||||||
computedTypes.forEach((version, types) -> {
|
computedTypes.forEach((version, types) -> {
|
||||||
System.out.println("Version: " + version);
|
System.out.println("Version: " + version);
|
||||||
System.out.println("\tTypes: " + types.size());
|
System.out.println("\tTypes: " + types.size());
|
||||||
System.out.println("\tVersioned types: " + types.values().stream().filter(t -> (t instanceof VersionedComputedType)).count());
|
System.out.println("\tVersioned types: " + types.values().stream().filter(t -> (t instanceof VersionedComputedType)).count());
|
||||||
var unchanged = types.values().stream().filter(t -> (t instanceof VersionedComputedType versionedComputedType && versionedComputedType.getVersion() < version)).count();
|
var unchanged = types.values().stream().filter(t -> (t instanceof VersionedComputedType versionedComputedType
|
||||||
var changed = types.values().stream().filter(t -> (t instanceof VersionedComputedType versionedComputedType && versionedComputedType.getVersion() == version)).count();
|
&& versionedComputedType.getVersion().getVersion() != version)).count();
|
||||||
|
var changed = types.values().stream().filter(t -> (t instanceof VersionedComputedType versionedComputedType
|
||||||
|
&& versionedComputedType.getVersion().getVersion() == version)).count();
|
||||||
unchangedTot.add(unchanged);
|
unchangedTot.add(unchanged);
|
||||||
changedTot.add(changed);
|
changedTot.add(changed);
|
||||||
System.out.println("\t\tUnchanged: " + unchanged + " (" + (unchanged * 100 / (changed + unchanged)) + "%)");
|
System.out.println("\t\tUnchanged: " + unchanged + " (" + (unchanged * 100 / Math.max(changed + unchanged, 1)) + "%)");
|
||||||
System.out.println("\t\tChanged: " + changed + " (" + (changed * 100 / (changed + unchanged)) + "%)");
|
System.out.println("\t\tChanged: " + changed + " (" + (changed * 100 / Math.max(changed + unchanged, 1)) + "%)");
|
||||||
});
|
});
|
||||||
System.out.println("Result:");
|
System.out.println("Result:");
|
||||||
var unchanged = unchangedTot.sum();
|
var unchanged = unchangedTot.sum();
|
||||||
var changed = changedTot.sum();
|
var changed = changedTot.sum();
|
||||||
System.out.println("\tAvoided type versions: " + unchanged + " (" + (unchanged * 100 / (changed + unchanged)) + "%)");
|
System.out.println("\tAvoided type versions: " + unchanged + " (" + (unchanged * 100 / (changed + unchanged)) + "%)");
|
||||||
System.out.println("\tType versions: " + changed + " (" + (changed * 100 / (changed + unchanged)) + "%)");
|
System.out.println("\tType versions: " + changed + " (" + (changed * 100 / (changed + unchanged)) + "%)");
|
||||||
this.currentVersion = versionsCount - 1;
|
this.currentVersion = computedVersions.get(versionsCount - 1);
|
||||||
this.superTypes = superTypesData;
|
this.superTypes = superTypesData;
|
||||||
this.customTypes = customTypesData;
|
this.customTypes = customTypesData;
|
||||||
this.computedTypes = computedTypes;
|
this.computedTypes = computedTypes;
|
||||||
@ -604,17 +642,36 @@ public class DataModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getCurrentVersionNumber() {
|
public int getCurrentVersionNumber() {
|
||||||
return currentVersion;
|
return currentVersion.getVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComputedVersion getCurrentVersion() {
|
public ComputedVersion getCurrentVersion() {
|
||||||
return versions.get(currentVersion);
|
return currentVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Set<String>> getSuperTypes() {
|
@Deprecated
|
||||||
|
public Map<String, Set<String>> getSuperTypesRaw() {
|
||||||
return this.superTypes;
|
return this.superTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Stream<ComputedTypeSuper> getSuperTypesComputed() {
|
||||||
|
return getSuperTypesComputed(currentVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<ComputedTypeSuper> getSuperTypesComputed(ComputedVersion version) {
|
||||||
|
return this.computedTypes.get(version.getVersion()).values().stream()
|
||||||
|
.filter(t -> t instanceof ComputedTypeSuper).map(t -> (ComputedTypeSuper) t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<ComputedTypeBase> getBaseTypesComputed() {
|
||||||
|
return getBaseTypesComputed(currentVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<ComputedTypeBase> getBaseTypesComputed(ComputedVersion version) {
|
||||||
|
return this.computedTypes.get(version.getVersion()).values().stream()
|
||||||
|
.filter(t -> t instanceof ComputedTypeBase).map(t -> (ComputedTypeBase) t);
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<ComputedVersion> getNextVersion(ComputedVersion versionConfiguration) {
|
public Optional<ComputedVersion> getNextVersion(ComputedVersion versionConfiguration) {
|
||||||
var nextVersion = versions.get(versionConfiguration.getVersion() + 1);
|
var nextVersion = versions.get(versionConfiguration.getVersion() + 1);
|
||||||
return Optional.ofNullable(nextVersion);
|
return Optional.ofNullable(nextVersion);
|
||||||
@ -628,6 +685,7 @@ public class DataModel {
|
|||||||
return interfacesData;
|
return interfacesData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public Map<String, CustomTypesConfiguration> getCustomTypes() {
|
public Map<String, CustomTypesConfiguration> getCustomTypes() {
|
||||||
return customTypes;
|
return customTypes;
|
||||||
}
|
}
|
||||||
@ -636,6 +694,10 @@ public class DataModel {
|
|||||||
return computedTypes;
|
return computedTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, ComputedType> getComputedTypes(ComputedVersion version) {
|
||||||
|
return computedTypes.get(version.getVersion());
|
||||||
|
}
|
||||||
|
|
||||||
public VersionedType getNextVersion(VersionedType type) {
|
public VersionedType getNextVersion(VersionedType type) {
|
||||||
return versionedTypeNextVersion.get(type);
|
return versionedTypeNextVersion.get(type);
|
||||||
}
|
}
|
||||||
@ -644,27 +706,134 @@ public class DataModel {
|
|||||||
return versionedTypePrevVersion.get(type);
|
return versionedTypePrevVersion.get(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComputedType getNextVersion(ComputedType type) {
|
public <T extends ComputedType> T getNextVersion(T type) {
|
||||||
if (type instanceof VersionedComputedType versionedComputedType) {
|
if (type instanceof VersionedComputedType versionedComputedType) {
|
||||||
var result = versionedTypeNextVersion.get(new VersionedType(versionedComputedType.getName(), versionedComputedType.getVersion()));
|
var result = versionedTypeNextVersion.get(new VersionedType(versionedComputedType.getName(), versionedComputedType.getVersion()));
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return this.computedTypes.get(result.version()).get(result.type());
|
//noinspection unchecked
|
||||||
|
return (T) this.computedTypes.get(result.version().getVersion()).get(result.type());
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComputedType getPrevVersion(ComputedType type) {
|
public <T extends ComputedType> T getPrevVersion(T type) {
|
||||||
if (type instanceof VersionedComputedType versionedComputedType) {
|
if (type instanceof VersionedComputedType versionedComputedType) {
|
||||||
var result = versionedTypePrevVersion.get(new VersionedType(versionedComputedType.getName(), versionedComputedType.getVersion()));
|
var result = versionedTypePrevVersion.get(new VersionedType(versionedComputedType.getName(), versionedComputedType.getVersion()));
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return this.computedTypes.get(result.version()).get(result.type());
|
//noinspection unchecked
|
||||||
|
return (T) this.computedTypes.get(result.version().getVersion()).get(result.type());
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isTypeForVersion(ComputedVersion versionConfiguration, String key) {
|
||||||
|
var type = getComputedTypes(versionConfiguration).get(key);
|
||||||
|
return type instanceof VersionedComputedType versionedComputedType
|
||||||
|
&& versionedComputedType.getVersion().getVersion() == versionConfiguration.getVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComputedVersion getTypeFirstSameVersion(VersionedComputedType type) {
|
||||||
|
var prevVersion = getPrevVersion(type);
|
||||||
|
if (prevVersion != null) {
|
||||||
|
return versions.get(prevVersion.getVersion().getVersion() + 1);
|
||||||
|
} else {
|
||||||
|
return type.getVersion();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<ComputedVersion> getTypeSameVersions(VersionedComputedType type) {
|
||||||
|
var initialVersion = getTypeFirstSameVersion(type);
|
||||||
|
var lastVersion = type.getVersion();
|
||||||
|
return getVersionRange(initialVersion, lastVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public ComputedVersion getVersion(int version) {
|
||||||
|
return Objects.requireNonNull(versions.get(version));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComputedVersion getVersion(VersionedComputedType versionedComputedType) {
|
||||||
|
return Objects.requireNonNull(versions.get(versionedComputedType.getVersion().getVersion()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<ComputedVersion> getVersionRange(ComputedVersion initialVersionInclusive,
|
||||||
|
ComputedVersion lastVersionInclusive) {
|
||||||
|
if (initialVersionInclusive.getVersion() > lastVersionInclusive.getVersion()) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
return IntStream
|
||||||
|
.rangeClosed(initialVersionInclusive.getVersion(), lastVersionInclusive.getVersion())
|
||||||
|
.mapToObj(versions::get);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersionPackage(ComputedVersion version, String basePackageName) {
|
||||||
|
return version.getPackage(basePackageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersionDataPackage(ComputedVersion version, String basePackageName) {
|
||||||
|
return version.getDataPackage(basePackageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public String getVersionDataPackage(VersionedComputedType type, String basePackageName) {
|
||||||
|
return type.getVersion().getDataPackage(basePackageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRootPackage(String basePackageName) {
|
||||||
|
return joinPackage(basePackageName, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String joinPackage(String basePackageName, String packageName) {
|
||||||
|
if (basePackageName.isBlank()) {
|
||||||
|
basePackageName = "org.generated";
|
||||||
|
}
|
||||||
|
if (packageName.isBlank()) {
|
||||||
|
return basePackageName;
|
||||||
|
} else {
|
||||||
|
return basePackageName + "." + packageName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<ComputedTypeSuper> getSuperTypesOf(VersionedComputedType baseType) {
|
||||||
|
return getSuperTypesComputed(baseType.getVersion()).filter(type -> type.subTypes().contains(baseType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<ComputedTypeSuper> getExtendsInterfaces(ComputedTypeSuper superType) {
|
||||||
|
if (superType.getVersion().isCurrent()) {
|
||||||
|
var interfaces = interfacesData.get(superType.getName());
|
||||||
|
if (interfaces != null) {
|
||||||
|
return interfaces.extendInterfaces.stream()
|
||||||
|
.map(name -> (ComputedTypeSuper) this.computedTypes.get(currentVersion.getVersion()).get(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Stream.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<Entry<String, ComputedType>> getCommonInterfaceGetters(ComputedTypeSuper superType) {
|
||||||
|
if (superType.getVersion().isCurrent()) {
|
||||||
|
var interfaces = interfacesData.get(superType.getName());
|
||||||
|
if (interfaces != null) {
|
||||||
|
return interfaces.commonGetters.entrySet().stream().map(x ->
|
||||||
|
Map.entry(x.getKey(), this.computedTypes.get(currentVersion.getVersion()).get(x.getValue())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Stream.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<Entry<String, ComputedType>> getCommonInterfaceData(ComputedTypeSuper superType) {
|
||||||
|
if (superType.getVersion().isCurrent()) {
|
||||||
|
var interfaces = interfacesData.get(superType.getName());
|
||||||
|
if (interfaces != null) {
|
||||||
|
return interfaces.commonData.entrySet().stream().map(x ->
|
||||||
|
Map.entry(x.getKey(), this.computedTypes.get(currentVersion.getVersion()).get(x.getValue())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Stream.of();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
package it.cavallium.data.generator.plugin;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.TypeName;
|
||||||
|
|
||||||
|
public record FieldLocation(TypeName className, String fieldName) {}
|
@ -20,6 +20,9 @@ public class MavenPlugin extends AbstractMojo {
|
|||||||
@Parameter( required = true)
|
@Parameter( required = true)
|
||||||
private String basePackageName;
|
private String basePackageName;
|
||||||
|
|
||||||
|
@Parameter( required = true, defaultValue = "true")
|
||||||
|
private String deepCheckBeforeCreatingNewEqualInstances;
|
||||||
|
|
||||||
@Parameter( required = true, defaultValue = "false")
|
@Parameter( required = true, defaultValue = "false")
|
||||||
private String useRecordBuilder;
|
private String useRecordBuilder;
|
||||||
|
|
||||||
@ -39,7 +42,7 @@ public class MavenPlugin extends AbstractMojo {
|
|||||||
|
|
||||||
Path outPath = genRecordsPath.resolve("java");
|
Path outPath = genRecordsPath.resolve("java");
|
||||||
this.project.addCompileSourceRoot(outPath.toString());
|
this.project.addCompileSourceRoot(outPath.toString());
|
||||||
sourcesGenerator.generateSources(basePackageName, outPath, Boolean.parseBoolean(useRecordBuilder));
|
sourcesGenerator.generateSources(basePackageName, outPath, Boolean.parseBoolean(useRecordBuilder), false, Boolean.parseBoolean(deepCheckBeforeCreatingNewEqualInstances));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new MojoExecutionException("Exception while generating classes", e);
|
throw new MojoExecutionException("Exception while generating classes", e);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package it.cavallium.data.generator.plugin;
|
|||||||
|
|
||||||
import static it.cavallium.data.generator.plugin.DataModel.fixType;
|
import static it.cavallium.data.generator.plugin.DataModel.fixType;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
@ -14,7 +13,8 @@ public final class ParsedClass {
|
|||||||
public String stringRepresenter;
|
public String stringRepresenter;
|
||||||
|
|
||||||
public LinkedHashMap<String, String> data;
|
public LinkedHashMap<String, String> data;
|
||||||
public boolean changed;
|
public boolean differentThanPrev;
|
||||||
|
public boolean differentThanNext;
|
||||||
|
|
||||||
public ParsedClass(ClassConfiguration baseTypesData) {
|
public ParsedClass(ClassConfiguration baseTypesData) {
|
||||||
this.stringRepresenter = baseTypesData.stringRepresenter;
|
this.stringRepresenter = baseTypesData.stringRepresenter;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,6 @@ public class Standalone {
|
|||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
SourcesGenerator sourcesGenerator = SourcesGenerator.load(Paths.get(args[0]));
|
SourcesGenerator sourcesGenerator = SourcesGenerator.load(Paths.get(args[0]));
|
||||||
sourcesGenerator.generateSources(args[1], Paths.get(args[2]), Boolean.parseBoolean(args[3]));
|
sourcesGenerator.generateSources(args[1], Paths.get(args[2]), Boolean.parseBoolean(args[3]), false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,24 @@ import java.util.Set;
|
|||||||
public class VersionChangeChecker {
|
public class VersionChangeChecker {
|
||||||
|
|
||||||
private final Set<String> changedTypes;
|
private final Set<String> changedTypes;
|
||||||
|
private final int version;
|
||||||
|
private final int latestVersion;
|
||||||
|
|
||||||
public VersionChangeChecker(Set<String> changedTypes) {
|
public VersionChangeChecker(Set<String> changedTypes, int version, int latestVersion) {
|
||||||
this.changedTypes = changedTypes;
|
this.changedTypes = changedTypes;
|
||||||
|
this.version = version;
|
||||||
|
this.latestVersion = latestVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean checkChanged(String name) {
|
public boolean checkChanged(String name) {
|
||||||
return changedTypes.contains(name);
|
return changedTypes.contains(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLatestVersion() {
|
||||||
|
return latestVersion;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
package it.cavallium.data.generator.plugin;
|
package it.cavallium.data.generator.plugin;
|
||||||
|
|
||||||
public record VersionedType(String type, int version) {
|
import java.util.Objects;
|
||||||
|
|
||||||
public VersionedType withVersion(int version) {
|
public record VersionedType(String type, ComputedVersion version) {
|
||||||
if (version == this.version) {
|
|
||||||
|
public VersionedType withVersion(ComputedVersion version) {
|
||||||
|
if (Objects.equals(version, this.version)) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
return new VersionedType(type, version);
|
return new VersionedType(type, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public VersionedType withVersionIfChanged(int version, VersionChangeChecker versionChangeChecker) {
|
public VersionedType withVersionIfChanged(ComputedVersion version, VersionChangeChecker versionChangeChecker) {
|
||||||
if (versionChangeChecker.checkChanged(this.type)) {
|
if (versionChangeChecker.checkChanged(this.type)) {
|
||||||
return withVersion(version);
|
return withVersion(version);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
package it.cavallium.data.generator.plugin.classgen;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.TypeSpec;
|
||||||
|
import it.cavallium.data.generator.plugin.ClassGenerator;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
|
||||||
|
public class GenBaseType extends ClassGenerator {
|
||||||
|
|
||||||
|
public GenBaseType(ClassGeneratorParams params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stream<GeneratedClass> generateClasses() {
|
||||||
|
var baseTypeClass = TypeSpec.enumBuilder("BaseType");
|
||||||
|
baseTypeClass.addModifiers(Modifier.PUBLIC);
|
||||||
|
dataModel.getBaseTypesComputed().forEach(baseType -> baseTypeClass.addEnumConstant(baseType.getName()));
|
||||||
|
return Stream.of(new GeneratedClass(dataModel.getRootPackage(basePackageName), baseTypeClass));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,191 @@
|
|||||||
|
package it.cavallium.data.generator.plugin.classgen;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.CodeBlock;
|
||||||
|
import com.squareup.javapoet.FieldSpec;
|
||||||
|
import com.squareup.javapoet.MethodSpec;
|
||||||
|
import com.squareup.javapoet.ParameterSpec;
|
||||||
|
import com.squareup.javapoet.ParameterizedTypeName;
|
||||||
|
import com.squareup.javapoet.TypeName;
|
||||||
|
import com.squareup.javapoet.TypeSpec;
|
||||||
|
import com.squareup.javapoet.TypeSpec.Builder;
|
||||||
|
import com.squareup.javapoet.TypeVariableName;
|
||||||
|
import com.squareup.javapoet.WildcardTypeName;
|
||||||
|
import it.cavallium.data.generator.plugin.ClassGenerator;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedType;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedVersion;
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
|
||||||
|
public class GenCurrentVersion extends ClassGenerator {
|
||||||
|
|
||||||
|
public GenCurrentVersion(ClassGeneratorParams params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stream<GeneratedClass> generateClasses() {
|
||||||
|
var currentVersionDataPackage = dataModel.getCurrentVersion().getDataPackage(basePackageName);
|
||||||
|
|
||||||
|
var currentVersionClass = TypeSpec.classBuilder("CurrentVersion");
|
||||||
|
currentVersionClass.addModifiers(Modifier.PUBLIC);
|
||||||
|
currentVersionClass.addModifiers(Modifier.FINAL);
|
||||||
|
// Add a static variable for the current version
|
||||||
|
{
|
||||||
|
var versionNumberField = FieldSpec.builder(ClassName
|
||||||
|
.get(dataModel.getCurrentVersion().getPackage(basePackageName),
|
||||||
|
"Version"), "VERSION").addModifiers(Modifier.PUBLIC).addModifiers(Modifier.STATIC)
|
||||||
|
.addModifiers(Modifier.FINAL).initializer("new " + dataModel.getCurrentVersion().getPackage(basePackageName)
|
||||||
|
+ ".Version()").build();
|
||||||
|
currentVersionClass.addField(versionNumberField);
|
||||||
|
}
|
||||||
|
// Check latest version method
|
||||||
|
{
|
||||||
|
var isLatestVersionMethod = MethodSpec.methodBuilder("isLatestVersion").addModifiers(Modifier.PUBLIC)
|
||||||
|
.addModifiers(Modifier.FINAL).addModifiers(Modifier.STATIC).returns(TypeName.BOOLEAN)
|
||||||
|
.addParameter(ParameterSpec.builder(TypeName.INT, "version").build())
|
||||||
|
.addCode("return version == VERSION.getVersion();").build();
|
||||||
|
currentVersionClass.addMethod(isLatestVersionMethod);
|
||||||
|
}
|
||||||
|
// Get super type classes method
|
||||||
|
{
|
||||||
|
var getSuperTypeClasses = MethodSpec.methodBuilder("getSuperTypeClasses").addModifiers(Modifier.PUBLIC)
|
||||||
|
.addModifiers(Modifier.FINAL).addModifiers(Modifier.STATIC)
|
||||||
|
.returns(ParameterizedTypeName.get(ClassName.get(Set.class),
|
||||||
|
ParameterizedTypeName.get(ClassName.get(Class.class),
|
||||||
|
WildcardTypeName.subtypeOf(ClassName.get(currentVersionDataPackage, "IType")))))
|
||||||
|
.addCode("return $T.of(\n", Set.class);
|
||||||
|
AtomicBoolean isFirst = new AtomicBoolean(true);
|
||||||
|
dataModel.getSuperTypesComputed(dataModel.getCurrentVersion()).forEach(superType -> {
|
||||||
|
if (!isFirst.getAndSet(false)) {
|
||||||
|
getSuperTypeClasses.addCode(",\n");
|
||||||
|
}
|
||||||
|
getSuperTypeClasses.addCode("$T.class",
|
||||||
|
ClassName.get(dataModel.getVersion(superType).getDataPackage(basePackageName), superType.getName())
|
||||||
|
);
|
||||||
|
});
|
||||||
|
getSuperTypeClasses.addCode("\n);");
|
||||||
|
currentVersionClass.addMethod(getSuperTypeClasses.build());
|
||||||
|
}
|
||||||
|
// Get super type subtypes classes method
|
||||||
|
{
|
||||||
|
var getSuperTypeSubtypesClasses = MethodSpec.methodBuilder("getSuperTypeSubtypesClasses").addModifiers(Modifier.PUBLIC)
|
||||||
|
.addModifiers(Modifier.FINAL).addModifiers(Modifier.STATIC)
|
||||||
|
.returns(ParameterizedTypeName.get(ClassName.get(Set.class),
|
||||||
|
ParameterizedTypeName.get(ClassName.get(Class.class),
|
||||||
|
WildcardTypeName.subtypeOf(ClassName.get(currentVersionDataPackage, "IBaseType")))));
|
||||||
|
getSuperTypeSubtypesClasses
|
||||||
|
.addParameter(ParameterSpec.builder(ParameterizedTypeName.get(ClassName.get(Class.class),
|
||||||
|
WildcardTypeName.subtypeOf(ClassName.get(currentVersionDataPackage, "IType"))
|
||||||
|
), "superTypeClass").build());
|
||||||
|
getSuperTypeSubtypesClasses.beginControlFlow("return switch (superTypeClass.getCanonicalName())");
|
||||||
|
dataModel.getSuperTypesComputed(dataModel.getCurrentVersion()).forEach(superType -> {
|
||||||
|
getSuperTypeSubtypesClasses.addCode("case \"" + ClassName
|
||||||
|
.get(currentVersionDataPackage, superType.getName())
|
||||||
|
.canonicalName() + "\" -> $T.of(\n", Set.class);
|
||||||
|
getSuperTypeSubtypesClasses.addCode("$>");
|
||||||
|
AtomicBoolean isFirst = new AtomicBoolean(true);
|
||||||
|
for (ComputedType subType : superType.subTypes()) {
|
||||||
|
if (!isFirst.getAndSet(false)) {
|
||||||
|
getSuperTypeSubtypesClasses.addCode(",\n");
|
||||||
|
}
|
||||||
|
getSuperTypeSubtypesClasses.addCode("$T.class",
|
||||||
|
ClassName.get(currentVersionDataPackage, subType.getName())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
getSuperTypeSubtypesClasses.addCode("$<");
|
||||||
|
getSuperTypeSubtypesClasses.addCode("\n);\n");
|
||||||
|
});
|
||||||
|
getSuperTypeSubtypesClasses.addStatement("default -> throw new $T()", IllegalArgumentException.class);
|
||||||
|
getSuperTypeSubtypesClasses.addCode(CodeBlock.of("$<};"));
|
||||||
|
currentVersionClass.addMethod(getSuperTypeSubtypesClasses.build());
|
||||||
|
}
|
||||||
|
// UpgradeDataToLatestVersion1 Method
|
||||||
|
{
|
||||||
|
var upgradeDataToLatestVersion1MethodBuilder = MethodSpec.methodBuilder("upgradeDataToLatestVersion")
|
||||||
|
.addTypeVariable(TypeVariableName.get("U", ClassName.get(currentVersionDataPackage, "IBaseType")))
|
||||||
|
.addModifiers(Modifier.PUBLIC).addModifiers(Modifier.STATIC).addModifiers(Modifier.FINAL).returns(TypeVariableName.get("U"))
|
||||||
|
.addParameter(ParameterSpec.builder(TypeName.INT, "oldVersion").build()).addParameter(
|
||||||
|
ParameterSpec.builder(ClassName.get(dataModel.getRootPackage(basePackageName), "BaseType"), "type").build())
|
||||||
|
.addParameter(ParameterSpec.builder(DataInput.class, "oldDataInput").build())
|
||||||
|
.addException(IOException.class).beginControlFlow("return upgradeDataToLatestVersion(oldVersion, switch (oldVersion)");
|
||||||
|
for (var versionConfiguration : dataModel.getVersionsSet()) {
|
||||||
|
// Add a case in which the data version deserializes the serialized data and upgrades it
|
||||||
|
var versions = ClassName.get(dataModel.getRootPackage(basePackageName), "Versions");
|
||||||
|
upgradeDataToLatestVersion1MethodBuilder.addStatement("case $T.$N -> $T.INSTANCE.getSerializer(type).deserialize(oldDataInput)",
|
||||||
|
versions,
|
||||||
|
versionConfiguration.getVersionVarName(),
|
||||||
|
ClassName.get(versionConfiguration.getPackage(basePackageName), "Version")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
var upgradeDataToLatestVersion1Method = upgradeDataToLatestVersion1MethodBuilder
|
||||||
|
.addStatement("default -> throw new $T(\"Unknown version: \" + oldVersion)", IOException.class)
|
||||||
|
.addCode(CodeBlock.of("$<});"))
|
||||||
|
.build();
|
||||||
|
currentVersionClass.addMethod(upgradeDataToLatestVersion1Method);
|
||||||
|
}
|
||||||
|
// UpgradeDataToLatestVersion2 Method
|
||||||
|
{
|
||||||
|
var versionsClassName = ClassName.get(dataModel.getRootPackage(basePackageName), "Versions");
|
||||||
|
var upgradeDataToLatestVersion2MethodBuilder = MethodSpec.methodBuilder("upgradeDataToLatestVersion")
|
||||||
|
.addModifiers(Modifier.PUBLIC).addModifiers(Modifier.STATIC).addModifiers(Modifier.FINAL).addTypeVariable(TypeVariableName.get("T"))
|
||||||
|
.addTypeVariable(TypeVariableName.get("U", ClassName.get(currentVersionDataPackage, "IBaseType")))
|
||||||
|
.returns(TypeVariableName.get("U"))
|
||||||
|
.addParameter(ParameterSpec.builder(TypeName.INT, "oldVersion").build())
|
||||||
|
.addParameter(ParameterSpec.builder(TypeVariableName.get("T"), "oldData").build())
|
||||||
|
.addException(IOException.class)
|
||||||
|
.addStatement("$T data = oldData", Object.class);
|
||||||
|
upgradeDataToLatestVersion2MethodBuilder.beginControlFlow("switch (oldVersion)");
|
||||||
|
for (var versionConfiguration : dataModel.getVersionsSet()) {
|
||||||
|
// Add a case in which the data version deserializes the serialized data and upgrades it
|
||||||
|
upgradeDataToLatestVersion2MethodBuilder.addCode("case $T.$N: ",
|
||||||
|
versionsClassName,
|
||||||
|
versionConfiguration.getVersionVarName()
|
||||||
|
);
|
||||||
|
if (versionConfiguration.isCurrent()) {
|
||||||
|
// This is the latest version, don't upgrade.
|
||||||
|
upgradeDataToLatestVersion2MethodBuilder.addStatement("return ($T) data", TypeVariableName.get("U"));
|
||||||
|
} else {
|
||||||
|
// Upgrade
|
||||||
|
ComputedVersion computedVersion = dataModel.getNextVersionOrThrow(versionConfiguration);
|
||||||
|
upgradeDataToLatestVersion2MethodBuilder
|
||||||
|
.addStatement(
|
||||||
|
"data = " + versionConfiguration.getPackage(basePackageName)
|
||||||
|
+ ".Version.upgradeToNextVersion(($T) data)",
|
||||||
|
ClassName.get(versionConfiguration.getDataPackage(basePackageName), "IBaseType")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
upgradeDataToLatestVersion2MethodBuilder.addStatement("default: throw new $T(\"Unknown version: \" + oldVersion)", IOException.class);
|
||||||
|
upgradeDataToLatestVersion2MethodBuilder.endControlFlow();
|
||||||
|
currentVersionClass.addMethod(upgradeDataToLatestVersion2MethodBuilder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
generateGetClass(dataModel.getCurrentVersion(), currentVersionClass);
|
||||||
|
|
||||||
|
return Stream.of(new GeneratedClass(dataModel.getCurrentVersion().getPackage(basePackageName), currentVersionClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateGetClass(ComputedVersion version, Builder classBuilder) {
|
||||||
|
var methodBuilder = MethodSpec.methodBuilder("getClass");
|
||||||
|
|
||||||
|
methodBuilder.addModifiers(Modifier.PUBLIC);
|
||||||
|
|
||||||
|
var baseTypeClassName = ClassName.get(dataModel.getRootPackage(basePackageName), "BaseType");
|
||||||
|
methodBuilder.addParameter(baseTypeClassName, "type");
|
||||||
|
|
||||||
|
var iBaseTypeClassName = ClassName.get(version.getDataPackage(basePackageName), "IBaseType");
|
||||||
|
methodBuilder.returns(ParameterizedTypeName.get(ClassName.get(Class.class), WildcardTypeName.subtypeOf(iBaseTypeClassName)));
|
||||||
|
|
||||||
|
methodBuilder.beginControlFlow("return switch (type)");
|
||||||
|
dataModel.getBaseTypesComputed(version).forEach(baseType -> {
|
||||||
|
methodBuilder.addStatement("case $N -> $T.class", baseType.getName(), baseType.getJTypeName(basePackageName));
|
||||||
|
});
|
||||||
|
methodBuilder.addCode(CodeBlock.of("$<};"));
|
||||||
|
classBuilder.addMethod(methodBuilder.build());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
package it.cavallium.data.generator.plugin.classgen;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.MethodSpec;
|
||||||
|
import com.squareup.javapoet.ParameterSpec;
|
||||||
|
import com.squareup.javapoet.TypeSpec;
|
||||||
|
import it.cavallium.data.generator.plugin.ClassGenerator;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedTypeBase;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedVersion;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class GenDataBaseX extends ClassGenerator {
|
||||||
|
|
||||||
|
public GenDataBaseX(ClassGeneratorParams params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stream<GeneratedClass> generateClasses() {
|
||||||
|
return dataModel.getVersionsSet().parallelStream().flatMap(this::generateVersionClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream<GeneratedClass> generateVersionClasses(ComputedVersion version) {
|
||||||
|
return dataModel
|
||||||
|
.getBaseTypesComputed(version)
|
||||||
|
.filter(type -> type.getVersion().equals(version))
|
||||||
|
.map(type -> generateTypeVersioned(version, type));
|
||||||
|
}
|
||||||
|
|
||||||
|
private GeneratedClass generateTypeVersioned(ComputedVersion version, ComputedTypeBase base) {
|
||||||
|
var type = (ClassName) base.getJTypeName(basePackageName);
|
||||||
|
var classBuilder = TypeSpec.recordBuilder(type.simpleName());
|
||||||
|
|
||||||
|
classBuilder.addModifiers(Modifier.PUBLIC);
|
||||||
|
|
||||||
|
var baseTypeClass = ClassName.get(dataModel.getRootPackage(basePackageName), "BaseType");
|
||||||
|
var iTypeClass = ClassName.get(version.getPackage(basePackageName), "IBaseType");
|
||||||
|
classBuilder.addSuperinterface(iTypeClass);
|
||||||
|
|
||||||
|
dataModel.getSuperTypesOf(base).forEach(superType -> {
|
||||||
|
classBuilder.addSuperinterface(superType.getJTypeName(basePackageName));
|
||||||
|
|
||||||
|
classBuilder.addMethod(MethodSpec
|
||||||
|
.methodBuilder("getMetaId$" + superType.getName())
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
||||||
|
.addAnnotation(Override.class)
|
||||||
|
.returns(int.class)
|
||||||
|
.addStatement("return " + superType.subTypes().indexOf(base))
|
||||||
|
.build());
|
||||||
|
});
|
||||||
|
|
||||||
|
var ofMethod = MethodSpec
|
||||||
|
.methodBuilder("of")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL);
|
||||||
|
|
||||||
|
base.getData().forEach((fieldName, fieldType) -> {
|
||||||
|
var fieldTypeName = fieldType.getJTypeName(basePackageName);
|
||||||
|
|
||||||
|
var param = ParameterSpec
|
||||||
|
.builder(fieldTypeName, fieldName)
|
||||||
|
.addAnnotation(NotNull.class)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ofMethod.addParameter(param);
|
||||||
|
classBuilder.addRecordComponent(param);
|
||||||
|
|
||||||
|
var setter = MethodSpec
|
||||||
|
.methodBuilder("set" + StringUtils.capitalize(fieldName))
|
||||||
|
.addModifiers(Modifier.PUBLIC)
|
||||||
|
.addParameter(ParameterSpec.builder(fieldTypeName, fieldName).addAnnotation(NotNull.class).build())
|
||||||
|
.addAnnotation(NotNull.class)
|
||||||
|
.returns(type);
|
||||||
|
|
||||||
|
if (!fieldTypeName.isPrimitive()) {
|
||||||
|
setter.addStatement("$T.requireNonNull($N)", Objects.class, fieldName);
|
||||||
|
}
|
||||||
|
if (fieldTypeName.isPrimitive() || !deepCheckBeforeCreatingNewEqualInstances) {
|
||||||
|
setter.addCode("return $N == this.$N ? this : new $T(", fieldName, fieldName, type);
|
||||||
|
setter.addCode(String.join(", ", base.getData().keySet()));
|
||||||
|
setter.addStatement(")");
|
||||||
|
} else {
|
||||||
|
setter.addCode("return $T.equals($N, this.$N) ? this : new $T(", Objects.class, fieldName, fieldName, type);
|
||||||
|
setter.addCode(String.join(", ", base.getData().keySet()));
|
||||||
|
setter.addStatement(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
classBuilder.addMethod(setter.build());
|
||||||
|
});
|
||||||
|
|
||||||
|
classBuilder.addMethod(MethodSpec
|
||||||
|
.methodBuilder("getBaseType$")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
||||||
|
.addAnnotation(Override.class)
|
||||||
|
.returns(baseTypeClass)
|
||||||
|
.addStatement("return $T.$N", baseTypeClass, base.getName())
|
||||||
|
.build());
|
||||||
|
|
||||||
|
ofMethod.addCode("return new $T(", type);
|
||||||
|
ofMethod.addCode(String.join(", ", base.getData().keySet()));
|
||||||
|
ofMethod.addStatement(")");
|
||||||
|
ofMethod.returns(type);
|
||||||
|
classBuilder.addMethod(ofMethod.build());
|
||||||
|
|
||||||
|
return new GeneratedClass(type.packageName(), classBuilder);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
package it.cavallium.data.generator.plugin.classgen;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.MethodSpec;
|
||||||
|
import com.squareup.javapoet.ParameterSpec;
|
||||||
|
import com.squareup.javapoet.TypeSpec;
|
||||||
|
import it.cavallium.data.generator.plugin.ClassGenerator;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedTypeSuper;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedVersion;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class GenDataSuperX extends ClassGenerator {
|
||||||
|
|
||||||
|
public GenDataSuperX(ClassGeneratorParams params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stream<GeneratedClass> generateClasses() {
|
||||||
|
return dataModel.getVersionsSet().parallelStream().flatMap(this::generateVersionClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream<GeneratedClass> generateVersionClasses(ComputedVersion version) {
|
||||||
|
return dataModel
|
||||||
|
.getSuperTypesComputed(version)
|
||||||
|
.filter(type -> type.getVersion().equals(version))
|
||||||
|
.map(type -> generateTypeVersioned(version, type));
|
||||||
|
}
|
||||||
|
|
||||||
|
private GeneratedClass generateTypeVersioned(ComputedVersion version, ComputedTypeSuper typeSuper) {
|
||||||
|
var type = (ClassName) typeSuper.getJTypeName(basePackageName);
|
||||||
|
var classBuilder = TypeSpec.interfaceBuilder(type.simpleName());
|
||||||
|
|
||||||
|
classBuilder.addModifiers(Modifier.PUBLIC);
|
||||||
|
|
||||||
|
var baseTypeClass = ClassName.get(dataModel.getRootPackage(basePackageName), "BaseType");
|
||||||
|
var iBaseTypeClass = ClassName.get(version.getPackage(basePackageName), "IBaseType");
|
||||||
|
classBuilder.addSuperinterface(iBaseTypeClass);
|
||||||
|
|
||||||
|
dataModel.getExtendsInterfaces(typeSuper).forEach(superType -> {
|
||||||
|
classBuilder.addSuperinterface(superType.getJTypeName(basePackageName));
|
||||||
|
});
|
||||||
|
|
||||||
|
Stream
|
||||||
|
.concat(dataModel.getCommonInterfaceData(typeSuper), dataModel.getCommonInterfaceGetters(typeSuper))
|
||||||
|
.forEach(superType -> {
|
||||||
|
var returnType = superType.getValue().getJTypeName(basePackageName);
|
||||||
|
var getter = MethodSpec
|
||||||
|
.methodBuilder(superType.getKey())
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
|
||||||
|
.returns(returnType);
|
||||||
|
if (!returnType.isPrimitive()) {
|
||||||
|
getter.addAnnotation(NotNull.class);
|
||||||
|
}
|
||||||
|
classBuilder.addMethod(getter.build());
|
||||||
|
});
|
||||||
|
|
||||||
|
dataModel.getCommonInterfaceData(typeSuper).forEach(superType -> {
|
||||||
|
var returnType = superType.getValue().getJTypeName(basePackageName);
|
||||||
|
|
||||||
|
var setter = MethodSpec
|
||||||
|
.methodBuilder("set" + StringUtils.capitalize(superType.getKey()))
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
|
||||||
|
.addParameter(ParameterSpec.builder(returnType, "value").addAnnotation(NotNull.class).build())
|
||||||
|
.addAnnotation(NotNull.class)
|
||||||
|
.returns(type);
|
||||||
|
classBuilder.addMethod(setter.build());
|
||||||
|
});
|
||||||
|
|
||||||
|
dataModel.getSuperTypesOf(typeSuper).forEach(superType -> {
|
||||||
|
classBuilder.addSuperinterface(superType.getJTypeName(basePackageName));
|
||||||
|
});
|
||||||
|
|
||||||
|
classBuilder.addMethod(MethodSpec
|
||||||
|
.methodBuilder("getMetaId$" + typeSuper.getName())
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
|
||||||
|
.returns(int.class)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
return new GeneratedClass(type.packageName(), classBuilder);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package it.cavallium.data.generator.plugin.classgen;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.MethodSpec;
|
||||||
|
import com.squareup.javapoet.TypeSpec;
|
||||||
|
import it.cavallium.data.generator.plugin.ClassGenerator;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedVersion;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
|
||||||
|
public class GenIBaseType extends ClassGenerator {
|
||||||
|
|
||||||
|
public GenIBaseType(ClassGeneratorParams params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stream<GeneratedClass> generateClasses() {
|
||||||
|
return dataModel.getVersionsSet().stream().map(this::generateClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GeneratedClass generateClass(ComputedVersion version) {
|
||||||
|
var interfaceBuilder = TypeSpec.interfaceBuilder("IBaseType");
|
||||||
|
|
||||||
|
interfaceBuilder.addModifiers(Modifier.PUBLIC);
|
||||||
|
|
||||||
|
var iTypeClassName = ClassName.get(version.getDataPackage(basePackageName), "IType");
|
||||||
|
var baseTypeClassName = ClassName.get(dataModel.getRootPackage(basePackageName), "BaseType");
|
||||||
|
interfaceBuilder.addSuperinterface(iTypeClassName);
|
||||||
|
|
||||||
|
interfaceBuilder.addMethod(MethodSpec
|
||||||
|
.methodBuilder("getBaseType$")
|
||||||
|
.addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC)
|
||||||
|
.returns(baseTypeClassName)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
return new GeneratedClass(version.getPackage(basePackageName), interfaceBuilder);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package it.cavallium.data.generator.plugin.classgen;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.MethodSpec;
|
||||||
|
import com.squareup.javapoet.TypeSpec;
|
||||||
|
import it.cavallium.data.generator.plugin.ClassGenerator;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedVersion;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
|
||||||
|
public class GenINullableBaseType extends ClassGenerator {
|
||||||
|
|
||||||
|
public GenINullableBaseType(ClassGeneratorParams params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stream<GeneratedClass> generateClasses() {
|
||||||
|
return dataModel.getVersionsSet().stream().map(this::generateClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GeneratedClass generateClass(ComputedVersion version) {
|
||||||
|
var interfaceBuilder = TypeSpec.interfaceBuilder("INullableBaseType");
|
||||||
|
|
||||||
|
interfaceBuilder.addModifiers(Modifier.PUBLIC);
|
||||||
|
|
||||||
|
var iNullableITypeClass = ClassName.get(version.getDataNullablesPackage(basePackageName), "INullableIType");
|
||||||
|
var baseTypeClass = ClassName.get(dataModel.getRootPackage(basePackageName), "BaseType");
|
||||||
|
interfaceBuilder.addSuperinterface(iNullableITypeClass);
|
||||||
|
|
||||||
|
interfaceBuilder.addMethod(MethodSpec
|
||||||
|
.methodBuilder("getBaseType$")
|
||||||
|
.addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC)
|
||||||
|
.returns(baseTypeClass)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
return new GeneratedClass(version.getDataNullablesPackage(basePackageName), interfaceBuilder);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package it.cavallium.data.generator.plugin.classgen;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.TypeSpec;
|
||||||
|
import it.cavallium.data.generator.nativedata.INullable;
|
||||||
|
import it.cavallium.data.generator.plugin.ClassGenerator;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedVersion;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
|
||||||
|
public class GenINullableIType extends ClassGenerator {
|
||||||
|
|
||||||
|
public GenINullableIType(ClassGeneratorParams params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stream<GeneratedClass> generateClasses() {
|
||||||
|
return dataModel.getVersionsSet().stream().map(this::generateClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GeneratedClass generateClass(ComputedVersion version) {
|
||||||
|
var interfaceBuilder = TypeSpec.interfaceBuilder("INullableIType");
|
||||||
|
|
||||||
|
interfaceBuilder.addModifiers(Modifier.PUBLIC);
|
||||||
|
|
||||||
|
var iTypeClass = ClassName.get(version.getPackage(basePackageName), "IType");
|
||||||
|
var iSuperNullableClass = ClassName.get(INullable.class);
|
||||||
|
interfaceBuilder.addSuperinterface(iTypeClass);
|
||||||
|
interfaceBuilder.addSuperinterface(iSuperNullableClass);
|
||||||
|
|
||||||
|
return new GeneratedClass(version.getDataNullablesPackage(basePackageName), interfaceBuilder);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package it.cavallium.data.generator.plugin.classgen;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.MethodSpec;
|
||||||
|
import com.squareup.javapoet.TypeSpec;
|
||||||
|
import it.cavallium.data.generator.plugin.ClassGenerator;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedVersion;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
|
||||||
|
public class GenINullableSuperType extends ClassGenerator {
|
||||||
|
|
||||||
|
public GenINullableSuperType(ClassGeneratorParams params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stream<GeneratedClass> generateClasses() {
|
||||||
|
return dataModel.getVersionsSet().stream().map(this::generateClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GeneratedClass generateClass(ComputedVersion version) {
|
||||||
|
var interfaceBuilder = TypeSpec.interfaceBuilder("INullableSuperType");
|
||||||
|
|
||||||
|
interfaceBuilder.addModifiers(Modifier.PUBLIC);
|
||||||
|
|
||||||
|
var iNullableITypeClass = ClassName.get(version.getDataNullablesPackage(basePackageName), "INullableIType");
|
||||||
|
var superTypeClass = ClassName.get(dataModel.getRootPackage(basePackageName), "SuperType");
|
||||||
|
interfaceBuilder.addSuperinterface(iNullableITypeClass);
|
||||||
|
|
||||||
|
interfaceBuilder.addMethod(MethodSpec
|
||||||
|
.methodBuilder("getSuperType$")
|
||||||
|
.addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC)
|
||||||
|
.returns(superTypeClass)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
return new GeneratedClass(version.getDataNullablesPackage(basePackageName), interfaceBuilder);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package it.cavallium.data.generator.plugin.classgen;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.TypeSpec;
|
||||||
|
import it.cavallium.data.generator.plugin.ClassGenerator;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedVersion;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
|
||||||
|
public class GenIType extends ClassGenerator {
|
||||||
|
|
||||||
|
public GenIType(ClassGeneratorParams params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stream<GeneratedClass> generateClasses() {
|
||||||
|
return dataModel.getVersionsSet().stream().map(this::generateClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GeneratedClass generateClass(ComputedVersion version) {
|
||||||
|
var interfaceBuilder = TypeSpec.interfaceBuilder("IType");
|
||||||
|
|
||||||
|
interfaceBuilder.addModifiers(Modifier.PUBLIC);
|
||||||
|
|
||||||
|
interfaceBuilder.addSuperinterface(ClassName.get(Serializable.class));
|
||||||
|
|
||||||
|
return new GeneratedClass(version.getPackage(basePackageName), interfaceBuilder);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package it.cavallium.data.generator.plugin.classgen;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.MethodSpec;
|
||||||
|
import com.squareup.javapoet.ParameterSpec;
|
||||||
|
import com.squareup.javapoet.ParameterizedTypeName;
|
||||||
|
import com.squareup.javapoet.TypeName;
|
||||||
|
import com.squareup.javapoet.TypeSpec;
|
||||||
|
import com.squareup.javapoet.TypeVariableName;
|
||||||
|
import com.squareup.javapoet.WildcardTypeName;
|
||||||
|
import it.cavallium.data.generator.DataSerializer;
|
||||||
|
import it.cavallium.data.generator.plugin.ClassGenerator;
|
||||||
|
import it.cavallium.data.generator.plugin.ClassGenerator.ClassGeneratorParams;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
|
||||||
|
public class GenIVersion extends ClassGenerator {
|
||||||
|
|
||||||
|
public GenIVersion(ClassGeneratorParams params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stream<GeneratedClass> generateClasses() {
|
||||||
|
var iVersionClass = TypeSpec.interfaceBuilder("IVersion");
|
||||||
|
iVersionClass.addModifiers(Modifier.PUBLIC);
|
||||||
|
iVersionClass.addTypeVariable(TypeVariableName.get("B"));
|
||||||
|
|
||||||
|
// Add getClass method
|
||||||
|
{
|
||||||
|
var getClassMethodBuilder = MethodSpec
|
||||||
|
.methodBuilder("getClass")
|
||||||
|
.addModifiers(Modifier.PUBLIC)
|
||||||
|
.addModifiers(Modifier.ABSTRACT)
|
||||||
|
.returns(ParameterizedTypeName.get(ClassName.get(Class.class),
|
||||||
|
WildcardTypeName.subtypeOf(TypeVariableName.get("B"))
|
||||||
|
))
|
||||||
|
.addParameter(ParameterSpec
|
||||||
|
.builder(ClassName.get(dataModel.getRootPackage(basePackageName), "BaseType"), "type")
|
||||||
|
.build());
|
||||||
|
iVersionClass.addMethod(getClassMethodBuilder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add getSerializer method
|
||||||
|
{
|
||||||
|
var getSerializerMethodBuilder = MethodSpec
|
||||||
|
.methodBuilder("getSerializer")
|
||||||
|
.addModifiers(Modifier.PUBLIC)
|
||||||
|
.addModifiers(Modifier.ABSTRACT)
|
||||||
|
.addTypeVariable(TypeVariableName.get("T",
|
||||||
|
TypeVariableName.get("B")
|
||||||
|
))
|
||||||
|
.returns(ParameterizedTypeName.get(ClassName.get(DataSerializer.class), TypeVariableName.get("T")))
|
||||||
|
.addException(IOException.class)
|
||||||
|
.addParameter(ParameterSpec
|
||||||
|
.builder(ClassName.get(dataModel.getRootPackage(basePackageName), "BaseType"), "type")
|
||||||
|
.build());
|
||||||
|
iVersionClass.addMethod(getSerializerMethodBuilder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add getVersion method
|
||||||
|
{
|
||||||
|
var getVersionMethod = MethodSpec
|
||||||
|
.methodBuilder("getVersion")
|
||||||
|
.addModifiers(Modifier.PUBLIC)
|
||||||
|
.addModifiers(Modifier.ABSTRACT)
|
||||||
|
.returns(TypeName.INT)
|
||||||
|
.build();
|
||||||
|
iVersionClass.addMethod(getVersionMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Stream.of(new GeneratedClass(dataModel.getRootPackage(basePackageName), iVersionClass));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,137 @@
|
|||||||
|
package it.cavallium.data.generator.plugin.classgen;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.FieldSpec;
|
||||||
|
import com.squareup.javapoet.MethodSpec;
|
||||||
|
import com.squareup.javapoet.ParameterSpec;
|
||||||
|
import com.squareup.javapoet.ParameterizedTypeName;
|
||||||
|
import com.squareup.javapoet.TypeSpec;
|
||||||
|
import it.cavallium.data.generator.TypedNullable;
|
||||||
|
import it.cavallium.data.generator.nativedata.INullable;
|
||||||
|
import it.cavallium.data.generator.plugin.ClassGenerator;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedTypeBase;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedTypeNullableVersioned;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedTypeSuper;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedVersion;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class GenNullableX extends ClassGenerator {
|
||||||
|
|
||||||
|
public GenNullableX(ClassGeneratorParams params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stream<GeneratedClass> generateClasses() {
|
||||||
|
return dataModel.getVersionsSet().parallelStream().flatMap(this::generateVersionClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream<GeneratedClass> generateVersionClasses(ComputedVersion version) {
|
||||||
|
return dataModel
|
||||||
|
.getComputedTypes(version)
|
||||||
|
.values()
|
||||||
|
.stream()
|
||||||
|
.filter(type -> type instanceof ComputedTypeNullableVersioned)
|
||||||
|
.map(type -> (ComputedTypeNullableVersioned) type)
|
||||||
|
.filter(type -> type.getVersion().equals(version))
|
||||||
|
.map(type -> generateTypeVersioned(version, type));
|
||||||
|
}
|
||||||
|
|
||||||
|
private GeneratedClass generateTypeVersioned(ComputedVersion version, ComputedTypeNullableVersioned computedType) {
|
||||||
|
var type = (ClassName) computedType.getJTypeName(basePackageName);
|
||||||
|
var classBuilder = TypeSpec.recordBuilder(type.simpleName());
|
||||||
|
|
||||||
|
var base = computedType.getBase();
|
||||||
|
var baseType = base.getJTypeName(basePackageName);
|
||||||
|
|
||||||
|
classBuilder.addModifiers(Modifier.PUBLIC);
|
||||||
|
classBuilder.addRecordComponent(ParameterSpec.builder(baseType, "value").build());
|
||||||
|
|
||||||
|
var iNullableITypeClass = ClassName.get(version.getDataNullablesPackage(basePackageName), "INullableIType");
|
||||||
|
var iNullableClass = ClassName.get(INullable.class);
|
||||||
|
var typedNullable = ParameterizedTypeName.get(ClassName.get(TypedNullable.class), baseType);
|
||||||
|
|
||||||
|
if (base instanceof ComputedTypeSuper computedTypeSuper) {
|
||||||
|
var iNullableSuperTypeClass = ClassName.get(version.getDataNullablesPackage(basePackageName), "INullableSuperType");
|
||||||
|
var superTypeClass = ClassName.get(dataModel.getRootPackage(basePackageName), "SuperType");
|
||||||
|
classBuilder.addSuperinterface(iNullableSuperTypeClass);
|
||||||
|
|
||||||
|
classBuilder.addMethod(MethodSpec
|
||||||
|
.methodBuilder("getSuperType$")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
||||||
|
.returns(superTypeClass)
|
||||||
|
.addStatement("return $T.$N", superTypeClass, base.getName())
|
||||||
|
.build());
|
||||||
|
} else if (base instanceof ComputedTypeBase computedTypeBase) {
|
||||||
|
var iNullableBaseTypeClass = ClassName.get(version.getDataNullablesPackage(basePackageName), "INullableBaseType");
|
||||||
|
var baseTypeClass = ClassName.get(dataModel.getRootPackage(basePackageName), "BaseType");
|
||||||
|
classBuilder.addSuperinterface(iNullableBaseTypeClass);
|
||||||
|
|
||||||
|
classBuilder.addMethod(MethodSpec
|
||||||
|
.methodBuilder("getBaseType$")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
||||||
|
.returns(baseTypeClass)
|
||||||
|
.addStatement("return $T.$N", baseTypeClass, base.getName())
|
||||||
|
.build());
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version.isCurrent()) {
|
||||||
|
classBuilder.addSuperinterfaces(List.of(iNullableITypeClass, iNullableClass, typedNullable));
|
||||||
|
|
||||||
|
classBuilder.addField(FieldSpec.builder(type, "NULL").addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL).initializer("new $T(($T)null)", type, baseType).build());
|
||||||
|
|
||||||
|
classBuilder.addMethod(MethodSpec
|
||||||
|
.methodBuilder("of")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
|
||||||
|
.addParameter(ParameterSpec.builder(baseType, "value").build())
|
||||||
|
.addException(ClassName.get(NullPointerException.class))
|
||||||
|
.returns(type)
|
||||||
|
.beginControlFlow("if (value != null)")
|
||||||
|
.addStatement("return new $T(value)", type)
|
||||||
|
.nextControlFlow("else")
|
||||||
|
.addStatement("throw new $T()", NullPointerException.class)
|
||||||
|
.endControlFlow()
|
||||||
|
.build());
|
||||||
|
|
||||||
|
classBuilder.addMethod(MethodSpec
|
||||||
|
.methodBuilder("ofNullable")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
|
||||||
|
.addParameter(ParameterSpec.builder(baseType, "value").build())
|
||||||
|
.returns(type)
|
||||||
|
.addStatement("return value != null ? new $T(value) : NULL", type)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
classBuilder.addMethod(MethodSpec
|
||||||
|
.methodBuilder("empty")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
|
||||||
|
.returns(type)
|
||||||
|
.addStatement("return NULL")
|
||||||
|
.build());
|
||||||
|
|
||||||
|
classBuilder.addMethod(MethodSpec
|
||||||
|
.methodBuilder("or")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
||||||
|
.addAnnotation(NotNull.class)
|
||||||
|
.returns(type)
|
||||||
|
.addParameter(ParameterSpec.builder(type, "fallback").addAnnotation(NotNull.class).build())
|
||||||
|
.addStatement("return this.value == null ? fallback : this")
|
||||||
|
.build());
|
||||||
|
|
||||||
|
classBuilder.addMethod(MethodSpec
|
||||||
|
.methodBuilder("getNullable")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
||||||
|
.addAnnotation(Nullable.class)
|
||||||
|
.returns(baseType)
|
||||||
|
.addStatement("return this.value")
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new GeneratedClass(type.packageName(), classBuilder);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package it.cavallium.data.generator.plugin.classgen;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.TypeSpec;
|
||||||
|
import it.cavallium.data.generator.plugin.ClassGenerator;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
|
||||||
|
public class GenSuperType extends ClassGenerator {
|
||||||
|
|
||||||
|
public GenSuperType(ClassGeneratorParams params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stream<GeneratedClass> generateClasses() {
|
||||||
|
var superTypeClass = TypeSpec.enumBuilder("SuperType");
|
||||||
|
superTypeClass.addModifiers(Modifier.PUBLIC);
|
||||||
|
dataModel.getSuperTypesComputed().forEach(superType -> superTypeClass.addEnumConstant(superType.getName()));
|
||||||
|
return Stream.of(new GeneratedClass(dataModel.getRootPackage(basePackageName), superTypeClass));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,228 @@
|
|||||||
|
package it.cavallium.data.generator.plugin.classgen;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.CodeBlock;
|
||||||
|
import com.squareup.javapoet.FieldSpec;
|
||||||
|
import com.squareup.javapoet.MethodSpec;
|
||||||
|
import com.squareup.javapoet.ParameterizedTypeName;
|
||||||
|
import com.squareup.javapoet.TypeName;
|
||||||
|
import com.squareup.javapoet.TypeSpec;
|
||||||
|
import com.squareup.javapoet.TypeSpec.Builder;
|
||||||
|
import com.squareup.javapoet.TypeVariableName;
|
||||||
|
import it.cavallium.data.generator.DataSerializer;
|
||||||
|
import it.cavallium.data.generator.plugin.ClassGenerator;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedType.VersionedComputedType;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedTypeCustom;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedVersion;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
|
||||||
|
public class GenVersion extends ClassGenerator {
|
||||||
|
|
||||||
|
private static final boolean STRICT_SWITCH = false;
|
||||||
|
|
||||||
|
public GenVersion(ClassGeneratorParams params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stream<GeneratedClass> generateClasses() {
|
||||||
|
return dataModel.getVersionsSet().stream().map(this::generateClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GeneratedClass generateClass(ComputedVersion version) {
|
||||||
|
var classBuilder = TypeSpec.classBuilder("Version");
|
||||||
|
|
||||||
|
classBuilder.addModifiers(Modifier.PUBLIC, Modifier.FINAL);
|
||||||
|
|
||||||
|
var iVersionClassName = ClassName.get(dataModel.getRootPackage(basePackageName), "IVersion");
|
||||||
|
var iBaseTypeClassName = ClassName.get(version.getDataPackage(basePackageName), "IBaseType");
|
||||||
|
classBuilder.addSuperinterface(ParameterizedTypeName.get(iVersionClassName, iBaseTypeClassName));
|
||||||
|
|
||||||
|
generateVersionField(version, classBuilder);
|
||||||
|
|
||||||
|
generateInstanceField(version, classBuilder);
|
||||||
|
|
||||||
|
generateUpgradeToNextVersion(version, classBuilder);
|
||||||
|
|
||||||
|
generateSerializerInstance(version, classBuilder);
|
||||||
|
|
||||||
|
generateUpgraderInstance(version, classBuilder);
|
||||||
|
|
||||||
|
generateGetSerializer(version, classBuilder);
|
||||||
|
|
||||||
|
generateGetVersion(version, classBuilder);
|
||||||
|
|
||||||
|
return new GeneratedClass(version.getPackage(basePackageName), classBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a static variable for the current version
|
||||||
|
*/
|
||||||
|
private void generateVersionField(ComputedVersion version, Builder classBuilder) {
|
||||||
|
var versionNumberXField = FieldSpec
|
||||||
|
.builder(TypeName.INT, "VERSION")
|
||||||
|
.addModifiers(Modifier.PUBLIC)
|
||||||
|
.addModifiers(Modifier.STATIC)
|
||||||
|
.addModifiers(Modifier.FINAL)
|
||||||
|
.initializer("$T." + version.getVersionVarName(),
|
||||||
|
ClassName.get(dataModel.getRootPackage(basePackageName), "Versions")
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
classBuilder.addField(versionNumberXField);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a static instance for the current version
|
||||||
|
*/
|
||||||
|
private void generateInstanceField(ComputedVersion version, Builder classBuilder) {
|
||||||
|
var versionClassType = ClassName.get(version.getPackage(basePackageName), "Version");
|
||||||
|
var versionInstanceField = FieldSpec
|
||||||
|
.builder(versionClassType, "INSTANCE")
|
||||||
|
.addModifiers(Modifier.PUBLIC)
|
||||||
|
.addModifiers(Modifier.STATIC)
|
||||||
|
.addModifiers(Modifier.FINAL)
|
||||||
|
.initializer("new $T()", versionClassType)
|
||||||
|
.build();
|
||||||
|
classBuilder.addField(versionInstanceField);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateUpgradeToNextVersion(ComputedVersion version, Builder classBuilder) {
|
||||||
|
var nextVersion = dataModel.getNextVersion(version).orElse(null);
|
||||||
|
|
||||||
|
// Skip upgrade if it's the latest version
|
||||||
|
if (nextVersion == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var methodBuilder = MethodSpec.methodBuilder("upgradeToNextVersion");
|
||||||
|
|
||||||
|
methodBuilder.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL);
|
||||||
|
methodBuilder.addException(ClassName.get(IOException.class));
|
||||||
|
|
||||||
|
var nextIBaseType = ClassName.get(nextVersion.getDataPackage(basePackageName), "IBaseType");
|
||||||
|
methodBuilder.returns(nextIBaseType);
|
||||||
|
|
||||||
|
var iBaseTypeClassName = ClassName.get(version.getDataPackage(basePackageName), "IBaseType");
|
||||||
|
methodBuilder.addParameter(iBaseTypeClassName, "oldData");
|
||||||
|
|
||||||
|
methodBuilder.beginControlFlow( "return switch (oldData.getBaseType$$())");
|
||||||
|
dataModel.getBaseTypesComputed(version).forEach(baseType -> {
|
||||||
|
if (baseType.shouldUpgradeAfter(version)) {
|
||||||
|
var nextBaseType = dataModel.getNextVersion(baseType);
|
||||||
|
var versionType = ClassName.get(baseType.getVersion().getPackage(basePackageName), "Version");
|
||||||
|
methodBuilder.addStatement("case $N -> ($T) $T.$NUpgraderInstance.upgrade(($T) oldData)",
|
||||||
|
baseType.getName(),
|
||||||
|
nextBaseType.getJTypeName(basePackageName),
|
||||||
|
versionType,
|
||||||
|
baseType.getName(),
|
||||||
|
baseType.getJTypeName(basePackageName)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (STRICT_SWITCH) {
|
||||||
|
methodBuilder.addStatement("case $N -> ($T) oldData",
|
||||||
|
baseType.getName(),
|
||||||
|
baseType.getJTypeName(basePackageName)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!STRICT_SWITCH) {
|
||||||
|
methodBuilder.addStatement("default -> ($T) oldData", nextIBaseType);
|
||||||
|
}
|
||||||
|
methodBuilder.addCode(CodeBlock.of("$<};"));
|
||||||
|
classBuilder.addMethod(methodBuilder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateSerializerInstance(ComputedVersion version, Builder classBuilder) {
|
||||||
|
var versionClassType = ClassName.get(version.getPackage(basePackageName), "Version");
|
||||||
|
dataModel.getComputedTypes(version).forEach((typeName, type) -> {
|
||||||
|
boolean shouldCreateInstanceField;
|
||||||
|
// Check if the type matches the current version
|
||||||
|
shouldCreateInstanceField = type instanceof VersionedComputedType versionedComputedType
|
||||||
|
&& versionedComputedType.getVersion().equals(version);
|
||||||
|
|
||||||
|
// Check if the type is custom, and this is the latest version
|
||||||
|
shouldCreateInstanceField |= version.isCurrent() && type instanceof ComputedTypeCustom;
|
||||||
|
|
||||||
|
if (!shouldCreateInstanceField) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var serializerFieldLocation = type.getJSerializerInstance(basePackageName);
|
||||||
|
if (!versionClassType.equals(serializerFieldLocation.className())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var serializerClassName = type.getJSerializerName(basePackageName);
|
||||||
|
|
||||||
|
var fieldBuilder = FieldSpec.builder(ParameterizedTypeName.get(ClassName.get(DataSerializer.class),
|
||||||
|
type.getJTypeName(basePackageName)
|
||||||
|
), serializerFieldLocation.fieldName(), Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL);
|
||||||
|
fieldBuilder.initializer("new $T()", serializerClassName);
|
||||||
|
classBuilder.addField(fieldBuilder.build());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateUpgraderInstance(ComputedVersion version, Builder classBuilder) {
|
||||||
|
var versionClassType = ClassName.get(version.getPackage(basePackageName), "Version");
|
||||||
|
dataModel.getComputedTypes(version).forEach((typeName, type) -> {
|
||||||
|
boolean shouldCreateInstanceField = type instanceof VersionedComputedType versionedComputedType
|
||||||
|
&& versionedComputedType.getVersion().equals(version);
|
||||||
|
if (!shouldCreateInstanceField) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var upgraderFieldLocation = type.getJUpgraderInstance(basePackageName);
|
||||||
|
if (!versionClassType.equals(upgraderFieldLocation.className())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var upgraderClassName = type.getJUpgraderName(basePackageName);
|
||||||
|
|
||||||
|
var fieldBuilder = FieldSpec.builder(upgraderClassName,
|
||||||
|
upgraderFieldLocation.fieldName(),
|
||||||
|
Modifier.PUBLIC,
|
||||||
|
Modifier.STATIC,
|
||||||
|
Modifier.FINAL
|
||||||
|
);
|
||||||
|
fieldBuilder.initializer("new $T()", upgraderClassName);
|
||||||
|
classBuilder.addField(fieldBuilder.build());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateGetSerializer(ComputedVersion version, Builder classBuilder) {
|
||||||
|
var methodBuilder = MethodSpec.methodBuilder("getSerializer");
|
||||||
|
|
||||||
|
methodBuilder.addModifiers(Modifier.PUBLIC);
|
||||||
|
methodBuilder.addAnnotation(Override.class);
|
||||||
|
methodBuilder.addException(ClassName.get(IOException.class));
|
||||||
|
|
||||||
|
var iBaseTypeClassName = ClassName.get(version.getDataPackage(basePackageName), "IBaseType");
|
||||||
|
methodBuilder.addTypeVariable(TypeVariableName.get("T", iBaseTypeClassName));
|
||||||
|
|
||||||
|
var baseTypeClassName = ClassName.get(dataModel.getRootPackage(basePackageName), "BaseType");
|
||||||
|
methodBuilder.addParameter(baseTypeClassName, "type");
|
||||||
|
|
||||||
|
methodBuilder.returns(ParameterizedTypeName.get(ClassName.get(DataSerializer.class), TypeVariableName.get("T")));
|
||||||
|
|
||||||
|
methodBuilder.beginControlFlow("return switch (type)");
|
||||||
|
dataModel.getBaseTypesComputed(version).forEach(baseType -> {
|
||||||
|
var field = baseType.getJSerializerInstance(basePackageName);
|
||||||
|
methodBuilder.addStatement("case $N -> $T.$N", baseType.getName(), field.className(), field.fieldName());
|
||||||
|
});
|
||||||
|
methodBuilder.addCode(CodeBlock.of("$<};"));
|
||||||
|
classBuilder.addMethod(methodBuilder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateGetVersion(ComputedVersion version, Builder classBuilder) {
|
||||||
|
classBuilder.addMethod(MethodSpec
|
||||||
|
.methodBuilder("getVersion")
|
||||||
|
.addModifiers(Modifier.PUBLIC)
|
||||||
|
.returns(int.class)
|
||||||
|
.addStatement("return VERSION")
|
||||||
|
.addAnnotation(Override.class)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package it.cavallium.data.generator.plugin.classgen;
|
||||||
|
|
||||||
|
import com.squareup.javapoet.ArrayTypeName;
|
||||||
|
import com.squareup.javapoet.ClassName;
|
||||||
|
import com.squareup.javapoet.CodeBlock;
|
||||||
|
import com.squareup.javapoet.FieldSpec;
|
||||||
|
import com.squareup.javapoet.TypeName;
|
||||||
|
import com.squareup.javapoet.TypeSpec;
|
||||||
|
import it.cavallium.data.generator.plugin.ClassGenerator;
|
||||||
|
import it.cavallium.data.generator.plugin.ComputedVersion;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
|
||||||
|
public class GenVersions extends ClassGenerator {
|
||||||
|
|
||||||
|
public GenVersions(ClassGeneratorParams params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Stream<GeneratedClass> generateClasses() {
|
||||||
|
var versionsClass = TypeSpec.classBuilder("Versions");
|
||||||
|
versionsClass.addModifiers(Modifier.PUBLIC);
|
||||||
|
versionsClass.addModifiers(Modifier.FINAL);
|
||||||
|
var versionsInstances = FieldSpec.builder(ArrayTypeName.of(ClassName.get(dataModel.getRootPackage(basePackageName), "IVersion")),
|
||||||
|
"VERSIONS",
|
||||||
|
Modifier.PUBLIC,
|
||||||
|
Modifier.STATIC,
|
||||||
|
Modifier.FINAL
|
||||||
|
);
|
||||||
|
List<CodeBlock> versionsInstancesValue = new ArrayList<>();
|
||||||
|
for (ComputedVersion version : dataModel.getVersionsSet()) {
|
||||||
|
// Add a static variable for this version, containing the normalized version number
|
||||||
|
var versionNumberField = FieldSpec
|
||||||
|
.builder(TypeName.INT, version.getVersionVarName())
|
||||||
|
.addModifiers(Modifier.PUBLIC)
|
||||||
|
.addModifiers(Modifier.STATIC)
|
||||||
|
.addModifiers(Modifier.FINAL)
|
||||||
|
.initializer(version.getVersionShortInt())
|
||||||
|
.build();
|
||||||
|
// Add the fields to the class
|
||||||
|
versionsClass.addField(versionNumberField);
|
||||||
|
|
||||||
|
var versionPackage = version.getPackage(basePackageName);
|
||||||
|
var versionClassType = ClassName.get(versionPackage, "Version");
|
||||||
|
|
||||||
|
versionsInstancesValue.add(CodeBlock.builder().add("$T.INSTANCE", versionClassType).build());
|
||||||
|
}
|
||||||
|
versionsInstances.initializer(CodeBlock
|
||||||
|
.builder()
|
||||||
|
.add("{\n")
|
||||||
|
.add(CodeBlock.join(versionsInstancesValue, ",\n"))
|
||||||
|
.add("\n}")
|
||||||
|
.build());
|
||||||
|
versionsClass.addField(versionsInstances.build());
|
||||||
|
return Stream.of(new GeneratedClass(dataModel.getRootPackage(basePackageName), versionsClass));
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
package it.cavallium.data.generator.plugin;
|
package it.cavallium.data.generator.plugin;
|
||||||
|
|
||||||
import it.cavallium.data.generator.plugin.SourcesGenerator;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Path;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class TestGenerator {
|
public class TestGenerator {
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ public class TestGenerator {
|
|||||||
public void test() throws IOException {
|
public void test() throws IOException {
|
||||||
var dir = Files.createTempDirectory("data-generator-test");
|
var dir = Files.createTempDirectory("data-generator-test");
|
||||||
try {
|
try {
|
||||||
SourcesGenerator.load(this.getClass().getResourceAsStream("/test.yaml")).generateSources("it.test", dir, false);
|
SourcesGenerator.load(this.getClass().getResourceAsStream("/test.yaml")).generateSources("it.test", dir, false, true, false);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
FileUtils.deleteDirectory(dir.toFile());
|
FileUtils.deleteDirectory(dir.toFile());
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package it.cavallium.data.generator.nativedata;
|
||||||
|
|
||||||
|
public class Serializers {
|
||||||
|
public static final StringSerializer StringSerializerInstance = new StringSerializer();
|
||||||
|
public static final Int52Serializer Int52SerializerInstance = new Int52Serializer();
|
||||||
|
|
||||||
|
public static final NullableStringSerializer NullableStringSerializerInstance = new NullableStringSerializer();
|
||||||
|
public static final NullableInt52Serializer NullableInt52SerializerInstance = new NullableInt52Serializer();
|
||||||
|
public static final NullablebooleanSerializer NullablebooleanSerializerInstance = new NullablebooleanSerializer();
|
||||||
|
public static final NullablebyteSerializer NullablebyteSerializerInstance = new NullablebyteSerializer();
|
||||||
|
public static final NullableshortSerializer NullableshortSerializerInstance = new NullableshortSerializer();
|
||||||
|
public static final NullablecharSerializer NullablecharSerializerInstance = new NullablecharSerializer();
|
||||||
|
public static final NullableintSerializer NullableintSerializerInstance = new NullableintSerializer();
|
||||||
|
public static final NullablelongSerializer NullablelongSerializerInstance = new NullablelongSerializer();
|
||||||
|
public static final NullablefloatSerializer NullablefloatSerializerInstance = new NullablefloatSerializer();
|
||||||
|
public static final NullabledoubleSerializer NullabledoubleSerializer = new NullabledoubleSerializer();
|
||||||
|
|
||||||
|
public static final ArrayStringSerializer ArrayStringSerializerInstance = new ArrayStringSerializer();
|
||||||
|
public static final ArrayInt52Serializer ArrayInt52SerializerInstance = new ArrayInt52Serializer();
|
||||||
|
public static final ArraybooleanSerializer ArraybooleanSerializerInstance = new ArraybooleanSerializer();
|
||||||
|
public static final ArraybyteSerializer ArraybyteSerializerInstance = new ArraybyteSerializer();
|
||||||
|
public static final ArrayshortSerializer ArrayshortSerializerInstance = new ArrayshortSerializer();
|
||||||
|
public static final ArraycharSerializer ArraycharSerializerInstance = new ArraycharSerializer();
|
||||||
|
public static final ArrayintSerializer ArrayintSerializerInstance = new ArrayintSerializer();
|
||||||
|
public static final ArraylongSerializer ArraylongSerializerInstance = new ArraylongSerializer();
|
||||||
|
public static final ArrayfloatSerializer ArrayfloatSerializerInstance = new ArrayfloatSerializer();
|
||||||
|
public static final ArraydoubleSerializer ArraydoubleSerializer = new ArraydoubleSerializer();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user