All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.liferay.poshi.runner.prose.PoshiProseStatement Maven / Gradle / Ivy

/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library 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 Lesser General Public License for more
 * details.
 */

package com.liferay.poshi.runner.prose;

import com.liferay.poshi.runner.util.Dom4JUtil;
import com.liferay.poshi.runner.util.StringUtil;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.dom4j.Element;
import org.dom4j.tree.DefaultAttribute;

/**
 * @author Yi-Chen Tsai
 */
public class PoshiProseStatement extends BasePoshiProse {

	public PoshiProseStatement(String proseStatement) {
		for (String proseKeyword : PoshiProseStatement.KEYWORDS) {
			if (proseStatement.startsWith(proseKeyword)) {
				proseStatement = StringUtil.replaceFirst(
					proseStatement, proseKeyword, "");

				break;
			}
		}

		_proseStatement = proseStatement;

		proseStatement = formatProseStatement(proseStatement);

		String proseStatementMatchingString = getProseStatementMatchingString();

		_poshiProseMatcher = PoshiProseMatcher.getPoshiProseMatcher(
			proseStatementMatchingString);

		if (_poshiProseMatcher == null) {
			StringBuilder sb = new StringBuilder();

			sb.append("Unable to find matching prose for '");
			sb.append(proseStatementMatchingString);
			sb.append("'");

			throw new RuntimeException(sb.toString());
		}

		List varNames = _poshiProseMatcher.getVarNames();

		List varValues = new ArrayList<>();

		Matcher varValueMatcher = _varValuePattern.matcher(proseStatement);

		while (varValueMatcher.find()) {
			varValues.add(varValueMatcher.group(1));
		}

		for (int i = 0; i < varNames.size(); i++) {
			String varName = varNames.get(i);

			if (_varMap.containsKey(varName)) {
				StringBuilder sb = new StringBuilder();

				sb.append("Duplicate variable value assignment: ${");
				sb.append(varName);
				sb.append("} already has a value of ");
				sb.append(_varMap.get(varName));
				sb.append("\nProse statement: ");
				sb.append(_proseStatement);
				sb.append("\nMatching macro prose statement: ");
				sb.append(_poshiProseMatcher.getPoshiProse());

				throw new RuntimeException(sb.toString());
			}

			String varValue;

			if ((i + 1) == varNames.size()) {
				Matcher multiLineStringMatcher =
					_multiLineStringPattern.matcher(proseStatement);
				Matcher tableMatcher = _tablePattern.matcher(proseStatement);

				if (multiLineStringMatcher.find()) {
					varValue = multiLineStringMatcher.group(1);
				}
				else if (tableMatcher.find()) {
					varValue = tableMatcher.group(1);
				}
				else {
					varValue = varValues.get(i);
				}
			}
			else {
				varValue = varValues.get(i);
			}

			_varMap.put(varName, varValue);
		}
	}

	@Override
	public Element toElement() {
		Element element = Dom4JUtil.getNewElement(
			"execute", null,
			new DefaultAttribute(
				"macro",
				_poshiProseMatcher.getMacroNamespacedClassCommandName()));

		Element proseElement = Dom4JUtil.getNewElement("prose", element);

		proseElement.addCDATA(_proseStatement);

		for (Map.Entry varMapEntry : _varMap.entrySet()) {
			Element varElement = Dom4JUtil.getNewElement(
				"var", null,
				new DefaultAttribute("name", varMapEntry.getKey()));

			String value = varMapEntry.getValue();

			if (value.matches(_tablePattern.pattern())) {
				varElement.addAttribute("type", "Table");

				varElement.addCDATA(value);
			}
			else if (value.contains(_LINE_SEPARATOR)) {
				varElement.addCDATA(value);
			}
			else {
				varElement.addAttribute("value", value);
			}

			Dom4JUtil.addToElement(element, varElement);
		}

		return element;
	}

	protected String formatProseStatement(String proseStatement) {
		String formattedProseStatement = proseStatement.trim();

		formattedProseStatement = formattedProseStatement.replaceAll(
			_LINE_SEPARATOR + "\t\t", _LINE_SEPARATOR);

		return formattedProseStatement;
	}

	protected String getProseStatementMatchingString() {
		String proseStatement = formatProseStatement(_proseStatement);

		String proseStatementMatchingString = proseStatement.replaceAll(
			_multiLineStringPattern.pattern(), " \"\"");

		proseStatementMatchingString = proseStatementMatchingString.replaceAll(
			_tablePattern.pattern(), " \"\"");

		proseStatementMatchingString = proseStatementMatchingString.replaceAll(
			_varValuePattern.pattern(), "\"\"");

		return proseStatementMatchingString;
	}

	protected static final String[] KEYWORDS = {
		"*", "And", "Given", "Then", "When"
	};

	private static final String _LINE_SEPARATOR = System.lineSeparator();

	private static final Pattern _multiLineStringPattern = Pattern.compile(
		"(?s)\\s*\"\"\".*?\\R(.*?)\\s*\"\"\"");
	private static final Pattern _tablePattern = Pattern.compile(
		"(?s)\\s*(\\|.*\\|$)");
	private static final Pattern _varValuePattern = Pattern.compile(
		"\"(.*?)\"");

	private final PoshiProseMatcher _poshiProseMatcher;
	private final String _proseStatement;
	private final Map _varMap = new LinkedHashMap<>();

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy