/* ==================================================================
* Created [2009-4-27 下午11:32:55] by Jon.King
* ==================================================================
* TSS
* ==================================================================
* mailTo:jinpujun@hotmail.com
* Copyright (c) Jon.King, 2009-2012
* ==================================================================
*/
package com.jinhe.tss.core.util;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* <p>
* 宏代码编译器
* </p>
*/
public class MacrocodeCompiler {
/**
* 宏代码标志
*/
public static char MACROCODE_SYMBOL = '$';
/**
* 变量标志
*/
public static char VARIABLE_SYMBOL = '#';
/**
* 宏代码名称起始标记:必须跟在宏代码、变量标志后有效
*/
public static char NAME_START_SYMBOL = '{';
/**
* 宏代码名称结束标记:起始标记后第一个此符号为配对的结束标记
*/
public static char NAME_END_SYMBOL = '}';
/**
* 空格字符串,用于变量初始化
*/
protected static char NULL = ' ';
/**
* <p>
* 将包含宏代码、变量等的脚本字符串解析成字符串片段后放到segment列表中<br>
* 以宏代码:${}、#{}分开,风别存放到List对象中<br>
* 如下:<br>
* 普通代码<br>
* ${XXXX}<br>
* 普通代码<br>
* #{YYYY}<br>
* 普通代码
* </p>
*
* @param code
* String 包含宏代码、变量等的字符串 比如 123${xxx}456
* @return List
* 代码片段列表 List{123, ${xxx}, 456}
*/
private static List<String> compile(String code) {
if (code == null) {
return null;
}
List<String> segment = new ArrayList<String>();
char curChar = NULL;
char preChar = NULL;
int startIndex = 0;
int endIndex = 0;
boolean isMacro = false;
for (int curIndex = 0;curIndex < code.length(); curIndex++) {
preChar = curChar;
curChar = code.charAt(curIndex);
if (isMacro) {
// 检测宏代码结束标记 curChar = '}'
if ( isEndSymbol(curChar) ) {
isMacro = false;
endIndex = curIndex + 1; // 连 “}” 一块截
if (endIndex > startIndex) {
segment.add(code.substring(startIndex, endIndex)); // 将宏代码、变量截取出来
startIndex = endIndex;
}
}
} else {
// 检测宏代码起始标记 preChar + curChar = "&{" or "#{"
if (isStartSymbol(curChar) && isMacroStartTag(preChar) ) {
isMacro = true;
endIndex = curIndex - 1; // 截取时回退两位,剔除 “${” 或 “#{”
if (endIndex > startIndex) {
segment.add(code.substring(startIndex, endIndex)); // 将非宏代码、变量截取出来
startIndex = endIndex;
}
}
}
}
if (startIndex < code.length()) {
segment.add(code.substring(startIndex, code.length()));
}
return segment;
}
/**
* <p>
* 将包含宏代码、变量代码的字符串解释其代码含义后,返回执行结果字符串 如下:<br>
* ${portlet}:PortletNode对象<br>
* #{title}:Portlet名称
* </p>
*
* @param code
* String 包含宏代码、变量等的字符串
* @param macrocodes
* Map 宏代码、值对应表
* @return String 宏代码、变量执行后的字符串
*/
public static String run(String code, Map<String, ? extends Object> macrocodes) {
List<String> segment = compile(code);
if (segment == null) return "";
StringBuffer sb = new StringBuffer();
for(String item : segment) {
if (item == null) continue;
if (item.length() > 3
&& isMacroStartTag(item.charAt(0)) && isStartSymbol(item.charAt(1)) && isEndSymbol(item.charAt(item.length() - 1))
&& macrocodes != null) {
Object macro = macrocodes.get(item);
if (macro != null) {
sb.append(macro);
}
}
else {
sb.append(item);
}
}
return sb.toString();
}
/** 是否宏代码标记 '$' or '#' */
private static boolean isMacroStartTag(char c){
return c == MACROCODE_SYMBOL || c == VARIABLE_SYMBOL;
}
/** 是否宏定义开始标记 '{' */
private static boolean isStartSymbol(char c){
return c == NAME_START_SYMBOL ;
}
/** 是否宏定义结束标记 '}' */
private static boolean isEndSymbol(char c){
return c == NAME_END_SYMBOL;
}
/**
* 生成 ${key}
* @param key
* @return ${key}
*/
public static String createMacroCode(String key){
return MACROCODE_SYMBOL + NAME_START_SYMBOL + key + NAME_END_SYMBOL;
}
/**
* 生成 #{key}
* @param key
* @return #{key}
*/
public static String createVariable(String key){
return VARIABLE_SYMBOL + NAME_START_SYMBOL + key + NAME_END_SYMBOL;
}
}