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

com.liferay.source.formatter.check.XMLPoshiFileCheck Maven / Gradle / Ivy

There is a newer version: 1.0.1457
Show newest version
/**
 * SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com
 * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
 */

package com.liferay.source.formatter.check;

import com.liferay.petra.string.StringBundler;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.source.formatter.check.comparator.ElementComparator;
import com.liferay.source.formatter.check.util.SourceUtil;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;

/**
 * @author Hugo Huijser
 */
public class XMLPoshiFileCheck extends BaseFileCheck {

	@Override
	protected String doProcess(
			String fileName, String absolutePath, String content)
		throws DocumentException {

		if (fileName.endsWith(".action") || fileName.endsWith(".function") ||
			fileName.endsWith(".macro") || fileName.endsWith(".testcase")) {

			content = _formatPoshiXML(fileName, content);
		}

		return content;
	}

	private void _checkPoshiCharactersAfterDefinition(
		String fileName, String content) {

		if (content.contains("/definition>") &&
			!content.endsWith("/definition>")) {

			addMessage(fileName, "Characters found after definition element");
		}
	}

	private void _checkPoshiCharactersBeforeDefinition(
		String fileName, String content) {

		if (!content.startsWith("");
		}

		return content;
	}

	private String _fixPoshiXMLEndLines(String content) {
		Matcher matcher = _poshiEndLinesPattern.matcher(content);

		while (matcher.find()) {
			String statement = matcher.group();

			String newStatement = StringUtil.replace(
				statement, matcher.group(), ">\n\n" + matcher.group(1));

			content = StringUtil.replace(content, statement, newStatement);
		}

		return content;
	}

	private String _fixPoshiXMLEndLinesAfterClosingElement(String content) {
		Matcher matcher = _poshiEndLinesAfterClosingElementPattern.matcher(
			content);

		while (matcher.find()) {
			String statement = matcher.group();

			String closingElementName = matcher.group(1);

			if (StringUtil.equalsIgnoreCase("", closingElementName) ||
				StringUtil.equalsIgnoreCase("", closingElementName) ||
				StringUtil.equalsIgnoreCase("", closingElementName) ||
				StringUtil.equalsIgnoreCase("", closingElementName) ||
				StringUtil.equalsIgnoreCase("", closingElementName)) {

				String newStatement = StringUtil.replace(
					statement, matcher.group(2), "\n");

				content = StringUtil.replace(content, statement, newStatement);
			}
			else if (!StringUtil.equalsIgnoreCase(
						"", closingElementName)) {

				String newStatement = StringUtil.replace(
					statement, matcher.group(2), "\n\n");

				content = StringUtil.replace(content, statement, newStatement);
			}
		}

		return content;
	}

	private String _fixPoshiXMLEndLinesBeforeClosingElement(String content) {
		Matcher matcher = _poshiEndLinesBeforeClosingElementPattern.matcher(
			content);

		while (matcher.find()) {
			String statement = matcher.group();

			String newStatement = StringUtil.replace(
				statement, matcher.group(1), "\n");

			content = StringUtil.replace(content, statement, newStatement);
		}

		return content;
	}

	private String _formatPoshiXML(String fileName, String content) {
		_checkPoshiCharactersAfterDefinition(fileName, content);
		_checkPoshiCharactersBeforeDefinition(fileName, content);

		try {
			Document document = SourceUtil.readXML(content);

			if (document == null) {
				return content;
			}

			Element rootElement = document.getRootElement();

			List commandElements = rootElement.elements("command");

			for (Element commandElement : commandElements) {
				checkElementOrder(
					fileName, commandElement, "property", null,
					new ElementComparator());
			}
		}
		catch (Exception exception) {
			if (_log.isDebugEnabled()) {
				_log.debug(exception);
			}
		}

		content = _sortPoshiCommands(content);
		content = _sortPoshiVariables(content);

		content = _fixPoshiXMLElementWithNoChild(content);

		content = _fixPoshiXMLEndLinesAfterClosingElement(content);

		content = _fixPoshiXMLEndLinesBeforeClosingElement(content);

		return _fixPoshiXMLEndLines(content);
	}

