org.springframework.cloud.contract.verifier.util.DelegatingJsonVerifiable.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.cloud.contract.verifier.util.DelegatingJsonVerifiable.java

Source

/*
 *  Copyright 2013-2016 the original author or authors.
 *
 *  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 org.springframework.cloud.contract.verifier.util;

import java.util.LinkedList;
import java.util.regex.Pattern;

import com.toomuchcoding.jsonassert.JsonVerifiable;

import static org.apache.commons.lang3.StringEscapeUtils.escapeJava;

/**
 * Implementation of the {@link MethodBufferingJsonVerifiable} that contains a list
 * of String method commands that need to be executed to assert JSONs.
 *
 * @author Marcin Grzejszczak
 *
 * @since 1.0.0
 */
class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {

    private static final Pattern FIELD_PATTERN = Pattern.compile("\\.field\\((\")?(.)+(\")?\\)");
    private static final Pattern ARRAY_PATTERN = Pattern.compile("\\.array\\((\")?(.)+(\")?\\)");

    final JsonVerifiable delegate;
    final LinkedList<String> methodsBuffer;

    DelegatingJsonVerifiable(JsonVerifiable delegate, LinkedList<String> methodsBuffer) {
        this.delegate = delegate;
        this.methodsBuffer = new LinkedList<>(methodsBuffer);
    }

    DelegatingJsonVerifiable(JsonVerifiable delegate) {
        this.delegate = delegate;
        this.methodsBuffer = new LinkedList<>();
    }

    private static String stringWithEscapedQuotes(Object object) {
        String stringValue = object.toString();
        return stringValue.replaceAll("\"", "\\\\\"");
    }

    private static String wrapValueWithQuotes(Object value) {
        return value instanceof String ? "\"" + stringWithEscapedQuotes(value) + "\"" : value.toString();
    }

    private void appendMethodWithValue(String methodName, Object value) {
        this.methodsBuffer.offer("." + methodName + "(" + value + ")");
    }

    private void appendMethodWithQuotedValue(String methodName, Object value) {
        appendMethodWithValue(methodName, wrapValueWithQuotes(value));
    }

    @Override
    public MethodBufferingJsonVerifiable contains(Object value) {
        DelegatingJsonVerifiable verifiable = new FinishedDelegatingJsonVerifiable(this.delegate.contains(value),
                this.methodsBuffer);
        verifiable.appendMethodWithQuotedValue("contains", value);
        if (isAssertingAValueInArray()) {
            verifiable.methodsBuffer.offer(".value()");
        }
        return verifiable;
    }

