/** * Copyright (C) 2015-2019 Expedia, 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.hotels.heat.core.utils; import java.util.HashMap; import java.util.Map; import com.hotels.heat.core.handlers.PlaceholderHandler; import com.hotels.heat.core.handlers.TestSuiteHandler; import com.hotels.heat.core.specificexception.HeatException; import com.hotels.heat.core.utils.log.LoggingUtils; import io.restassured.response.Response; /** * Class useful to extract data from all kind of modality; * It has to manage "actualValue" and "expectedValue", processing it and retrieving values that has to be * checked in the "verify" step. */ public class DataExtractionSupport { public static final String STRING_TO_PARSE_JSON_ELEMENT = "stringToParse"; public static final String REGEXP_JSON_ELEMENT = "regexp"; public static final String REGEXP_MATCH_JSON_ELEMENT = "regexpToMatch"; public static final String OCCURRENCE_JSON_ELEMENT = "occurrenceOf"; private final LoggingUtils logUtils; private Map<Integer, Map<String, String>> retrievedParametersFlowMode; public DataExtractionSupport(LoggingUtils logUtils) { this.logUtils = logUtils; this.retrievedParametersFlowMode = new HashMap(); } /** * This method gets in input the structure of "actualValue" or "expectedValue" and gives in output * the final string we have to use for the verification step. * @param extractionObj the input "object" that represents "actualValue" or "expectedValue". It can be, in the simplest context, a string. But it can be another json object with inner parameters, for example a regexp on the service response, useful to retrieve a value. In case of inner json object, there is a recursive use of "placeholderProcessString" method. * @param response It is the response retrieved after the request to the service under test. * @param retrievedParametersFlowMode The parameters passed to the steps in flow mode * @return the final string we have to use for the verification step */ public String process(Object extractionObj, Response response, Map retrievedParametersFlowMode) { String outputStr = ""; this.retrievedParametersFlowMode = retrievedParametersFlowMode; logUtils.trace("extractionObj = '{}'", extractionObj.toString()); if (extractionObj.getClass().equals(String.class)) { outputStr = processString((String) extractionObj, response); } else if (extractionObj.getClass().equals(HashMap.class)) { // we are using HashMap because JsonPath uses maps to manage json object outputStr = processMap((Map) extractionObj, response); } else { throw new HeatException(logUtils.getExceptionDetails() + "actualValue/expectedValue belongs to " + extractionObj.getClass().toString() + " not supported"); } logUtils.trace("outputStr = '{}' (class: {})", outputStr, extractionObj.getClass().toString()); return outputStr; } /** * placeholderProcessString method simply get a string and, if necessary, processes it with PlaceholderHandler. * @param inputString is the string to be processed * @param response is the response retrieved from the service under test * @return the string processed. If it is a simple string (without any placeholder or * processing needed), the output will be the same as the input */ private String processString(String inputString, Response response) { PlaceholderHandler placeholderHandler = new PlaceholderHandler(); placeholderHandler.setResponse(response); placeholderHandler.setFlowVariables(retrievedParametersFlowMode); String outputStr = (String) placeholderHandler.placeholderProcessString(inputString); logUtils.trace("input value='{}' / outputStr='{}'", inputString, outputStr); return outputStr; } /** * This method is used when "actualValue" or "expectedValue" are json object and not simple strings. * In particular it can manage: * - regular expression extraction * - occurrence of a given string in another string * - ... TBD * @param map it is the map representing the json object of the "actualValue" or "expectedValue" * @param response is the response retrieved from the service under test. * @return the final string to use for the verification step */ private String processMap(Map map, Response response) { String outputStr = ""; if (map.containsKey(REGEXP_JSON_ELEMENT) && map.containsKey(STRING_TO_PARSE_JSON_ELEMENT)) { outputStr = regexpExtractorProcessing(map, response); } else if (map.containsKey(REGEXP_MATCH_JSON_ELEMENT) && map.containsKey(STRING_TO_PARSE_JSON_ELEMENT)) { outputStr = regexpMatchExtractorProcessing(map, response); } else if (map.containsKey(OCCURRENCE_JSON_ELEMENT) && map.containsKey(STRING_TO_PARSE_JSON_ELEMENT)) { outputStr = occurrenceOfProcessing(map, response); } else { throw new HeatException(logUtils.getExceptionDetails() + "configuration " + map.toString() + " not supported"); } return outputStr; } /** * Regular expression extraction management. * example: * "actualValue": { * "regexp":"PIPPO_(.*?)_PLUTO", * "stringToParse":"PIPPO_123_PLUTO" * } * expected output = "123" * @param map it is the map representing the json object of the "actualValue" or "expectedValue" * @param response is the response retrieved from the service under test. * @return the final string to use for the verification step */ private String regexpExtractorProcessing(Map map, Response response) { String stringToParse = processString((String) map.get(STRING_TO_PARSE_JSON_ELEMENT), response); String regularExpression = (String) map.get(REGEXP_JSON_ELEMENT); TestCaseUtils testCaseUtils = TestSuiteHandler.getInstance().getTestCaseUtils(); return testCaseUtils.regexpExtractor(stringToParse, regularExpression, 1); } /** * Regular expression match extraction management. * example: * "actualValue": { * "regexpToMatch":"PIPPO_(.*?)_PLUTO", * "stringToParse":"PIPPO_123_PLUTO" * } * expected output = "true" * @param map it is the map representing the json object of the "actualValue" or "expectedValue" * @param response is the response retrieved from the service under test. * @return the final string to use for the verification step */ private String regexpMatchExtractorProcessing(Map map, Response response) { String stringToParse = processString((String) map.get(STRING_TO_PARSE_JSON_ELEMENT), response); String regularExpression = (String) map.get(REGEXP_MATCH_JSON_ELEMENT); TestCaseUtils testCaseUtils = TestSuiteHandler.getInstance().getTestCaseUtils(); String outputRegexp = testCaseUtils.getRegexpMatch(stringToParse, regularExpression, 1); return TestCaseUtils.NO_MATCH.equals(outputRegexp) ? "false" : "true"; } /** * occurrences of a string extraction management. * example: * "actualValue": { * "occurrenceOf":"PIPPO", * "stringToParse":"PIPPO_PLUTO_PIPPO_MICKEY" * } * expected output = "2" * @param map it is the map representing the json object of the "actualValue" or "expectedValue" * @param response is the response retrieved from the service under test. * @return the final string to use for the verification step */ private String occurrenceOfProcessing(Map map, Response response) { String stringToParse = processString((String) map.get(STRING_TO_PARSE_JSON_ELEMENT), response); String occurrenceString = (String) map.get(OCCURRENCE_JSON_ELEMENT); int occurrences = stringToParse.split(occurrenceString).length - 1; return String.valueOf(occurrences); } }