	private String _sortPoshiCommands(String content) {
		Matcher matcher = _poshiCommandsPattern.matcher(content);

		Map commandBlocksMap = new TreeMap<>(
			String.CASE_INSENSITIVE_ORDER);

		String previousName = StringPool.BLANK;

		boolean hasUnsortedCommands = false;

		while (matcher.find()) {
			String commandBlock = matcher.group();
			String commandName = matcher.group(1);

			commandBlocksMap.put(commandName, commandBlock);

			if (!hasUnsortedCommands &&
				(commandName.compareToIgnoreCase(previousName) < 0)) {

				hasUnsortedCommands = true;
			}

			previousName = commandName;
		}

		if (!hasUnsortedCommands) {
			return content;
		}

		StringBundler sb = new StringBundler();

		matcher = _poshiSetUpPattern.matcher(content);

		if (matcher.find()) {
			String setUpBlock = matcher.group();

			content = StringUtil.removeSubstring(content, setUpBlock);

			sb.append(setUpBlock);
		}

		matcher = _poshiTearDownPattern.matcher(content);

		if (matcher.find()) {
			String tearDownBlock = matcher.group();

			content = StringUtil.removeSubstring(content, tearDownBlock);

			sb.append(tearDownBlock);
		}

		for (Map.Entry entry : commandBlocksMap.entrySet()) {
			sb.append("\n\t");
			sb.append(entry.getValue());
			sb.append("\n");
		}

		int x = content.indexOf("");

		String commandBlock = content.substring(x, y);

		commandBlock = "\n\t" + commandBlock + "\n";

		String newCommandBlock = sb.toString();

		return StringUtil.replaceFirst(content, commandBlock, newCommandBlock);
	}

	private String _sortPoshiVariables(String content) {
		Matcher matcher = _poshiVariablesBlockPattern.matcher(content);

		while (matcher.find()) {
			String previousName = StringPool.BLANK;
			String tabs = StringPool.BLANK;

			Map variableLinesMap = new TreeMap<>(
				String.CASE_INSENSITIVE_ORDER);

			String variableBlock = matcher.group(1);

			variableBlock = variableBlock.trim();

			Matcher variableLineMatcher = _poshiVariableLinePattern.matcher(
				variableBlock);

			boolean hasUnsortedVariables = false;

			while (variableLineMatcher.find()) {
				if (tabs.equals(StringPool.BLANK)) {
					tabs = variableLineMatcher.group(1);
				}

				String variableLine = variableLineMatcher.group(2);
				String variableName = variableLineMatcher.group(3);

				variableLinesMap.put(variableName, variableLine);

				if (!hasUnsortedVariables &&
					(variableName.compareToIgnoreCase(previousName) < 0)) {

					hasUnsortedVariables = true;
				}

				previousName = variableName;
			}

			if (!hasUnsortedVariables) {
				continue;
			}

			StringBundler sb = new StringBundler();

			for (Map.Entry entry :
					variableLinesMap.entrySet()) {

				sb.append(tabs);
				sb.append(entry.getValue());
				sb.append("\n");
			}

			String newVariableBlock = sb.toString();

			newVariableBlock = newVariableBlock.trim();

			content = StringUtil.replaceFirst(
				content, variableBlock, newVariableBlock);
		}

		return content;
	}

	private static final Log _log = LogFactoryUtil.getLog(
		XMLPoshiFileCheck.class);

	private static final Pattern _poshiCommandsPattern = Pattern.compile(
		"\\[\\s\\S]*?\\" +
			"[\\n|\\t]*?(?:[^(?:/\\>)]*?--\\>)*+");
	private static final Pattern _poshiElementWithNoChildPattern =
		Pattern.compile("\\\"[\\s]*\\>[\\n\\s\\t]*\\");
	private static final Pattern _poshiEndLinesAfterClosingElementPattern =
		Pattern.compile("(\\)(\\n+)\\t*\\<[a-z]+");
	private static final Pattern _poshiEndLinesBeforeClosingElementPattern =
		Pattern.compile("(\\n+)(\\t*)");
	private static final Pattern _poshiEndLinesPattern = Pattern.compile(
		"\\>\\n\\n\\n+(\\t*\\<)");
	private static final Pattern _poshiSetUpPattern = Pattern.compile(
		"\\n[\\t]++\\([\\s\\S]*?)\\" +
			"[\\n|\\t]*?(?:[^(?:/\\>)]*?--\\>)*+\\n");
	private static final Pattern _poshiTearDownPattern = Pattern.compile(
		"\\n[\\t]++\\([\\s\\S]*?)\\" +
			"[\\n|\\t]*?(?:[^(?:/\\>)]*?--\\>)*+\\n");
	private static final Pattern _poshiVariableLinePattern = Pattern.compile(
		"([\\t]*+)(\\" +
			".*+(?:\\)??)");
	private static final Pattern _poshiVariablesBlockPattern = Pattern.compile(
		"((?:[\\t]*+\\\\n[\\t]*+){2,}?)" +
			"(?:(?:\\n){1,}+|\\)");

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy