com.jfinal.template.EngineConfig Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of enjoy Show documentation
Show all versions of enjoy Show documentation
Enjoy is a simple, light, rapid, independent, extensible Java Template Engine.
The newest version!
/**
* Copyright (c) 2011-2023, James Zhan 詹波 ([email protected]).
*
* 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 com.jfinal.template;
import java.lang.reflect.Method;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import com.jfinal.kit.StrKit;
import com.jfinal.template.expr.ast.Arith;
import com.jfinal.template.expr.ast.ExprList;
import com.jfinal.template.expr.ast.SharedMethodKit;
import com.jfinal.template.ext.directive.*;
import com.jfinal.template.ext.sharedmethod.SharedMethodLib;
import com.jfinal.template.io.EncoderFactory;
import com.jfinal.template.io.WriterBuffer;
import com.jfinal.template.source.FileSource;
import com.jfinal.template.source.FileSourceFactory;
import com.jfinal.template.source.ISource;
import com.jfinal.template.source.ISourceFactory;
import com.jfinal.template.source.StringSource;
import com.jfinal.template.stat.Compressor;
import com.jfinal.template.stat.Location;
import com.jfinal.template.stat.OutputDirectiveFactory;
import com.jfinal.template.stat.Parser;
import com.jfinal.template.stat.ast.Define;
import com.jfinal.template.stat.ast.Output;
/**
* EngineConfig
*/
public class EngineConfig {
public static final String DEFAULT_ENCODING = "UTF-8";
WriterBuffer writerBuffer = new WriterBuffer();
Compressor compressor = null;
private Map sharedFunctionMap = createSharedFunctionMap(); // new HashMap(512, 0.25F);
private List sharedFunctionSourceList = new ArrayList(); // for devMode only
Map sharedObjectMap = null;
private OutputDirectiveFactory outputDirectiveFactory = OutputDirectiveFactory.me;
private ISourceFactory sourceFactory = new FileSourceFactory();
private Map> directiveMap = new HashMap>(64, 0.5F);
private SharedMethodKit sharedMethodKit = new SharedMethodKit();
// 保留指令所在行空白字符的指令
private Set keepLineBlankDirectives = new HashSet<>();
private boolean devMode = false;
private boolean reloadModifiedSharedFunctionInDevMode = true;
private String baseTemplatePath = null;
private String encoding = DEFAULT_ENCODING;
private String datePattern = "yyyy-MM-dd HH:mm";
// 浮点数输出与运算时使用的舍入模式,默认值为 "四舍五入"
private RoundingMode roundingMode = RoundingMode.HALF_UP;
private boolean supportStaticMethodExpression = false;
private boolean supportStaticFieldExpression = false;
public EngineConfig() {
// 内置指令 #() 与 #include() 需要配置,保留指令所在行前后空白字符以及行尾换行字符 '\n'
setKeepLineBlank("output", true);
setKeepLineBlank("include", true);
// Add official directive of Template Engine
addDirective("render", RenderDirective.class, true);
addDirective("date", DateDirective.class, true);
addDirective("escape", EscapeDirective.class, true);
addDirective("random", RandomDirective.class, true);
addDirective("number", NumberDirective.class, true);
addDirective("call", CallDirective.class, false);
addDirective("string", StringDirective.class, false);
// Add official shared method of Template Engine
addSharedMethod(new SharedMethodLib());
}
/**
* Add shared function with file
*/
public void addSharedFunction(String fileName) {
fileName = fileName.replace("\\", "/");
// FileSource fileSource = new FileSource(baseTemplatePath, fileName, encoding);
ISource source = sourceFactory.getSource(baseTemplatePath, fileName, encoding);
doAddSharedFunction(source, fileName);
}
private synchronized void doAddSharedFunction(ISource source, String fileName) {
Env env = new Env(this);
new Parser(env, source.getContent(), fileName).parse();
addToSharedFunctionMap(sharedFunctionMap, env);
if (devMode) {
sharedFunctionSourceList.add(source);
env.addSource(source);
}
}
/**
* Add shared function with files
*/
public void addSharedFunction(String... fileNames) {
for (String fileName : fileNames) {
addSharedFunction(fileName);
}
}
/**
* Add shared function by string content
*/
public void addSharedFunctionByString(String content) {
// content 中的内容被解析后会存放在 Env 之中,而 StringSource 所对应的
// Template 对象 isModified() 始终返回 false,所以没有必要对其缓存
StringSource stringSource = new StringSource(content, false);
doAddSharedFunction(stringSource, null);
}
/**
* Add shared function by ISource
*/
public void addSharedFunction(ISource source) {
String fileName = source instanceof FileSource ? ((FileSource)source).getFileName() : null;
doAddSharedFunction(source, fileName);
}
private void addToSharedFunctionMap(Map sharedFunctionMap, Env env) {
Map funcMap = env.getFunctionMap();
for (Entry e : funcMap.entrySet()) {
if (sharedFunctionMap.containsKey(e.getKey())) {
throw new IllegalArgumentException("Template function already exists : " + e.getKey());
}
Define func = e.getValue();
if (devMode) {
func.setEnvForDevMode(env);
}
sharedFunctionMap.put(e.getKey(), func);
}
}
/**
* Get shared function by Env
*/
Define getSharedFunction(String functionName) {
Define func = sharedFunctionMap.get(functionName);
if (func == null) {
/**
* 如果 func 最初未定义,但后续在共享模板文件中又被添加进来
* 此时在本 if 分支中无法被感知,仍然返回了 null
*
* 但共享模板文件会在后续其它的 func 调用时被感知修改并 reload
* 所以本 if 分支不考虑处理模板文件中追加 #define 的情况
*
* 如果要处理,只能是每次在 func 为 null 时,判断 sharedFunctionSourceList
* 中的模板是否被修改过,再重新加载,不优雅
*/
return null;
}
if (devMode && reloadModifiedSharedFunctionInDevMode) {
if (func.isSourceModifiedForDevMode()) {
synchronized (this) {
func = sharedFunctionMap.get(functionName);
if (func.isSourceModifiedForDevMode()) {
reloadSharedFunctionSourceList();
func = sharedFunctionMap.get(functionName);
}
}
}
}
return func;
}
/**
* Reload shared function source list
*
* devMode 要照顾到 sharedFunctionFiles,所以暂不提供
* removeSharedFunction(String functionName) 功能
* 开发者可直接使用模板注释功能将不需要的 function 直接注释掉
*/
private synchronized void reloadSharedFunctionSourceList() {
Map newMap = createSharedFunctionMap();
for (int i = 0, size = sharedFunctionSourceList.size(); i < size; i++) {
ISource source = sharedFunctionSourceList.get(i);
String fileName = source instanceof FileSource ? ((FileSource)source).getFileName() : null;
Env env = new Env(this);
new Parser(env, source.getContent(), fileName).parse();
addToSharedFunctionMap(newMap, env);
if (devMode) {
env.addSource(source);
}
}
this.sharedFunctionMap = newMap;
}
private Map createSharedFunctionMap() {
return new HashMap(512, 0.25F);
}
public synchronized void addSharedObject(String name, Object object) {
if (sharedObjectMap == null) {
sharedObjectMap = new HashMap(64, 0.25F);
} else if (sharedObjectMap.containsKey(name)) {
throw new IllegalArgumentException("Shared object already exists: " + name);
}
sharedObjectMap.put(name, object);
}
public Map getSharedObjectMap() {
return sharedObjectMap;
}
public synchronized void removeSharedObject(String name) {
if (sharedObjectMap != null) {
sharedObjectMap.remove(name);
}
}
/**
* Set output directive factory
*/
public void setOutputDirectiveFactory(OutputDirectiveFactory outputDirectiveFactory) {
if (outputDirectiveFactory == null) {
throw new IllegalArgumentException("outputDirectiveFactory can not be null");
}
this.outputDirectiveFactory = outputDirectiveFactory;
}
public Output getOutputDirective(ExprList exprList, Location location) {
return outputDirectiveFactory.getOutputDirective(exprList, location);
}
/**
* Invoked by Engine only
*/
void setDevMode(boolean devMode) {
this.devMode = devMode;
}
public boolean isDevMode() {
return devMode;
}
/**
* Invoked by Engine only
*/
void setSourceFactory(ISourceFactory sourceFactory) {
if (sourceFactory == null) {
throw new IllegalArgumentException("sourceFactory can not be null");
}
this.sourceFactory = sourceFactory;
}
public ISourceFactory getSourceFactory() {
return sourceFactory;
}
public void setBaseTemplatePath(String baseTemplatePath) {
// 使用 ClassPathSourceFactory 时,允许 baseTemplatePath 为 null 值
if (baseTemplatePath == null) {
this.baseTemplatePath = null;
return ;
}
if (StrKit.isBlank(baseTemplatePath)) {
throw new IllegalArgumentException("baseTemplatePath can not be blank");
}
baseTemplatePath = baseTemplatePath.trim();
baseTemplatePath = baseTemplatePath.replace("\\", "/");
if (baseTemplatePath.length() > 1) {
if (baseTemplatePath.endsWith("/")) {
baseTemplatePath = baseTemplatePath.substring(0, baseTemplatePath.length() - 1);
}
}
this.baseTemplatePath = baseTemplatePath;
}
public String getBaseTemplatePath() {
return baseTemplatePath;
}
public void setEncoding(String encoding) {
if (StrKit.isBlank(encoding)) {
throw new IllegalArgumentException("encoding can not be blank");
}
this.encoding = encoding;
writerBuffer.setEncoding(encoding); // 间接设置 EncoderFactory.encoding
}
public void setEncoderFactory(EncoderFactory encoderFactory) {
writerBuffer.setEncoderFactory(encoderFactory);
writerBuffer.setEncoding(encoding); // 间接设置 EncoderFactory.encoding
}
public void setBufferSize(int bufferSize) {
writerBuffer.setBufferSize(bufferSize);
}
public void setReentrantBufferSize(int reentrantBufferSize) {
writerBuffer.setReentrantBufferSize(reentrantBufferSize);
}
/**
* 配置自己的 WriterBuffer 实现,配置方法:
* engine.getEngineConfig().setWriterBuffer(...);
*/
public void setWriterBuffer(WriterBuffer writerBuffer) {
Objects.requireNonNull(writerBuffer, "writerBuffer can not be null");
this.writerBuffer = writerBuffer;
}
public String getEncoding() {
return encoding;
}
public void setDatePattern(String datePattern) {
if (StrKit.isBlank(datePattern)) {
throw new IllegalArgumentException("datePattern can not be blank");
}
this.datePattern = datePattern;
}
public String getDatePattern() {
return datePattern;
}
public void setReloadModifiedSharedFunctionInDevMode(boolean reloadModifiedSharedFunctionInDevMode) {
this.reloadModifiedSharedFunctionInDevMode = reloadModifiedSharedFunctionInDevMode;
}
public synchronized void addDirective(String directiveName, Class extends Directive> directiveClass, boolean keepLineBlank) {
if (StrKit.isBlank(directiveName)) {
throw new IllegalArgumentException("directive name can not be blank");
}
if (directiveClass == null) {
throw new IllegalArgumentException("directiveClass can not be null");
}
if (directiveMap.containsKey(directiveName)) {
throw new IllegalArgumentException("directive already exists : " + directiveName);
}
directiveMap.put(directiveName, directiveClass);
if (keepLineBlank) {
keepLineBlankDirectives.add(directiveName);
}
}
public void addDirective(String directiveName, Class extends Directive> directiveClass) {
addDirective(directiveName, directiveClass, false);
}
public Class extends Directive> getDirective(String directiveName) {
return directiveMap.get(directiveName);
}
public void removeDirective(String directiveName) {
directiveMap.remove(directiveName);
keepLineBlankDirectives.remove(directiveName);
}
public void setKeepLineBlank(String directiveName, boolean keepLineBlank) {
if (keepLineBlank) {
keepLineBlankDirectives.add(directiveName);
} else {
keepLineBlankDirectives.remove(directiveName);
}
}
public Set getKeepLineBlankDirectives() {
return keepLineBlankDirectives;
}
/**
* Add shared method from object
*/
public void addSharedMethod(Object sharedMethodFromObject) {
sharedMethodKit.addSharedMethod(sharedMethodFromObject);
}
/**
* Add shared method from class
*/
public void addSharedMethod(Class> sharedMethodFromClass) {
sharedMethodKit.addSharedMethod(sharedMethodFromClass);
}
/**
* Add shared static method of Class
*/
public void addSharedStaticMethod(Class> sharedStaticMethodFromClass) {
sharedMethodKit.addSharedStaticMethod(sharedStaticMethodFromClass);
}
/**
* Remove shared Method with method name
*/
public void removeSharedMethod(String methodName) {
sharedMethodKit.removeSharedMethod(methodName);
}
/**
* Remove shared Method of the Class
*/
public void removeSharedMethod(Class> sharedClass) {
sharedMethodKit.removeSharedMethod(sharedClass);
}
/**
* Remove shared Method
*/
public void removeSharedMethod(Method method) {
sharedMethodKit.removeSharedMethod(method);
}
/**
* Remove shared Method
*/
public void removeSharedMethod(String methodName, Class>... paraTypes) {
sharedMethodKit.removeSharedMethod(methodName, paraTypes);
}
public SharedMethodKit getSharedMethodKit() {
return sharedMethodKit;
}
public void setCompressor(Compressor compressor) {
this.compressor = compressor;
}
public Compressor getCompressor() {
return compressor;
}
/**
* 设置 #number 指令与 Arith 中浮点数的舍入规则,默认为 RoundingMode.HALF_UP "四舍五入"
*/
public void setRoundingMode(RoundingMode roundingMode) {
this.roundingMode = roundingMode;
Arith.setBigDecimalDivideRoundingMode(roundingMode);
}
public RoundingMode getRoundingMode() {
return roundingMode;
}
/**
* 设置为 true 支持静态方法调用表达式,自 jfinal 5.0.2 版本开始默认值为 false
*/
public void setStaticMethodExpression(boolean enable) {
this.supportStaticMethodExpression = enable;
}
public boolean isStaticMethodExpressionEnabled() {
return supportStaticMethodExpression;
}
/**
* 设置为 true 支持静态属性访问表达式,自 jfinal 5.0.2 版本开始默认值为 false
*/
public void setStaticFieldExpression(boolean enable) {
this.supportStaticFieldExpression = enable;
}
public boolean isStaticFieldExpressionEnabled() {
return supportStaticFieldExpression;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy