enjoy 3.5

This commit is contained in:
James 2018-08-12 12:15:01 +08:00
parent 3e89651aa4
commit 1ce7068072
16 changed files with 183 additions and 95 deletions

View File

@ -0,0 +1,92 @@
/**
* Copyright (c) 2011-2019, James Zhan 詹波 (jfinal@126.com).
*
* 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.kit;
import java.util.HashMap;
import java.util.Map;
/**
* SyncWriteMap 同步写 HashMap
* 创建原因是 HashMap扩容时遇到并发修改可能造成 100% CPU 占用
*
* SyncWriteMap 拥有 HashMap 的性能但不保障并发访问的线程安全
* 只用于读多写少且不用保障线程安全的场景
*
* 例如 MethodKit 中用于缓存 MethodInfo cache被写入的数据
* 不用保障是单例读取之后会做 null 值判断
*
* ActionMapping 中的 HashMap 是系统启动时在独立线程内初始化的
* 不存在并发写只存在并发读的情况所以仍然可以使用 HashMap
*/
public class SyncWriteMap<K, V> extends HashMap<K, V> {
private static final long serialVersionUID = -7287230891751869148L;
public SyncWriteMap() {
}
public SyncWriteMap(int initialCapacity) {
super(initialCapacity);
}
public SyncWriteMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
}
public SyncWriteMap(Map<? extends K, ? extends V> m) {
super(m);
}
@Override
public V put(K key, V value) {
synchronized (this) {
return super.put(key, value);
}
}
@Override
public V putIfAbsent(K key, V value) {
synchronized (this) {
return super.putIfAbsent(key, value);
}
}
@Override
public void putAll(Map<? extends K, ? extends V> m) {
synchronized (this) {
super.putAll(m);
}
}
@Override
public V remove(Object key) {
synchronized (this) {
return super.remove(key);
}
}
@Override
public void clear() {
synchronized (this) {
super.clear();
}
}
}

View File

