org.tinygroup.template.interpret.TemplateFromContext.java Source code

Java tutorial

Introduction

Here is the source code for org.tinygroup.template.interpret.TemplateFromContext.java

Source

/**
 * Copyright (c) 1997-2013, www.tinygroup.org (luo_guo@icloud.com).
 * <p/>
 * Licensed under the GPL, Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p/>
 * http://www.gnu.org/licenses/gpl.html
 * <p/>
 * 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 org.tinygroup.template.interpret;

import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.tinygroup.template.TemplateContext;
import org.tinygroup.template.TemplateException;
import org.tinygroup.template.impl.AbstractTemplate;
import org.tinygroup.template.impl.TemplateEngineDefault;
import org.tinygroup.template.parser.grammer.TinyTemplateParser;
import org.tinygroup.template.rumtime.TemplateUtil;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by luog on 15/7/19.
 */
public class TemplateFromContext extends AbstractTemplate {
    Map<ParseTree, byte[]> terminalNodeMap = new ConcurrentHashMap<ParseTree, byte[]>();
    Map<ParseTree, Object> objectMap = new ConcurrentHashMap<ParseTree, Object>();
    private String path;
    TinyTemplateParser.TemplateContext templateContext;
    private static String[] stripWithSpaceChars = { " ", "    " };//  \t

    public String getText(ParseTree parseTree) {
        String result = (String) objectMap.get(parseTree);
        if (result == null) {
            result = parseTree.getText();
            objectMap.put(parseTree, result);
        }
        return result;
    }

    public void putObject(ParseTree parseTree, Object object) {
        objectMap.put(parseTree, object);
    }

    public <T> T getObject(ParseTree parseTree) {
        return (T) objectMap.get(parseTree);
    }

    public byte[] getTerminalNodeBytes(TerminalNode terminalNode, TemplateFromContext templateFromContext, int left,
            int right) throws TemplateException {
        byte[] bytes = terminalNodeMap.get(terminalNode);
        if (bytes == null) {
            try {
                String text = terminalNode.getText();

                // 
                if (getTemplateEngine().isCompactMode()) {
                    // Trim ?Set ? ?
                    text = trimCommentsDirectiveWhileSpaceNewLine(text, terminalNode, true);
                } else {
                    // Trim ?Set?\r\n
                    text = trimCommentsDirectiveWhileSpaceNewLine(text, terminalNode, false);
                }

                bytes = text.getBytes(getTemplateEngine().getEncode());
                terminalNodeMap.put(terminalNode, bytes);
            } catch (UnsupportedEncodingException e) {
                throw new TemplateException(e);
            }
        }
        return bytes;
    }