    @Override
    public MethodBufferingJsonVerifiable field(Object value) {
        Object valueToPut = value instanceof ShouldTraverse ? ((ShouldTraverse) value).value : value;
        DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.field(valueToPut),
                this.methodsBuffer);
        if (this.delegate.isIteratingOverArray() && !(value instanceof ShouldTraverse)) {
            verifiable.appendMethodWithQuotedValue("contains", valueToPut);
        } else {
            verifiable.appendMethodWithQuotedValue("field", valueToPut);
        }
        return verifiable;
    }

    @Override
    public MethodBufferingJsonVerifiable field(String... strings) {
        MethodBufferingJsonVerifiable verifiable = null;
        for (String string : strings) {
            verifiable = verifiable == null ? field(string) : verifiable.field(string);
        }
        return verifiable;
    }

    @Override
    public MethodBufferingJsonVerifiable array(Object value) {
        DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.array(value),
                this.methodsBuffer);
        verifiable.appendMethodWithQuotedValue("array", value);
        return verifiable;
    }

    @Override
    public MethodBufferingJsonVerifiable arrayField(Object value) {
        DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.field(value).arrayField(),
                this.methodsBuffer);
        verifiable.appendMethodWithQuotedValue("array", value);
        return verifiable;
    }

    @Override
    public MethodBufferingJsonVerifiable arrayField() {
        DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.arrayField(),
                this.methodsBuffer);
        verifiable.methodsBuffer.offer(".arrayField()");
        return verifiable;
    }

    @Override
    public MethodBufferingJsonVerifiable array() {
        DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.array(),
                this.methodsBuffer);
        verifiable.methodsBuffer.offer(".array()");
        return verifiable;
    }

    @Override
    public JsonVerifiable elementWithIndex(int i) {
        DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(this.delegate.elementWithIndex(i),
                this.methodsBuffer);
        this.methodsBuffer.offer(".elementWithIndex(" + i + ")");
        return verifiable;
    }

    @Override
    public MethodBufferingJsonVerifiable iterationPassingArray() {
        return new DelegatingJsonVerifiable(this.delegate, this.methodsBuffer);
    }

    @Override
    public MethodBufferingJsonVerifiable isEqualTo(String value) {
        DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.isEqualTo(value),
                this.methodsBuffer);
        if (this.delegate.isAssertingAValueInArray()
                && readyToCheck.methodsBuffer.peekLast().equals(".arrayField()")) {
            readyToCheck.appendMethodWithQuotedValue("isEqualTo", escapeJava(value));
            readyToCheck.methodsBuffer.offer(".value()");
        } else if (this.delegate.isAssertingAValueInArray()
                && !readyToCheck.methodsBuffer.peekLast().contains("array")) {
            readyToCheck.methodsBuffer.offer(".value()");
        } else {
            readyToCheck.appendMethodWithQuotedValue("isEqualTo", escapeJava(value));
        }
        return readyToCheck;
    }

    @Override
    public MethodBufferingJsonVerifiable isEqualTo(Object value) {
        if (value == null) {
            return isNull();
        }
        return isEqualTo(value.toString());
    }

    @Override
    public MethodBufferingJsonVerifiable isEqualTo(Number value) {
        DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.isEqualTo(value),
                this.methodsBuffer);
        // related to #271 - the problem is with asserting arrays of maps vs arrays of primitives
        String last = readyToCheck.methodsBuffer.peekLast();
        boolean containsAMatcher = containsAnyMatcher(last);
        if (this.delegate.isAssertingAValueInArray() && containsAMatcher) {
            readyToCheck.methodsBuffer.offer(".value()");
        } else {
            readyToCheck.appendMethodWithValue("isEqualTo", String.valueOf(value));
        }
        return readyToCheck;
    }

    private boolean containsAnyMatcher(String string) {
        return string.contains("isEqualTo") || string.contains("matches") || string.contains("isNull");
    }

    @Override
    public MethodBufferingJsonVerifiable isNull() {
        DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.isNull(),
                this.methodsBuffer);
        readyToCheck.methodsBuffer.offer(".isNull()");
        return readyToCheck;
    }

    @Override
    public MethodBufferingJsonVerifiable matches(String value) {
        DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.matches(value),
                this.methodsBuffer);
        if (this.delegate.isAssertingAValueInArray()) {
            readyToCheck.appendMethodWithQuotedValue("matches", escapeJava(value));
            readyToCheck.methodsBuffer.offer(".value()");
        } else {
            readyToCheck.appendMethodWithQuotedValue("matches", escapeJava(value));
        }
        return readyToCheck;
    }

    @Override
    public MethodBufferingJsonVerifiable isEqualTo(Boolean value) {
        DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.isEqualTo(value),
                this.methodsBuffer);
        if (this.delegate.isAssertingAValueInArray()) {
            readyToCheck.methodsBuffer.offer(".value()");
        } else {
            readyToCheck.appendMethodWithValue("isEqualTo", String.valueOf(value));
        }
        return readyToCheck;
    }

    @Override
    public MethodBufferingJsonVerifiable value() {
        return new FinishedDelegatingJsonVerifiable(this.delegate, this.methodsBuffer);
    }

    @Override
    public boolean assertsSize() {
        for (String s : this.methodsBuffer) {
            if (s.contains(".hasSize(")) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean assertsConcreteValue() {
        for (String s : this.methodsBuffer) {
            if (FIELD_PATTERN.matcher(s).matches() || ARRAY_PATTERN.matcher(s).matches()) {
                return true;
            }
        }
        return false;
    }

    @Override
    public JsonVerifiable withoutThrowingException() {
        return this.delegate.withoutThrowingException();
    }

    @Override
    public String jsonPath() {
        return this.delegate.jsonPath();
    }

    @Override
    public void matchesJsonPath(String s) {
        this.delegate.matchesJsonPath(s);
    }

    @Override
    public JsonVerifiable hasSize(int size) {
        FinishedDelegatingJsonVerifiable verifiable = new FinishedDelegatingJsonVerifiable(
                this.delegate.hasSize(size), this.methodsBuffer);
        verifiable.methodsBuffer.offer(".hasSize(" + size + ")");
        return verifiable;
    }

    @Override
    public boolean isIteratingOverNamelessArray() {
        return this.delegate.isIteratingOverNamelessArray();
    }

    @Override
    public boolean isIteratingOverArray() {
        return this.delegate.isIteratingOverArray();
    }

    @Override
    public boolean isAssertingAValueInArray() {
        return this.delegate.isAssertingAValueInArray();
    }

    @Override
    public String method() {
        return createMethodString();
    }

    private String createMethodString() {
        LinkedList<String> queue = new LinkedList<>(this.methodsBuffer);
        StringBuilder stringBuffer = new StringBuilder();
        while (!queue.isEmpty()) {
            stringBuffer.append(queue.remove());
        }
        return stringBuffer.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;

        DelegatingJsonVerifiable that = (DelegatingJsonVerifiable) o;

        if (this.delegate != null ? !this.delegate.equals(that.delegate) : that.delegate != null)
            return false;
        if (this.delegate == null) {
            return false;
        }
        if (this.delegate.jsonPath() == null && that.delegate.jsonPath() == null)
            return true;
        return this.delegate.jsonPath().equals(that.delegate.jsonPath());

    }

    @Override
    public int hashCode() {
        int result = this.delegate != null ? this.delegate.jsonPath().hashCode() : 0;
        return 31 * result;
    }

    @Override
    public String toString() {
        return "DelegatingJsonVerifiable{" + "delegate=\n" + this.delegate + ", methodsBuffer=" + this.methodsBuffer
                + '}';
    }

    @Override
    public <T> T read(Class<T> aClass) {
        return this.delegate.read(aClass);
    }
}