package com.xceptance.xlt.common.util.action.data;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.yaml.snakeyaml.Yaml;
import bsh.EvalError;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import com.xceptance.xlt.api.util.XltLogger;
import com.xceptance.xlt.common.util.Constants;
import com.xceptance.xlt.common.util.ParameterUtils;
import com.xceptance.xlt.common.util.ParameterUtils.Reason;
import com.xceptance.xlt.common.util.bsh.ParameterInterpreter;
/**
* Implementation of the {@link URLActionDataListBuilder} for files of type 'YAML'.
* <ul>
* <li>Takes a file of type yaml and build a List<{@link #URLActionData}> from it.
* <li>The syntax of the file must follow the yaml 1.1 specification.
* <li>The structure of the data is determined within this class and described in syntax.yml
* <li>The names of the tags, whose values should be parsed into a URLActionData are also determined here.
* <li>Since the used yaml parser ({@link #Yaml SnakeYaml})returns a monstrous {@link #HashMap}, this class is quite
* busy with slaughtering this HashMap in small tasty pieces, doing some nasty type checking and converting, as well as
* error handling. Therefore the structure and quality of the code is not very charming, but it works.
* <li>If you want to change the names of the tags, you can do it easily.
* <li>If you want to change the general structure of the data, you better write a new Builder and think about SRP
* (Single responsibility principle).
* </ul>
*
* @author matthias mitterreiter
*/
public class YAMLBasedURLActionDataListBuilder extends URLActionDataListBuilder
{
protected final URLActionDataValidationBuilder validationBuilder;
protected final URLActionDataStoreBuilder storeBuilder;
static private final String SPECIFICATION = "YAMLSyntaxSpecification.txt";
static private final String SEESPEC = "See " + SPECIFICATION + " for the correct Syntax!";
private String actionName = null;
/**
* Default static URLs
*/
private List<String> d_static = new ArrayList<String>();
/**
* @param filePath
* : path to the yaml file.
* @param interpreter
* : {@link ParameterInterpreter}
* @param actionBuilder
* : {@link URLActionDataBuilder}
* @param validationBuilder
* :{@link URLActionDataValidationBuilder }
* @param storeBuilder
* : {@link URLActionDataStoreBuilder }
*/
public YAMLBasedURLActionDataListBuilder(final String filePath, final ParameterInterpreter interpreter,
final URLActionDataBuilder actionBuilder,
final URLActionDataValidationBuilder validationBuilder,
final URLActionDataStoreBuilder storeBuilder)
{
super(filePath, interpreter, actionBuilder);
ParameterUtils.isNotNull(storeBuilder, "URLActionStoreBuilder");
ParameterUtils.isNotNull(validationBuilder, "URLActionStoreBuilder");
this.storeBuilder = storeBuilder;
this.validationBuilder = validationBuilder;
}
/**
* For debugging purpose. <br>
* 'err-streams' the attributes of the object. <br>
*/
public void outline()
{
System.err.println("YAMLBasedURLActionListBuilder");
if (!d_static.isEmpty())
{
System.err.println("Static");
for (final String s : d_static)
{
System.err.println("\t" + s);
}
}
this.actionBuilder.outline();
if (!actions.isEmpty())
{
System.err.println("URLAction actions:");
for (final URLActionData action : actions)
{
action.outline();
}
}
}
/**
* Parses the data of the yaml file into List<{@link #URLActionData}>.
*
* @return List<{@link #URLActionData}>
*/
@Override
public List<URLActionData> buildURLActionDataList()
{
try
{
@SuppressWarnings("unchecked")
final List<Object> dataList = (List<Object>) getOrParseData();
createActionList(dataList);
final List<URLActionData> copy = new ArrayList<>(actions);
actions.clear();
return copy;
}
catch (final Exception e)
{
throw new IllegalArgumentException(new StringBuilder("Failed to parse file '").append(filePath).append("' as YAML. ").append(e.getMessage()).toString(), e);
}
}
@Override
protected Object parseData() throws IOException
{
final InputStream input = new FileInputStream(new File(this.filePath));
final Yaml yaml = new Yaml();
Object o = yaml.load(input);
if (o != null)
{
ParameterUtils.isArrayListMessage(o, "YAML-Data", "See the no-coding syntax sepecification!");
XltLogger.runTimeLogger.info(MessageFormat.format("Loading YAML data from file: \"{0}\" ", this.filePath));
}
else
{
o = Collections.emptyList();
XltLogger.runTimeLogger.warn(MessageFormat.format("Empty file: \"{0}\" ", this.filePath));
}
return o;
}
private void checkForInvalidTags (final LinkedHashMap<String, Object> lhm, String parentItemName)
{
final Set<?> entrySet = lhm.entrySet();
final Iterator<?> it = entrySet.iterator();
if (parentItemName.equals(Constants.ACTION) || parentItemName.equals(Constants.XHR))
{
final Object nameObject = lhm.get(Constants.NAME);
if (nameObject == null)
{
throw new IllegalArgumentException(MessageFormat.format("Name of \"{0}\" cannot be Null", parentItemName));
}
else
{
actionName = nameObject.toString();
}
}
for (int i = 0; i < entrySet.size(); i++)
{
final Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();
String itemName = entry.getKey().toString();
XltLogger.runTimeLogger.debug("Handling tag: " + itemName);
switch (parentItemName) {
case Constants.ACTION:
if (!Constants.isPermittedActionItem(itemName))
{
throw new IllegalArgumentException(MessageFormat.format("Invalid tag: \"{0}\" at Action \"{1}\". \"{0}\" is not a valid child of \"Action\"", itemName, actionName));
}
break;
case Constants.REQUEST:
if (!Constants.isPermittedRequestItem(itemName))
{
throw new IllegalArgumentException(MessageFormat.format("Invalid tag: \"{0}\" at Action \"{1}\". \"{0}\" is not a valid child of \"Request\"", itemName, actionName));
}
break;
case Constants.RESPONSE:
if (!Constants.isPermittedResponseItem(itemName))
{
throw new IllegalArgumentException(MessageFormat.format("Invalid tag: \"{0}\" at Action \"{1}\". \"{0}\" is not a valid child of \"Response\"", itemName, actionName));
}
break;
case Constants.SUBREQUESTS:
if (!(entrySet.size() <= 1))
{
throw new IllegalArgumentException(MessageFormat.format("Incorrect syntax at item: \"Subrequest\" of Aciton: \"{0}\". Please mind the whitespaces.", actionName));
}
else if (!Constants.isPermittedSubRequestItem(itemName))
{
throw new IllegalArgumentException(MessageFormat.format("Invalid tag: \"{0}\" at Action \"{1}\". \"{0}\" is not a valid child of \"Subrequests\"", itemName, actionName));
}
break;
case Constants.XHR:
if (!Constants.isPermittedActionItem(itemName))
{
throw new IllegalArgumentException(MessageFormat.format("Invalid tag: \"{0}\" at Action \"{1}\". \"{0}\" is not a valid child of \"Xhr\"", itemName, actionName));
}
break;
default:
throw new IllegalArgumentException(MessageFormat.format("Key: \"{0}\" is not a valid Tag", itemName));
}
}
}
@SuppressWarnings("unchecked")
private void createActionList(final List<Object> dataList)
{
XltLogger.runTimeLogger.info("Start building URLAction list");
for (final Object listObject : dataList)
{
ParameterUtils.isLinkedHashMapMessage(listObject, "YAML - List", SEESPEC);
final LinkedHashMap<String, Object> listItem = (LinkedHashMap<String, Object>) listObject;
handleListItem(listItem);
}
XltLogger.runTimeLogger.info("Finished building URLAction list");
}
private void handleListItem(final LinkedHashMap<String, Object> listItem)
{
final String itemName = determineTagName(listItem);
XltLogger.runTimeLogger.debug("Handling tag: " + itemName);
if (!Constants.isPermittedListItem(itemName))
{
throw new IllegalArgumentException(MessageFormat.format("Invalid list item: \"{0}\"", itemName));
}
switch (itemName)
{
case Constants.ACTION:
handleActionListItem(listItem);
break;
case Constants.NAME:
setDefaultName(listItem);
break;
case Constants.BODY:
setDefaultBody(listItem);
break;
case Constants.HTTPCODE:
setDefaultHttpCode(listItem);
break;
case Constants.URL:
setDefaultUrl(listItem);
break;
case Constants.METHOD:
setDefaultMethod(listItem);
break;
case Constants.ENCODEPARAMETERS:
setDefaultEncodeParameters(listItem);
break;
case Constants.ENCODEBODY:
setDefaultEncodeBody(listItem);
break;
case Constants.XHR:
setDefaultXhr(listItem);
break;
case Constants.PARAMETERS:
setDefaultParameters(listItem);
break;
case Constants.COOKIES:
setDefaultCookies(listItem);
break;
case Constants.STATIC:
setDefaultStatic(listItem);
break;
case Constants.HEADERS:
setDefaultHeaders(listItem);
break;
case Constants.STORE:
setDynamicStoreVariables(listItem);
break;
default:
break;
}
}
private void setDefaultName(final LinkedHashMap<String, Object> nameItem)
{
final Object nameObject = nameItem.get(Constants.NAME);
ParameterUtils.isString(nameObject, Constants.NAME);
final String name = (String) nameObject;
if (name.equals(Constants.DELETE))
{
actionBuilder.setDefaultName(null);
}
else
{
actionBuilder.setDefaultName(name);
}
}
private void setDefaultBody(final LinkedHashMap<String, Object> bodyItem)
{
final Object bodyObject = bodyItem.get(Constants.BODY);
ParameterUtils.isString(bodyObject, Constants.BODY);
final String body = (String) bodyObject;
if (body.equals(Constants.DELETE))
{
actionBuilder.setDefaultBody(null);
}
else
{
actionBuilder.setDefaultBody(body);
}
}
private void setDefaultHttpCode(final LinkedHashMap<String, Object> codeItem)
{
final Object codeObject = codeItem.get(Constants.HTTPCODE);
if (codeObject instanceof Integer)
{
final Integer code = (Integer) codeObject;
actionBuilder.setDefaultHttpResponceCode(code.toString());
}
else if (codeObject instanceof String)
{
final String code = (String) codeObject;
if (code.equals(Constants.DELETE))
{
actionBuilder.setDefaultHttpResponceCode(null);
}
else
{
actionBuilder.setDefaultHttpResponceCode(code);
}
}
else
{
ParameterUtils.doThrow(Constants.HTTPCODE, Reason.UNSUPPORTED_TYPE);
}
}
private void setDefaultUrl(final LinkedHashMap<String, Object> urlItem)
{
final Object urlObject = urlItem.get(Constants.URL);
ParameterUtils.isString(urlObject, Constants.URL);
final String url = (String) urlObject;
if (url.equals(Constants.DELETE))
{
actionBuilder.setDefaultUrl(null);
}
else
{
actionBuilder.setDefaultUrl(url);
}
}
private void setDefaultMethod(final LinkedHashMap<String, Object> methodItem)
{
final Object methodObject = methodItem.get(Constants.METHOD);
ParameterUtils.isString(methodObject, Constants.METHOD);
final String method = (String) methodObject;
if (method.equals(Constants.DELETE))
{
actionBuilder.setDefaultMethod(null);
}
else
{
actionBuilder.setDefaultMethod(method);
}
}
private void setDefaultEncodeParameters(final LinkedHashMap<String, Object> encodedItem)
{
final Object encodedObject = encodedItem.get(Constants.ENCODEPARAMETERS);
if (encodedObject instanceof Boolean)
{
final Boolean encoded = (Boolean) encodedObject;
actionBuilder.setDefaultEncodeParameters(encoded.toString());
}
else if (encodedObject instanceof String)
{
final String encoded = (String) encodedObject;
if (encoded.equals(Constants.DELETE))
{
actionBuilder.setDefaultEncodeParameters(null);
}
else
{
actionBuilder.setDefaultEncodeParameters(encoded);
}
}
else
{
ParameterUtils.doThrow(Constants.ENCODEPARAMETERS, Reason.UNSUPPORTED_TYPE);
}
}
private void setDefaultEncodeBody(final LinkedHashMap<String, Object> encodedItem)
{
final Object encodedObject = encodedItem.get(Constants.ENCODEBODY);
if (encodedObject instanceof Boolean)
{
final Boolean encoded = (Boolean) encodedObject;
actionBuilder.setDefaultEncodeBody(encoded.toString());
}
else if (encodedObject instanceof String)
{
final String encoded = (String) encodedObject;
if (encoded.equals(Constants.DELETE))
{
actionBuilder.setDefaultEncodeBody(null);
}
else
{
actionBuilder.setDefaultEncodeBody(encoded);
}
}
else
{
ParameterUtils.doThrow(Constants.ENCODEBODY, Reason.UNSUPPORTED_TYPE);
}
}
private void setDefaultXhr(final LinkedHashMap<String, Object> xhrItem)
{
final Object xhrObject = xhrItem.get(Constants.XHR);
if (xhrObject instanceof Boolean)
{
final Boolean xhr = (Boolean) xhrObject;
if (xhr)
{
actionBuilder.setDefaultType(URLActionData.TYPE_XHR);
}
else
{
actionBuilder.setDefaultType(URLActionData.TYPE_ACTION);
}
}
else if (xhrObject instanceof String)
{
final String xhr = (String) xhrObject;
if (xhr.equals(Constants.DELETE))
{
actionBuilder.setDefaultType(null);
}
else
{
actionBuilder.setDefaultType(xhr);
}
}
else
{
ParameterUtils.doThrow(Constants.XHR, Reason.UNSUPPORTED_TYPE);
}
}
private void setDefaultParameters(final LinkedHashMap<String, Object> parametersItem)
{
final Object parametersObject = parametersItem.get(Constants.PARAMETERS);
if (parametersObject instanceof String)
{
final String parameters = (String) parametersObject;
if (parameters.equals(Constants.DELETE))
{
actionBuilder.setDefaultParameters(Collections.<NameValuePair>emptyList());
}
else
{
ParameterUtils.doThrow(Constants.PARAMETERS, parameters, Reason.UNSUPPORTED_VALUE);
}
}
else if (parametersObject instanceof ArrayList)
{
@SuppressWarnings("unchecked")
final List<Object> objectList = (ArrayList<Object>) parametersObject;
final List<NameValuePair> newList = new ArrayList<NameValuePair>();
for (final Object object : objectList)
{
ParameterUtils.isLinkedHashMap(object, Constants.PARAMETERS);
@SuppressWarnings("unchecked")
final LinkedHashMap<Object, Object> lhm = (LinkedHashMap<Object, Object>) object;
newList.add(createPairfromLinkedHashMap(lhm));
}
actionBuilder.setDefaultParameters(newList);
}
else
{
ParameterUtils.doThrow(Constants.PARAMETERS, Reason.UNSUPPORTED_TYPE);
}
}
private void setDefaultCookies(final LinkedHashMap<String, Object> cookiesItem)
{
final Object cookiesObject = cookiesItem.get(Constants.COOKIES);
if (cookiesObject instanceof String)
{
final String cookies = (String) cookiesObject;
if (cookies.equals(Constants.DELETE))
{
actionBuilder.setDefaultCookies(Collections.<NameValuePair>emptyList());
}
else
{
ParameterUtils.doThrow(Constants.COOKIES, cookies, Reason.UNSUPPORTED_VALUE);
}
}
else if (cookiesObject instanceof ArrayList)
{
@SuppressWarnings("unchecked")
final List<Object> objectList = (ArrayList<Object>) cookiesObject;
final List<NameValuePair> newList = new ArrayList<NameValuePair>();
for (final Object object : objectList)
{
ParameterUtils.isLinkedHashMap(object, Constants.COOKIES);
@SuppressWarnings("unchecked")
final LinkedHashMap<Object, Object> lhm = (LinkedHashMap<Object, Object>) object;
newList.add(createPairfromLinkedHashMap(lhm));
}
actionBuilder.setDefaultCookies(newList);
}
else
{
ParameterUtils.doThrow(Constants.COOKIES, Reason.UNSUPPORTED_TYPE);
}
}
private void setDefaultHeaders(final LinkedHashMap<String, Object> headersItem)
{
final Object headersObject = headersItem.get(Constants.HEADERS);
if (headersObject instanceof String)
{
final String headersString = (String) headersObject;
if (headersString.equals(Constants.DELETE))
{
actionBuilder.setDefaultHeaders(Collections.<NameValuePair>emptyList());
}
else
{
ParameterUtils.doThrow(Constants.HEADERS, headersString, Reason.UNSUPPORTED_VALUE);
}
}
else if (headersObject instanceof ArrayList)
{
@SuppressWarnings("unchecked")
final List<Object> objectList = (ArrayList<Object>) headersObject;
final List<NameValuePair> newList = new ArrayList<NameValuePair>();
for (final Object object : objectList)
{
ParameterUtils.isLinkedHashMap(object, Constants.HEADERS);
@SuppressWarnings("unchecked")
final LinkedHashMap<Object, Object> lhm = (LinkedHashMap<Object, Object>) object;
newList.add(createPairfromLinkedHashMap(lhm));
}
actionBuilder.setDefaultHeaders(newList);
}
else
{
ParameterUtils.doThrow(Constants.HEADERS, Reason.UNSUPPORTED_TYPE);
}
}
private void setDefaultStatic(final LinkedHashMap<String, Object> headersItem)
{
final Object staticObject = headersItem.get(Constants.STATIC);
if (staticObject instanceof String)
{
final String staticString = (String) staticObject;
if (staticString.equals(Constants.DELETE))
{
this.d_static = Collections.emptyList();
}
else
{
ParameterUtils.doThrow(Constants.STATIC, staticString, Reason.UNSUPPORTED_VALUE);
}
}
else if (staticObject instanceof ArrayList)
{
@SuppressWarnings("unchecked")
final List<Object> objectList = (ArrayList<Object>) staticObject;
final List<String> newList = new ArrayList<String>();
for (final Object object : objectList)
{
ParameterUtils.isString(object, Constants.STATIC);
newList.add((String) object);
}
this.d_static = newList;
}
else
{
ParameterUtils.doThrow(Constants.HEADERS, Reason.UNSUPPORTED_TYPE);
}
}
private void setDynamicStoreVariables(final LinkedHashMap<String, Object> headersItem)
{
final Object storeObject = headersItem.get(Constants.STORE);
if (storeObject instanceof String)
{
final String storeString = (String) storeObject;
if (storeString.equals(Constants.DELETE))
{
XltLogger.runTimeLogger.warn("CANNOT DELETE DATA IN STORE (YET)");
}
else
{
ParameterUtils.doThrow(Constants.STORE, storeString, Reason.UNSUPPORTED_VALUE);
}
}
else if (storeObject instanceof ArrayList)
{
@SuppressWarnings("unchecked")
final List<Object> objectList = (ArrayList<Object>) storeObject;
@SuppressWarnings("unused")
final List<NameValuePair> newList = new ArrayList<NameValuePair>();
for (final Object object : objectList)
{
ParameterUtils.isLinkedHashMap(object, Constants.STORE);
@SuppressWarnings("unchecked")
final LinkedHashMap<Object, Object> lhm = (LinkedHashMap<Object, Object>) object;
final NameValuePair nvp = createPairfromLinkedHashMap(lhm);
final NameValuePair nvp2 = new NameValuePair(interpreter.processDynamicData(nvp.getName()),
interpreter.processDynamicData(nvp.getValue()));
try
{
this.interpreter.set(nvp2);
}
catch (final EvalError e)
{
// We just Set Values, so NP
}
}
}
else
{
ParameterUtils.doThrow(Constants.STORE, Reason.UNSUPPORTED_TYPE);
}
}
private void handleActionListItem(final LinkedHashMap<String, Object> listItem)
{
final Object actionObject = listItem.get(Constants.ACTION);
ParameterUtils.isNotNull(actionObject, Constants.ACTION);
ParameterUtils.isLinkedHashMapMessage(actionObject, Constants.ACTION, "Missing Content");
@SuppressWarnings("unchecked")
final LinkedHashMap<String, Object> rawAction = (LinkedHashMap<String, Object>) actionObject;
checkForInvalidTags(rawAction, Constants.ACTION);
fillURLActionBuilder(rawAction);
final URLActionData action = actionBuilder.build();
this.actions.add(action);
handleSubrequests(rawAction);
}
private void handleSubrequests(final LinkedHashMap<String, Object> rawAction)
{
final Object subrequestObject = rawAction.get(Constants.SUBREQUESTS);
if (subrequestObject != null)
{
ParameterUtils.isArrayListMessage(subrequestObject, Constants.SUBREQUESTS, "");
@SuppressWarnings("unchecked")
final List<Object> subrequests = (List<Object>) subrequestObject;
for (final Object subrequestItem : subrequests)
{
ParameterUtils.isLinkedHashMapMessage(subrequestItem, Constants.STATIC, "");
@SuppressWarnings("unchecked")
final LinkedHashMap<String, Object> subrequest = (LinkedHashMap<String, Object>) subrequestItem;
checkForInvalidTags(subrequest, Constants.SUBREQUESTS);
createSubrequest(subrequest);
}
}
else
{
XltLogger.runTimeLogger.warn(MessageFormat.format("Subrequest of Action: \"{0}\" is null", rawAction.get(Constants.NAME)));
}
}
private void createSubrequest(final LinkedHashMap<String, Object> subrequest)
{
final Object staticSubrequestObject = subrequest.get(Constants.STATIC);
if (staticSubrequestObject != null)
{
ParameterUtils.isArrayListMessage(staticSubrequestObject, Constants.SUBREQUESTS, "");
@SuppressWarnings("unchecked")
final List<Object> staticSubrequest = (List<Object>) staticSubrequestObject;
handleStaticSubrequests(staticSubrequest);
}
else if (!d_static.isEmpty())
{
for (int i = 0; i < d_static.size(); i++)
{
actionBuilder.reset();
actionBuilder.setUrl(d_static.get(i));
actionBuilder.setType(URLActionData.TYPE_STATIC);
actionBuilder.setMethod(URLActionData.METHOD_GET);
actionBuilder.setName("static-subrequest" + i);
actionBuilder.setInterpreter(this.interpreter);
actions.add(actionBuilder.build());
}
}
final Object xhrSubrequestObject = subrequest.get(Constants.XHR);
if (xhrSubrequestObject != null)
{
ParameterUtils.isLinkedHashMapMessage(xhrSubrequestObject, Constants.SUBREQUESTS, "");
@SuppressWarnings("unchecked")
final LinkedHashMap<String, Object> xhrSubrequest = (LinkedHashMap<String, Object>) xhrSubrequestObject;
handleXhrSubrequests(xhrSubrequest);
}
}
private void handleXhrSubrequests(final LinkedHashMap<String, Object> xhrSubrequest)
{
checkForInvalidTags(xhrSubrequest, Constants.XHR);
actionBuilder.reset();
fillURLActionBuilder(xhrSubrequest);
actionBuilder.setType(URLActionData.TYPE_XHR);
final URLActionData xhrAction = actionBuilder.build();
actions.add(xhrAction);
handleSubrequests(xhrSubrequest);
}
private void handleStaticSubrequests(final List<Object> staticUrls)
{
for (int i = 0; i < staticUrls.size(); i++)
{
final Object o = staticUrls.get(i);
ParameterUtils.isStringMessage(o, Constants.STATIC, "");
final String urlString = (String) o;
actionBuilder.reset();
actionBuilder.setType(URLActionData.TYPE_STATIC);
actionBuilder.setMethod(URLActionData.METHOD_GET);
actionBuilder.setUrl(urlString);
actionBuilder.setName("static-subrequest" + i);
actionBuilder.setInterpreter(this.interpreter);
actions.add(actionBuilder.build());
}
}
private void fillURLActionBuilder(final LinkedHashMap<String, Object> rawAction)
{
actionBuilder.reset();
actionBuilder.setInterpreter(this.interpreter);
fillUrlActionBuilderWithName(rawAction);
fillUrlActionBuilderWithRequestData(rawAction);
fillUrlActionBuilderWithResponseData(rawAction);
}
private void fillUrlActionBuilderWithName(final LinkedHashMap<String, Object> rawAction)
{
final Object nameObject = rawAction.get(Constants.NAME);
if (nameObject != null)
{
ParameterUtils.isString(nameObject, Constants.NAME);
final String name = (String) nameObject;
actionBuilder.setName(name);
}
}
private void fillUrlActionBuilderWithRequestData(final LinkedHashMap<String, Object> rawAction)
{
final Object requestObject = rawAction.get(Constants.REQUEST);
if (requestObject != null)
{
ParameterUtils.isLinkedHashMapMessage(requestObject, Constants.REQUEST, "");
@SuppressWarnings("unchecked")
final LinkedHashMap<String, Object> rawRequest = (LinkedHashMap<String, Object>) requestObject;
checkForInvalidTags(rawRequest, Constants.REQUEST);
fillURLActionBuilderWithBodyData(rawRequest);
fillURLActionBuilderWithHeaderData(rawRequest);
fillURLActionBuilderWithEncodeParametersData(rawRequest);
fillURLActionBuilderWithEncodeBodyData(rawRequest);
fillURLActionBuilderWithMethodData(rawRequest);
fillURLActionBuilderWithParameterData(rawRequest);
fillURLActionBuilderWithCookieData(rawRequest);
fillURLActionBuilderWithXhrData(rawRequest);
fillURLActionBuilderWithUrlData(rawRequest);
}
}
private void fillURLActionBuilderWithBodyData(final LinkedHashMap<String, Object> rawRequest)
{
final Object bodyObject = rawRequest.get(Constants.BODY);
if (bodyObject != null)
{
ParameterUtils.isString(bodyObject, Constants.BODY);
final String body = (String) bodyObject;
actionBuilder.setBody(body);
}
}
private void fillURLActionBuilderWithHeaderData(final LinkedHashMap<String, Object> rawRequest)
{
final Object headersObject = rawRequest.get(Constants.HEADERS);
if (headersObject != null)
{
if (headersObject instanceof ArrayList)
{
@SuppressWarnings(
{
"unchecked"
})
final List<Object> objectList = (ArrayList<Object>) headersObject;
final List<NameValuePair> newList = new ArrayList<NameValuePair>();
for (final Object object : objectList)
{
ParameterUtils.isLinkedHashMap(object, Constants.HEADERS);
@SuppressWarnings("unchecked")
final LinkedHashMap<Object, Object> lhm = (LinkedHashMap<Object, Object>) object;
final NameValuePair nvp = createPairfromLinkedHashMap(lhm);
newList.add(nvp);
}
actionBuilder.setHeaders(newList);
}
else
{
ParameterUtils.doThrow(Constants.HEADERS, Reason.UNSUPPORTED_TYPE);
}
}
}
private void fillURLActionBuilderWithParameterData(final LinkedHashMap<String, Object> rawRequest)
{
final Object parametersObject = rawRequest.get(Constants.PARAMETERS);
if (parametersObject != null)
{
if (parametersObject instanceof ArrayList)
{
@SuppressWarnings("unchecked")
final List<Object> objectList = (ArrayList<Object>) parametersObject;
final List<NameValuePair> newList = new ArrayList<NameValuePair>();
for (final Object object : objectList)
{
ParameterUtils.isLinkedHashMap(object, Constants.PARAMETERS);
@SuppressWarnings("unchecked")
final LinkedHashMap<Object, Object> lhm = (LinkedHashMap<Object, Object>) object;
final NameValuePair nvp = createPairfromLinkedHashMap(lhm);
newList.add(nvp);
}
actionBuilder.setParameters(newList);
}
else
{
ParameterUtils.doThrow(Constants.PARAMETERS, Reason.UNSUPPORTED_TYPE);
}
}
}
private void fillURLActionBuilderWithCookieData(final LinkedHashMap<String, Object> rawRequest)
{
final Object cookiesObject = rawRequest.get(Constants.COOKIES);
if (cookiesObject != null)
{
if (cookiesObject instanceof ArrayList)
{
@SuppressWarnings("unchecked")
final List<Object> objectList = (ArrayList<Object>) cookiesObject;
final List<NameValuePair> newList = new ArrayList<NameValuePair>();
for (final Object object : objectList)
{
ParameterUtils.isLinkedHashMap(object, Constants.COOKIES);
@SuppressWarnings("unchecked")
final LinkedHashMap<Object, Object> lhm = (LinkedHashMap<Object, Object>) object;
final NameValuePair nvp = createPairfromLinkedHashMap(lhm);
newList.add(nvp);
}
actionBuilder.setCookies(newList);
}
else
{
ParameterUtils.doThrow(Constants.COOKIES, Reason.UNSUPPORTED_TYPE);
}
}
}
private void fillURLActionBuilderWithXhrData(final LinkedHashMap<String, Object> rawRequest)
{
final Object xhrObject = rawRequest.get(Constants.XHR);
if (xhrObject != null)
{
if (xhrObject instanceof Boolean)
{
final Boolean xhr = (Boolean) xhrObject;
if (xhr)
{
actionBuilder.setType(URLActionData.TYPE_XHR);
}
else
{
actionBuilder.setType(URLActionData.TYPE_ACTION);
}
}
else if (xhrObject instanceof String)
{
final String xhr = (String) xhrObject;
actionBuilder.setType(xhr);
}
else
{
ParameterUtils.doThrow(Constants.XHR, Reason.UNSUPPORTED_TYPE);
}
}
}
private void fillURLActionBuilderWithMethodData(final LinkedHashMap<String, Object> rawRequest)
{
final Object methodObject = rawRequest.get(Constants.METHOD);
if (methodObject != null)
{
ParameterUtils.isString(methodObject, Constants.METHOD);
final String method = (String) methodObject;
actionBuilder.setMethod(method);
}
}
private void fillURLActionBuilderWithUrlData(final LinkedHashMap<String, Object> rawRequest)
{
final Object urlObject = rawRequest.get(Constants.URL);
if (urlObject != null)
{
ParameterUtils.isString(urlObject, Constants.URL);
final String url = (String) urlObject;
actionBuilder.setUrl(url);
}
}
private void fillURLActionBuilderWithEncodeParametersData(final LinkedHashMap<String, Object> rawRequest)
{
final Object encodedObject = rawRequest.get(Constants.ENCODEPARAMETERS);
if (encodedObject != null)
{
if (encodedObject instanceof Boolean)
{
final Boolean encoded = (Boolean) encodedObject;
actionBuilder.setEncodeParameters(encoded.toString());
}
else if (encodedObject instanceof String)
{
final String encoded = (String) encodedObject;
actionBuilder.setEncodeParameters(encoded);
}
else
{
ParameterUtils.doThrow(Constants.ENCODEPARAMETERS, Reason.UNSUPPORTED_TYPE);
}
}
}
private void fillURLActionBuilderWithEncodeBodyData(final LinkedHashMap<String, Object> rawRequest)
{
final Object encodedObject = rawRequest.get(Constants.ENCODEBODY);
if (encodedObject != null)
{
if (encodedObject instanceof Boolean)
{
final Boolean encoded = (Boolean) encodedObject;
actionBuilder.setEncodeBody(encoded.toString());
}
else if (encodedObject instanceof String)
{
final String encoded = (String) encodedObject;
actionBuilder.setEncodeBody(encoded);
}
else
{
ParameterUtils.doThrow(Constants.ENCODEBODY, Reason.UNSUPPORTED_TYPE);
}
}
}
private void fillUrlActionBuilderWithResponseData(final LinkedHashMap<String, Object> rawAction)
{
final Object responseObject = rawAction.get(Constants.RESPONSE);
if (responseObject != null)
{
ParameterUtils.isLinkedHashMapMessage(responseObject, Constants.RESPONSE, "");
@SuppressWarnings("unchecked")
final LinkedHashMap<String, Object> rawResponse = (LinkedHashMap<String, Object>) responseObject;
checkForInvalidTags(rawResponse, Constants.RESPONSE);
fillURLActionBuilderWithHttpResponseCodeData(rawResponse);
fillURLActionBuilderWithValidationData(rawResponse);
fillURLActionBuilderWithStoreData(rawResponse);
}
}
private void fillURLActionBuilderWithHttpResponseCodeData(final LinkedHashMap<String, Object> rawResponse)
{
final Object codeObject = rawResponse.get(Constants.HTTPCODE);
if (codeObject != null)
{
if (codeObject instanceof Integer)
{
final Integer code = (Integer) codeObject;
actionBuilder.setHttpResponceCode(code.toString());
}
else if (codeObject instanceof String)
{
final String code = (String) codeObject;
actionBuilder.setHttpResponceCode(code);
}
else
{
ParameterUtils.doThrow(Constants.HTTPCODE, Reason.UNSUPPORTED_TYPE);
}
}
}
private void fillURLActionBuilderWithValidationData(final LinkedHashMap<String, Object> rawResponse)
{
final Object validationsObject = rawResponse.get(Constants.VALIDATION);
if (validationsObject != null)
{
ParameterUtils.isArrayListMessage(validationsObject, Constants.VALIDATION, "");
@SuppressWarnings("unchecked")
final List<Object> validations = (List<Object>) validationsObject;
for (final Object validationObject : validations)
{
ParameterUtils.isLinkedHashMapMessage(validationObject, Constants.VALIDATION, "");
@SuppressWarnings("unchecked")
final LinkedHashMap<String, Object> validationItem = (LinkedHashMap<String, Object>) validationObject;
if (!(validationItem.entrySet().size() <= 1))
{
throw new IllegalArgumentException(MessageFormat.format("Incorrect syntax at \"Validate\" of Aciton: \"{0}\". Please mind the whitespaces.", actionName));
}
fillURLActionValidationBuilder(validationItem);
final URLActionDataValidation validation = validationBuilder.build();
actionBuilder.addValidation(validation);
}
}
}
private void fillURLActionValidationBuilder(final LinkedHashMap<String, Object> rawValidationItem)
{
validationBuilder.reset();
final String validationName = getNameOfFirstElementFromLinkedHashMap(rawValidationItem);
validationBuilder.setName(validationName);
validationBuilder.setInterpreter(this.interpreter);
final Object rawValidateSubObject = rawValidationItem.get(validationName);
if (rawValidateSubObject != null)
{
ParameterUtils.isLinkedHashMapMessage(rawValidateSubObject, validationName, "");
@SuppressWarnings("unchecked")
final LinkedHashMap<String, Object> validateListSubItem = (LinkedHashMap<String, Object>) rawValidateSubObject;
fillURLActionValidationBuilderWithDataFromLinkedHashMap(validateListSubItem);
}
else
{
throw new IllegalArgumentException (MessageFormat.format("Validation Item: \"{0}\" at Action: \"{1}\" failed because: \"{2}\"", validationName, actionName, Reason.UNCOMPLETE));
}
}
private void fillURLActionValidationBuilderWithDataFromLinkedHashMap(final LinkedHashMap<String, Object> rawValidateSubItem)
{
final Set<?> entrySet = rawValidateSubItem.entrySet();
if (entrySet.size() >2)
{
throw new IllegalArgumentException (MessageFormat.format("Validation Item: \"{0}\" of Action: \"{1}\" has too manny selection- or validationMode ", validationBuilder.getName(), actionName));
}
final Iterator<?> it = entrySet.iterator();
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();
final String selectionMode = (String) entry.getKey();
final String selectionContent = (String) entry.getValue();
String validationMode = null;
String validationContent = null;
if (it.hasNext())
{
entry = (Map.Entry<?, ?>) it.next();
validationMode = entry.getKey().toString();
Object validationContentObject = entry.getValue();
switch (validationMode)
{
case Constants.EXISTS:
if (validationContentObject == null)
{
throw new IllegalArgumentException(MessageFormat.format("Validation Item: \"{0}\" of Action: \"{1}\". Validation content of \"{2}\" can not be null", validationBuilder.getName(), actionName, validationMode));
}
else
{
if (validationContentObject.toString().equals("false"))
{
throw new IllegalArgumentException(MessageFormat.format("Validation Item: \"{0}\" of Action: \"{1}\". Validation content of \"{2}\" can not be \"false\"", validationBuilder.getName(), actionName, validationMode));
}
XltLogger.runTimeLogger.warn("Validation mode \"Exists\" is implicit in every validation. The exlpicit delacration of this mode is deprecated and will be removed soon.");
validationContent = validationContentObject.toString();
}
break;
default:
if (!Constants.isPermittedValidationMode(validationMode))
{
throw new IllegalArgumentException(MessageFormat.format("Invalid ValidationMode: \"{0}\" at Validation Item: \"{1}\" of Action \"{2}\"", validationMode, validationBuilder.getName(), actionName));
}
else if (validationContentObject == null)
{
throw new IllegalArgumentException(MessageFormat.format("Validation Item: \"{0}\" of Action: \"{1}\" have more than one selection- or validationMode ", validationBuilder.getName(), actionName, validationMode));
}
validationContent = validationContentObject.toString();
break;
}
}
if (validationMode == null)
{
validationMode = URLActionDataValidation.EXISTS;
}
validationBuilder.setSelectionMode(selectionMode);
validationBuilder.setValidationContent(validationContent);
validationBuilder.setValidationMode(validationMode);
validationBuilder.setSelectionContent(selectionContent);
}
private void fillURLActionBuilderWithStoreData(final LinkedHashMap<String, Object> rawResponse)
{
final Object storeObject = rawResponse.get(Constants.STORE);
if (storeObject != null)
{
ParameterUtils.isArrayListMessage(storeObject, Constants.STORE, "");
@SuppressWarnings("unchecked")
final List<Object> storeObjects = (List<Object>) storeObject;
for (final Object storeObjectsItem : storeObjects)
{
ParameterUtils.isLinkedHashMapMessage(storeObjectsItem, Constants.STORE, "");
@SuppressWarnings("unchecked")
final LinkedHashMap<String, Object> storeItem = (LinkedHashMap<String, Object>) storeObjectsItem;
fillURLActionStoreBuilder(storeItem);
final URLActionDataStore store = storeBuilder.build();
actionBuilder.addStore(store);
}
}
}
private void fillURLActionStoreBuilder(final LinkedHashMap<String, Object> storeItem)
{
storeBuilder.reset();
final String storeName = getNameOfFirstElementFromLinkedHashMap(storeItem);
storeBuilder.setName(storeName);
storeBuilder.setInterpreter(interpreter);
final Object rawStoreSubObject = storeItem.get(storeName);
if (rawStoreSubObject != null)
{
ParameterUtils.isLinkedHashMapMessage(rawStoreSubObject, storeName, "");
@SuppressWarnings("unchecked")
final LinkedHashMap<Object, Object> rawStoreSubItem = (LinkedHashMap<Object, Object>) rawStoreSubObject;
fillStoreBuilderWithDataFromLinkedHashMap(rawStoreSubItem);
}
else
{
ParameterUtils.doThrow(Constants.STORE, storeName, Reason.UNCOMPLETE);
}
}
private void fillStoreBuilderWithDataFromLinkedHashMap(final LinkedHashMap<Object, Object> rawStoreSubItem)
{
final Set<?> entrySet = rawStoreSubItem.entrySet();
final Iterator<?> it = entrySet.iterator();
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();
final String selectionMode = (String) entry.getKey();
final String selectionContent = (String) entry.getValue();
String subSelectionMode = null;
String subSelectionContent = null;
if (it.hasNext())
{
entry = (Map.Entry<?, ?>) it.next();
subSelectionMode = entry.getKey().toString();
subSelectionContent = entry.getValue().toString();
}
storeBuilder.setSelectionMode(selectionMode);
storeBuilder.setSelectionContent(selectionContent);
if (subSelectionMode != null)
{
storeBuilder.setSubSelectionMode(subSelectionMode);
storeBuilder.setSubSelectionContent(subSelectionContent);
}
}
private String determineTagName(final LinkedHashMap<String, Object> tag)
{
return getNameOfFirstElementFromLinkedHashMap(tag);
}
private NameValuePair createPairfromLinkedHashMap(final LinkedHashMap<Object, Object> lhm)
{
final Set<?> entrySet = lhm.entrySet();
final Iterator<?> it = entrySet.iterator();
final Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();
final String key = entry.getKey() != null ? entry.getKey().toString() : null;
final String value = entry.getValue() != null ? entry.getValue().toString() : null;
final NameValuePair nvp = new NameValuePair(key, value);
return nvp;
}
private String getNameOfFirstElementFromLinkedHashMap(final LinkedHashMap<String, Object> lhm)
{
final Set<?> entrySet = lhm.entrySet();
final Iterator<?> it = entrySet.iterator();
final Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();
final String name = entry.getKey().toString();
return name;
}
}