/** * Copyright 2008-2016 Qualogy Solutions B.V. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.qualogy.qafe.jaxrs.businessaction; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.lang.annotation.Annotation; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.ws.rs.Consumes; import javax.ws.rs.Produces; 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 com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.qualogy.qafe.bind.core.application.Configuration; import com.qualogy.qafe.businessaction.impl.BusinessActionParameterBean; import com.qualogy.qafe.core.application.ApplicationCluster; /** * Due to the dynamic nature of business action parameters (number and type of input/output parameters are * unknown beforehand), this provider supports converting a json stream to a list of business action * parameters and vice versa. * * @author sdahlberg * */ @Provider @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public final class ParameterMessageBodyReaderWriter implements MessageBodyReader<List<BusinessActionParameterBean>>, MessageBodyWriter<List<BusinessActionParameterBean>> { private static final String UTF_8 = "UTF-8"; private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; private final Gson gson; public ParameterMessageBodyReaderWriter() { final String configDateFormat = ApplicationCluster.getInstance().getConfigurationItem(Configuration.WEB_SERVICE_FORMAT_DATE); final String dateFormat; if (configDateFormat == null) { dateFormat = DEFAULT_DATE_FORMAT; } else { dateFormat = configDateFormat; } gson = new GsonBuilder().setDateFormat(dateFormat).create(); } @Override public boolean isReadable(final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) { if (type != List.class && !(genericType instanceof ParameterizedType)) { return false; } final ParameterizedType parameterizedType = (ParameterizedType) genericType; final Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); if (actualTypeArguments.length == 0) { return false; } return actualTypeArguments[0] == BusinessActionParameterBean.class; } @Override public List<BusinessActionParameterBean> readFrom(final Class<List<BusinessActionParameterBean>> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType, final MultivaluedMap<String, String> httpHeaders, final InputStream entityStream) throws IOException { final List<Map<String, String>> fromJson = parseJson(entityStream); final List<BusinessActionParameterBean> inputParameters = toInputParameters(fromJson); return inputParameters; } @Override public long getSize(final List<BusinessActionParameterBean> parameters, final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) { return -1; } @Override public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) { return isReadable(type, genericType, annotations, mediaType); } @Override public void writeTo(final List<BusinessActionParameterBean> parameters, final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType, final MultivaluedMap<String, Object> arg5, final OutputStream entityStream) throws IOException { final List<Map<String, Object>> jsonParameters = new ArrayList<Map<String, Object>>(); for (final BusinessActionParameterBean parameterBean : parameters) { final Map<String, Object> keyValuePair = new HashMap<String, Object>(); keyValuePair.put(parameterBean.getKey(), parameterBean.getValue()); jsonParameters.add(keyValuePair); } final OutputStreamWriter writer = new OutputStreamWriter(entityStream, UTF_8); try { gson.toJson(jsonParameters, writer); } finally { writer.close(); } } @SuppressWarnings("unchecked") private List<Map<String, String>> parseJson(final InputStream inputStream) throws IOException { final InputStreamReader reader = new InputStreamReader(inputStream, UTF_8); try { // By default gson parses the Object into a list of maps of string to string return (List<Map<String, String>>) gson.fromJson(reader, Object.class); } finally { reader.close(); } } private List<BusinessActionParameterBean> toInputParameters(final List<Map<String, String>> parsedInput) { final List<BusinessActionParameterBean> inputParameters = new ArrayList<BusinessActionParameterBean>(parsedInput.size()); for (final Map<String, String> input : parsedInput) { final BusinessActionParameterBean inputParameterBean = new BusinessActionParameterBean(); final Entry<String, String> next = input.entrySet().iterator().next(); inputParameterBean.setKey(next.getKey()); inputParameterBean.setValue(next.getValue()); inputParameters.add(inputParameterBean); } return inputParameters; } }