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