@ -21,11 +21,13 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.jfinal.kit.HashKit; import com.jfinal.kit.HashKit;
import com.jfinal.kit.StrKit; import com.jfinal.kit.StrKit;
import com.jfinal.kit.SyncWriteMap;
import com.jfinal.template.expr.ast.MethodKit; import com.jfinal.template.expr.ast.MethodKit;
import com.jfinal.template.source.ClassPathSourceFactory; import com.jfinal.template.source.ClassPathSourceFactory;
import com.jfinal.template.source.ISource; import com.jfinal.template.source.ISource;
import com.jfinal.template.source.ISourceFactory; import com.jfinal.template.source.ISourceFactory;
import com.jfinal.template.source.StringSource; import com.jfinal.template.source.StringSource;
import com.jfinal.template.stat.OutputDirectiveFactory;
import com.jfinal.template.stat.Parser; import com.jfinal.template.stat.Parser;
import com.jfinal.template.stat.ast.Stat; import com.jfinal.template.stat.ast.Stat;
@ -41,7 +43,7 @@ public class Engine {
public static final String MAIN_ENGINE_NAME = "main"; public static final String MAIN_ENGINE_NAME = "main";
private static Engine MAIN_ENGINE; private static Engine MAIN_ENGINE;
private static Map<String, Engine> engineMap = new HashMap<String, Engine>(); private static Map<String, Engine> engineMap = new HashMap<String, Engine>(64, 0.5F);
// Create main engine // Create main engine
static { static {
@ -54,7 +56,7 @@ public class Engine {
private EngineConfig config = new EngineConfig(); private EngineConfig config = new EngineConfig();
private ISourceFactory sourceFactory = config.getSourceFactory(); private ISourceFactory sourceFactory = config.getSourceFactory();
private Map<String, Template> templateCache = new HashMap<String, Template>(); private Map<String, Template> templateCache = new SyncWriteMap<String, Template>(2048, 0.5F);
/** /**
* Create engine without management of JFinal * Create engine without management of JFinal
@ -276,7 +278,7 @@ public class Engine {
/** /**
* Set output directive factory * Set output directive factory
*/ */
public Engine setOutputDirectiveFactory(IOutputDirectiveFactory outputDirectiveFactory) { public Engine setOutputDirectiveFactory(OutputDirectiveFactory outputDirectiveFactory) {
config.setOutputDirectiveFactory(outputDirectiveFactory); config.setOutputDirectiveFactory(outputDirectiveFactory);
return this; return this;
} }

View File

@ -35,6 +35,7 @@ import com.jfinal.template.source.ISource;
import com.jfinal.template.source.ISourceFactory; import com.jfinal.template.source.ISourceFactory;
import com.jfinal.template.source.StringSource; import com.jfinal.template.source.StringSource;
import com.jfinal.template.stat.Location; import com.jfinal.template.stat.Location;
import com.jfinal.template.stat.OutputDirectiveFactory;
import com.jfinal.template.stat.Parser; import com.jfinal.template.stat.Parser;
import com.jfinal.template.stat.ast.Define; import com.jfinal.template.stat.ast.Define;
import com.jfinal.template.stat.ast.Output; import com.jfinal.template.stat.ast.Output;
@ -48,14 +49,14 @@ public class EngineConfig {
WriterBuffer writerBuffer = new WriterBuffer(); WriterBuffer writerBuffer = new WriterBuffer();
private Map<String, Define> sharedFunctionMap = new HashMap<String, Define>(); private Map<String, Define> sharedFunctionMap = createSharedFunctionMap(); // new HashMap<String, Define>(512, 0.25F);
private List<ISource> sharedFunctionSourceList = new ArrayList<ISource>(); // for devMode only private List<ISource> sharedFunctionSourceList = new ArrayList<ISource>(); // for devMode only
Map<String, Object> sharedObjectMap = null; Map<String, Object> sharedObjectMap = null;
private IOutputDirectiveFactory outputDirectiveFactory = OutputDirectiveFactory.me; private OutputDirectiveFactory outputDirectiveFactory = OutputDirectiveFactory.me;
private ISourceFactory sourceFactory = new FileSourceFactory(); private ISourceFactory sourceFactory = new FileSourceFactory();
private Map<String, Class<? extends Directive>> directiveMap = new HashMap<String, Class<? extends Directive>>(); private Map<String, Class<? extends Directive>> directiveMap = new HashMap<String, Class<? extends Directive>>(64, 0.5F);
private SharedMethodKit sharedMethodKit = new SharedMethodKit(); private SharedMethodKit sharedMethodKit = new SharedMethodKit();
private boolean devMode = false; private boolean devMode = false;
@ -179,7 +180,7 @@ public class EngineConfig {
* 开发者可直接使用模板注释功能将不需要的 function 直接注释掉 * 开发者可直接使用模板注释功能将不需要的 function 直接注释掉
*/ */
private synchronized void reloadSharedFunctionSourceList() { private synchronized void reloadSharedFunctionSourceList() {
Map<String, Define> newMap = new HashMap<String, Define>(); Map<String, Define> newMap = createSharedFunctionMap();
for (int i = 0, size = sharedFunctionSourceList.size(); i < size; i++) { for (int i = 0, size = sharedFunctionSourceList.size(); i < size; i++) {
ISource source = sharedFunctionSourceList.get(i); ISource source = sharedFunctionSourceList.get(i);
String fileName = source instanceof FileSource ? ((FileSource)source).getFileName() : null; String fileName = source instanceof FileSource ? ((FileSource)source).getFileName() : null;
@ -194,9 +195,13 @@ public class EngineConfig {
this.sharedFunctionMap = newMap; this.sharedFunctionMap = newMap;
} }
private Map<String, Define> createSharedFunctionMap() {
return new HashMap<String, Define>(512, 0.25F);
}
public synchronized void addSharedObject(String name, Object object) { public synchronized void addSharedObject(String name, Object object) {
if (sharedObjectMap == null) { if (sharedObjectMap == null) {
sharedObjectMap = new HashMap<String, Object>(); sharedObjectMap = new HashMap<String, Object>(64, 0.25F);
} else if (sharedObjectMap.containsKey(name)) { } else if (sharedObjectMap.containsKey(name)) {
throw new IllegalArgumentException("Shared object already exists: " + name); throw new IllegalArgumentException("Shared object already exists: " + name);
} }
@ -210,7 +215,7 @@ public class EngineConfig {
/** /**
* Set output directive factory * Set output directive factory
*/ */
public void setOutputDirectiveFactory(IOutputDirectiveFactory outputDirectiveFactory) { public void setOutputDirectiveFactory(OutputDirectiveFactory outputDirectiveFactory) {
if (outputDirectiveFactory == null) { if (outputDirectiveFactory == null) {
throw new IllegalArgumentException("outputDirectiveFactory can not be null"); throw new IllegalArgumentException("outputDirectiveFactory can not be null");
} }

View File

@ -35,7 +35,7 @@ import com.jfinal.template.stat.ast.Define;
public class Env { public class Env {
protected EngineConfig engineConfig; protected EngineConfig engineConfig;
protected Map<String, Define> functionMap = new HashMap<String, Define>(); protected Map<String, Define> functionMap = new HashMap<String, Define>(16, 0.5F);
// 代替 Template 持有该属性便于在 #include 指令中调用 Env.addSource() // 代替 Template 持有该属性便于在 #include 指令中调用 Env.addSource()
protected List<ISource> sourceList = null; protected List<ISource> sourceList = null;

View File

@ -1,34 +0,0 @@
/**
* Copyright (c) 2011-2019, James Zhan 詹波 (jfinal@126.com).
*
* 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 com.jfinal.template.expr.ast.ExprList;
import com.jfinal.template.stat.Location;
import com.jfinal.template.stat.ast.Output;
/**
* OutputDirectiveFactory
*/
public class OutputDirectiveFactory implements IOutputDirectiveFactory {
public static final OutputDirectiveFactory me = new OutputDirectiveFactory();
public Output getOutputDirective(ExprList exprList, Location location) {
return new Output(exprList, location);
}
}

View File

@ -18,13 +18,14 @@ package com.jfinal.template.expr.ast;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.HashMap; import java.util.HashMap;
import com.jfinal.kit.SyncWriteMap;
/** /**
* FieldKit * FieldKit
*/ */
public class FieldKit { public class FieldKit {
private static final HashMap<Long, Object> fieldCache = new HashMap<Long, Object>(); private static final HashMap<Long, Object> fieldCache = new SyncWriteMap<Long, Object>(512, 0.5F);
public static Field getField(Long key, Class<?> targetClass, String fieldName) { public static Field getField(Long key, Class<?> targetClass, String fieldName) {
Object field = fieldCache.get(key); Object field = fieldCache.get(key);

View File

@ -24,6 +24,17 @@ import com.jfinal.template.stat.Scope;
/** /**
* Method : expr '.' ID '(' exprList? ')' * Method : expr '.' ID '(' exprList? ')'
*
* 每次通过 MethodKit.getMethod(...) MethodInfo 而不是用属性持有其对象
* 是为了支持 target 对象的动态类型MethodInfo 中的 Method 被调用 15 次以后
* 会被 JDK 动态生成 GeneratedAccessorXXX 字节码性能不是问题
* 唯一的性能损耗是从 HashMap 中获取 MethodInfo 对象可以忽略不计
*
* 如果在未来通过结合 #dynamic(boolean) 指令来优化需要在 Ctrl 中引入一个
* boolean dynamic = false 变量而不能在 EnvScope 引入该变量
*
* 还需要引入一个 NullMethodInfo 以及 isNull() 方法此优化复杂度提高不少
* 暂时不做此优化
*/ */
public class Method extends Expr { public class Method extends Expr {

View File

@ -23,6 +23,7 @@ import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import com.jfinal.kit.ReflectKit; import com.jfinal.kit.ReflectKit;
import com.jfinal.kit.SyncWriteMap;
import com.jfinal.template.ext.extensionmethod.ByteExt; import com.jfinal.template.ext.extensionmethod.ByteExt;
import com.jfinal.template.ext.extensionmethod.DoubleExt; import com.jfinal.template.ext.extensionmethod.DoubleExt;
import com.jfinal.template.ext.extensionmethod.FloatExt; import com.jfinal.template.ext.extensionmethod.FloatExt;
@ -37,10 +38,10 @@ import com.jfinal.template.ext.extensionmethod.StringExt;
public class MethodKit { public class MethodKit {
private static final Class<?>[] NULL_ARG_TYPES = new Class<?>[0]; private static final Class<?>[] NULL_ARG_TYPES = new Class<?>[0];
private static final Set<String> forbiddenMethods = new HashSet<String>(); private static final Set<String> forbiddenMethods = new HashSet<String>(64);
private static final Set<Class<?>> forbiddenClasses = new HashSet<Class<?>>(); private static final Set<Class<?>> forbiddenClasses = new HashSet<Class<?>>(64);
private static final Map<Class<?>, Class<?>> primitiveMap = new HashMap<Class<?>, Class<?>>(); private static final Map<Class<?>, Class<?>> primitiveMap = new HashMap<Class<?>, Class<?>>(64);
private static final HashMap<Long, Object> methodCache = new HashMap<Long, Object>(); private static final Map<Long, Object> methodCache = new SyncWriteMap<Long, Object>(2048, 0.25F);
// 初始化在模板中调用 method 时所在的被禁止使用类 // 初始化在模板中调用 method 时所在的被禁止使用类
static { static {
@ -307,7 +308,7 @@ public class MethodKit {
} }
} }
private static final Map<Class<?>, Class<?>> primitiveToBoxedMap = new HashMap<Class<?>, Class<?>>(); private static final Map<Class<?>, Class<?>> primitiveToBoxedMap = new HashMap<Class<?>, Class<?>>(64);
// 初始化 primitive type boxed type 的映射 // 初始化 primitive type boxed type 的映射
static { static {

View File

@ -27,6 +27,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import com.jfinal.kit.HashKit; import com.jfinal.kit.HashKit;
import com.jfinal.kit.ReflectKit; import com.jfinal.kit.ReflectKit;
import com.jfinal.kit.SyncWriteMap;
/** /**
* SharedMethodKit * SharedMethodKit
@ -44,7 +45,7 @@ public class SharedMethodKit {
} }
private final List<SharedMethodInfo> sharedMethodList = new ArrayList<SharedMethodInfo>(); private final List<SharedMethodInfo> sharedMethodList = new ArrayList<SharedMethodInfo>();
private final HashMap<Long, SharedMethodInfo> methodCache = new HashMap<Long, SharedMethodInfo>(); private final HashMap<Long, SharedMethodInfo> methodCache = new SyncWriteMap<Long, SharedMethodInfo>(512, 0.25F);
public SharedMethodInfo getSharedMethodInfo(String methodName, Object[] argValues) { public SharedMethodInfo getSharedMethodInfo(String methodName, Object[] argValues) {
Class<?>[] argTypes = MethodKit.getArgTypes(argValues); Class<?>[] argTypes = MethodKit.getArgTypes(argValues);

View File

@ -79,23 +79,25 @@ public class DateDirective extends Directive {
private void outputWithoutDatePattern(Env env, Scope scope, Writer writer) { private void outputWithoutDatePattern(Env env, Scope scope, Writer writer) {
Object value = valueExpr.eval(scope); Object value = valueExpr.eval(scope);
if (value != null) { if (value instanceof Date) {
write(writer, (Date)value, env.getEngineConfig().getDatePattern()); write(writer, (Date)value, env.getEngineConfig().getDatePattern());
} else if (value != null) {
throw new TemplateException("The first parameter date of #date directive must be Date type", location);
} }
} }
private void outputWithDatePattern(Env env, Scope scope, Writer writer) { private void outputWithDatePattern(Env env, Scope scope, Writer writer) {
Object value = valueExpr.eval(scope); Object value = valueExpr.eval(scope);
if (value == null) { if (value instanceof Date) {
return ;
}
Object datePattern = this.datePatternExpr.eval(scope); Object datePattern = this.datePatternExpr.eval(scope);
if ( !(datePattern instanceof String) ) { if (datePattern instanceof String) {
write(writer, (Date)value, (String)datePattern);
} else {
throw new TemplateException("The sencond parameter datePattern of #date directive must be String", location); throw new TemplateException("The sencond parameter datePattern of #date directive must be String", location);
} }
} else if (value != null) {
write(writer, (Date)value, (String)datePattern); throw new TemplateException("The first parameter date of #date directive must be Date type", location);
}
} }
private void write(Writer writer, Date date, String datePattern) { private void write(Writer writer, Date date, String datePattern) {

View File

@ -52,11 +52,12 @@ public class EscapeDirective extends Directive {
case '>': case '>':
ret.append("&gt;"); ret.append("&gt;");
break; break;
case '\"': case '"':
ret.append("&quot;"); ret.append("&quot;");
break; break;
case '\'': case '\'':
ret.append("&apos;"); // IE 不支持 &apos; 考虑 &#39; // ret.append("&apos;"); // IE 不支持 &apos; 考虑 &#39;
ret.append("&#39;");
break; break;
case '&': case '&':
ret.append("&amp;"); ret.append("&amp;");

View File

@ -16,8 +16,8 @@
package com.jfinal.template.ext.directive; package com.jfinal.template.ext.directive;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.jfinal.kit.SyncWriteMap;
import com.jfinal.template.Directive; import com.jfinal.template.Directive;
import com.jfinal.template.EngineConfig; import com.jfinal.template.EngineConfig;
import com.jfinal.template.Env; import com.jfinal.template.Env;
@ -60,7 +60,7 @@ import com.jfinal.template.stat.ast.StatList;
public class RenderDirective extends Directive { public class RenderDirective extends Directive {
private String parentFileName; private String parentFileName;
private Map<String, StatInfo> statInfoCache = new HashMap<String,StatInfo>(); private Map<String, StatInfo> statInfoCache = new SyncWriteMap<String,StatInfo>(16, 0.5F);
public void setExprList(ExprList exprList) { public void setExprList(ExprList exprList) {
int len = exprList.length(); int len = exprList.length();

View File

@ -16,6 +16,7 @@
package com.jfinal.template.ext.spring; package com.jfinal.template.ext.spring;
import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
@ -56,8 +57,20 @@ public class JFinalView extends AbstractTemplateView {
} }
} }
try {
OutputStream os = response.getOutputStream(); OutputStream os = response.getOutputStream();
JFinalViewResolver.engine.getTemplate(getUrl()).render(model, os); JFinalViewResolver.engine.getTemplate(getUrl()).render(model, os);
} catch (Exception e) { // 捕获 ByteWriter.close() 抛出的 RuntimeException
Throwable cause = e.getCause();
if (cause instanceof IOException) { // ClientAbortExceptionEofException 直接或间接继承自 IOException
String name = cause.getClass().getSimpleName();
if ("ClientAbortException".equals(name) || "EofException".equals(name)) {
return ;
}
}
throw e;
}
} }
@SuppressWarnings({"unchecked", "rawtypes", "deprecation"}) @SuppressWarnings({"unchecked", "rawtypes", "deprecation"})

View File

@ -17,12 +17,11 @@
package com.jfinal.template.source; package com.jfinal.template.source;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.JarURLConnection;
import java.net.URL; import java.net.URL;
import java.net.URLConnection;
import com.jfinal.template.EngineConfig; import com.jfinal.template.EngineConfig;
/** /**
@ -72,17 +71,12 @@ public class ClassPathSource implements ISource {
} }
protected void processIsInJarAndlastModified() { protected void processIsInJarAndlastModified() {
try { if ("file".equalsIgnoreCase(url.getProtocol())) {
URLConnection conn = url.openConnection(); isInJar = false;
if ("jar".equals(url.getProtocol()) || conn instanceof JarURLConnection) { lastModified = new File(url.getFile()).lastModified();
} else {
isInJar = true; isInJar = true;
lastModified = -1; lastModified = -1;
} else {
isInJar = false;
lastModified = conn.getLastModified();
}
} catch (IOException e) {
throw new RuntimeException(e);
} }
} }
@ -120,12 +114,7 @@ public class ClassPathSource implements ISource {
} }
protected long getLastModified() { protected long getLastModified() {
try { return new File(url.getFile()).lastModified();
URLConnection conn = url.openConnection();
return conn.getLastModified();
} catch (IOException e) {
throw new RuntimeException(e);
}
} }
/** /**

View File

@ -14,14 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
package com.jfinal.template; package com.jfinal.template.stat;
import com.jfinal.template.expr.ast.ExprList; import com.jfinal.template.expr.ast.ExprList;
import com.jfinal.template.stat.Location;
import com.jfinal.template.stat.ast.Output; import com.jfinal.template.stat.ast.Output;
/** /**
* IOutputDirectiveFactory * OutputDirectiveFactory
* 用于定制自定义输出指令替换系统默认输出指令满足个性化需求 * 用于定制自定义输出指令替换系统默认输出指令满足个性化需求
* *
* 用法 * 用法
@ -32,12 +31,15 @@ import com.jfinal.template.stat.ast.Output;
* } * }
* *
* public void exec(Env env, Scope scope, Writer writer) { * public void exec(Env env, Scope scope, Writer writer) {
* write(writer, exprList.eval(scope)); * Object value = exprList.eval(scope);
* if (value != null) {
* write(writer, value.toString());
* }
* } * }
* } * }
* *
* 2定义 MyOutputDirectiveFactory * 2定义 MyOutputDirectiveFactory
* public class MyOutputDirectiveFactory implements IOutputDirectiveFactory { * public class MyOutputDirectiveFactory extends OutputDirectiveFactory {
* public Output getOutputDirective(ExprList exprList) { * public Output getOutputDirective(ExprList exprList) {
* return new MyOutput(exprList); * return new MyOutput(exprList);
* } * }
@ -46,11 +48,13 @@ import com.jfinal.template.stat.ast.Output;
* 3配置 * 3配置
* engine.setOutputDirectiveFactory(new MyOutputDirectiveFactory()) * engine.setOutputDirectiveFactory(new MyOutputDirectiveFactory())
*/ */
public interface IOutputDirectiveFactory { public class OutputDirectiveFactory {
public Output getOutputDirective(ExprList exprList, Location location); public static final OutputDirectiveFactory me = new OutputDirectiveFactory();
public Output getOutputDirective(ExprList exprList, Location location) {
return new Output(exprList, location);
}
} }

View File

@ -58,7 +58,7 @@ enum Symbol {
* 扩展指令在得到 # id ( 序列以后才要求得到正确的后续 Token 序列否则仅仅 return fail() * 扩展指令在得到 # id ( 序列以后才要求得到正确的后续 Token 序列否则仅仅 return fail()
*/ */
@SuppressWarnings("serial") @SuppressWarnings("serial")
private static final Map<String, Symbol> keywords = new HashMap<String, Symbol>() {{ private static final Map<String, Symbol> keywords = new HashMap<String, Symbol>(64) {{
put(Symbol.IF.getName(), IF); put(Symbol.IF.getName(), IF);
put(Symbol.ELSEIF.getName(), ELSEIF); put(Symbol.ELSEIF.getName(), ELSEIF);
put(Symbol.ELSE.getName(), ELSE); put(Symbol.ELSE.getName(), ELSE);