package org.emfjson.jackson.databind.property;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.*;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.emfjson.jackson.databind.EMFContext;
import org.emfjson.jackson.databind.deser.ReferenceEntries;
import org.emfjson.jackson.databind.deser.ReferenceEntry;
import org.emfjson.jackson.databind.type.FeatureKind;
import java.io.IOException;
import static org.emfjson.jackson.annotations.JsonAnnotations.getElementName;
import static org.emfjson.jackson.module.EMFModule.Feature.OPTION_SERIALIZE_DEFAULT_VALUE;
public class EObjectFeatureProperty extends EObjectProperty {
private final EStructuralFeature feature;
private final JavaType javaType;
private final boolean defaultValues;
private JsonSerializer<Object> serializer;
public EObjectFeatureProperty(EStructuralFeature feature, JavaType type, int features) {
super(getElementName(feature));
this.feature = feature;
this.javaType = type;
this.defaultValues = OPTION_SERIALIZE_DEFAULT_VALUE.enabledIn(features);
}
@Override
public void deserializeAndSet(JsonParser jp, EObject current, DeserializationContext ctxt, Resource resource) throws IOException {
final JsonDeserializer<Object> deserializer = ctxt.findContextualValueDeserializer(javaType, null);
if (jp.getCurrentToken() == JsonToken.FIELD_NAME) {
jp.nextToken();
}
if (jp.getCurrentToken() == JsonToken.VALUE_NULL) {
return;
}
switch (FeatureKind.get(feature)) {
case MAP:
case MANY_CONTAINMENT:
case SINGLE_CONTAINMENT: {
EMFContext.setFeature(ctxt, feature);
EMFContext.setParent(ctxt, current);
}
case SINGLE_ATTRIBUTE:
case MANY_ATTRIBUTE: {
if (feature.getEType() instanceof EDataType) {
EMFContext.setDataType(ctxt, feature.getEType());
}
if (feature.isMany()) {
deserializer.deserialize(jp, ctxt, current.eGet(feature));
} else {
Object value = deserializer.deserialize(jp, ctxt);
if (value != null) {
current.eSet(feature, value);
}
}
}
break;
case MANY_REFERENCE:
case SINGLE_REFERENCE: {
EMFContext.setFeature(ctxt, feature);
EMFContext.setParent(ctxt, current);
ReferenceEntries entries = EMFContext.getEntries(ctxt);
if (feature.isMany()) {
deserializer.deserialize(jp, ctxt, entries.entries());
} else {
Object value = deserializer.deserialize(jp, ctxt);
if (entries != null && value instanceof ReferenceEntry) {
entries.entries().add((ReferenceEntry) value);
}
}
}
break;
}
}
@Override
public void serialize(EObject bean, JsonGenerator jg, SerializerProvider provider) throws IOException {
if (serializer == null) {
serializer = provider.findValueSerializer(javaType);
}
EMFContext.setParent(provider, bean);
EMFContext.setFeature(provider, feature);
if (bean.eIsSet(feature)) {
Object value = bean.eGet(feature, false);
jg.writeFieldName(getFieldName());
serializer.serialize(value, jg, provider);
} else if (defaultValues) {
Object value = feature.getDefaultValue();
if (value != null) {
jg.writeFieldName(getFieldName());
serializer.serialize(value, jg, provider);
}
}
}
@Override
public EObject deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
return null;
}
}