001package systems.dmx.webservice.provider;
002
003import systems.dmx.core.osgi.CoreActivator;
004import systems.dmx.core.util.JavaUtils;
005
006import org.codehaus.jettison.json.JSONObject;
007
008import java.io.InputStream;
009import java.io.IOException;
010import java.lang.annotation.Annotation;
011import java.lang.reflect.Constructor;
012import java.lang.reflect.Method;
013import java.lang.reflect.Type;
014import java.util.logging.Logger;
015
016import javax.ws.rs.WebApplicationException;
017import javax.ws.rs.core.MediaType;
018import javax.ws.rs.core.MultivaluedMap;
019import javax.ws.rs.ext.MessageBodyReader;
020import javax.ws.rs.ext.Provider;
021
022
023
024@Provider
025public class ObjectProvider implements MessageBodyReader<Object> {
026
027    // ---------------------------------------------------------------------------------------------- Instance Variables
028
029    private Logger logger = Logger.getLogger(getClass().getName());
030
031    // -------------------------------------------------------------------------------------------------- Public Methods
032
033    // *** MessageBodyReader Implementation ***
034
035    @Override
036    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
037        // Note: unlike equals() isCompatible() ignores parameters like "charset" in "application/json;charset=UTF-8"
038        return (getFactoryMethod(type) != null || getJSONConstructor(type) != null) &&
039            mediaType.isCompatible(MediaType.APPLICATION_JSON_TYPE);
040    }
041
042    @Override
043    public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
044                           MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
045                                                                  throws IOException, WebApplicationException {
046        try {
047            JSONObject json = new JSONObject(JavaUtils.readText(entityStream));
048            Method method = getFactoryMethod(type);
049            if (method != null) {
050                return method.invoke(CoreActivator.getModelFactory(), json);
051            } else {
052                return getJSONConstructor(type).newInstance(json);
053            }
054        } catch (Exception e) {
055            throw new RuntimeException("Deserializing a " + type.getName() + " object failed", e);
056        }
057    }
058
059    // ------------------------------------------------------------------------------------------------- Private Methods
060
061    private Method getFactoryMethod(Class<?> type) {
062        try {
063            String methodName = "new" + type.getSimpleName();
064            return CoreActivator.getModelFactory().getClass().getDeclaredMethod(methodName, JSONObject.class);
065        } catch (NoSuchMethodException e) {
066            return null;
067        }
068    }
069
070    private Constructor<?> getJSONConstructor(Class<?> type) {
071        try {
072            return type.getDeclaredConstructor(JSONObject.class);
073        } catch (NoSuchMethodException e) {
074            return null;
075        }
076    }
077}