    /**
     * Trim ?Set ? ?
     * @param text 
     * @param nowTerminalNode 
     * @param trimWhileSpace ???
     * @return
     */
    private String trimCommentsDirectiveWhileSpaceNewLine(String text, TerminalNode nowTerminalNode,
            boolean trimWhileSpace) {
        if (text == null || text.length() == 0) {
            return "";
        }

        if (nowTerminalNode.getParent() instanceof TinyTemplateParser.TextContext) {
            // ??TextContext
            TinyTemplateParser.TextContext parseTree = (TinyTemplateParser.TextContext) nowTerminalNode.getParent();
            // ?Text Context?Block
            ParserRuleContext parentParserRuleContext = getParseTrreeParentButBlock(parseTree);
            if (isDirectiveNeedTrim(parentParserRuleContext)) {// ??Trim\r\n
                text = trimTextLeft(text);
                if (trimWhileSpace) {
                    text = TemplateUtil.trimStart(text, stripWithSpaceChars);
                    text = TemplateUtil.trimEnd(text, stripWithSpaceChars);
                }
            } else if (parentParserRuleContext instanceof TinyTemplateParser.BlockContext) {
                // ?Text ContextBlockContext?
                int parentChildrenIndex = getParentChildrenIndex(parseTree, parentParserRuleContext);
                // ?
                if (parentChildrenIndex > 0) {
                    // ?
                    ParseTree previousParseContext = parentParserRuleContext.getChild(parentChildrenIndex - 1);
                    // text??
                    if (previousParseContext instanceof TinyTemplateParser.CommentContext
                            || (previousParseContext instanceof TinyTemplateParser.DirectiveContext
                                    && (previousParseContext
                                            .getChild(0) instanceof TinyTemplateParser.Set_directiveContext
                                            || previousParseContext.getChild(
                                                    0) instanceof TinyTemplateParser.Blank_directiveContext
                                            || previousParseContext.getChild(
                                                    0) instanceof TinyTemplateParser.Call_macro_directiveContext
                                            || previousParseContext.getChild(
                                                    0) instanceof TinyTemplateParser.Call_macro_block_directiveContext
                                            || previousParseContext.getChild(
                                                    0) instanceof TinyTemplateParser.Import_directiveContext
                                            || previousParseContext.getChild(
                                                    0) instanceof TinyTemplateParser.If_directiveContext))) {
                        text = trimTextLeft(text);
                        if (trimWhileSpace) {
                            text = TemplateUtil.trimStart(text, stripWithSpaceChars);
                        }
                    }

                }

                if (trimWhileSpace) {
                    // ???
                    if (parentChildrenIndex < parentParserRuleContext.getChildCount()) {
                        // ?
                        ParseTree previousParseContext = parentParserRuleContext.getChild(parentChildrenIndex + 1);
                        // text??
                        if (previousParseContext instanceof TinyTemplateParser.CommentContext
                                || (previousParseContext instanceof TinyTemplateParser.DirectiveContext
                                        && (previousParseContext
                                                .getChild(0) instanceof TinyTemplateParser.Set_directiveContext
                                                || previousParseContext.getChild(
                                                        0) instanceof TinyTemplateParser.Blank_directiveContext
                                                || previousParseContext.getChild(
                                                        0) instanceof TinyTemplateParser.Call_macro_directiveContext
                                                || previousParseContext.getChild(
                                                        0) instanceof TinyTemplateParser.Call_macro_block_directiveContext
                                                || previousParseContext.getChild(
                                                        0) instanceof TinyTemplateParser.Import_directiveContext
                                                || previousParseContext.getChild(
                                                        0) instanceof TinyTemplateParser.If_directiveContext))) {
                            text = TemplateUtil.trimEnd(text, stripWithSpaceChars);
                        }
                    }
                }
            }
        }

        return text;
    }

    /**
     * Trim ?
     * @param str 
     * @return
        
    private static String trimStartWhiteSpace(String str) {
    int strLen;
    if (str != null && (strLen = str.length()) != 0) {
    int start = 0;
    while (start < strLen
    && (      " ".indexOf(str.charAt(start)) != -1          // ' '
    || "    ".indexOf(str.charAt(start)) != -1)) {      // '\t'
    ++start;
    }
        
    return str.substring(start);
    }
    return str;
    }*/

    /**
     * Trim ?
     * @param str 
     * @return
        
    private static String trimEndWhiteSpace(String str) {
    int end;
    if (str != null && (end = str.length()) != 0) {
    while ( end != 0
    && (      " ".indexOf(str.charAt(end - 1)) != -1         // ' '
    || "    ".indexOf(str.charAt(end - 1)) != -1 )) {    // '\t'
    --end;
    }
        
    return str.substring(0,end);
    }
    return str;
    }*/

    /**
     * Trim TextContext\r\n
     * @param text 
     * @return
     */
    private String trimTextLeft(String text) {
        int len = text.length();
        int leftPos = 0;
        for (int i = 0; i < len; i++) {
            char c = text.charAt(i);
            if (c == ' ' || c == '\t') {
                continue;
            } else if (c == '\r') {
                int n = i + 1;
                if (n < len && text.charAt(n) == '\n') {
                    leftPos = n + 1; // window: \r\n
                } else {
                    leftPos = n; // mac: \r
                }
                break;
            } else if (c == '\n') {
                leftPos = i + 1; // linux: \n
                break;
            } else {
                break;
            }
        }

        if (leftPos > 0) {
            if (text.equals("\r\n")) { // ?text'\r\n'
                text = "";
            } else {
                text = text.substring(leftPos, len);
            }
        }
        return text;
    }

