/*
* Copyright 2014, The Sporting Exchange Limited
*
* 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.betfair.cougar.marshalling.impl.databinding.json;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.*;
import com.betfair.cougar.api.fault.FaultCode;
import com.betfair.cougar.core.api.client.EnumWrapper;
import com.betfair.cougar.core.api.exception.CougarMarshallingException;
import com.betfair.cougar.core.api.fault.CougarFault;
import com.betfair.cougar.core.api.fault.FaultDetail;
import com.betfair.cougar.core.api.transcription.EnumDerialisationException;
import com.betfair.cougar.core.api.transcription.ParameterType;
import com.betfair.cougar.marshalling.api.databinding.FaultUnMarshaller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.type.SimpleType;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.betfair.cougar.marshalling.api.databinding.UnMarshaller;
public class JSONUnMarshaller implements UnMarshaller, FaultUnMarshaller {
private final ObjectMapper objectMapper;
public JSONUnMarshaller(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override
public String getFormat() {
return "json";
}
@Override
public Object unmarshall(InputStream inputStream, Class<?> clazz, String encoding, boolean client) {
try {
Reader reader = new BufferedReader(new InputStreamReader(inputStream,encoding));
return objectMapper.readValue(reader, clazz);
} catch (JsonProcessingException e) {
// if (e.getCause() instanceof CougarException) {
// throw (CougarException) e.getCause();
// }
throw CougarMarshallingException.unmarshallingException(getFormat(), e, client);
} catch (IOException e) {
throw CougarMarshallingException.unmarshallingException(getFormat(), "Failed to unmarshall object", e, client);
}
}
private static final ParameterType STRING_PARAM_TYPE = new ParameterType(String.class, null);
public Object unmarshall(InputStream inputStream, ParameterType parameterType, String encoding, boolean client) {
try {
Reader reader = new BufferedReader(new InputStreamReader(inputStream,encoding));
if (parameterType.getImplementationClass().equals(EnumWrapper.class)) {
String value = objectMapper.readValue(reader, buildJavaType(STRING_PARAM_TYPE));
//noinspection unchecked
return new EnumWrapper(parameterType.getComponentTypes()[0].getImplementationClass(), value);
}
else {
return objectMapper.readValue(reader, buildJavaType(parameterType));
}
} catch (EnumDerialisationException e) {
throw CougarMarshallingException.unmarshallingException(getFormat(), "Failed to unmarshall enum", e, client);
} catch (JsonProcessingException e) {
throw CougarMarshallingException.unmarshallingException(getFormat(), "Failed to unmarshall object", e, client);
} catch (IOException e) {
throw CougarMarshallingException.unmarshallingException(getFormat(), "Failed to unmarshall object", e, client);
}
}
public static JavaType buildJavaType(ParameterType paramType) {
return paramType.transform(new ParameterType.TransformingVisitor<JavaType>() {
@Override
public JavaType transformMapType(JavaType keyType, JavaType valueType) {
return TypeFactory.defaultInstance().constructMapType(HashMap.class, keyType, valueType);
}
@Override
public JavaType transformListType(JavaType elemType) {
return TypeFactory.defaultInstance().constructCollectionType(ArrayList.class, elemType);
}
@Override
public JavaType transformSetType(JavaType elemType) {
return TypeFactory.defaultInstance().constructCollectionType(HashSet.class, elemType);
}
@Override
public JavaType transformType(ParameterType.Type type, Class implementationClass) {
return TypeFactory.defaultInstance().uncheckedSimpleType(implementationClass);
}
});
}
@Override
public CougarFault unMarshallFault(InputStream inputStream, String encoding) {
//noinspection unchecked
final HashMap<String,Object> faultMap = (HashMap<String,Object>) unmarshall(inputStream, HashMap.class, encoding, true);
final String faultString = (String)faultMap.get("faultstring");
final FaultCode faultCode = FaultCode.valueOf((String) faultMap.get("faultcode"));
//noinspection unchecked
final HashMap<String, Object> detailMap = (HashMap<String, Object>)faultMap.get("detail");
String exceptionName = (String)detailMap.get("exceptionname");
List<String[]> faultParams = Collections.emptyList();
if (exceptionName != null) {
faultParams = new ArrayList<>();
//noinspection unchecked
Map<String, Object> paramMap = (Map<String, Object>) detailMap.get(exceptionName);
for(Map.Entry e:paramMap.entrySet()){
String[] nvpair=new String[] { (String)e.getKey(), e.getValue().toString() };
faultParams.add(nvpair);
}
}
final FaultDetail fd=new FaultDetail(faultString, faultParams);
return new CougarFault() {
@Override
public String getErrorCode() {
return faultString;
}
@Override
public FaultCode getFaultCode() {
return faultCode;
}
@Override
public FaultDetail getDetail() {
return fd;
}
};
}
}