<%-- ADOBE CONFIDENTIAL ___________________ Copyright 2020 Adobe All Rights Reserved. NOTICE: All information contained herein is, and remains the property of Adobe and its suppliers, if any. The intellectual and technical concepts contained herein are proprietary to Adobe and its suppliers and are protected by all applicable intellectual property laws, including trade secret and copyright laws. Dissemination of this information or reproduction of this material is strictly forbidden unless prior written permission is obtained from Adobe. --%><% %><%@include file="/libs/granite/ui/global.jsp" %><% %><%@page session="false" import="javax.jcr.Node, java.util.ArrayList, javax.jcr.Property, java.util.regex.Pattern, org.apache.sling.api.resource.Resource, com.adobe.granite.ui.components.Config, java.util.List"%><% %><%! public final String PRESET_DATA_VALUE__LITERAL = "literal"; public final String PRESET_DATA_VALUE__SEQUENCE = "sequence"; public final String PRESET_DATA_VALUE__COMPLEX = "rawcode"; //flags operations that the block does within its group public final String PRESET_DATA_VALUE__GROUP_LOGICAL_AND = "and"; public final String PRESET_DATA_VALUE__GROUP_LOGICAL_OR = "or"; //flags regex blocks of literal type public final String PRESET_DATA_VALUE__LITERAL_EXCLUDE = "exclude"; public final String PRESET_DATA_VALUE__LITERAL_ANY = "matchany"; public final String PRESET_DATA_VALUE__LITERAL_EXACT = "exact"; //flags regex blocks of sequence types public final String PRESET_DATA_VALUE__SEQUENCE_ONE_CHARACTER = "one"; public final String PRESET_DATA_VALUE__SEQUENCE_ANY_NUMBER_OF_CHARACTERS = "anynumber"; public final String PRESET_DATA_VALUE__SEQUENCE_N_CHARACTERS = "series"; //flags case sensitivity for sequence blocks public final String PRESET_DATA_VALUE__SEQUENCE_CASE_UPPER = "uppercase"; public final String PRESET_DATA_VALUE__SEQUENCE_CASE_LOWER = "lowercase"; //flags character type sensitivity for sequence blocks public final String PRESET_DATA_VALUE__SEQUENCE_CHAR_ALPHA = "alpha"; public final String PRESET_DATA_VALUE__SEQUENCE_CHAR_NUMERIC = "numeric"; public final String PRESET_DATA_VALUE__SEQUENCE_CHAR_ALPHANUMERIC = "alphanumeric"; public final String PRESET_DATA_VALUE__SEQUENCE_CASE_INSENSITIVE = "insensitive"; %><% Config cfg = cmp.getConfig(); String msgPath = cfg.get("msgPath", String.class); String blockType = cfg.get("blockType", String.class); List lst = null; String batSetPresetPath = slingRequest.getRequestPathInfo().getSuffix(); if(batSetPresetPath != null && blockType != null && !blockType.isEmpty()) { Resource batchSetPresetResource = resourceResolver.getResource(batSetPresetPath + "/jcr:content"); if(batchSetPresetResource != null) { Node batchSetPresetNode = batchSetPresetResource.adaptTo(Node.class); if(batchSetPresetNode.hasProperty(blockType)) { Property prop = batchSetPresetNode.getProperty(blockType); BatchSetPresetRegexParser parser = new BatchSetPresetRegexParser(); lst = parser.listOfOutputs(prop.getString()); } } } boolean initial = false; if(lst == null && blockType == null) { lst = new ArrayList<>(); lst.add(new BatchSetRulePartVO()); initial = true; } Resource msgResource = resource; if(msgPath != null) { msgResource = resourceResolver.getResource(msgPath); } String matchSelect = ""; String phraseChoise = ""; String exectValue = ""; String seriesChoise = ""; String numValue = ""; String alphaChoise = ""; String caseChoise = ""; String rawmatchValue = ""; String andSelect = ""; if(lst != null) { for(BatchSetRulePartVO onepart : lst) { matchSelect = onepart.model != null ? onepart.model : PRESET_DATA_VALUE__LITERAL; phraseChoise = onepart.queryType != null ? onepart.queryType : PRESET_DATA_VALUE__LITERAL_EXACT; exectValue = onepart.output != null ? onepart.output : "*"; seriesChoise = onepart.rangeMatchType != null ? onepart.rangeMatchType : PRESET_DATA_VALUE__SEQUENCE_ANY_NUMBER_OF_CHARACTERS; numValue = onepart.numberInput != null ? onepart.numberInput : "1"; alphaChoise = onepart.charType != null ? onepart.charType : PRESET_DATA_VALUE__SEQUENCE_CHAR_ALPHANUMERIC; caseChoise = onepart.alphaCase != null ? onepart.alphaCase : PRESET_DATA_VALUE__SEQUENCE_CASE_INSENSITIVE; rawmatchValue = onepart.output != null ? onepart.output : "*"; andSelect = onepart.isMarkedAsOr != null && onepart.isMarkedAsOr ? PRESET_DATA_VALUE__GROUP_LOGICAL_OR : PRESET_DATA_VALUE__GROUP_LOGICAL_AND; if(PRESET_DATA_VALUE__LITERAL_ANY.equals(phraseChoise)) { if(exectValue.indexOf("[") == 0) { exectValue = exectValue.substring(1); if(exectValue.lastIndexOf("]") == (exectValue.length() - 1)) { exectValue = exectValue.substring(0, exectValue.length() - 1); } } } else if(PRESET_DATA_VALUE__LITERAL_EXCLUDE.equals(phraseChoise)) { if(exectValue.indexOf("[^") == 0) { exectValue = exectValue.substring(2); if(exectValue.lastIndexOf("]") == (exectValue.length() - 1)) { exectValue = exectValue.substring(0, exectValue.length() - 1); } } } %> <% if(!initial) { %>
<% } %>
And Or
Literal Match Sequence Match Raw Code
> Exact Phrase Match any Exclude any of these characters
> any number of a series of one
>
"/> Alphanumeric Numeric Alpha
> "/> Case Insensitive Uppercase Lowercase
>
<% if(!initial) { %>
<% } %> <% } // for %> <% } // if %> <%! final static class BatchSetRulePartVO { public String output; public String queryType; public Boolean isMarkedAsOr; public Boolean isInGroup; public Boolean isTopOfGroup; public Boolean isBottomOfGroup; //-------------------- public String model; public String charType; public String rangeMatchType; public String alphaCase; public String numberInput; public String stringLiteral; } protected class BatchSetPresetRegexParser { private String _expressionProxy; private Boolean _groupIsOpen = false; public List listOfOutputs(String source) { List outputList = createListOfOutputs(source, true); for(BatchSetRulePartVO curpart : outputList) { curpart.queryType = determineQueryType(curpart.output); switch (curpart.queryType) { case PRESET_DATA_VALUE__COMPLEX: setDefaults(curpart); curpart.model = PRESET_DATA_VALUE__COMPLEX; break; case PRESET_DATA_VALUE__SEQUENCE_ANY_NUMBER_OF_CHARACTERS: case PRESET_DATA_VALUE__SEQUENCE_ONE_CHARACTER: case PRESET_DATA_VALUE__SEQUENCE_N_CHARACTERS: parseCharTypeFromOutput(curpart); parseAlphaCaseFromOutput(curpart); parseLengthFromRawValue(curpart); curpart.rangeMatchType = curpart.queryType; curpart.model = PRESET_DATA_VALUE__SEQUENCE; break; case PRESET_DATA_VALUE__LITERAL_EXACT: case PRESET_DATA_VALUE__LITERAL_EXCLUDE: case PRESET_DATA_VALUE__LITERAL_ANY: parseModifierAndInputFromRawValue(curpart); curpart.model = PRESET_DATA_VALUE__LITERAL; break; } } return outputList; } public List createListOfOutputs(String source) { return createListOfOutputs(source, true); } public List createListOfOutputs(String source, Boolean generateVOs) { String sanityCheck; BatchSetRulePartVO vo; List outputList = new ArrayList<>(); if (!source.isEmpty()) { _expressionProxy = source; do { sanityCheck = _expressionProxy; //this is hacky and needs to be redone. //factoryCreateRulesVO() breaks apart the regex query into discreet chunks //however we dont want to assign type under some cirumstances as it is a recursive operation vo = factoryCreateRulesVO(generateVOs); if (sanityCheck.equals(_expressionProxy)) { // sanityCheck == _expressionProxy if (generateVOs) { outputList.add(generateVO(_expressionProxy)); } else { outputList.add(null); } break; } else { if (generateVOs) { outputList.add(vo); } else { outputList.add(null); } } } while (_expressionProxy.length() > 0); } return outputList; } private void setDefaults(BatchSetRulePartVO curpart) { } private void parseCharTypeFromOutput(BatchSetRulePartVO curpart) { boolean isAlpha = curpart.output.toLowerCase().contains("a-z"); boolean isNumeric = curpart.output.contains("0-9"); if (isNumeric && !isAlpha) { curpart.charType = PRESET_DATA_VALUE__SEQUENCE_CHAR_NUMERIC; } else if (isAlpha && !isNumeric) { curpart.charType = PRESET_DATA_VALUE__SEQUENCE_CHAR_ALPHA; } else { curpart.charType = PRESET_DATA_VALUE__SEQUENCE_CHAR_ALPHANUMERIC; } } private void parseAlphaCaseFromOutput(BatchSetRulePartVO curpart) { boolean isUpper = curpart.output.contains("A-Z"); boolean isLower = curpart.output.contains("a-z"); if (isUpper && !isLower) { curpart.alphaCase = PRESET_DATA_VALUE__SEQUENCE_CASE_UPPER; } else if (isLower && !isUpper) { curpart.alphaCase = PRESET_DATA_VALUE__SEQUENCE_CASE_LOWER; } else { curpart.alphaCase = PRESET_DATA_VALUE__SEQUENCE_CASE_INSENSITIVE; } } private void parseLengthFromRawValue(BatchSetRulePartVO curpart) { if (curpart.output.contains("{") && (curpart.output.indexOf("}") > curpart.output.indexOf("{"))) { curpart.numberInput = curpart.output.substring(curpart.output.indexOf("{") + 1, curpart.output.lastIndexOf("}")); } } private void parseModifierAndInputFromRawValue(BatchSetRulePartVO curpart) { switch (curpart.queryType) { case PRESET_DATA_VALUE__LITERAL_EXCLUDE: curpart.stringLiteral = curpart.output.substring(curpart.output.indexOf("^") + 1, curpart.output.lastIndexOf("]")); break; case PRESET_DATA_VALUE__LITERAL_ANY: curpart.stringLiteral = curpart.output.substring(curpart.output.indexOf("[") + 1, curpart.output.lastIndexOf("]")); break; case PRESET_DATA_VALUE__LITERAL_EXACT: curpart.stringLiteral = curpart.output; } } private BatchSetRulePartVO factoryCreateRulesVO() { return factoryCreateRulesVO(false); } private BatchSetRulePartVO factoryCreateRulesVO(Boolean assignType) { BatchSetRulePartVO vo; // for some special cases, we don't split the regular expression anymore, for example: the parenthesis and {1,2} if (isComplicatedRE(_expressionProxy)) { vo = generateVO(_expressionProxy, PRESET_DATA_VALUE__COMPLEX); vo.isTopOfGroup = false; vo.isBottomOfGroup = false; vo.isInGroup = false; vo.isMarkedAsOr = false; _expressionProxy=""; return vo; } else { Boolean isTopOfGroup = (_expressionProxy.charAt(0) == '('); Boolean isMarkedAsOr = (_expressionProxy.charAt(0) == '|'); if (isTopOfGroup || isMarkedAsOr) { sliceExpressionProxy(0, 1); } String query = parseOutNextRegexElement(); String expressionBackup = _expressionProxy; String type = (assignType) ? determineQueryType(query) : null; Boolean isBottomOfGroup; _expressionProxy = expressionBackup; vo = generateVO(query, type); isBottomOfGroup = _expressionProxy.length() != 0 && (_expressionProxy.charAt(0) == ')'); if (isBottomOfGroup) { sliceExpressionProxy(0, 1); } vo.isTopOfGroup = isTopOfGroup; vo.isBottomOfGroup = isBottomOfGroup; vo.isInGroup = (isTopOfGroup || isBottomOfGroup || _groupIsOpen); vo.isMarkedAsOr = isMarkedAsOr; if (isTopOfGroup) { _groupIsOpen = true; } else if (isBottomOfGroup) { _groupIsOpen = false; } return vo; } } private Boolean isComplicatedRE(String reStr) { return Pattern.compile("(\\{\\d*,\\d*\\})|\\(|\\)").matcher(reStr).find(); } public String determineQueryType(String regex) { if (createListOfOutputs(regex, false).size() > 1) { return PRESET_DATA_VALUE__COMPLEX; } if (isComplicatedRE(regex)) { return PRESET_DATA_VALUE__COMPLEX; } _expressionProxy = regex; String result; try { if (_expressionProxy.charAt(0) == '[') { if (checkIfStringIsChracterClassBlock(regex)) { result = scrapeCharacterClassBlockFromExpressionProxy(); //separate ranges from literals if (!result.contains("-")) { //work with literals if (result.contains("^")) { return PRESET_DATA_VALUE__LITERAL_EXCLUDE; } else { return PRESET_DATA_VALUE__LITERAL_ANY; } } else { //work with ranges if (isCharacterClassBlockComplex(result)) { return PRESET_DATA_VALUE__COMPLEX; } else if (result.contains("?")) { return PRESET_DATA_VALUE__SEQUENCE_ONE_CHARACTER; } else if (result.contains("{")) { return PRESET_DATA_VALUE__SEQUENCE_N_CHARACTERS; } else if (result.contains("a-z") || result.contains("A-Z") || result.contains("0-9")) { return PRESET_DATA_VALUE__SEQUENCE_ANY_NUMBER_OF_CHARACTERS; } } } else { return PRESET_DATA_VALUE__COMPLEX; } } else { if (checkIfStringIsStringLiteral(regex)) { return PRESET_DATA_VALUE__LITERAL_EXACT; } else { return PRESET_DATA_VALUE__COMPLEX; } } } catch (Exception e) { //its cool - we cant parse it no worries. } return PRESET_DATA_VALUE__COMPLEX; } Boolean isCharacterClassBlockComplex(String characterClass) { characterClass = characterClass.substring(characterClass.indexOf("[") + 1, characterClass.indexOf("]")); characterClass = characterClass.replaceFirst("a-z", ""); characterClass = characterClass.replaceFirst("A-Z", ""); characterClass = characterClass.replaceFirst("0-9", ""); return (!characterClass.isEmpty()); } public BatchSetRulePartVO generateVO(String expressionPart) { return generateVO(expressionPart, null); } public BatchSetRulePartVO generateVO(String expressionPart, String queryType) { if (queryType == null) { queryType = PRESET_DATA_VALUE__LITERAL_EXACT; } BatchSetRulePartVO vo = new BatchSetRulePartVO(); vo.output = expressionPart; vo.queryType = queryType; return vo; } String parseOutNextRegexElement() { if (_expressionProxy.charAt(0) == '[') { return scrapeCharacterClassBlockFromExpressionProxy(); } return scrapeStringLiteralFromExpressionProxy(); } String scrapeStringLiteralFromExpressionProxy() { if (!checkIfStringIsStringLiteral(_expressionProxy)) { if (_expressionProxy.length() > 2) { if (_expressionProxy.charAt(0) == '?' && _expressionProxy.charAt(1) == '!') { return sliceExpressionProxy(0, 2); } } for (int i = 0; i < (_expressionProxy.length() - 1); i++) { switch (_expressionProxy.charAt(i + 1)) { case '(': case ')': case '|': case '[': case ']': case '{': case '}': case '?': case '!': case '^': case '+': return sliceExpressionProxy(0, (i + 1)); } } } return sliceExpressionProxy(0, _expressionProxy.length()); } Boolean checkIfStringIsStringLiteral(String regex) { return (!hasStr("(", 0, regex) && !hasStr(")", 0, regex) && !hasStr("|", 0, regex) && !hasStr("[", 0, regex) && !hasStr("]", 0, regex) && !hasStr("{", 0, regex) && !hasStr("}", 0, regex) && !hasStr("?", 0, regex) && !hasStr("!", 0, regex) && !hasStr("^", 0, regex) && !hasStr("+", 0, regex)); } String scrapeCharacterClassBlockFromExpressionProxy() { if (checkIfStringIsChracterClassBlock(_expressionProxy)) { int entryPoint = locate("["); int exitPoint = locate("]") + 1; if(exitPoint >=0 && exitPoint < _expressionProxy.length()) { if (_expressionProxy.charAt(exitPoint) == '{' && hasStr("}", locate("{"), null) ) { exitPoint = locate("}", exitPoint) + 1; } else if (_expressionProxy.charAt(exitPoint) == '+') { exitPoint++; } else if (_expressionProxy.charAt(exitPoint) == '*') { exitPoint++; } else if (_expressionProxy.charAt(exitPoint) == '?') { exitPoint++; } } return sliceExpressionProxy(entryPoint, exitPoint); } //cant parse - do ze default return scrapeStringLiteralFromExpressionProxy(); } Boolean checkIfStringIsChracterClassBlock(String regex) { return ( hasStr("[", 0, regex) && hasStr("]", locate("["), regex) ) && ( (!hasStr("{", 0, regex) && !hasStr("}", 0, regex) ) || ( hasStr("{", 0, regex) && hasStr("}", locate("{"), regex) ) ); } private String sliceExpressionProxy(int entryPoint, int exitPoint) { String query = _expressionProxy.substring(entryPoint, exitPoint); if (entryPoint > 0) { _expressionProxy = _expressionProxy.substring(0, entryPoint) + _expressionProxy.substring(exitPoint, _expressionProxy.length()); } else { _expressionProxy = _expressionProxy.substring(exitPoint, _expressionProxy.length()); } return query; } private Boolean hasStr(String val, int startIndex, String regex) { if (regex == null) { return locate(val, startIndex) >= 0; } return (regex.indexOf(val, startIndex) >= 0); } private int locate(String val) { return locate(val, 0); } private int locate(String val, int startIndex) { return _expressionProxy.indexOf(val, startIndex); } } %>