/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.transport.jaxrs;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import org.fudgemsg.FudgeField;
import org.fudgemsg.FudgeMsg;
import org.fudgemsg.FudgeMsgEnvelope;
import org.fudgemsg.MutableFudgeMsg;
import org.joda.beans.Bean;
import org.joda.beans.MetaProperty;
import org.joda.beans.impl.flexi.FlexiBean;
import org.joda.beans.ser.JodaBeanMimeType;
import org.joda.beans.ser.JodaBeanSer;
import com.opengamma.util.fudgemsg.OpenGammaFudgeContext;
/**
* A JAX-RS provider to convert RESTful Joda-Bean instances to and from JSON encoded messages.
*/
@Provider
@Produces(JodaBeanMimeType.JSON)
@Consumes(JodaBeanMimeType.JSON)
public class JodaBeanJsonProducerConsumer implements MessageBodyReader<Object>, MessageBodyWriter<Object> {
/**
* Creates an instance.
*/
public JodaBeanJsonProducerConsumer() {
super();
}
//-------------------------------------------------------------------------
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return Bean.class.isAssignableFrom(type) || type == FudgeResponse.class ||
FudgeMsgEnvelope.class.isAssignableFrom(type) || FudgeMsg.class.isAssignableFrom(type);
}
@Override
public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
boolean isBean = Bean.class.isAssignableFrom(type);
Class<? extends Bean> cls = (isBean ? type.asSubclass(Bean.class) : FlexiBean.class);
Reader reader = new InputStreamReader(entityStream, StandardCharsets.UTF_8);
Bean bean = JodaBeanSer.PRETTY.jsonReader().read(reader, cls);
if (isBean) {
return bean;
}
FlexiBean fbean = (FlexiBean) bean;
if (((Object) type) == FudgeResponse.class) {
return FudgeResponse.of(fbean.get("value"));
}
if (((Object) type) == FudgeMsg.class) {
return createMessage(bean);
}
if (((Object) type) == FudgeMsgEnvelope.class) {
return new FudgeMsgEnvelope(createMessage(bean));
}
return bean;
}
private MutableFudgeMsg createMessage(Bean bean) {
MutableFudgeMsg msg = OpenGammaFudgeContext.getInstance().newMessage();
for (MetaProperty<?> mp : bean.metaBean().metaPropertyIterable()) {
Object obj = mp.get(bean);
if (obj instanceof Bean) {
msg.add(mp.name(), createMessage((Bean) obj));
} else {
msg.add(mp.name(), obj);
}
}
return msg;
}
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return Bean.class.isAssignableFrom(type) || type == FudgeResponse.class ||
FudgeMsgEnvelope.class.isAssignableFrom(type) || FudgeMsg.class.isAssignableFrom(type);
}
@Override
public long getSize(Object bean, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return -1;
}
@Override
public void writeTo(Object obj, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
Bean bean = null;
if (Bean.class.isAssignableFrom(type)) {
bean = (Bean) obj;
} else {
if (((Object) type) == FudgeResponse.class) {
FudgeResponse rsp = (FudgeResponse) obj;
FlexiBean fb = new FlexiBean();
fb.set("value", rsp.getValue());
bean = fb;
} else if (((Object) type) == FudgeMsg.class) {
FudgeMsg msg = (FudgeMsg) obj;
bean = createBean(msg);
} else if (((Object) type) == FudgeMsgEnvelope.class) {
FudgeMsgEnvelope env = (FudgeMsgEnvelope) obj;
bean = createBean(env.getMessage());
}
}
String json = JodaBeanSer.PRETTY.jsonWriter().write(bean);
byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
entityStream.write(bytes);
}
private Bean createBean(FudgeMsg msg) {
FlexiBean fb = new FlexiBean();
for (FudgeField field : msg.getAllFields()) {
Object obj = field.getValue();
if (obj instanceof FudgeMsg) {
fb.set(field.getName(), createBean((FudgeMsg) obj));
} else {
fb.set(field.getName(), obj);
}
}
return fb;
}
}