blob: 1266dc811fa5c40826cffc7bb10e9ffd37e91a35 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Roman Grigoriadi
******************************************************************************/
package org.eclipse.persistence.json.bind.internal.serializer;
import org.eclipse.persistence.json.bind.internal.Marshaller;
import org.eclipse.persistence.json.bind.internal.adapter.AdapterBinding;
import org.eclipse.persistence.json.bind.internal.properties.MessageKeys;
import org.eclipse.persistence.json.bind.internal.properties.Messages;
import org.eclipse.persistence.json.bind.internal.unmarshaller.CurrentItem;
import org.eclipse.persistence.json.bind.model.ClassModel;
import org.eclipse.persistence.json.bind.model.Customization;
import org.eclipse.persistence.json.bind.model.JsonBindingModel;
import org.eclipse.persistence.json.bind.model.JsonContext;
import javax.json.bind.JsonbException;
import javax.json.bind.adapter.JsonbAdapter;
import javax.json.bind.serializer.JsonbSerializer;
import javax.json.bind.serializer.SerializationContext;
import javax.json.stream.JsonGenerator;
import java.lang.reflect.Type;
/**
* Serializer for adapted object.
* Converts object using adapter first, than seriazizes result with standard process.
* @author Roman Grigoriadi
*/
public class AdaptedObjectSerializer<T, A> implements CurrentItem<T>, JsonbSerializer<T> {
private final static class AdaptedObjectSerializerModel implements JsonBindingModel {
private final JsonBindingModel wrapperSerializerModel;
private final Type adaptedType;
public AdaptedObjectSerializerModel(JsonBindingModel wrapperSerializerModel, Type adaptedType) {
this.wrapperSerializerModel = wrapperSerializerModel;
this.adaptedType = adaptedType;
}
@Override
public String getWriteName() {
return wrapperSerializerModel.getWriteName();
}
/**
* Array context if root.
*/
@Override
public JsonContext getContext() {
return wrapperSerializerModel != null ?
wrapperSerializerModel.getContext() : JsonContext.JSON_ARRAY;
}
/**
* Get wrapper customization or empty if wrapper not present (root).
*/
@Override
public Customization getCustomization() {
return wrapperSerializerModel != null ?
wrapperSerializerModel.getCustomization() : null;
}
@Override
public Type getType() {
return adaptedType;
}
}
private final JsonBindingModel model;
private final AdapterBinding adapterInfo;
public AdaptedObjectSerializer(JsonBindingModel model, AdapterBinding adapter) {
this.model = new AdaptedObjectSerializerModel(model, adapter.getToType());
this.adapterInfo = adapter;
}
@Override
public void serialize(T obj, JsonGenerator generator, SerializationContext ctx) {
try {
final JsonbAdapter<T, A> adapter = (JsonbAdapter<T, A>) adapterInfo.getAdapter();
A adapted = adapter.adaptToJson(obj);
final JsonbSerializer<A> serializer = resolveSerializer((Marshaller) ctx, adapted);
serializer.serialize(adapted, generator, ctx);
} catch (Exception e) {
throw new JsonbException(Messages.getMessage(MessageKeys.ADAPTER_EXCEPTION, adapterInfo.getBindingType(), adapterInfo.getToType(), adapterInfo.getAdapter().getClass()), e);
}
}
@SuppressWarnings("unchekced")
private JsonbSerializer<A> resolveSerializer(Marshaller ctx, A adapted) {
final ContainerSerializerProvider cached = ctx.getMappingContext().getSerializerProvider(adapted.getClass());
if (cached != null) {
return (JsonbSerializer<A>) cached.provideSerializer(this, adapted.getClass(), null, model);
}
return (JsonbSerializer<A>) new SerializerBuilder(ctx.getJsonbContext()).withObjectClass(adapted.getClass()).withModel(model).withWrapper(this).build();
}
/**
* Class model containing property for this item.
*
* @return class model
*/
@Override
public ClassModel getClassModel() {
return null;
}
/**
* Item wrapper. Null only in case of a root item.
*
* @return wrapper item of this item
*/
@Override
public CurrentItem<?> getWrapper() {
return null;
}
/**
* Binding model of this item in wrapper. May be JavaBean property or a container like collection.
*
* @return wrapper model.
*/
@Override
public JsonBindingModel getWrapperModel() {
return model;
}
/**
* Runtime type of a class. Can be a class, ParameterizedType, or TypeVariable.
* When a field or a class is declared including generic information this will return runtime type info.
*
* @return
*/
@Override
public Type getRuntimeType() {
return null;
}
}