Java tutorial
/* * * Copyright 2015 Andrey Yakovlev * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package jodtemplate.template.expression; import java.util.Arrays; import java.util.List; import jodtemplate.exception.JODTemplateException; import jodtemplate.template.TemplateEngine; import org.apache.commons.lang3.StringUtils; public class DefaultExpressionHandler implements ExpressionHandler { private static final String POINT = "."; private static final Character INLINE_LIST_ITEM_BEGIN = '('; private static final Character INLINE_LIST_ITEM_END = ')'; private static final String BEGIN_LIST_TAG_PATTERN = "{{#list %s as %s}}"; private static final String END_LIST_TAG_PATTERN = "{{#end list}}"; private static final String REGEXP_START = "^"; private static final String REGEXP_END = "$"; private static final String VAR_REGEXP_PART = "([a-zA-Z_]+[a-zA-Z_0-9]*(\\[[0-9]+\\])?)"; private static final String VAR_REGEXP_SEPARATOR = "(\\.)"; private static final String VAR_REGEXP_PARAMS = "(\\?[a-zA-Z_]+(\\((([a-zA-Z_]+)|(\"([^\"]|\\\")+\"))\\))*)*"; private static final String VAR_REGEXP_DEFAULT_VALUE = "(\\!\"([^\"]|\\\")*\")?"; private static final String VAR_REGEXP_VARIABLE = VAR_REGEXP_PART + "(" + VAR_REGEXP_SEPARATOR + VAR_REGEXP_PART + ")*"; private static final String VAR_REGEXP_WITH_PARAMS = REGEXP_START + VAR_REGEXP_VARIABLE + VAR_REGEXP_PARAMS + VAR_REGEXP_DEFAULT_VALUE + REGEXP_END; private static final String DEFAULT_VALUE_SEPARATOR = "!"; private static final String PARAMS_VALUE_SEPARATOR = "?"; private static final String BEGIN_LIST_REGEXP = REGEXP_START + "#list\\s+?" + VAR_REGEXP_VARIABLE + "\\s+?as\\s+?" + VAR_REGEXP_PART + REGEXP_END; private static final String END_LIST_REGEXP = REGEXP_START + "#end\\s+?list" + REGEXP_END; // e.g. (model1.model2).field1.field2 private static final String INLINE_LIST_REGEXP = REGEXP_START + "\\(" + VAR_REGEXP_VARIABLE + "\\)(\\." + VAR_REGEXP_VARIABLE + ")*?" + REGEXP_END; private String beginTag; private String endTag; private TemplateEngine engine; public DefaultExpressionHandler(final TemplateEngine engine, final String beginTag, final String endTag) { this.engine = engine; this.beginTag = beginTag; this.endTag = endTag; } @Override public boolean isExpression(final String text) { return text.startsWith(beginTag) && text.endsWith(endTag); } @Override public String translateExpression(final String expression) throws JODTemplateException { final String expressionBody = getExpressionBody(expression); String trandlatedExpression; if (isVariableBody(expressionBody)) { final VariableExpression variableExpression = createVariableExpressionNoCheck(expressionBody); trandlatedExpression = engine.createVariable(variableExpression); } else if (isBeginListBody(expressionBody)) { final ListExpression beginListExpression = createBeginListExpressionNoCheck(expressionBody); trandlatedExpression = engine.createBeginListDirective(beginListExpression); } else if (isEndListBody(expressionBody)) { trandlatedExpression = engine.createEndListDirective(); } else { throw new JODTemplateException("Expression syntax error: " + expression); } return trandlatedExpression; } @Override public VariableExpression createVariableExpression(final String expression) throws JODTemplateException { final String expressionBody = getExpressionBody(expression); if (isVariableBody(expressionBody)) { return createVariableExpressionNoCheck(expressionBody); } else { throw new JODTemplateException("Expression is not a variable: " + expression); } } @Override public ListExpression createBeginListExpression(final String expression) throws JODTemplateException { final String expressionBody = getExpressionBody(expression); if (isBeginListBody(expressionBody)) { return createBeginListExpressionNoCheck(expressionBody); } else { throw new JODTemplateException("Expression is not a begin list: " + expression); } } @Override public InlineListExpression createInlineListExpression(final String expression) throws JODTemplateException { final String expressionBody = getExpressionBody(expression); if (isInlineListBody(expressionBody)) { return createInlineListExpressionNoCheck(expressionBody); } else { throw new JODTemplateException("Expression is not an inline list: " + expression); } } @Override public String getBeginTag() { return beginTag; } @Override public void setBeginTag(final String beginTag) { this.beginTag = beginTag; } @Override public String getEndTag() { return endTag; } @Override public void setEndTag(final String endTag) { this.endTag = endTag; } @Override public TemplateEngine getEngine() { return engine; } @Override public void setEngine(final TemplateEngine engine) { this.engine = engine; } @Override public boolean isVariable(final String expression) { if (!isExpression(expression)) { return false; } final String expressionBody = getExpressionBody(expression); return expressionBody.matches(VAR_REGEXP_WITH_PARAMS); } @Override public boolean isBeginList(final String expression) { if (!isExpression(expression)) { return false; } final String expressionBody = getExpressionBody(expression); return expressionBody.matches(BEGIN_LIST_REGEXP); } @Override public boolean isEndList(final String expression) { if (!isExpression(expression)) { return false; } final String expressionBody = getExpressionBody(expression); return expressionBody.matches(END_LIST_REGEXP); } @Override public boolean isInlineList(final String expression) { if (!isExpression(expression)) { return false; } final String expressionBody = getExpressionBody(expression); return expressionBody.matches(INLINE_LIST_REGEXP); } @Override public String createVariable(final String variable) { return beginTag + variable + endTag; } @Override public String createBeginList(final String what, final String as) { return String.format(BEGIN_LIST_TAG_PATTERN, what, as); } @Override public String createEndList() { return END_LIST_TAG_PATTERN; } private VariableExpression createVariableExpressionNoCheck(final String expressionBody) { String defaultValue = StringUtils.substringAfterLast(expressionBody, DEFAULT_VALUE_SEPARATOR).trim(); defaultValue = StringUtils.remove(defaultValue, '"'); final String variableWithParams = StringUtils.substringBefore(expressionBody, DEFAULT_VALUE_SEPARATOR); final String variable = StringUtils.substringBefore(variableWithParams, PARAMS_VALUE_SEPARATOR); final String paramsString = StringUtils.substringAfter(variableWithParams, PARAMS_VALUE_SEPARATOR); final List<String> params = Arrays.asList(StringUtils.split(paramsString, PARAMS_VALUE_SEPARATOR)); final VariableExpression variableExpression = new VariableExpression(variable, params, defaultValue); return variableExpression; } private ListExpression createBeginListExpressionNoCheck(final String expressionBody) { final String[] parts = StringUtils.split(expressionBody); final int whatIndex = 1; final int asIndex = 3; return new ListExpression(parts[whatIndex], parts[asIndex]); } private InlineListExpression createInlineListExpressionNoCheck(final String expressionBody) { final String listFullName = getInlineListFullName(expressionBody); final String listName = getInlineListName(listFullName); final String itemName = listName + "_item"; final String variable = replaceInlineListItemWithVariable(expressionBody, itemName); return new InlineListExpression(listFullName, itemName, variable); } private static String getInlineListName(final String text) { if (text.contains(POINT)) { return StringUtils.substringAfterLast(text, POINT); } return text; } private static String getInlineListFullName(final String text) { return StringUtils.substringBetween(text, INLINE_LIST_ITEM_BEGIN.toString(), INLINE_LIST_ITEM_END.toString()); } private static String replaceInlineListItemWithVariable(final String text, final String replace) { return text.replaceFirst("\\" + INLINE_LIST_ITEM_BEGIN + ".*?\\" + INLINE_LIST_ITEM_END, replace); } private String getExpressionBody(final String expression) { String expressionBody = StringUtils.substringBetween(expression, beginTag, endTag); expressionBody = StringUtils.trim(expressionBody); expressionBody = expressionBody.replaceAll("[?]", "\""); return expressionBody; } private boolean isVariableBody(final String expressionBody) { return expressionBody.matches(VAR_REGEXP_WITH_PARAMS); } private boolean isBeginListBody(final String expressionBody) { return expressionBody.matches(BEGIN_LIST_REGEXP); } private boolean isEndListBody(final String expressionBody) { return expressionBody.matches(END_LIST_REGEXP); } private boolean isInlineListBody(final String expressionBody) { return expressionBody.matches(INLINE_LIST_REGEXP); } }