
com.xlrit.gears.engine.importer.JpaImportTarget Maven / Gradle / Ivy
package com.xlrit.gears.engine.importer;
import java.util.*;
import com.google.common.base.Preconditions;
import com.xlrit.gears.engine.meta.*;
import jakarta.persistence.EntityManager;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
@RequiredArgsConstructor
public class JpaImportTarget extends ResolveDirectImportTarget {
private final MetaManager metaManager;
private final EntityManager entityManager;
private EntityInfo> currentEntity = null;
@Override @SneakyThrows
public void startCollection(String name) {
super.startCollection(name);
Class> entityClass = Class.forName(name);
currentEntity = metaManager.requireEntityInfo(entityClass);
}
@Override
protected void doAdd(SkeletonObject skeleton) {
Preconditions.checkState(currentEntity != null, "Tried to add object before starting collection");
Object entity = currentEntity.newInstance(skeleton.id());
for (var entry : skeleton.attributes().entrySet()) {
SkeletonAttribute attribute = entry.getValue();
if (attribute.isNull()) continue;
BaseField field = currentEntity.getField(entry.getKey());
if (field.isReadOnly()) continue;
TypeInfo attributeType = field.getTypeInfo();
if (attribute.isBasicValue()) {
Object attrValue = buildSimpleValue(attributeType, attribute.getBasicValue());
field.setValue(entity, attrValue);
} // can safely assume direct references are either not present or other side already exists, since ResolveDirectImportTarget handles this
else {
Object attrValue = buildPointerValue(attributeType, attribute.getPointerValue());
field.trySetValueBidi(entity, attrValue);
}
}
entityManager.persist(entity);
}
private Object buildSimpleValue(TypeInfo attributeType, String rawValue) {
if (!(attributeType instanceof BasicTypeInfo basicTypeInfo)) {
throw new IllegalArgumentException("Cannot build simple value for attribute of type " + attributeType);
}
return rawValue == null ? null : basicTypeInfo.parse(rawValue);
}
@SneakyThrows
private Object buildPointerValue(TypeInfo attributeType, List pointers) {
if (attributeType instanceof EntityInfo>) {
if (pointers.size() != 1) {
throw new IllegalArgumentException("Cannot build multiple pointers into one-to-X association");
}
Pointer pointer = pointers.getFirst();
return requireReference(Class.forName(pointer.classFqn()), pointer.id());
} else if (attributeType instanceof MultipleInfo multipleType) {
if (!(multipleType.getElementType() instanceof EntityInfo>)) {
throw new IllegalArgumentException("Cannot build multiple attribute of type " + multipleType.getElementType());
}
List classes = pointers.stream().map(Pointer::classFqn).distinct().toList();
if (classes.size() != 1) {
throw new IllegalArgumentException("Cannot mix pointers to different types in multiple");
}
Class> clazz = Class.forName(classes.getFirst());
return pointers.stream()
.map(ptr -> requireReference(clazz, ptr.id()))
.toList();
}
throw new IllegalArgumentException("Cannot build pointer value for attribute of type " + attributeType);
}
private Object requireReference(Class> clazz, String id) {
Object object = entityManager.find(clazz, id);
if (object == null) {
throw new IllegalStateException(String.format("Tried to resolve reference to transient or non-existent object with id %s of class %s", id, clazz.getName()));
}
return object;
}
@Override
public void endCollection() {
entityManager.flush();
}
@Override
public void close() {
entityManager.close();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy