
com.xlrit.gears.engine.meta.ObjectInfo Maven / Gradle / Ivy
package com.xlrit.gears.engine.meta;
import java.lang.reflect.Constructor;
import java.util.List;
import java.util.stream.Collectors;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.NullNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import com.xlrit.gears.base.execution.Execution;
import com.xlrit.gears.engine.form.SubmitContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.checkNotNull;
public abstract class ObjectInfo implements TypeInfo, PathEval {
private static final Logger LOG = LoggerFactory.getLogger(ObjectInfo.class);
protected final String kind;
protected final Class> clazz;
protected final List extends F> fields;
protected final Constructor extends T> constructor; // can be null, in which case no new instance can be created
protected ObjectInfo(String kind, Class extends T> clazz, List extends F> fields) {
this.kind = checkNotNull(kind);
this.clazz = checkNotNull(clazz);
this.fields = checkNotNull(fields);
this.constructor = findDefaultConstructor(clazz);
}
@Override
public boolean isEntityReference() {
return false;
}
@Override
public Class> getJavaType() {
return clazz;
}
public String getKind() {
return kind;
}
public Class> getObjectClass() {
return clazz;
}
public List extends F> getFields() {
return fields;
}
private List getFieldNames() {
return fields.stream()
.map(BaseField::getName)
.collect(Collectors.toList());
}
public F getField(String name) {
return fields.stream()
.filter(field -> name.equals(field.getName()))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("No field found with name '" + name + "' in object info for " + clazz.getSimpleName() + " " + getFieldNames()));
}
@Override
public R evaluate(String path, Execution execution, FieldFunction f) {
String[] result = PathEval.extractName(path);
String name = result[0]; String rest = result[1];
return getField(name).evaluate(rest, execution, f);
}
@Override
public String getTypeName() {
return clazz.getName();
}
@Override
public String getId(Object instance) {
return null;
}
@Override
public Object getInstance(String id) {
throw new UnsupportedOperationException();
}
@Override
public String print(Object obj, PrintOptions printOptions) {
return String.valueOf(obj);
}
@Override
public Object fromFormValue(JsonNode formValue, SubmitContext ctx) {
throw new UnsupportedOperationException();
}
@Override
public JsonNode toFormValue(Object obj, ObjectMapper objectMapper) {
throw new UnsupportedOperationException();
}
public T newInstance() {
if (constructor == null) {
throw new RuntimeException("Unable to create new instance of " + clazz + ": no accessable default constructor");
}
try {
return constructor.newInstance();
}
catch (ReflectiveOperationException e) {
throw new RuntimeException("Unable to create new instance of " + clazz + ": " + e.getMessage(), e);
}
}
@Override
public JsonNode serialize(Object instance, ObjectMapper objectMapper, PrintOptions printOptions) {
if (instance == null) return NullNode.instance;
ObjectNode result = objectMapper.createObjectNode();
result.set("__kind", TextNode.valueOf(kind));
String id = getId(instance);
if (id != null) {
result.set("__id", TextNode.valueOf(id));
result.set("__typeName", TextNode.valueOf(getTypeName()));
if (printOptions != null) result.put("__text", print(instance, printOptions));
}
else {
for (F field : fields) {
String fieldName = field.getName();
Object fieldValue = field.getValue(instance);
result.set(fieldName, field.serialize(objectMapper, fieldValue, printOptions));
}
}
LOG.debug("Object {} serialized as {}", instance, result);
return result;
}
@Override
public Object deserialize(JsonNode node, ObjectMapper objectMapper) {
if (node == null || node.isNull()) return null;
JsonNode idNode = node.get("__id");
if (idNode != null) {
Object instance = getInstance(idNode.asText());
LOG.debug("JSON {} deserialized using reference {} as {}", node, idNode.asText(), instance);
return instance;
}
else {
Object obj = newInstance();
for (F field : fields) {
if (field.isReadOnly()) continue;
JsonNode valueNode = node.get(field.getName());
Object value = field.deserialize(objectMapper, valueNode);
field.setValue(obj, value);
}
LOG.debug("JSON {} deserialized as {}", node, obj);
return obj;
}
}
private static Constructor findDefaultConstructor(Class clazz) {
try {
Constructor constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
return constructor;
}
catch (ReflectiveOperationException e) {
return null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy