jodtemplate.template.expression.DefaultExpressionHandler.java Source code

Java tutorial

Introduction

Here is the source code for jodtemplate.template.expression.DefaultExpressionHandler.java

Source

/*
 * 
 * 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);
    }

}