    /**
     * ??TextContext?...?BlockContext
     * @param parseTree
     * @return
     */
    private ParserRuleContext getParseTrreeParentButBlock(ParserRuleContext parseTree) {
        ParserRuleContext parentParserRuleContext = parseTree.getParent();
        if (parentParserRuleContext instanceof TinyTemplateParser.TemplateContext)
            return parentParserRuleContext;
        if (parentParserRuleContext instanceof TinyTemplateParser.BlockContext) {
            if (parentParserRuleContext.getParent() instanceof TinyTemplateParser.TemplateContext)
                return parentParserRuleContext;
            if (parentParserRuleContext.getParent() instanceof TinyTemplateParser.BlockContext) {
                return getParseTrreeParentButBlock(parentParserRuleContext.getParent());
            } else
                return parentParserRuleContext.getParent();
        }
        return parentParserRuleContext;
    }

    /**
     * ??TextContext(?TextContextBlockContext)?List?
     * @param parseTree ?
     * @param parserRuleContext 
     * @return
     */
    private int getParentChildrenIndex(ParserRuleContext parseTree, ParserRuleContext parserRuleContext) {
        int parentChildrenIndex = 0;
        for (int i = 0; i < parserRuleContext.getChildCount(); i++) {
            ParserRuleContext childrenTree = (ParserRuleContext) parserRuleContext.getChild(i);
            if (childrenTree == parseTree) {
                parentChildrenIndex = i;
                break;
            }
        }
        return parentChildrenIndex;
    }

    /**
     * ??Trim\r\n === Set
     * #if #else #elseif #end #eol ${}
     * #for #foreach #while #break #continue
     * #macro
     * #@layout
     * @param parseTree ?
     * @return
     */
    public boolean isDirectiveNeedTrim(ParseTree parseTree) {
        return parseTree instanceof TinyTemplateParser.ValueContext
                || parseTree instanceof TinyTemplateParser.If_directiveContext
                || parseTree instanceof TinyTemplateParser.For_directiveContext
                || parseTree instanceof TinyTemplateParser.Else_directiveContext
                || parseTree instanceof TinyTemplateParser.Call_directiveContext
                || parseTree instanceof TinyTemplateParser.While_directiveContext
                || parseTree instanceof TinyTemplateParser.Break_directiveContext
                || parseTree instanceof TinyTemplateParser.Elseif_directiveContext
                || parseTree instanceof TinyTemplateParser.Return_directiveContext
                || parseTree instanceof TinyTemplateParser.Continue_directiveContext
                || parseTree instanceof TinyTemplateParser.Endofline_directiveContext
                || parseTree instanceof TinyTemplateParser.Call_macro_block_directiveContext
                || parseTree instanceof TinyTemplateParser.Macro_directiveContext
                || parseTree instanceof TinyTemplateParser.Call_block_directiveContext
                || parseTree instanceof TinyTemplateParser.Layout_impl_directiveContext;
    }

    public TemplateFromContext(String path, TinyTemplateParser.TemplateContext templateContext) {
        this.path = path;
        this.templateContext = templateContext;
    }

    @Override
    protected void renderContent(TemplateContext context, OutputStream outputStream)
            throws IOException, TemplateException {
        try {
            TemplateEngineDefault templateEngine = (TemplateEngineDefault) getTemplateEngine();
            TemplateEngineDefault.interpreter.interpret(templateEngine, this, templateContext, context, context,
                    outputStream, path);
        } catch (StopException e) {
            //Do Nothing
        } catch (ReturnException e) {
            //Do Nothing
        } catch (MacroException e) {
            throw e;
        } catch (TemplateException e) {
            throw e;
        } catch (Exception e) {
            throw new TemplateException(e);
        }
    }

    public String getPath() {
        return path;
    }

}