com.bazaarvoice.jolt.jsonUtil.testdomain.five.MappingTest5.java Source code

Java tutorial

Introduction

Here is the source code for com.bazaarvoice.jolt.jsonUtil.testdomain.five.MappingTest5.java

Source

/*
 * Copyright 2014 Bazaarvoice, Inc.
 *
 * 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.bazaarvoice.jolt.jsonUtil.testdomain.five;

import com.bazaarvoice.jolt.Diffy;
import com.bazaarvoice.jolt.JsonUtil;
import com.bazaarvoice.jolt.JsonUtils;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.testng.AssertJUnit;
import org.testng.annotations.Test;

import java.io.IOException;
import java.util.Map;

public class MappingTest5 {

    private Diffy diffy = new Diffy();

    public static class QueryFilter5Deserializer extends JsonDeserializer<QueryFilter5> {

        /**
         * I tried moving this logic to be an @JsonDeserialize on the QueryFilter5 interface
         *  but I could not get it to work.
         *
         * When this logic was moved there (and other logic was messed with), I would either get
         *  A) Deserializaion error on the List<QueryFilter5> in the LogicalFilter5 or
         *  B) stack overflow from bad recursion
         *
         * The problem with the List<QueryFilter5> in the LogicalFilter5, seemed like it
         *  looked at the type of the first QueryFilter5, and assumed that all the elements in
         *  the Array/List would be the same time, which totally breaks the goal of mixing
         *  Real and Logical QueryFilter subclasses.
         */
        @Override
        public QueryFilter5 deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {

            ObjectNode root = jp.readValueAsTree();

            // pass in our objectCodec so that the subJsonParser knows about our configured Modules and Annotations
            JsonParser subJsonParser = root.traverse(jp.getCodec());

            // Check if it is a "RealFilter"
            JsonNode valuesParam = root.get("values");

            if (valuesParam == null) {
                return subJsonParser.readValueAs(LogicalFilter5.class);
            }
            if (!valuesParam.isArray()) {
                throw new RuntimeException("Expected an Array");
            }

            return subJsonParser.readValueAs(RealFilter5.class);
        }
    }

    @Test
    public void testPolymorphicJacksonSerializationAndDeserialization() {
        ObjectMapper mapper = new ObjectMapper();

        SimpleModule testModule = new SimpleModule("testModule", new Version(1, 0, 0, null, null, null))
                .addDeserializer(QueryFilter5.class, new QueryFilter5Deserializer());

        mapper.registerModule(testModule);

        // Verifying that we can pass in a custom Mapper and create a new JsonUtil
        JsonUtil jsonUtil = JsonUtils.customJsonUtil(mapper);

        String testFixture = "/jsonUtils/testdomain/five/queryFilter-realAndLogical5.json";

        // TEST JsonUtil and our deserialization logic
        QueryFilter5 queryFilter = jsonUtil.classpathToType(testFixture, new TypeReference<QueryFilter5>() {
        });

        // Make sure the hydrated QFilter looks right
        AssertJUnit.assertTrue(queryFilter instanceof LogicalFilter5);
        LogicalFilter5 andFilter = (LogicalFilter5) queryFilter;
        AssertJUnit.assertEquals(Operator.AND, andFilter.getOperator());
        AssertJUnit.assertNotNull(andFilter.getValues());
        AssertJUnit.assertEquals(3, andFilter.getValues().size());

        // Make sure one of the top level RealFilters looks right
        QueryFilter5 productIdFilter = andFilter.getValues().get(1);
        AssertJUnit.assertTrue(productIdFilter instanceof StringRealFilter5);
        StringRealFilter5 stringRealProductIdFilter = (StringRealFilter5) productIdFilter;
        AssertJUnit.assertEquals(Field.PRODUCTID, stringRealProductIdFilter.getField());
        AssertJUnit.assertEquals(Operator.EQ, stringRealProductIdFilter.getOperator());
        AssertJUnit.assertEquals("Acme-1234", stringRealProductIdFilter.getValues().get(0));

        // Make sure the nested OR looks right
        QueryFilter5 orFilter = andFilter.getValues().get(2);
        AssertJUnit.assertTrue(orFilter instanceof LogicalFilter5);
        LogicalFilter5 realOrFilter = (LogicalFilter5) orFilter;
        AssertJUnit.assertEquals(Operator.OR, realOrFilter.getOperator());
        AssertJUnit.assertEquals(2, realOrFilter.getValues().size());

        // Make sure nested AND looks right
        QueryFilter5 nestedAndFilter = realOrFilter.getValues().get(1);
        AssertJUnit.assertTrue(nestedAndFilter instanceof LogicalFilter5);
        AssertJUnit.assertEquals(Operator.AND, nestedAndFilter.getOperator());
        AssertJUnit.assertEquals(3, nestedAndFilter.getValues().size());

        // SERIALIZE TO STRING to test serialization logic
        String unitTestString = jsonUtil.toJsonString(queryFilter);

        // LOAD and Diffy the plain vanilla JSON versions of the documents
        Map<String, Object> actual = JsonUtils.jsonToMap(unitTestString);
        Map<String, Object> expected = JsonUtils.classpathToMap(testFixture);

        // Diffy the vanilla versions
        Diffy.Result result = diffy.diff(expected, actual);
        if (!result.isEmpty()) {
            AssertJUnit.fail("Failed.\nhere is a diff:\nexpected: " + JsonUtils.toJsonString(result.expected)
                    + "\n  actual: " + JsonUtils.toJsonString(result.actual));
        }
    }
}