001/*
002 *   Copyright 2020 Vonage
003 *
004 *   Licensed under the Apache License, Version 2.0 (the "License");
005 *   you may not use this file except in compliance with the License.
006 *   You may obtain a copy of the License at
007 *
008 *        http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *   Unless required by applicable law or agreed to in writing, software
011 *   distributed under the License is distributed on an "AS IS" BASIS,
012 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *   See the License for the specific language governing permissions and
014 *   limitations under the License.
015 */
016package com.vonage.client.verify;
017
018import com.fasterxml.jackson.core.JsonParser;
019import com.fasterxml.jackson.databind.DeserializationContext;
020import com.fasterxml.jackson.databind.JsonDeserializer;
021import com.fasterxml.jackson.databind.JsonNode;
022import com.fasterxml.jackson.databind.ObjectMapper;
023
024import java.io.IOException;
025import java.text.SimpleDateFormat;
026import java.util.Collections;
027
028public class SearchVerifyResponseDeserializer extends JsonDeserializer<SearchVerifyResponse> {
029    @Override
030    public SearchVerifyResponse deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
031        JsonNode node = p.getCodec().readTree(p);
032        // TODO: Restructure objects to handle this better.
033        // Deserialization is a little complicated here.  There are a few things to consider:
034        // (1) A search request with a single result comes back with that single result as json.
035        // (2) A search request with multiple results comes back with those results as an array in the
036        //     verification_requests property.
037        // (3) A search request which comes back in error has different Status values than search requests
038        //     that come back without error. (See VerifyStatus vs VerifyDetails.Status)
039
040        // If the results has a verification_requests node then we can successfully map our object as normal.
041        if (node.has("verification_requests")) {
042            // Have to create a second object mapper to handle this as we want to bypass custom deserialization.
043            ObjectMapper mapper = new ObjectMapper();
044            mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
045            return mapper.readValue(node.toString(), SearchVerifyResponse.class);
046        }
047
048        // If the result has error_text, we can assume that the only fields that matter are status and the error.
049        if (node.has("error_text")) {
050            return new SearchVerifyResponse(VerifyStatus.fromInt(node.get("status").asInt()),
051                                            node.get("error_text").asText());
052        }
053        // Otherwise we need to map the single result and then put it on the list as is.
054        VerifyDetails details = p.getCodec().treeToValue(node, VerifyDetails.class);
055        return new SearchVerifyResponse(Collections.singletonList(details));
056    }
057}