mirror of
https://github.com/usatiuk/dhfs.git
synced 2025-10-29 04:57:48 +01:00
seemingly working object allocator generator
This commit is contained in:
@@ -22,10 +22,6 @@
|
|||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>io.quarkus</groupId>
|
|
||||||
<artifactId>quarkus-resteasy-reactive</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.usatiuk</groupId>
|
<groupId>com.usatiuk</groupId>
|
||||||
<artifactId>autoprotomap</artifactId>
|
<artifactId>autoprotomap</artifactId>
|
||||||
@@ -41,11 +37,6 @@
|
|||||||
<artifactId>quarkus-junit5</artifactId>
|
<artifactId>quarkus-junit5</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>io.rest-assured</groupId>
|
|
||||||
<artifactId>rest-assured</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.quarkus</groupId>
|
<groupId>io.quarkus</groupId>
|
||||||
<artifactId>quarkus-grpc</artifactId>
|
<artifactId>quarkus-grpc</artifactId>
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
* (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.usatiuk.autoprotomap.it;
|
|
||||||
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
|
||||||
import jakarta.ws.rs.GET;
|
|
||||||
import jakarta.ws.rs.Path;
|
|
||||||
|
|
||||||
@Path("/autoprotomap")
|
|
||||||
@ApplicationScoped
|
|
||||||
public class AutoprotomapResource {
|
|
||||||
// add some rest methods here
|
|
||||||
|
|
||||||
@GET
|
|
||||||
public String hello() {
|
|
||||||
return "Hello autoprotomap";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -21,6 +21,11 @@
|
|||||||
<artifactId>objects-alloc</artifactId>
|
<artifactId>objects-alloc</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.usatiuk</groupId>
|
||||||
|
<artifactId>objects-common-deployment</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.quarkus</groupId>
|
<groupId>io.quarkus</groupId>
|
||||||
<artifactId>quarkus-junit5-internal</artifactId>
|
<artifactId>quarkus-junit5-internal</artifactId>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.usatiuk.objects.alloc.deployment;
|
package com.usatiuk.objects.alloc.deployment;
|
||||||
|
|
||||||
import org.jboss.jandex.Type;
|
import org.jboss.jandex.DotName;
|
||||||
|
|
||||||
public record JDataFieldInfo(String name, Type type) {
|
public record JDataFieldInfo(String name, DotName type) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
package com.usatiuk.objects.alloc.deployment;
|
|
||||||
|
|
||||||
import org.jboss.jandex.ClassInfo;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public record JDataInfo(ClassInfo klass, Map<String, JDataFieldInfo> fields) {
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.usatiuk.objects.alloc.deployment;
|
||||||
|
|
||||||
|
import io.quarkus.builder.item.MultiBuildItem;
|
||||||
|
import org.jboss.jandex.ClassInfo;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public final class JDataInfoBuildItem extends MultiBuildItem {
|
||||||
|
public final ClassInfo klass;
|
||||||
|
public final Map<String, JDataFieldInfo> fields;
|
||||||
|
|
||||||
|
public JDataInfoBuildItem(ClassInfo klass, Map<String, JDataFieldInfo> fields) {
|
||||||
|
this.klass = klass;
|
||||||
|
this.fields = fields;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,25 +1,28 @@
|
|||||||
package com.usatiuk.objects.alloc.deployment;
|
package com.usatiuk.objects.alloc.deployment;
|
||||||
|
|
||||||
import com.usatiuk.objects.alloc.runtime.ObjectAllocator;
|
import com.usatiuk.objects.alloc.runtime.ObjectAllocator;
|
||||||
import com.usatiuk.objects.common.JData;
|
import com.usatiuk.objects.common.runtime.JData;
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
import com.usatiuk.objects.common.runtime.JObjectKey;
|
||||||
import io.quarkus.arc.deployment.GeneratedBeanBuildItem;
|
import io.quarkus.arc.deployment.GeneratedBeanBuildItem;
|
||||||
import io.quarkus.arc.deployment.GeneratedBeanGizmoAdaptor;
|
import io.quarkus.arc.deployment.GeneratedBeanGizmoAdaptor;
|
||||||
|
import io.quarkus.deployment.GeneratedClassGizmoAdaptor;
|
||||||
import io.quarkus.deployment.annotations.BuildProducer;
|
import io.quarkus.deployment.annotations.BuildProducer;
|
||||||
import io.quarkus.deployment.annotations.BuildStep;
|
import io.quarkus.deployment.annotations.BuildStep;
|
||||||
import io.quarkus.deployment.builditem.ApplicationIndexBuildItem;
|
import io.quarkus.deployment.builditem.ApplicationIndexBuildItem;
|
||||||
import io.quarkus.deployment.builditem.GeneratedClassBuildItem;
|
import io.quarkus.deployment.builditem.GeneratedClassBuildItem;
|
||||||
import io.quarkus.gizmo.*;
|
import io.quarkus.gizmo.*;
|
||||||
import jakarta.inject.Singleton;
|
import jakarta.inject.Singleton;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.jboss.jandex.ClassInfo;
|
import org.jboss.jandex.ClassInfo;
|
||||||
|
import org.jboss.jandex.DotName;
|
||||||
import org.jboss.jandex.MethodInfo;
|
import org.jboss.jandex.MethodInfo;
|
||||||
import org.jboss.jandex.Type;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.*;
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static java.lang.reflect.Modifier.*;
|
||||||
|
|
||||||
class ObjectsAllocProcessor {
|
class ObjectsAllocProcessor {
|
||||||
@BuildStep
|
@BuildStep
|
||||||
@@ -36,81 +39,305 @@ class ObjectsAllocProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String KEY_NAME = "key";
|
||||||
|
|
||||||
JDataInfo collectData(JDataIndexBuildItem item) {
|
String propNameToFieldName(String name) {
|
||||||
var methodNameToInfo = item.jData.methods().stream()
|
return name;
|
||||||
.collect(Collectors.toUnmodifiableMap(MethodInfo::name, x -> x));
|
|
||||||
|
|
||||||
var reducableSet = new TreeSet<>(methodNameToInfo.keySet());
|
|
||||||
|
|
||||||
var fields = new TreeMap<String, JDataFieldInfo>();
|
|
||||||
|
|
||||||
// Find pairs of getters and setters
|
|
||||||
// FIXME:
|
|
||||||
while (!reducableSet.isEmpty()) {
|
|
||||||
var name = reducableSet.first();
|
|
||||||
reducableSet.remove(name);
|
|
||||||
if (name.startsWith("get")) {
|
|
||||||
var setterName = "set" + name.substring(3);
|
|
||||||
if (reducableSet.contains(setterName)) {
|
|
||||||
reducableSet.remove(setterName);
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException("Missing setter for getter: " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
var getter = methodNameToInfo.get(name);
|
|
||||||
var setter = methodNameToInfo.get(setterName);
|
|
||||||
|
|
||||||
if (!getter.returnType().equals(setter.parameters().getFirst().type())) {
|
|
||||||
throw new RuntimeException("Getter and setter types do not match: " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
var variableName = name.substring(3, 4).toLowerCase() + name.substring(4);
|
|
||||||
|
|
||||||
fields.put(variableName, new JDataFieldInfo(variableName, getter.returnType()));
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException("Unknown method name: " + name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new JDataInfo(item.jData, Collections.unmodifiableMap(fields));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TypeFunction {
|
String propNameToGetterName(String name) {
|
||||||
void apply(Type type);
|
return "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void matchClass(BytecodeCreator bytecodeCreator, ResultHandle value, List<Type> types, TypeFunction fn) {
|
String propNameToSetterName(String name) {
|
||||||
// bytecodeCreator.insta
|
return "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ClassTagFunction {
|
DotName getDataClassName(ClassInfo jData) {
|
||||||
void apply(ClassInfo type, BytecodeCreator branch);
|
return DotName.createComponentized(jData.name().packagePrefixName(), jData.name().local() + "Data");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns false branch
|
DotName getCTClassName(ClassInfo jData) {
|
||||||
<T> BytecodeCreator matchClassTag(BytecodeCreator bytecodeCreator, ResultHandle toMatch, List<ClassInfo> types, ClassTagFunction fn) {
|
return DotName.createComponentized(jData.name().packagePrefixName(), jData.name().local() + "CTData");
|
||||||
if (types.isEmpty()) {
|
}
|
||||||
return bytecodeCreator;
|
|
||||||
}
|
|
||||||
|
|
||||||
var eq = bytecodeCreator.invokeVirtualMethod(
|
DotName getImmutableClassName(ClassInfo jData) {
|
||||||
MethodDescriptor.ofMethod(Object.class, "equals", boolean.class, Object.class),
|
return DotName.createComponentized(jData.name().packagePrefixName(), jData.name().local() + "ImmutableData");
|
||||||
toMatch,
|
|
||||||
bytecodeCreator.loadClass(types.getFirst())
|
|
||||||
);
|
|
||||||
|
|
||||||
var cmp = bytecodeCreator.ifTrue(eq);
|
|
||||||
fn.apply(types.getFirst(), cmp.trueBranch());
|
|
||||||
return matchClassTag(cmp.falseBranch(), toMatch, types.subList(1, types.size()), fn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@BuildStep
|
@BuildStep
|
||||||
void makeJDataThingy(List<JDataIndexBuildItem> jDataItems,
|
void generateDataClass(List<JDataInfoBuildItem> jDataItems, BuildProducer<GeneratedClassBuildItem> generatedClasses) {
|
||||||
BuildProducer<GeneratedBeanBuildItem> generatedBeans,
|
var gizmoAdapter = new GeneratedClassGizmoAdaptor(generatedClasses, true);
|
||||||
BuildProducer<GeneratedClassBuildItem> generatedClasses) {
|
for (var item : jDataItems) {
|
||||||
|
try (ClassCreator classCreator = ClassCreator.builder()
|
||||||
|
.className(getDataClassName(item.klass).toString())
|
||||||
|
.interfaces(JData.class)
|
||||||
|
.interfaces(item.klass.name().toString())
|
||||||
|
.interfaces(Serializable.class)
|
||||||
|
.classOutput(gizmoAdapter)
|
||||||
|
.build()) {
|
||||||
|
|
||||||
var data = jDataItems.stream().map(this::collectData).collect(Collectors.toUnmodifiableMap(JDataInfo::klass, x -> x));
|
|
||||||
|
var fieldsMap = item.fields.values().stream().map(jDataFieldInfo -> {
|
||||||
|
var fc = classCreator.getFieldCreator(propNameToFieldName(jDataFieldInfo.name()), jDataFieldInfo.type().toString());
|
||||||
|
|
||||||
|
if (jDataFieldInfo.name().equals(KEY_NAME)) {
|
||||||
|
fc.setModifiers(PRIVATE | FINAL);
|
||||||
|
} else {
|
||||||
|
fc.setModifiers(PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
try (var getter = classCreator.getMethodCreator(propNameToGetterName(jDataFieldInfo.name()), jDataFieldInfo.type().toString())) {
|
||||||
|
getter.returnValue(getter.readInstanceField(fc.getFieldDescriptor(), getter.getThis()));
|
||||||
|
}
|
||||||
|
return Pair.of(jDataFieldInfo, fc.getFieldDescriptor());
|
||||||
|
}).collect(Collectors.toUnmodifiableMap(Pair::getLeft, Pair::getRight));
|
||||||
|
|
||||||
|
for (var field : fieldsMap.values()) {
|
||||||
|
if (field.getName().equals(KEY_NAME)) {
|
||||||
|
try (var constructor = classCreator.getConstructorCreator(JObjectKey.class)) {
|
||||||
|
constructor.invokeSpecialMethod(MethodDescriptor.ofConstructor(Object.class), constructor.getThis());
|
||||||
|
constructor.writeInstanceField(field, constructor.getThis(), constructor.getMethodParam(0));
|
||||||
|
constructor.returnVoid();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try (var setter = classCreator.getMethodCreator(propNameToSetterName(field.getName()), void.class, field.getType())) {
|
||||||
|
setter.writeInstanceField(field, setter.getThis(), setter.getMethodParam(0));
|
||||||
|
setter.returnVoid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String MODIFIED_FIELD_NAME = "_modified";
|
||||||
|
private static final String ON_CHANGE_METHOD_NAME = "onChange";
|
||||||
|
|
||||||
|
@BuildStep
|
||||||
|
void generateCTClass(List<JDataInfoBuildItem> jDataItems, BuildProducer<GeneratedClassBuildItem> generatedClasses) {
|
||||||
|
var gizmoAdapter = new GeneratedClassGizmoAdaptor(generatedClasses, true);
|
||||||
|
for (var item : jDataItems) {
|
||||||
|
try (ClassCreator classCreator = ClassCreator.builder()
|
||||||
|
.className(getCTClassName(item.klass).toString())
|
||||||
|
.interfaces(JData.class, ObjectAllocator.ChangeTrackingJData.class)
|
||||||
|
.interfaces(item.klass.name().toString())
|
||||||
|
.interfaces(Serializable.class)
|
||||||
|
.classOutput(gizmoAdapter)
|
||||||
|
.build()) {
|
||||||
|
var modified = classCreator.getFieldCreator(MODIFIED_FIELD_NAME, boolean.class);
|
||||||
|
modified.setModifiers(PRIVATE | TRANSIENT);
|
||||||
|
|
||||||
|
try (var modifiedGetter = classCreator.getMethodCreator("isModified", boolean.class)) {
|
||||||
|
modifiedGetter.returnValue(modifiedGetter.readInstanceField(modified.getFieldDescriptor(), modifiedGetter.getThis()));
|
||||||
|
}
|
||||||
|
|
||||||
|
try (var onChanged = classCreator.getMethodCreator(ON_CHANGE_METHOD_NAME, void.class)) {
|
||||||
|
onChanged.writeInstanceField(modified.getFieldDescriptor(), onChanged.getThis(), onChanged.load(true));
|
||||||
|
onChanged.returnVoid();
|
||||||
|
}
|
||||||
|
|
||||||
|
try (var wrapped = classCreator.getMethodCreator("wrapped", item.klass.name().toString())) {
|
||||||
|
wrapped.returnValue(wrapped.getThis());
|
||||||
|
}
|
||||||
|
|
||||||
|
try (var wrapped = classCreator.getMethodCreator("wrapped", JData.class)) {
|
||||||
|
wrapped.returnValue(wrapped.getThis());
|
||||||
|
}
|
||||||
|
|
||||||
|
var fieldsMap = item.fields.values().stream().map(jDataFieldInfo -> {
|
||||||
|
var fc = classCreator.getFieldCreator(propNameToFieldName(jDataFieldInfo.name()), jDataFieldInfo.type().toString());
|
||||||
|
|
||||||
|
if (jDataFieldInfo.name().equals(KEY_NAME)) {
|
||||||
|
fc.setModifiers(PRIVATE | FINAL);
|
||||||
|
} else {
|
||||||
|
fc.setModifiers(PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
try (var getter = classCreator.getMethodCreator(propNameToGetterName(jDataFieldInfo.name()), jDataFieldInfo.type().toString())) {
|
||||||
|
getter.returnValue(getter.readInstanceField(fc.getFieldDescriptor(), getter.getThis()));
|
||||||
|
}
|
||||||
|
return Pair.of(jDataFieldInfo, fc.getFieldDescriptor());
|
||||||
|
}).collect(Collectors.toUnmodifiableMap(Pair::getLeft, Pair::getRight));
|
||||||
|
|
||||||
|
for (var field : fieldsMap.values()) {
|
||||||
|
if (!field.getName().equals(KEY_NAME)) {
|
||||||
|
try (var setter = classCreator.getMethodCreator(propNameToSetterName(field.getName()), void.class, field.getType())) {
|
||||||
|
setter.writeInstanceField(field, setter.getThis(), setter.getMethodParam(0));
|
||||||
|
setter.invokeVirtualMethod(MethodDescriptor.ofMethod(classCreator.getClassName(), ON_CHANGE_METHOD_NAME, void.class), setter.getThis());
|
||||||
|
setter.returnVoid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try (var constructor = classCreator.getConstructorCreator(item.klass.name().toString())) {
|
||||||
|
constructor.invokeSpecialMethod(MethodDescriptor.ofConstructor(Object.class), constructor.getThis());
|
||||||
|
constructor.writeInstanceField(modified.getFieldDescriptor(), constructor.getThis(), constructor.load(false));
|
||||||
|
for (var field : fieldsMap.values()) {
|
||||||
|
constructor.writeInstanceField(field, constructor.getThis(), constructor.invokeInterfaceMethod(
|
||||||
|
MethodDescriptor.ofMethod(item.klass.name().toString(), propNameToGetterName(field.getName()), field.getType()),
|
||||||
|
constructor.getMethodParam(0)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
constructor.returnVoid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@BuildStep
|
||||||
|
void generateImmutableClass(List<JDataInfoBuildItem> jDataItems, BuildProducer<GeneratedClassBuildItem> generatedClasses) {
|
||||||
|
var gizmoAdapter = new GeneratedClassGizmoAdaptor(generatedClasses, true);
|
||||||
|
for (var item : jDataItems) {
|
||||||
|
try (ClassCreator classCreator = ClassCreator.builder()
|
||||||
|
.className(getImmutableClassName(item.klass).toString())
|
||||||
|
.interfaces(JData.class, ObjectAllocator.ChangeTrackingJData.class)
|
||||||
|
.interfaces(item.klass.name().toString())
|
||||||
|
.interfaces(Serializable.class)
|
||||||
|
.classOutput(gizmoAdapter)
|
||||||
|
.build()) {
|
||||||
|
|
||||||
|
var fieldsMap = item.fields.values().stream().map(jDataFieldInfo -> {
|
||||||
|
var fc = classCreator.getFieldCreator(propNameToFieldName(jDataFieldInfo.name()), jDataFieldInfo.type().toString());
|
||||||
|
|
||||||
|
if (jDataFieldInfo.name().equals(KEY_NAME)) {
|
||||||
|
fc.setModifiers(PRIVATE | FINAL);
|
||||||
|
} else {
|
||||||
|
fc.setModifiers(PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
try (var getter = classCreator.getMethodCreator(propNameToGetterName(jDataFieldInfo.name()), jDataFieldInfo.type().toString())) {
|
||||||
|
getter.returnValue(getter.readInstanceField(fc.getFieldDescriptor(), getter.getThis()));
|
||||||
|
}
|
||||||
|
return Pair.of(jDataFieldInfo, fc.getFieldDescriptor());
|
||||||
|
}).collect(Collectors.toUnmodifiableMap(Pair::getLeft, Pair::getRight));
|
||||||
|
|
||||||
|
for (var field : fieldsMap.values()) {
|
||||||
|
try (var setter = classCreator.getMethodCreator(propNameToSetterName(field.getName()), void.class, field.getType())) {
|
||||||
|
setter.throwException(UnsupportedOperationException.class, "Immutable object");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try (var constructor = classCreator.getConstructorCreator(item.klass.name().toString())) {
|
||||||
|
constructor.invokeSpecialMethod(MethodDescriptor.ofConstructor(Object.class), constructor.getThis());
|
||||||
|
for (var field : fieldsMap.values()) {
|
||||||
|
constructor.writeInstanceField(field, constructor.getThis(), constructor.invokeInterfaceMethod(
|
||||||
|
MethodDescriptor.ofMethod(item.klass.name().toString(), propNameToGetterName(field.getName()), field.getType()),
|
||||||
|
constructor.getMethodParam(0)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
constructor.returnVoid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ClassInfo> collectInterfaces(ClassInfo type, ApplicationIndexBuildItem jandex) {
|
||||||
|
return Stream.concat(Stream.of(type), type.interfaceNames().stream()
|
||||||
|
.flatMap(x -> {
|
||||||
|
var ret = jandex.getIndex().getClassByName(x);
|
||||||
|
if (ret == null) {
|
||||||
|
System.out.println("Interface not found! " + x);
|
||||||
|
return Stream.empty();
|
||||||
|
}
|
||||||
|
return Stream.of(ret);
|
||||||
|
})
|
||||||
|
.flatMap(i -> collectInterfaces(i, jandex).stream()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, MethodInfo> collectMethods(List<ClassInfo> types) {
|
||||||
|
return types.stream()
|
||||||
|
.flatMap(x -> x.methods().stream())
|
||||||
|
.collect(Collectors.toMap(MethodInfo::name, x -> x));
|
||||||
|
}
|
||||||
|
|
||||||
|
@BuildStep
|
||||||
|
void collectData(BuildProducer<JDataInfoBuildItem> producer, List<JDataIndexBuildItem> items, ApplicationIndexBuildItem jandex) {
|
||||||
|
for (var item : items) {
|
||||||
|
var methodNameToInfo = collectMethods(collectInterfaces(item.jData, jandex));
|
||||||
|
|
||||||
|
var reducableSet = new TreeSet<>(methodNameToInfo.keySet());
|
||||||
|
|
||||||
|
var fields = new TreeMap<String, JDataFieldInfo>();
|
||||||
|
if (reducableSet.contains(propNameToGetterName(KEY_NAME))) {
|
||||||
|
reducableSet.remove(propNameToGetterName(KEY_NAME));
|
||||||
|
var methodInfo = methodNameToInfo.get(propNameToGetterName(KEY_NAME));
|
||||||
|
if (!methodInfo.returnType().name().equals(DotName.createSimple(JObjectKey.class.getName()))) {
|
||||||
|
throw new RuntimeException("Key getter must return JObjectKey");
|
||||||
|
}
|
||||||
|
fields.put(KEY_NAME, new JDataFieldInfo(KEY_NAME, methodNameToInfo.get(propNameToGetterName(KEY_NAME)).returnType().name()));
|
||||||
|
} else {
|
||||||
|
// throw new RuntimeException("Missing key getter");
|
||||||
|
System.out.println("Missing key getter for " + item.jData);
|
||||||
|
// FIXME!: No matter what, I couldn't get JData to get indexed by jandex
|
||||||
|
fields.put(KEY_NAME, new JDataFieldInfo(KEY_NAME, DotName.createSimple(JObjectKey.class)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find pairs of getters and setters
|
||||||
|
// FIXME:
|
||||||
|
while (!reducableSet.isEmpty()) {
|
||||||
|
var name = reducableSet.first();
|
||||||
|
reducableSet.remove(name);
|
||||||
|
if (name.startsWith("get")) {
|
||||||
|
var setterName = "set" + name.substring(3);
|
||||||
|
if (reducableSet.contains(setterName)) {
|
||||||
|
reducableSet.remove(setterName);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Missing setter for getter: " + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
var getter = methodNameToInfo.get(name);
|
||||||
|
var setter = methodNameToInfo.get(setterName);
|
||||||
|
|
||||||
|
if (!getter.returnType().equals(setter.parameters().getFirst().type())) {
|
||||||
|
throw new RuntimeException("Getter and setter types do not match: " + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
var variableName = name.substring(3, 4).toLowerCase() + name.substring(4);
|
||||||
|
|
||||||
|
fields.put(variableName, new JDataFieldInfo(variableName, getter.returnType().name()));
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Unknown method name: " + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
producer.produce(new JDataInfoBuildItem(item.jData, Collections.unmodifiableMap(fields)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns false branch
|
||||||
|
void matchClass(BytecodeCreator bytecodeCreator, ResultHandle toMatch, List<ClassInfo> types, ClassTagFunction fn) {
|
||||||
|
for (var type : types) {
|
||||||
|
var eq = bytecodeCreator.instanceOf(toMatch, type.name().toString());
|
||||||
|
var cmp = bytecodeCreator.ifTrue(eq);
|
||||||
|
fn.apply(type, cmp.trueBranch(), toMatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ClassTagFunction {
|
||||||
|
void apply(ClassInfo type, BytecodeCreator branch, ResultHandle value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns false branch
|
||||||
|
void matchClassTag(BytecodeCreator bytecodeCreator, ResultHandle toMatch, List<ClassInfo> types, ClassTagFunction fn) {
|
||||||
|
for (var type : types) {
|
||||||
|
var eq = bytecodeCreator.invokeVirtualMethod(
|
||||||
|
MethodDescriptor.ofMethod(Object.class, "equals", boolean.class, Object.class),
|
||||||
|
toMatch,
|
||||||
|
bytecodeCreator.loadClass(type.name().toString())
|
||||||
|
);
|
||||||
|
|
||||||
|
var cmp = bytecodeCreator.ifTrue(eq);
|
||||||
|
fn.apply(type, cmp.trueBranch(), toMatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@BuildStep
|
||||||
|
void makeJDataThingy(List<JDataInfoBuildItem> jDataItems,
|
||||||
|
BuildProducer<GeneratedBeanBuildItem> generatedBeans) {
|
||||||
|
var data = jDataItems.stream().collect(Collectors.toUnmodifiableMap(i -> i.klass, x -> x));
|
||||||
var classes = data.keySet().stream().map(ClassInfo::asClass).toList();
|
var classes = data.keySet().stream().map(ClassInfo::asClass).toList();
|
||||||
|
|
||||||
var gizmoAdapter = new GeneratedBeanGizmoAdaptor(generatedBeans);
|
var gizmoAdapter = new GeneratedBeanGizmoAdaptor(generatedBeans);
|
||||||
@@ -124,18 +351,24 @@ class ObjectsAllocProcessor {
|
|||||||
classCreator.addAnnotation(Singleton.class);
|
classCreator.addAnnotation(Singleton.class);
|
||||||
|
|
||||||
try (MethodCreator methodCreator = classCreator.getMethodCreator("create", JData.class, Class.class, JObjectKey.class)) {
|
try (MethodCreator methodCreator = classCreator.getMethodCreator("create", JData.class, Class.class, JObjectKey.class)) {
|
||||||
matchClassTag(methodCreator, methodCreator.getMethodParam(0), classes, (type, branch) -> {
|
matchClassTag(methodCreator, methodCreator.getMethodParam(0), classes, (type, branch, value) -> {
|
||||||
branch.returnValue(branch.newInstance(MethodDescriptor.ofConstructor(type.toString(), JObjectKey.class), branch.getMethodParam(1)));
|
branch.returnValue(branch.newInstance(MethodDescriptor.ofConstructor(getDataClassName(type).toString(), JObjectKey.class), branch.getMethodParam(1)));
|
||||||
});
|
});
|
||||||
methodCreator.throwException(IllegalArgumentException.class, "Unknown type");
|
methodCreator.throwException(IllegalArgumentException.class, "Unknown type");
|
||||||
}
|
}
|
||||||
|
|
||||||
try (MethodCreator methodCreator = classCreator.getMethodCreator("copy", ObjectAllocator.ChangeTrackingJData.class, JData.class)) {
|
try (MethodCreator methodCreator = classCreator.getMethodCreator("copy", ObjectAllocator.ChangeTrackingJData.class, JData.class)) {
|
||||||
methodCreator.returnValue(methodCreator.loadNull());
|
matchClass(methodCreator, methodCreator.getMethodParam(0), classes, (type, branch, value) -> {
|
||||||
|
branch.returnValue(branch.newInstance(MethodDescriptor.ofConstructor(getCTClassName(type).toString(), type.name().toString()), value));
|
||||||
|
});
|
||||||
|
methodCreator.throwException(IllegalArgumentException.class, "Unknown type");
|
||||||
}
|
}
|
||||||
|
|
||||||
try (MethodCreator methodCreator = classCreator.getMethodCreator("unmodifiable", JData.class, JData.class)) {
|
try (MethodCreator methodCreator = classCreator.getMethodCreator("unmodifiable", JData.class, JData.class)) {
|
||||||
methodCreator.returnValue(methodCreator.loadNull());
|
matchClass(methodCreator, methodCreator.getMethodParam(0), classes, (type, branch, value) -> {
|
||||||
|
branch.returnValue(branch.newInstance(MethodDescriptor.ofConstructor(getImmutableClassName(type).toString(), type.name().toString()), value));
|
||||||
|
});
|
||||||
|
methodCreator.throwException(IllegalArgumentException.class, "Unknown type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
@@ -15,10 +16,6 @@
|
|||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>io.quarkus</groupId>
|
|
||||||
<artifactId>quarkus-rest</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.usatiuk</groupId>
|
<groupId>com.usatiuk</groupId>
|
||||||
<artifactId>objects-alloc</artifactId>
|
<artifactId>objects-alloc</artifactId>
|
||||||
@@ -30,13 +27,18 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.quarkus</groupId>
|
<groupId>com.usatiuk</groupId>
|
||||||
<artifactId>quarkus-junit5</artifactId>
|
<artifactId>objects-common</artifactId>
|
||||||
<scope>test</scope>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.rest-assured</groupId>
|
<groupId>com.usatiuk</groupId>
|
||||||
<artifactId>rest-assured</artifactId>
|
<artifactId>objects-common-deployment</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-junit5</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
@@ -68,7 +70,8 @@
|
|||||||
</executions>
|
</executions>
|
||||||
<configuration>
|
<configuration>
|
||||||
<systemPropertyVariables>
|
<systemPropertyVariables>
|
||||||
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
|
<native.image.path>${project.build.directory}/${project.build.finalName}-runner
|
||||||
|
</native.image.path>
|
||||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||||
<maven.home>${maven.home}</maven.home>
|
<maven.home>${maven.home}</maven.home>
|
||||||
</systemPropertyVariables>
|
</systemPropertyVariables>
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
* (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.usatiuk.objects.alloc.it;
|
|
||||||
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
|
||||||
import jakarta.ws.rs.GET;
|
|
||||||
import jakarta.ws.rs.Path;
|
|
||||||
|
|
||||||
@Path("/objects-alloc")
|
|
||||||
@ApplicationScoped
|
|
||||||
public class ObjectsAllocResource {
|
|
||||||
// add some rest methods here
|
|
||||||
|
|
||||||
@GET
|
|
||||||
public String hello() {
|
|
||||||
return "Hello objects-alloc";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.usatiuk.objects.alloc.it;
|
package com.usatiuk.objects.alloc.it;
|
||||||
|
|
||||||
import com.usatiuk.objects.common.JData;
|
import com.usatiuk.objects.common.runtime.JData;
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
import com.usatiuk.objects.common.runtime.JObjectKey;
|
||||||
|
|
||||||
interface TestJDataAssorted extends JData {
|
public interface TestJDataAssorted extends JData {
|
||||||
String getLastName();
|
String getLastName();
|
||||||
|
|
||||||
void setLastName(String lastName);
|
void setLastName(String lastName);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.usatiuk.objects.alloc.it;
|
package com.usatiuk.objects.alloc.it;
|
||||||
|
|
||||||
import com.usatiuk.objects.common.JData;
|
import com.usatiuk.objects.common.runtime.JData;
|
||||||
|
|
||||||
public interface TestJDataEmpty extends JData {
|
public interface TestJDataEmpty extends JData {
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package com.usatiuk.objects.alloc.it;
|
||||||
|
|
||||||
|
import com.usatiuk.objects.alloc.runtime.ObjectAllocator;
|
||||||
|
import com.usatiuk.objects.common.runtime.JObjectKey;
|
||||||
|
import io.quarkus.test.junit.QuarkusTest;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@QuarkusTest
|
||||||
|
public class ObjectAllocIT {
|
||||||
|
@Inject
|
||||||
|
ObjectAllocator objectAllocator;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCreateObject() {
|
||||||
|
var newObject = objectAllocator.create(TestJDataEmpty.class, new JObjectKey("TestJDataEmptyKey"));
|
||||||
|
Assertions.assertNotNull(newObject);
|
||||||
|
Assertions.assertEquals("TestJDataEmptyKey", newObject.getKey().name());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCopyObject() {
|
||||||
|
var newObject = objectAllocator.create(TestJDataAssorted.class, new JObjectKey("TestJDataAssorted"));
|
||||||
|
newObject.setLastName("1");
|
||||||
|
Assertions.assertNotNull(newObject);
|
||||||
|
Assertions.assertEquals("TestJDataAssorted", newObject.getKey().name());
|
||||||
|
|
||||||
|
var copyObject = objectAllocator.copy(newObject);
|
||||||
|
Assertions.assertNotNull(copyObject);
|
||||||
|
Assertions.assertFalse(copyObject.isModified());
|
||||||
|
Assertions.assertEquals("1", copyObject.wrapped().getLastName());
|
||||||
|
copyObject.wrapped().setLastName("2");
|
||||||
|
Assertions.assertTrue(copyObject.isModified());
|
||||||
|
Assertions.assertEquals("2", copyObject.wrapped().getLastName());
|
||||||
|
Assertions.assertEquals("1", newObject.getLastName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testImmutable() {
|
||||||
|
var newObject = objectAllocator.create(TestJDataAssorted.class, new JObjectKey("TestJDataAssorted"));
|
||||||
|
newObject.setLastName("1");
|
||||||
|
Assertions.assertNotNull(newObject);
|
||||||
|
Assertions.assertEquals("TestJDataAssorted", newObject.getKey().name());
|
||||||
|
|
||||||
|
var copyObject = objectAllocator.unmodifiable(newObject);
|
||||||
|
Assertions.assertNotNull(copyObject);
|
||||||
|
Assertions.assertEquals("1", copyObject.getLastName());
|
||||||
|
Assertions.assertThrows(UnsupportedOperationException.class, () -> copyObject.setLastName("2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testImmutable2() {
|
||||||
|
var newObject = objectAllocator.create(TestJDataEmpty.class, new JObjectKey("TestJDataEmpty"));
|
||||||
|
Assertions.assertNotNull(newObject);
|
||||||
|
Assertions.assertEquals("TestJDataEmpty", newObject.getKey().name());
|
||||||
|
|
||||||
|
var copyObject = objectAllocator.unmodifiable(newObject);
|
||||||
|
Assertions.assertNotNull(copyObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package com.usatiuk.objects.alloc.it;
|
|
||||||
|
|
||||||
import com.usatiuk.objects.alloc.runtime.ObjectAllocator;
|
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
|
||||||
import io.quarkus.test.junit.QuarkusTest;
|
|
||||||
import jakarta.inject.Inject;
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
@QuarkusTest
|
|
||||||
public class ObjectsAllocResourceTest {
|
|
||||||
@Inject
|
|
||||||
ObjectAllocator objectAllocator;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testCreateObject() {
|
|
||||||
var newObject = objectAllocator.create(TestJDataEmpty.class, new JObjectKey("TestJDataEmptyKey"));
|
|
||||||
Assertions.assertNotNull(newObject);
|
|
||||||
Assertions.assertEquals("TestJDataEmptyKey", newObject.getKey().name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
<artifactId>quarkus-arc</artifactId>
|
<artifactId>quarkus-arc</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.usatiuk.dhfs</groupId>
|
<groupId>com.usatiuk</groupId>
|
||||||
<artifactId>objects-common</artifactId>
|
<artifactId>objects-common</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
package com.usatiuk.objects.alloc.runtime;
|
|
||||||
|
|
||||||
import com.usatiuk.objects.common.JData;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
abstract class ChangeTrackerBase<T extends JData> implements ObjectAllocator.ChangeTrackingJData<T>, Serializable {
|
|
||||||
private transient boolean _modified = false;
|
|
||||||
|
|
||||||
public boolean isModified() {
|
|
||||||
return _modified;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onChange() {
|
|
||||||
_modified = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.usatiuk.objects.alloc.runtime;
|
package com.usatiuk.objects.alloc.runtime;
|
||||||
|
|
||||||
import com.usatiuk.objects.common.JData;
|
import com.usatiuk.objects.common.runtime.JData;
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
import com.usatiuk.objects.common.runtime.JObjectKey;
|
||||||
|
|
||||||
public interface ObjectAllocator {
|
public interface ObjectAllocator {
|
||||||
<T extends JData> T create(Class<T> type, JObjectKey key);
|
<T extends JData> T create(Class<T> type, JObjectKey key);
|
||||||
|
|||||||
51
dhfs-parent/objects-common/deployment/pom.xml
Normal file
51
dhfs-parent/objects-common/deployment/pom.xml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.usatiuk</groupId>
|
||||||
|
<artifactId>objects-common-parent</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>objects-common-deployment</artifactId>
|
||||||
|
<name>DHFS objects common stuff - Deployment</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-arc-deployment</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.usatiuk</groupId>
|
||||||
|
<artifactId>objects-common</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-junit5-internal</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>default-compile</id>
|
||||||
|
<configuration>
|
||||||
|
<annotationProcessorPaths>
|
||||||
|
<path>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-extension-processor</artifactId>
|
||||||
|
<version>${quarkus.platform.version}</version>
|
||||||
|
</path>
|
||||||
|
</annotationProcessorPaths>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.usatiuk.objects.common.deployment;
|
||||||
|
|
||||||
|
import io.quarkus.deployment.annotations.BuildStep;
|
||||||
|
import io.quarkus.deployment.builditem.FeatureBuildItem;
|
||||||
|
|
||||||
|
class ObjectsCommonProcessor {
|
||||||
|
|
||||||
|
private static final String FEATURE = "objects-common";
|
||||||
|
|
||||||
|
@BuildStep
|
||||||
|
FeatureBuildItem feature() {
|
||||||
|
return new FeatureBuildItem(FEATURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.usatiuk.objects.common.test;
|
||||||
|
|
||||||
|
import org.jboss.shrinkwrap.api.ShrinkWrap;
|
||||||
|
import org.jboss.shrinkwrap.api.spec.JavaArchive;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
|
||||||
|
import io.quarkus.test.QuarkusDevModeTest;
|
||||||
|
|
||||||
|
public class ObjectsCommonDevModeTest {
|
||||||
|
|
||||||
|
// Start hot reload (DevMode) test with your extension loaded
|
||||||
|
@RegisterExtension
|
||||||
|
static final QuarkusDevModeTest devModeTest = new QuarkusDevModeTest()
|
||||||
|
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void writeYourOwnDevModeTest() {
|
||||||
|
// Write your dev mode tests here - see the testing extension guide https://quarkus.io/guides/writing-extensions#testing-hot-reload for more information
|
||||||
|
Assertions.assertTrue(true, "Add dev mode assertions to " + getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.usatiuk.objects.common.test;
|
||||||
|
|
||||||
|
import org.jboss.shrinkwrap.api.ShrinkWrap;
|
||||||
|
import org.jboss.shrinkwrap.api.spec.JavaArchive;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
|
||||||
|
import io.quarkus.test.QuarkusUnitTest;
|
||||||
|
|
||||||
|
public class ObjectsCommonTest {
|
||||||
|
|
||||||
|
// Start unit test with your extension loaded
|
||||||
|
@RegisterExtension
|
||||||
|
static final QuarkusUnitTest unitTest = new QuarkusUnitTest()
|
||||||
|
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void writeYourOwnUnitTest() {
|
||||||
|
// Write your unit tests here - see the testing extension guide https://quarkus.io/guides/writing-extensions#testing-extensions for more information
|
||||||
|
Assertions.assertTrue(true, "Add some assertions to " + getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
93
dhfs-parent/objects-common/integration-tests/pom.xml
Normal file
93
dhfs-parent/objects-common/integration-tests/pom.xml
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.usatiuk</groupId>
|
||||||
|
<artifactId>objects-common-parent</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>objects-common-integration-tests</artifactId>
|
||||||
|
<name>DHFS objects common stuff - Integration Tests</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<skipITs>true</skipITs>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.usatiuk</groupId>
|
||||||
|
<artifactId>objects-common</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.usatiuk</groupId>
|
||||||
|
<artifactId>objects-common-deployment</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-junit5</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>build</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-failsafe-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>integration-test</goal>
|
||||||
|
<goal>verify</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<systemPropertyVariables>
|
||||||
|
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
|
||||||
|
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||||
|
<maven.home>${maven.home}</maven.home>
|
||||||
|
</systemPropertyVariables>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>native-image</id>
|
||||||
|
<activation>
|
||||||
|
<property>
|
||||||
|
<name>native</name>
|
||||||
|
</property>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<skipTests>${native.surefire.skip}</skipTests>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<properties>
|
||||||
|
<skipITs>false</skipITs>
|
||||||
|
<quarkus.native.enabled>true</quarkus.native.enabled>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
quarkus.package.jar.decompiler.enabled=true
|
||||||
@@ -1,20 +1,23 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>com.usatiuk.dhfs</groupId>
|
<groupId>com.usatiuk.dhfs</groupId>
|
||||||
<artifactId>parent</artifactId>
|
<artifactId>parent</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>objects-common</artifactId>
|
<groupId>com.usatiuk</groupId>
|
||||||
|
<artifactId>objects-common-parent</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<name>DHFS objects common stuff - Parent</name>
|
||||||
|
|
||||||
<properties>
|
<modules>
|
||||||
<maven.compiler.source>21</maven.compiler.source>
|
<module>deployment</module>
|
||||||
<maven.compiler.target>21</maven.compiler.target>
|
<module>runtime</module>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<module>integration-tests</module>
|
||||||
</properties>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
59
dhfs-parent/objects-common/runtime/pom.xml
Normal file
59
dhfs-parent/objects-common/runtime/pom.xml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.usatiuk</groupId>
|
||||||
|
<artifactId>objects-common-parent</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>objects-common</artifactId>
|
||||||
|
<name>DHFS objects common stuff - Runtime</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-arc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-extension-maven-plugin</artifactId>
|
||||||
|
<version>${quarkus.platform.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>extension-descriptor</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}
|
||||||
|
</deployment>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>default-compile</id>
|
||||||
|
<configuration>
|
||||||
|
<annotationProcessorPaths>
|
||||||
|
<path>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-extension-processor</artifactId>
|
||||||
|
<version>${quarkus.platform.version}</version>
|
||||||
|
</path>
|
||||||
|
</annotationProcessorPaths>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.usatiuk.objects.common;
|
package com.usatiuk.objects.common.runtime;
|
||||||
|
|
||||||
// TODO: This could be maybe moved to a separate module?
|
// TODO: This could be maybe moved to a separate module?
|
||||||
// The base class for JObject data
|
// The base class for JObject data
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.usatiuk.objects.common;
|
package com.usatiuk.objects.common.runtime;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
name: DHFS objects common stuff
|
||||||
|
#description: Do something useful.
|
||||||
|
metadata:
|
||||||
|
# keywords:
|
||||||
|
# - objects-common
|
||||||
|
# guide: ... # To create and publish this guide, see https://github.com/quarkiverse/quarkiverse/wiki#documenting-your-extension
|
||||||
|
# categories:
|
||||||
|
# - "miscellaneous"
|
||||||
|
# status: "preview"
|
||||||
@@ -76,10 +76,15 @@
|
|||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.usatiuk.dhfs</groupId>
|
<groupId>com.usatiuk</groupId>
|
||||||
<artifactId>objects-common</artifactId>
|
<artifactId>objects-common</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.usatiuk</groupId>
|
||||||
|
<artifactId>objects-common-deployment</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ package com.usatiuk.dhfs.objects;
|
|||||||
|
|
||||||
import com.usatiuk.dhfs.objects.transaction.LockingStrategy;
|
import com.usatiuk.dhfs.objects.transaction.LockingStrategy;
|
||||||
import com.usatiuk.dhfs.objects.transaction.Transaction;
|
import com.usatiuk.dhfs.objects.transaction.Transaction;
|
||||||
import com.usatiuk.objects.common.JData;
|
import com.usatiuk.objects.common.runtime.JData;
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
import com.usatiuk.objects.common.runtime.JObjectKey;
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import com.usatiuk.dhfs.objects.transaction.TransactionPrivate;
|
|||||||
import com.usatiuk.dhfs.objects.transaction.TxRecord;
|
import com.usatiuk.dhfs.objects.transaction.TxRecord;
|
||||||
import com.usatiuk.dhfs.utils.DataLocker;
|
import com.usatiuk.dhfs.utils.DataLocker;
|
||||||
import com.usatiuk.dhfs.utils.VoidFn;
|
import com.usatiuk.dhfs.utils.VoidFn;
|
||||||
import com.usatiuk.objects.common.JData;
|
import com.usatiuk.objects.common.runtime.JData;
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
import com.usatiuk.objects.common.runtime.JObjectKey;
|
||||||
import com.usatiuk.objects.alloc.runtime.ObjectAllocator;
|
import com.usatiuk.objects.alloc.runtime.ObjectAllocator;
|
||||||
import io.quarkus.logging.Log;
|
import io.quarkus.logging.Log;
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
@@ -24,7 +24,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||||||
import java.util.concurrent.locks.ReadWriteLock;
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
// Manages all access to com.usatiuk.objects.common.JData objects.
|
// Manages all access to com.usatiuk.objects.common.runtime.JData objects.
|
||||||
// In particular, it serves as a source of truth for what is committed to the backing storage.
|
// In particular, it serves as a source of truth for what is committed to the backing storage.
|
||||||
// All data goes through it, it is responsible for transaction atomicity
|
// All data goes through it, it is responsible for transaction atomicity
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
package com.usatiuk.dhfs.objects.serializer;
|
package com.usatiuk.dhfs.objects;
|
||||||
|
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import com.usatiuk.dhfs.objects.ObjectSerializer;
|
|
||||||
import com.usatiuk.dhfs.utils.SerializationHelper;
|
import com.usatiuk.dhfs.utils.SerializationHelper;
|
||||||
import com.usatiuk.objects.common.JData;
|
import com.usatiuk.objects.common.runtime.JData;
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
public class TestJDataSerializer implements ObjectSerializer<JData> {
|
public class JavaDataSerializer implements ObjectSerializer<JData> {
|
||||||
@Override
|
@Override
|
||||||
public ByteString serialize(JData obj) {
|
public ByteString serialize(JData obj) {
|
||||||
return SerializationHelper.serialize((Serializable) obj);
|
return SerializationHelper.serialize((Serializable) obj);
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.usatiuk.dhfs.objects;
|
package com.usatiuk.dhfs.objects;
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import com.usatiuk.objects.common.JData;
|
import com.usatiuk.objects.common.runtime.JData;
|
||||||
|
|
||||||
public interface ObjectSerializer<T extends JData> {
|
public interface ObjectSerializer<T extends JData> {
|
||||||
ByteString serialize(T obj);
|
ByteString serialize(T obj);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.usatiuk.dhfs.objects;
|
package com.usatiuk.dhfs.objects;
|
||||||
|
|
||||||
import com.usatiuk.objects.common.JData;
|
import com.usatiuk.objects.common.runtime.JData;
|
||||||
|
|
||||||
public interface TxBundle {
|
public interface TxBundle {
|
||||||
long getId();
|
long getId();
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package com.usatiuk.dhfs.objects.persistence;
|
|||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import com.google.protobuf.UnsafeByteOperations;
|
import com.google.protobuf.UnsafeByteOperations;
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
import com.usatiuk.objects.common.runtime.JObjectKey;
|
||||||
import com.usatiuk.dhfs.supportlib.UninitializedByteBuffer;
|
import com.usatiuk.dhfs.supportlib.UninitializedByteBuffer;
|
||||||
import com.usatiuk.dhfs.utils.ByteUtils;
|
import com.usatiuk.dhfs.utils.ByteUtils;
|
||||||
import com.usatiuk.dhfs.utils.SerializationHelper;
|
import com.usatiuk.dhfs.utils.SerializationHelper;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.usatiuk.dhfs.objects.persistence;
|
package com.usatiuk.dhfs.objects.persistence;
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
import com.usatiuk.objects.common.runtime.JObjectKey;
|
||||||
import io.quarkus.arc.properties.IfBuildProperty;
|
import io.quarkus.arc.properties.IfBuildProperty;
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.usatiuk.dhfs.objects.persistence;
|
package com.usatiuk.dhfs.objects.persistence;
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
import com.usatiuk.objects.common.runtime.JObjectKey;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.usatiuk.dhfs.objects.persistence;
|
package com.usatiuk.dhfs.objects.persistence;
|
||||||
|
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
import com.usatiuk.objects.common.runtime.JObjectKey;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.usatiuk.dhfs.objects.transaction;
|
package com.usatiuk.dhfs.objects.transaction;
|
||||||
|
|
||||||
import com.usatiuk.objects.common.JData;
|
import com.usatiuk.objects.common.runtime.JData;
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
import com.usatiuk.objects.common.runtime.JObjectKey;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.usatiuk.dhfs.objects.transaction;
|
package com.usatiuk.dhfs.objects.transaction;
|
||||||
|
|
||||||
import com.usatiuk.objects.common.JData;
|
import com.usatiuk.objects.common.runtime.JData;
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
import com.usatiuk.objects.common.runtime.JObjectKey;
|
||||||
import com.usatiuk.objects.alloc.runtime.ObjectAllocator;
|
import com.usatiuk.objects.alloc.runtime.ObjectAllocator;
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.usatiuk.dhfs.objects.transaction;
|
package com.usatiuk.dhfs.objects.transaction;
|
||||||
|
|
||||||
import com.usatiuk.objects.common.JData;
|
import com.usatiuk.objects.common.runtime.JData;
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
import com.usatiuk.objects.common.runtime.JObjectKey;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.usatiuk.dhfs.objects.transaction;
|
package com.usatiuk.dhfs.objects.transaction;
|
||||||
|
|
||||||
import com.usatiuk.objects.common.JData;
|
import com.usatiuk.objects.common.runtime.JData;
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
import com.usatiuk.objects.common.runtime.JObjectKey;
|
||||||
import com.usatiuk.objects.alloc.runtime.ObjectAllocator;
|
import com.usatiuk.objects.alloc.runtime.ObjectAllocator;
|
||||||
|
|
||||||
public class TxRecord {
|
public class TxRecord {
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ package com.usatiuk.dhfs.objects;
|
|||||||
|
|
||||||
import com.usatiuk.dhfs.objects.data.Parent;
|
import com.usatiuk.dhfs.objects.data.Parent;
|
||||||
import com.usatiuk.dhfs.objects.transaction.LockingStrategy;
|
import com.usatiuk.dhfs.objects.transaction.LockingStrategy;
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
import com.usatiuk.dhfs.objects.transaction.Transaction;
|
||||||
import com.usatiuk.objects.alloc.runtime.ObjectAllocator;
|
import com.usatiuk.objects.alloc.runtime.ObjectAllocator;
|
||||||
|
import com.usatiuk.objects.common.runtime.JObjectKey;
|
||||||
import io.quarkus.logging.Log;
|
import io.quarkus.logging.Log;
|
||||||
import io.quarkus.test.junit.QuarkusTest;
|
import io.quarkus.test.junit.QuarkusTest;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
@@ -20,7 +21,7 @@ public class ObjectsTest {
|
|||||||
TransactionManager txm;
|
TransactionManager txm;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
CurrentTransaction curTx;
|
Transaction curTx;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ObjectAllocator alloc;
|
ObjectAllocator alloc;
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
package com.usatiuk.dhfs.objects.allocator;
|
|
||||||
|
|
||||||
import com.usatiuk.objects.alloc.runtime.ObjectAllocator;
|
|
||||||
import com.usatiuk.objects.common.JData;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
public abstract class ChangeTrackerBase<T extends JData> implements ObjectAllocator.ChangeTrackingJData<T>, Serializable {
|
|
||||||
@Getter
|
|
||||||
private transient boolean _modified = false;
|
|
||||||
|
|
||||||
protected void onChange() {
|
|
||||||
_modified = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package com.usatiuk.dhfs.objects.allocator;
|
|
||||||
|
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
|
||||||
import com.usatiuk.dhfs.objects.data.Kid;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
public class KidDataCT extends ChangeTrackerBase<Kid> implements Kid {
|
|
||||||
private final JObjectKey _key;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private String _name;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setName(String name) {
|
|
||||||
_name = name;
|
|
||||||
onChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
public KidDataCT(Kid normal) {
|
|
||||||
_key = normal.getKey();
|
|
||||||
_name = normal.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JObjectKey getKey() {
|
|
||||||
return _key;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Kid wrapped() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package com.usatiuk.dhfs.objects.allocator;
|
|
||||||
|
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
|
||||||
import com.usatiuk.dhfs.objects.data.Kid;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
public class KidDataNormal implements Kid, Serializable {
|
|
||||||
private final JObjectKey _key;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
private String _name;
|
|
||||||
|
|
||||||
public KidDataNormal(JObjectKey key) {_key = key;}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JObjectKey getKey() {
|
|
||||||
return _key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package com.usatiuk.dhfs.objects.allocator;
|
|
||||||
|
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
|
||||||
import com.usatiuk.dhfs.objects.data.Parent;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
public class ParentDataCT extends ChangeTrackerBase<Parent> implements Parent {
|
|
||||||
@Getter
|
|
||||||
private JObjectKey _name;
|
|
||||||
@Getter
|
|
||||||
private JObjectKey _kidKey;
|
|
||||||
@Getter
|
|
||||||
private String _lastName;
|
|
||||||
|
|
||||||
public void setKidKey(JObjectKey key) {
|
|
||||||
_kidKey = key;
|
|
||||||
onChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLastName(String lastName) {
|
|
||||||
_lastName = lastName;
|
|
||||||
onChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ParentDataCT(Parent normal) {
|
|
||||||
_name = normal.getKey();
|
|
||||||
_kidKey = normal.getKidKey();
|
|
||||||
_lastName = normal.getLastName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JObjectKey getKey() {
|
|
||||||
return _name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Parent wrapped() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package com.usatiuk.dhfs.objects.allocator;
|
|
||||||
|
|
||||||
import com.usatiuk.dhfs.objects.data.Parent;
|
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
public class ParentDataNormal implements Parent, Serializable {
|
|
||||||
@Getter
|
|
||||||
private JObjectKey _name;
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
private JObjectKey _kidKey;
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
private String _lastName;
|
|
||||||
|
|
||||||
public ParentDataNormal(JObjectKey name) {
|
|
||||||
_name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JObjectKey getKey() {
|
|
||||||
return _name;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
package com.usatiuk.dhfs.objects.allocator;
|
|
||||||
|
|
||||||
import com.usatiuk.objects.common.JData;
|
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
|
||||||
|
|
||||||
public abstract class TestData implements JData {
|
|
||||||
private boolean _changed = false;
|
|
||||||
private final long _version;
|
|
||||||
private final JObjectKey _key;
|
|
||||||
|
|
||||||
protected TestData(long version, JObjectKey key) {
|
|
||||||
_version = version;
|
|
||||||
_key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onChanged() {
|
|
||||||
_changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isChanged() {
|
|
||||||
return _changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getVersion() {
|
|
||||||
return _version;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JObjectKey getKey() {
|
|
||||||
return _key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract TestData copy();
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package com.usatiuk.dhfs.objects.allocator;
|
|
||||||
|
|
||||||
import com.usatiuk.objects.common.JData;
|
|
||||||
import com.usatiuk.objects.alloc.runtime.ObjectAllocator;
|
|
||||||
import com.usatiuk.dhfs.objects.data.Kid;
|
|
||||||
import com.usatiuk.dhfs.objects.data.Parent;
|
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
|
||||||
|
|
||||||
@ApplicationScoped
|
|
||||||
public class TestObjectAllocator implements ObjectAllocator {
|
|
||||||
@Override
|
|
||||||
public <T extends JData> T create(Class<T> type, JObjectKey key) {
|
|
||||||
if (type == Kid.class) {
|
|
||||||
return type.cast(new KidDataNormal(key));
|
|
||||||
} else if (type == Parent.class) {
|
|
||||||
return type.cast(new ParentDataNormal(key));
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Unknown type: " + type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T extends JData> ChangeTrackingJData<T> copy(T obj) {
|
|
||||||
// if (obj instanceof ChangeTrackerBase<?>) {
|
|
||||||
// throw new IllegalArgumentException("Cannot copy a ChangeTrackerBase object");
|
|
||||||
// }
|
|
||||||
|
|
||||||
return switch (obj) {
|
|
||||||
case Kid kid -> (ChangeTrackingJData<T>) new KidDataCT(kid);
|
|
||||||
case Parent parent -> (ChangeTrackingJData<T>) new ParentDataCT(parent);
|
|
||||||
default -> throw new IllegalStateException("Unexpected value: " + obj);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T extends JData> T unmodifiable(T obj) {
|
|
||||||
return obj; // TODO:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.usatiuk.dhfs.objects.data;
|
package com.usatiuk.dhfs.objects.data;
|
||||||
|
|
||||||
import com.usatiuk.objects.common.JData;
|
import com.usatiuk.objects.common.runtime.JData;
|
||||||
|
|
||||||
public interface Kid extends JData {
|
public interface Kid extends JData {
|
||||||
String getName();
|
String getName();
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
package com.usatiuk.dhfs.objects.data;
|
package com.usatiuk.dhfs.objects.data;
|
||||||
|
|
||||||
import com.usatiuk.objects.common.JData;
|
import com.usatiuk.objects.common.runtime.JData;
|
||||||
import com.usatiuk.objects.common.JObjectKey;
|
import com.usatiuk.objects.common.runtime.JObjectKey;
|
||||||
|
|
||||||
public interface Parent extends JData {
|
public interface Parent extends JData {
|
||||||
JObjectKey getName();
|
|
||||||
|
|
||||||
String getLastName();
|
String getLastName();
|
||||||
|
|
||||||
void setLastName(String lastName);
|
void setLastName(String lastName);
|
||||||
|
|||||||
Reference in New Issue
Block a user