Java tutorial
/** * 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.tools.sourceformatter; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader; import com.liferay.portal.kernel.io.unsync.UnsyncStringReader; import com.liferay.portal.kernel.util.PropertiesUtil; import com.liferay.portal.kernel.util.PropsKeys; import com.liferay.portal.kernel.util.StringBundler; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.kernel.xml.Document; import com.liferay.portal.kernel.xml.Element; import com.liferay.portal.tools.ComparableRoute; import com.liferay.util.ContentUtil; /** * @author Hugo Huijser */ public class XMLSourceProcessor extends BaseSourceProcessor { public static String formatXML(String content) { String newContent = StringUtil.replace(content, "\"/>\n", "\" />\n"); while (true) { Matcher matcher = _commentPattern1.matcher(newContent); if (matcher.find()) { newContent = StringUtil.replaceFirst(newContent, ">\n", ">\n\n", matcher.start()); continue; } matcher = _commentPattern2.matcher(newContent); if (!matcher.find()) { break; } newContent = StringUtil.replaceFirst(newContent, "-->\n", "-->\n\n", matcher.start()); } return newContent; } protected void checkPoshiCharactersAfterDefinition(String fileName, String content) { Matcher matcher = _poshiCharactersAfterDefinitionTag.matcher(content); if (matcher.find()) { processErrorMessage(fileName, "Characters found after definition element: " + fileName); } } protected void checkPoshiCharactersBeforeDefinition(String fileName, String content) { Matcher matcher = _poshiCharactersBeforeDefinitionTag.matcher(content); if (matcher.find()) { processErrorMessage(fileName, "Characters found before definition element: " + fileName); } } protected void checkServiceXMLExceptions(String fileName, Element rootElement) { Element exceptionsElement = rootElement.element("exceptions"); if (exceptionsElement == null) { return; } List<Element> exceptionElements = exceptionsElement.elements("exception"); String previousException = StringPool.BLANK; for (Element exceptionElement : exceptionElements) { String exception = exceptionElement.getStringValue(); if (Validator.isNotNull(previousException) && (previousException.compareToIgnoreCase(exception) > 0)) { processErrorMessage(fileName, "sort: " + fileName + " " + exception); } previousException = exception; } } protected void checkServiceXMLFinders(String fileName, Element entityElement, String entityName) throws Exception { _columnNames = getColumnNames(fileName, entityName); FinderElementComparator finderElementComparator = new FinderElementComparator(); List<Element> finderElements = entityElement.elements("finder"); for (int i = 1; i < finderElements.size(); i++) { Element finderElement = finderElements.get(i); Element previousFinderElement = finderElements.get(i - 1); if (finderElementComparator.compare(previousFinderElement, finderElement) > 0) { String finderName = finderElement.attributeValue("name"); processErrorMessage(fileName, "order: " + fileName + " " + entityName + " " + finderName); } } } protected void checkServiceXMLReferences(String fileName, Element entityElement, String entityName) { String previousReferenceEntity = StringPool.BLANK; String previousReferencePackagePath = StringPool.BLANK; List<Element> referenceElements = entityElement.elements("reference"); for (Element referenceElement : referenceElements) { String referenceEntity = referenceElement.attributeValue("entity"); String referencePackagePath = referenceElement.attributeValue("package-path"); if (Validator.isNotNull(previousReferencePackagePath)) { if ((previousReferencePackagePath.compareToIgnoreCase(referencePackagePath) > 0) || (previousReferencePackagePath.equals(referencePackagePath) && (previousReferenceEntity.compareToIgnoreCase(referenceEntity) > 0))) { processErrorMessage(fileName, "sort: " + fileName + " " + entityName + " " + referenceEntity); } } previousReferenceEntity = referenceEntity; previousReferencePackagePath = referencePackagePath; } } @Override protected String doFormat(File file, String fileName, String absolutePath, String content) throws Exception { if (isExcluded(_xmlExclusions, absolutePath)) { return content; } String newContent = content; if (!fileName.contains("/build")) { newContent = trimContent(newContent, false); } if (fileName.contains("/build") && !fileName.contains("/tools/")) { newContent = formatAntXML(fileName, newContent); } else if (fileName.endsWith("structures.xml")) { newContent = formatDDLStructuresXML(newContent); } else if (fileName.endsWith("routes.xml")) { newContent = formatFriendlyURLRoutesXML(absolutePath, newContent); } else if (fileName.endsWith("/liferay-portlet.xml") || (portalSource && fileName.endsWith("/portlet-custom.xml")) || (!portalSource && fileName.endsWith("/portlet.xml"))) { newContent = formatPortletXML(fileName, absolutePath, newContent); } else if (portalSource && (fileName.endsWith(".action") || fileName.endsWith(".function") || fileName.endsWith(".macro") || fileName.endsWith(".testcase") || fileName.endsWith(".testxml"))) { newContent = formatPoshiXML(fileName, newContent); } else if (fileName.endsWith("/service.xml")) { formatServiceXML(fileName, newContent); } else if (portalSource && fileName.endsWith("/struts-config.xml")) { formatStrutsConfigXML(fileName, newContent); } else if (portalSource && fileName.endsWith("/tiles-defs.xml")) { formatTilesDefsXML(fileName, newContent); } else if ((portalSource && fileName.endsWith("portal-web/docroot/WEB-INF/web.xml")) || (!portalSource && fileName.endsWith("/web.xml"))) { newContent = formatWebXML(fileName, newContent); } return formatXML(newContent); } protected String fixAntXMLProjectName(String fileName, String content) { int x = 0; if (fileName.endsWith("-ext/build.xml")) { if (fileName.startsWith("ext/")) { x = 4; } } else if (fileName.endsWith("-hook/build.xml")) { if (fileName.startsWith("hooks/")) { x = 6; } } else if (fileName.endsWith("-layouttpl/build.xml")) { if (fileName.startsWith("layouttpl/")) { x = 10; } } else if (fileName.endsWith("-portlet/build.xml")) { if (fileName.startsWith("portlets/")) { x = 9; } } else if (fileName.endsWith("-theme/build.xml")) { if (fileName.startsWith("themes/")) { x = 7; } } else if (fileName.endsWith("-web/build.xml") && !fileName.endsWith("/ext-web/build.xml")) { if (fileName.startsWith("webs/")) { x = 5; } } else { return content; } if (content.contains("<project>")) { return content; } int y = fileName.indexOf("/", x); String correctProjectElementText = "<project name=\"" + fileName.substring(x, y) + "\""; if (!content.contains(correctProjectElementText)) { x = content.indexOf("<project name=\""); y = content.indexOf("\"", x) + 1; y = content.indexOf("\"", y) + 1; content = content.substring(0, x) + correctProjectElementText + content.substring(y); processErrorMessage(fileName, fileName + " has an incorrect project name"); } return content; } protected String fixPoshiXMLElementWithNoChild(String content) { Matcher matcher = _poshiElementWithNoChildPattern.matcher(content); while (matcher.find()) { content = StringUtil.replace(content, matcher.group(), "\" />"); } return content; } protected 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; } protected String fixPoshiXMLEndLinesAfterClosingElement(String content) { Matcher matcher = _poshiEndLinesAfterClosingElementPattern.matcher(content); while (matcher.find()) { String statement = matcher.group(); String closingElementName = matcher.group(1); if (StringUtil.equalsIgnoreCase("</and>", closingElementName) || StringUtil.equalsIgnoreCase("</elseif>", closingElementName) || StringUtil.equalsIgnoreCase("</not>", closingElementName) || StringUtil.equalsIgnoreCase("</or>", closingElementName) || StringUtil.equalsIgnoreCase("</then>", closingElementName)) { String newStatement = StringUtil.replace(statement, matcher.group(2), "\n"); content = StringUtil.replace(content, statement, newStatement); } else if (!StringUtil.equalsIgnoreCase("</var>", closingElementName)) { String newStatement = StringUtil.replace(statement, matcher.group(2), "\n\n"); content = StringUtil.replace(content, statement, newStatement); } } return content; } protected 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; } protected String fixPoshiXMLNumberOfTabs(String content) { Matcher matcher = _poshiTabsPattern.matcher(content); int tabCount = 0; boolean ignoredCdataBlock = false; boolean ignoredCommentBlock = false; while (matcher.find()) { String statement = matcher.group(); Matcher quoteWithSlashMatcher = _poshiQuoteWithSlashPattern.matcher(statement); String fixedQuoteStatement = statement; if (quoteWithSlashMatcher.find()) { fixedQuoteStatement = StringUtil.replace(statement, quoteWithSlashMatcher.group(), "\"\""); } Matcher closingTagMatcher = _poshiClosingTagPattern.matcher(fixedQuoteStatement); Matcher openingTagMatcher = _poshiOpeningTagPattern.matcher(fixedQuoteStatement); Matcher wholeTagMatcher = _poshiWholeTagPattern.matcher(fixedQuoteStatement); if (closingTagMatcher.find() && !openingTagMatcher.find() && !wholeTagMatcher.find() && !statement.contains("<!--") && !statement.contains("-->") && !statement.contains("<![CDATA[") && !statement.contains("]]>")) { tabCount--; } if (statement.contains("]]>")) { ignoredCdataBlock = false; } else if (statement.contains("<![CDATA[")) { ignoredCdataBlock = true; } if (statement.contains("-->")) { ignoredCommentBlock = false; } else if (statement.contains("<!--")) { ignoredCommentBlock = true; } if (!ignoredCommentBlock && !ignoredCdataBlock) { StringBundler sb = new StringBundler(tabCount + 1); for (int i = 0; i < tabCount; i++) { sb.append(StringPool.TAB); } sb.append(StringPool.LESS_THAN); String replacement = sb.toString(); if (!replacement.equals(matcher.group(1))) { String newStatement = StringUtil.replace(statement, matcher.group(1), replacement); return StringUtil.replaceFirst(content, statement, newStatement, matcher.start()); } } if (openingTagMatcher.find() && !closingTagMatcher.find() && !wholeTagMatcher.find() && !statement.contains("<!--") && !statement.contains("-->") && !statement.contains("<![CDATA[") && !statement.contains("]]>")) { tabCount++; } } return content; } @Override protected void format() throws Exception { String[] excludes = new String[] { "**\\.bnd\\**", "**\\.idea\\**", "**\\.ivy\\**", "portal-impl\\**\\*.action", "portal-impl\\**\\*.function", "portal-impl\\**\\*.macro", "portal-impl\\**\\*.testcase" }; String[] includes = new String[] { "**\\*.action", "**\\*.function", "**\\*.macro", "**\\*.testcase", "**\\*.xml" }; _friendlyUrlRoutesSortExclusions = getPropertyList("friendly.url.routes.sort.excludes.files"); _numericalPortletNameElementExclusions = getPropertyList("numerical.portlet.name.element.excludes.files"); _xmlExclusions = getPropertyList("xml.excludes.files"); List<String> fileNames = getFileNames(excludes, includes); for (String fileName : fileNames) { format(fileName); } } protected String formatAntXML(String fileName, String content) throws Exception { String newContent = trimContent(content, true); newContent = fixAntXMLProjectName(fileName, newContent); Document document = saxReaderUtil.read(newContent); Element rootElement = document.getRootElement(); String previousName = StringPool.BLANK; List<Element> targetElements = rootElement.elements("target"); for (Element targetElement : targetElements) { String name = targetElement.attributeValue("name"); if (name.equals("Test")) { name = StringUtil.toLowerCase(name); } if (name.compareTo(previousName) < -1) { processErrorMessage(fileName, fileName + " has an unordered target " + name); break; } previousName = name; } return newContent; } protected String formatDDLStructuresXML(String content) throws Exception { Document document = saxReaderUtil.read(content); Element rootElement = document.getRootElement(); rootElement.sortAttributes(true); rootElement.sortElementsByChildElement("structure", "name"); List<Element> structureElements = rootElement.elements("structure"); for (Element structureElement : structureElements) { Element structureRootElement = structureElement.element("root"); structureRootElement.sortElementsByAttribute("dynamic-element", "name"); List<Element> dynamicElementElements = structureRootElement.elements("dynamic-element"); for (Element dynamicElementElement : dynamicElementElements) { Element metaDataElement = dynamicElementElement.element("meta-data"); metaDataElement.sortElementsByAttribute("entry", "name"); } } return document.formattedString(); } protected String formatFriendlyURLRoutesXML(String absolutePath, String content) throws Exception { if (isExcluded(_friendlyUrlRoutesSortExclusions, absolutePath)) { return content; } Document document = saxReaderUtil.read(content); Element rootElement = document.getRootElement(); List<ComparableRoute> comparableRoutes = new ArrayList<ComparableRoute>(); for (Element routeElement : rootElement.elements("route")) { String pattern = routeElement.elementText("pattern"); ComparableRoute comparableRoute = new ComparableRoute(pattern); for (Element generatedParameterElement : routeElement.elements("generated-parameter")) { String name = generatedParameterElement.attributeValue("name"); String value = generatedParameterElement.getText(); comparableRoute.addGeneratedParameter(name, value); } for (Element ignoredParameterElement : routeElement.elements("ignored-parameter")) { String name = ignoredParameterElement.attributeValue("name"); comparableRoute.addIgnoredParameter(name); } for (Element implicitParameterElement : routeElement.elements("implicit-parameter")) { String name = implicitParameterElement.attributeValue("name"); String value = implicitParameterElement.getText(); comparableRoute.addImplicitParameter(name, value); } for (Element overriddenParameterElement : routeElement.elements("overridden-parameter")) { String name = overriddenParameterElement.attributeValue("name"); String value = overriddenParameterElement.getText(); comparableRoute.addOverriddenParameter(name, value); } comparableRoutes.add(comparableRoute); } Collections.sort(comparableRoutes); String mainReleaseVersion = getMainReleaseVersion(); StringBundler sb = new StringBundler(); sb.append("<?xml version=\"1.0\"?>\n"); sb.append("<!DOCTYPE routes PUBLIC \"-//Liferay//DTD Friendly URL "); sb.append("Routes "); sb.append(mainReleaseVersion); sb.append("//EN\" \"http://www.liferay.com/dtd/"); sb.append("liferay-friendly-url-routes_"); sb.append(StringUtil.replace(mainReleaseVersion, StringPool.PERIOD, StringPool.UNDERLINE)); sb.append(".dtd\">\n\n<routes>\n"); for (ComparableRoute comparableRoute : comparableRoutes) { sb.append("\t<route>\n"); sb.append("\t\t<pattern>"); sb.append(comparableRoute.getPattern()); sb.append("</pattern>\n"); Map<String, String> generatedParameters = comparableRoute.getGeneratedParameters(); for (Map.Entry<String, String> entry : generatedParameters.entrySet()) { sb.append("\t\t<generated-parameter name=\""); sb.append(entry.getKey()); sb.append("\">"); sb.append(entry.getValue()); sb.append("</generated-parameter>\n"); } Set<String> ignoredParameters = comparableRoute.getIgnoredParameters(); for (String entry : ignoredParameters) { sb.append("\t\t<ignored-parameter name=\""); sb.append(entry); sb.append("\" />\n"); } Map<String, String> implicitParameters = comparableRoute.getImplicitParameters(); for (Map.Entry<String, String> entry : implicitParameters.entrySet()) { sb.append("\t\t<implicit-parameter name=\""); sb.append(entry.getKey()); sb.append("\">"); sb.append(entry.getValue()); sb.append("</implicit-parameter>\n"); } Map<String, String> overriddenParameters = comparableRoute.getOverriddenParameters(); for (Map.Entry<String, String> entry : overriddenParameters.entrySet()) { sb.append("\t\t<overridden-parameter name=\""); sb.append(entry.getKey()); sb.append("\">"); sb.append(entry.getValue()); sb.append("</overridden-parameter>\n"); } sb.append("\t</route>\n"); } sb.append("</routes>"); return sb.toString(); } protected String formatPortletXML(String fileName, String absolutePath, String content) throws Exception { Document document = saxReaderUtil.read(content); Element rootElement = document.getRootElement(); rootElement.sortAttributes(true); boolean checkNumericalPortletNameElement = !isExcluded(_numericalPortletNameElementExclusions, absolutePath); List<Element> portletElements = rootElement.elements("portlet"); for (Element portletElement : portletElements) { if (checkNumericalPortletNameElement) { Element portletNameElement = portletElement.element("portlet-name"); String portletNameText = portletNameElement.getText(); if (!Validator.isNumber(portletNameText)) { processErrorMessage(fileName, fileName + " contains a nonstandard portlet-name element " + portletNameText); } } if (fileName.endsWith("/liferay-portlet.xml")) { continue; } portletElement.sortElementsByChildElement("init-param", "name"); Element portletPreferencesElement = portletElement.element("portlet-preferences"); if (portletPreferencesElement != null) { portletPreferencesElement.sortElementsByChildElement("preference", "name"); } } return document.formattedString(); } protected String formatPoshiXML(String fileName, String content) throws Exception { checkPoshiCharactersAfterDefinition(fileName, content); checkPoshiCharactersBeforeDefinition(fileName, content); content = sortPoshiAttributes(fileName, content); content = sortPoshiCommands(content); content = sortPoshiVariables(content); content = fixPoshiXMLElementWithNoChild(content); content = fixPoshiXMLEndLinesAfterClosingElement(content); content = fixPoshiXMLEndLinesBeforeClosingElement(content); content = fixPoshiXMLEndLines(content); return fixPoshiXMLNumberOfTabs(content); } protected void formatServiceXML(String fileName, String content) throws Exception { Document document = saxReaderUtil.read(content); Element rootElement = document.getRootElement(); List<Element> entityElements = rootElement.elements("entity"); String previousEntityName = StringPool.BLANK; for (Element entityElement : entityElements) { String entityName = entityElement.attributeValue("name"); if (Validator.isNotNull(previousEntityName) && (previousEntityName.compareToIgnoreCase(entityName) > 0)) { processErrorMessage(fileName, "sort: " + fileName + " " + entityName); } checkServiceXMLFinders(fileName, entityElement, entityName); checkServiceXMLReferences(fileName, entityElement, entityName); previousEntityName = entityName; } checkServiceXMLExceptions(fileName, rootElement); } protected void formatStrutsConfigXML(String fileName, String content) throws Exception { Document document = saxReaderUtil.read(content); Element rootElement = document.getRootElement(); Element actionMappingsElement = rootElement.element("action-mappings"); List<Element> actionElements = actionMappingsElement.elements("action"); String previousPath = StringPool.BLANK; for (Element actionElement : actionElements) { String path = actionElement.attributeValue("path"); if (Validator.isNotNull(previousPath) && (previousPath.compareTo(path) > 0) && (!previousPath.startsWith("/portal/") || path.startsWith("/portal/"))) { processErrorMessage(fileName, "sort: " + fileName + " " + path); } previousPath = path; } } protected void formatTilesDefsXML(String fileName, String content) throws Exception { Document document = saxReaderUtil.read(content); Element rootElement = document.getRootElement(); List<Element> definitionElements = rootElement.elements("definition"); String previousName = StringPool.BLANK; for (Element definitionElement : definitionElements) { String name = definitionElement.attributeValue("name"); if (Validator.isNotNull(previousName) && (previousName.compareTo(name) > 0) && !previousName.equals("portlet")) { processErrorMessage(fileName, "sort: " + fileName + " " + name); } previousName = name; } } protected String formatWebXML(String fileName, String content) throws Exception { if (!portalSource) { String webXML = ContentUtil.get("com/liferay/portal/deploy/dependencies/web.xml"); if (content.equals(webXML)) { processErrorMessage(fileName, fileName); } return content; } Properties properties = new Properties(); String propertiesContent = fileUtil.read(BASEDIR + "portal-impl/src/portal.properties"); PropertiesUtil.load(properties, propertiesContent); String[] locales = StringUtil.split(properties.getProperty(PropsKeys.LOCALES)); Arrays.sort(locales); Set<String> urlPatterns = new TreeSet<String>(); for (String locale : locales) { int pos = locale.indexOf(StringPool.UNDERLINE); String languageCode = locale.substring(0, pos); urlPatterns.add(languageCode); urlPatterns.add(locale); } StringBundler sb = new StringBundler(6 * urlPatterns.size()); for (String urlPattern : urlPatterns) { sb.append("\t<servlet-mapping>\n"); sb.append("\t\t<servlet-name>I18n Servlet</servlet-name>\n"); sb.append("\t\t<url-pattern>/"); sb.append(urlPattern); sb.append("/*</url-pattern>\n"); sb.append("\t</servlet-mapping>\n"); } int x = content.indexOf("<servlet-mapping>"); x = content.indexOf("<servlet-name>I18n Servlet</servlet-name>", x); x = content.lastIndexOf("<servlet-mapping>", x) - 1; int y = content.lastIndexOf("<servlet-name>I18n Servlet</servlet-name>"); y = content.indexOf("</servlet-mapping>", y) + 19; String newContent = content.substring(0, x) + sb.toString() + content.substring(y); x = newContent.indexOf("<security-constraint>"); x = newContent.indexOf("<web-resource-name>/c/portal/protected</web-resource-name>", x); x = newContent.indexOf("<url-pattern>", x) - 3; y = newContent.indexOf("<http-method>", x); y = newContent.lastIndexOf("</url-pattern>", y) + 15; sb = new StringBundler(3 * urlPatterns.size() + 1); sb.append("\t\t\t<url-pattern>/c/portal/protected</url-pattern>\n"); for (String urlPattern : urlPatterns) { sb.append("\t\t\t<url-pattern>/"); sb.append(urlPattern); sb.append("/c/portal/protected</url-pattern>\n"); } return newContent.substring(0, x) + sb.toString() + newContent.substring(y); } protected List<String> getColumnNames(String fileName, String entityName) throws Exception { List<String> columnNames = new ArrayList<String>(); Pattern pattern = Pattern.compile("create table " + entityName + "_? \\(\n([\\s\\S]*?)\n\\);"); Matcher matcher = pattern.matcher(getTablesContent(fileName)); if (!matcher.find()) { return columnNames; } String tableContent = matcher.group(1); UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(new UnsyncStringReader(tableContent)); String line = null; while ((line = unsyncBufferedReader.readLine()) != null) { line = StringUtil.trim(line); String columnName = line.substring(0, line.indexOf(StringPool.SPACE)); columnName = StringUtil.replace(columnName, StringPool.UNDERLINE, StringPool.BLANK); columnNames.add(columnName); } return columnNames; } protected String getTablesContent(String fileName) throws Exception { if (portalSource) { if (_tablesContent == null) { _tablesContent = getContent("sql/portal-tables.sql", 4); } return _tablesContent; } int pos = fileName.lastIndexOf(StringPool.SLASH); return getContent(fileName.substring(0, pos) + "/sql/tables.sql", 1); } protected String sortPoshiAttributes(String fileName, String content) throws Exception { StringBundler sb = new StringBundler(); try (UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader( new UnsyncStringReader(content))) { String line = null; int lineCount = 0; boolean sortAttributes = true; while ((line = unsyncBufferedReader.readLine()) != null) { lineCount++; String trimmedLine = StringUtil.trimLeading(line); if (sortAttributes) { if (trimmedLine.startsWith(StringPool.LESS_THAN) && trimmedLine.endsWith(StringPool.GREATER_THAN) && !trimmedLine.startsWith("<%") && !trimmedLine.startsWith("<!")) { line = sortAttributes(fileName, line, lineCount, false); } else if (trimmedLine.startsWith("<![CDATA[") && !trimmedLine.endsWith("]]>")) { sortAttributes = false; } } else if (trimmedLine.endsWith("]]>")) { sortAttributes = true; } sb.append(line); sb.append("\n"); } } content = sb.toString(); if (content.endsWith("\n")) { content = content.substring(0, content.length() - 1); } return content; } protected String sortPoshiCommands(String content) { Matcher matcher = _poshiCommandsPattern.matcher(content); Map<String, String> commandBlocksMap = new TreeMap<String, String>(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 = content.replace(setUpBlock, ""); sb.append(setUpBlock); } matcher = _poshiTearDownPattern.matcher(content); if (matcher.find()) { String tearDownBlock = matcher.group(); content = content.replace(tearDownBlock, ""); sb.append(tearDownBlock); } for (Map.Entry<String, String> entry : commandBlocksMap.entrySet()) { sb.append("\n\t"); sb.append(entry.getValue()); sb.append("\n"); } int x = content.indexOf("<command"); int y = content.lastIndexOf("</command>"); String commandBlock = content.substring(x, y); commandBlock = "\n\t" + commandBlock + "</command>\n"; String newCommandBlock = sb.toString(); return StringUtil.replaceFirst(content, commandBlock, newCommandBlock); } protected String sortPoshiVariables(String content) { Matcher matcher = _poshiVariablesBlockPattern.matcher(content); while (matcher.find()) { String previousName = StringPool.BLANK; String tabs = StringPool.BLANK; Map<String, String> variableLinesMap = new TreeMap<String, String>(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<String, String> 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 Pattern _commentPattern1 = Pattern.compile(">\n\t+<!--[\n ]"); private static Pattern _commentPattern2 = Pattern.compile("[\t ]-->\n[\t<]"); private List<String> _columnNames; private List<String> _friendlyUrlRoutesSortExclusions; private List<String> _numericalPortletNameElementExclusions; private Pattern _poshiCharactersAfterDefinitionTag = Pattern.compile("</definition>([\\w\\s\\t\\n\\<\\>]+)"); private Pattern _poshiCharactersBeforeDefinitionTag = Pattern.compile("([\\w\\s\\t\\n\\<\\>]+)<definition"); private Pattern _poshiClosingTagPattern = Pattern.compile("</[^>/]*>"); private Pattern _poshiCommandsPattern = Pattern .compile("\\<command.*name=\\\"([^\\\"]*)\\\".*\\>[\\s\\S]*?\\</command\\>" + "[\\n|\\t]*?(?:[^(?:/\\>)]*?--\\>)*+"); private Pattern _poshiElementWithNoChildPattern = Pattern.compile("\\\"[\\s]*\\>[\\n\\s\\t]*\\</[a-z\\-]+>"); private Pattern _poshiEndLinesAfterClosingElementPattern = Pattern .compile("(\\</[a-z\\-]+>)(\\n+)\\t*\\<[a-z]+"); private Pattern _poshiEndLinesBeforeClosingElementPattern = Pattern.compile("(\\n+)(\\t*</[a-z\\-]+>)"); private Pattern _poshiEndLinesPattern = Pattern.compile("\\>\\n\\n\\n+(\\t*\\<)"); private Pattern _poshiOpeningTagPattern = Pattern.compile("<[^/][^>]*[^/]>"); private Pattern _poshiQuoteWithSlashPattern = Pattern.compile("\"[^\"]*\\>[^\"]*\""); private Pattern _poshiSetUpPattern = Pattern .compile("\\n[\\t]++\\<set-up\\>([\\s\\S]*?)\\</set-up\\>" + "[\\n|\\t]*?(?:[^(?:/\\>)]*?--\\>)*+\\n"); private Pattern _poshiTabsPattern = Pattern.compile("\\n*([ \\t]*<).*"); private Pattern _poshiTearDownPattern = Pattern.compile( "\\n[\\t]++\\<tear-down\\>([\\s\\S]*?)\\</tear-down\\>" + "[\\n|\\t]*?(?:[^(?:/\\>)]*?--\\>)*+\\n"); private Pattern _poshiVariableLinePattern = Pattern .compile("([\\t]*+)(\\<var name=\\\"([^\\\"]*)\\\".*?/\\>.*+(?:\\</var\\>)??)"); private Pattern _poshiVariablesBlockPattern = Pattern .compile("((?:[\\t]*+\\<var.*?\\>\\n[\\t]*+){2,}?)" + "(?:(?:\\n){1,}+|\\</execute\\>)"); private Pattern _poshiWholeTagPattern = Pattern.compile("<[^\\>^/]*\\/>"); private String _tablesContent; private List<String> _xmlExclusions; private class FinderElementComparator implements Comparator<Element> { @Override public int compare(Element finderElement1, Element finderElement2) { List<Element> finderColumnElements1 = finderElement1.elements("finder-column"); List<Element> finderColumnElements2 = finderElement2.elements("finder-column"); int finderColumnCount1 = finderColumnElements1.size(); int finderColumnCount2 = finderColumnElements2.size(); if (finderColumnCount1 != finderColumnCount2) { return finderColumnCount1 - finderColumnCount2; } for (int i = 0; i < finderColumnCount1; i++) { Element finderColumnElement1 = finderColumnElements1.get(i); Element finderColumnElement2 = finderColumnElements2.get(i); String finderColumnName1 = finderColumnElement1.attributeValue("name"); String finderColumnName2 = finderColumnElement2.attributeValue("name"); int index1 = _columnNames.indexOf(finderColumnName1); int index2 = _columnNames.indexOf(finderColumnName2); if (index1 != index2) { return index1 - index2; } } String finderName1 = finderElement1.attributeValue("name"); String finderName2 = finderElement2.attributeValue("name"); int startsWithWeight = StringUtil.startsWithWeight(finderName1, finderName2); String strippedFinderName1 = finderName1.substring(startsWithWeight); String strippedFinderName2 = finderName2.substring(startsWithWeight); if (strippedFinderName1.startsWith("Gt") || strippedFinderName1.startsWith("Like") || strippedFinderName1.startsWith("Lt") || strippedFinderName1.startsWith("Not")) { if (!strippedFinderName2.startsWith("Gt") && !strippedFinderName2.startsWith("Like") && !strippedFinderName2.startsWith("Lt") && !strippedFinderName2.startsWith("Not")) { return 1; } else { return strippedFinderName1.compareTo(strippedFinderName2); } } return 0; } } }