
io.p8e.util.FactPojoHydrator.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of p8e-sdk Show documentation
Show all versions of p8e-sdk Show documentation
A collection of services and libraries that iteract and run Provenance Java based contracts.
package io.p8e.util
import com.google.protobuf.Message
import io.p8e.annotations.Fact
import io.p8e.client.P8eClient
import io.p8e.proto.ContractScope.Scope
import io.p8e.proto.ContractScope.Record
import io.p8e.util.CompletableFutureUtil.completableFuture
class FactPojoHydrator(
private val client: P8eClient
) {
fun hydrate(
scope: Scope,
clazz: Class
): T {
val constructor = clazz.declaredConstructors
.filter {
it.parameters.isNotEmpty() &&
it.parameters.all { param ->
Message::class.java.isAssignableFrom(param.type) &&
(param.getAnnotation(Fact::class.java) != null ||
param.type == Scope::class.java)
}
}
.takeIf { it.isNotEmpty() }
.orThrowContractDefinition("Unable to build POJO of type ${clazz.name} because not all constructor params implement ${Message::class.java.name} and have a Fact annotation")
.firstOrNull {
it.parameters.any { param ->
scope.recordGroupList.flatMap { it.recordsList }.any { record ->
(record.resultName == param.getAnnotation(Fact::class.java)?.name &&
record.classname == param.type.name) ||
param.type == Scope::class.java
}
}
}
.orThrowContractDefinition("No constructor params have a matching fact in scope ${scope.uuid.value}")
val params = constructor.parameters
.map {
it.getAnnotation(Fact::class.java)?.name to it.type
}
.map { (name, type) ->
if (type == Scope::class.java) {
type to scope
} else {
type to scope.recordGroupList
.flatMap { it.recordsList }
.find { record ->
(record.resultName == name &&
record.classname == type.name) ||
type == Scope::class.java
}
}
}.map { (type, record) ->
when (record) {
is Record ->
completableFuture(executor) {
client.loadProto(
record.resultHash,
type.name
)
}
is Scope -> completableFuture(executor) { record }
else -> null
}
}
return clazz.cast(constructor.newInstance(*params.map { it?.get() }.toList().toTypedArray()))
}
companion object {
val executor = ThreadPoolFactory.newFixedThreadPool(20, "fact-hydrator-%d")
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy