package com.epam.wilma.sequence.formatters; /*========================================================================== Copyright 2013-2017 EPAM Systems This file is part of Wilma. Wilma is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Wilma is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Wilma. If not, see <http://www.gnu.org/licenses/>. ===========================================================================*/ import java.nio.charset.StandardCharsets; import java.util.Map; import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.epam.wilma.domain.http.WilmaHttpRequest; import com.epam.wilma.domain.stubconfig.dialog.response.template.TemplateFormatter; import com.epam.wilma.domain.stubconfig.parameter.ParameterList; import com.epam.wilma.domain.sequence.WilmaSequence; import com.epam.wilma.sequence.formatters.helper.SequenceJsonTransformer; import com.epam.wilma.webapp.stub.response.formatter.json.JsonTemplateFormatter; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonPrimitive; import com.jayway.jsonpath.JsonPath; import javax.servlet.http.HttpServletResponse; /** * Generates a JSON response from the given template resource by using * parameters from the request. Properties in the templates with JsonPath value * will be replaces with the evaluated expression value (e.g. * {@code"$.persons[0].name"}). This formatter has access previous messages of * the session. Those messages can be accessed like * {@code"$BalanceCheckRequest.card_details.card_number"}). * * @author Balazs_Berkes */ @Component public class SequenceAwareJsonTemplateFormatter implements TemplateFormatter { @Autowired private SequenceJsonTransformer sequenceJsonTransformer; @Override public byte[] formatTemplate(final WilmaHttpRequest wilmaRequest, final HttpServletResponse resp, final byte[] templateResource, final ParameterList params) throws Exception { JsonElement response = new JsonParser().parse(IOUtils.toString(templateResource, StandardCharsets.UTF_8.name())); new SessionAwareJsonTreeEvaluator(wilmaRequest.getBody(), wilmaRequest.getSequence(), params).replaceAllNonRecursive(response); return response.toString().getBytes(); } private final class SessionAwareJsonTreeEvaluator extends JsonTemplateFormatter.NonRecursiveJsonTreeEvaluator { private static final String SELF_REQUEST_REFFERENCE = "request"; private static final String SIMPLE_JSON_PATH_PREFIX = "$."; private static final String SESSION_JSON_PATH_PREFIX = "$"; private final WilmaSequence sequence; private final ParameterList params; private SessionAwareJsonTreeEvaluator(final String source, final WilmaSequence sequence, final ParameterList params) { super(source); this.sequence = sequence; this.params = params; } @Override protected void replaceJsonPath(final JsonObject parent, final String key, final JsonPrimitive value) { if (isSimpleExpression(value.getAsString())) { evaluateSimpleExpression(parent, key, value); } else if (isSessionExpression(value.getAsString())) { evaluateSessionExpression(parent, key, value); } } private void evaluateSessionExpression(final JsonObject parent, final String key, final JsonPrimitive value) { String linkedSource = getReferredSource(value.getAsString()); String jsonQuery = rebuildQuery(value.getAsString()); String requestValue = JsonPath.read(linkedSource, jsonQuery).toString(); parent.add(key, new JsonPrimitive(requestValue)); } private void evaluateSimpleExpression(final JsonObject parent, final String key, final JsonPrimitive value) { String requestValue = JsonPath.read(getSource(), value.getAsString()); parent.add(key, new JsonPrimitive(requestValue)); } private String rebuildQuery(final String query) { String[] parts = query.split("\\."); StringBuilder newQuery = new StringBuilder("$"); for (int i = 1; i < parts.length; i++) { newQuery.append('.').append(parts[i]); } return newQuery.toString(); } private String getReferredSource(final String expression) { String[] parts = expression.substring(1).split("\\."); String link = parts[0]; String linkedContent; if (SELF_REQUEST_REFFERENCE.equals(link)) { linkedContent = getSource(); } else { Map<String, String> map = sequenceJsonTransformer.transform(params, sequence.getPairs()); linkedContent = map.get(link); } return linkedContent; } private boolean isSessionExpression(final String value) { return value.startsWith(SESSION_JSON_PATH_PREFIX); } private boolean isSimpleExpression(final String value) { return value.startsWith(SIMPLE_JSON_PATH_PREFIX); } } }