📄 environment.java
字号:
return dateTimeFormat;
}
default: {
throw new TemplateModelException("Unrecognized date type " + dateType);
}
}
}
DateFormat getDateFormatObject(int dateType, String pattern)
throws
TemplateModelException
{
if(dateFormats == null) {
dateFormats = new Map[4];
dateFormats[TemplateDateModel.UNKNOWN] = new HashMap();
dateFormats[TemplateDateModel.TIME] = new HashMap();
dateFormats[TemplateDateModel.DATE] = new HashMap();
dateFormats[TemplateDateModel.DATETIME] = new HashMap();
}
Map typedDateFormat = dateFormats[dateType];
DateFormat format = (DateFormat) typedDateFormat.get(pattern);
if(format != null) {
return format;
}
// Get format from global format cache
synchronized(localizedDateFormats) {
Locale locale = getLocale();
TimeZone timeZone = getTimeZone();
DateFormatKey fk = new DateFormatKey(dateType, pattern, locale, timeZone);
format = (DateFormat)localizedDateFormats.get(fk);
if(format == null) {
// Add format to global format cache. Note this is
// globally done once per locale per pattern.
StringTokenizer tok = new StringTokenizer(pattern, "_");
int style = tok.hasMoreTokens() ? parseDateStyleToken(tok.nextToken()) : DateFormat.DEFAULT;
if(style != -1) {
switch(dateType) {
case TemplateDateModel.UNKNOWN: {
throw new TemplateModelException(
"Can't convert the date to string using a " +
"built-in format, because it is not known which " +
"parts of the date variable are in use. Use " +
"?date, ?time or ?datetime built-in, or " +
"?string.<format> or ?string(<format>) built-in "+
"with explicit formatting pattern with this date.");
}
case TemplateDateModel.TIME: {
format = DateFormat.getTimeInstance(style, locale);
break;
}
case TemplateDateModel.DATE: {
format = DateFormat.getDateInstance(style, locale);
break;
}
case TemplateDateModel.DATETIME: {
int timestyle = tok.hasMoreTokens() ? parseDateStyleToken(tok.nextToken()) : style;
if(timestyle != -1) {
format = DateFormat.getDateTimeInstance(style, timestyle, locale);
}
break;
}
}
}
if(format == null) {
try {
format = new SimpleDateFormat(pattern, locale);
}
catch(IllegalArgumentException e) {
throw new TemplateModelException("Can't parse " + pattern + " to a date format.", e);
}
}
format.setTimeZone(timeZone);
localizedDateFormats.put(fk, format);
}
}
// Clone it and store the clone in the local cache
format = (DateFormat)format.clone();
typedDateFormat.put(pattern, format);
return format;
}
int parseDateStyleToken(String token) {
if("short".equals(token)) {
return DateFormat.SHORT;
}
if("medium".equals(token)) {
return DateFormat.MEDIUM;
}
if("long".equals(token)) {
return DateFormat.LONG;
}
return -1;
}
TemplateTransformModel getTransform(Expression exp) throws TemplateException {
TemplateTransformModel ttm = null;
TemplateModel tm = exp.getAsTemplateModel(this);
if (tm instanceof TemplateTransformModel) {
ttm = (TemplateTransformModel) tm;
}
else if (exp instanceof Identifier) {
tm = getConfiguration().getSharedVariable(exp.toString());
if (tm instanceof TemplateTransformModel) {
ttm = (TemplateTransformModel) tm;
}
}
return ttm;
}
/**
* Returns the loop or macro local variable corresponding to this
* variable name. Possibly null.
* (Note that the misnomer is kept for backward compatibility: loop variables
* are not local variables according to our terminology.)
*/
public TemplateModel getLocalVariable(String name) throws TemplateModelException {
if (localContextStack != null) {
for (int i = localContextStack.size()-1; i>=0; i--) {
LocalContext lc = (LocalContext) localContextStack.get(i);
TemplateModel tm = lc.getLocalVariable(name);
if (tm != null) {
return tm;
}
}
}
return currentMacroContext == null ? null : currentMacroContext.getLocalVariable(name);
}
/**
* Returns the variable that is visible in this context.
* This is the correspondent to an FTL top-level variable reading expression.
* That is, it tries to find the the variable in this order:
* <ol>
* <li>An loop variable (if we're in a loop or user defined directive body) such as foo_has_next
* <li>A local variable (if we're in a macro)
* <li>A variable defined in the current namespace (say, via <#assign ...>)
* <li>A variable defined globally (say, via <#global ....>)
* <li>Variable in the data model:
* <ol>
* <li>A variable in the root hash that was exposed to this
rendering environment in the Template.process(...) call
* <li>A shared variable set in the configuration via a call to Configuration.setSharedVariable(...)
* </ol>
* </li>
* </ol>
*/
public TemplateModel getVariable(String name) throws TemplateModelException {
TemplateModel result = getLocalVariable(name);
if (result == null) {
result = currentNamespace.get(name);
}
if (result == null) {
result = getGlobalVariable(name);
}
return result;
}
/**
* Returns the globally visible variable of the given name (or null).
* This is correspondent to FTL <code>.globals.<i>name</i></code>.
* This will first look at variables that were assigned globally via:
* <#global ...> and then at the data model exposed to the template.
*/
public TemplateModel getGlobalVariable(String name) throws TemplateModelException {
TemplateModel result = globalNamespace.get(name);
if (result == null) {
result = rootDataModel.get(name);
}
if (result == null) {
result = getConfiguration().getSharedVariable(name);
}
return result;
}
/**
* Sets a variable that is visible globally.
* This is correspondent to FTL <code><#global <i>name</i>=<i>model</i>></code>.
* This can be considered a convenient shorthand for:
* getGlobalNamespace().put(name, model)
*/
public void setGlobalVariable(String name, TemplateModel model) {
globalNamespace.put(name, model);
}
/**
* Sets a variable in the current namespace.
* This is correspondent to FTL <code><#assign <i>name</i>=<i>model</i>></code>.
* This can be considered a convenient shorthand for:
* getCurrentNamespace().put(name, model)
*/
public void setVariable(String name, TemplateModel model) {
currentNamespace.put(name, model);
}
/**
* Sets a local variable (one effective only during a macro invocation).
* This is correspondent to FTL <code><#local <i>name</i>=<i>model</i>></code>.
* @param name the identifier of the variable
* @param model the value of the variable.
* @throws IllegalStateException if the environment is not executing a
* macro body.
*/
public void setLocalVariable(String name, TemplateModel model) {
if(currentMacroContext == null) {
throw new IllegalStateException("Not executing macro body");
}
currentMacroContext.setLocalVar(name, model);
}
/**
* Returns a set of variable names that are known at the time of call. This
* includes names of all shared variables in the {@link Configuration},
* names of all global variables that were assigned during the template processing,
* names of all variables in the current name-space, names of all local variables
* and loop variables. If the passed root data model implements the
* {@link TemplateHashModelEx} interface, then all names it retrieves through a call to
* {@link TemplateHashModelEx#keys()} method are returned as well.
* The method returns a new Set object on each call that is completely
* disconnected from the Environment. That is, modifying the set will have
* no effect on the Environment object.
*/
public Set getKnownVariableNames() throws TemplateModelException {
// shared vars.
Set set = getConfiguration().getSharedVariableNames();
// root hash
if (rootDataModel instanceof TemplateHashModelEx) {
TemplateModelIterator rootNames =
((TemplateHashModelEx) rootDataModel).keys().iterator();
while(rootNames.hasNext()) {
set.add(((TemplateScalarModel)rootNames.next()).getAsString());
}
}
// globals
for (TemplateModelIterator tmi = globalNamespace.keys().iterator(); tmi.hasNext();) {
set.add(((TemplateScalarModel) tmi.next()).getAsString());
}
// current name-space
for (TemplateModelIterator tmi = currentNamespace.keys().iterator(); tmi.hasNext();) {
set.add(((TemplateScalarModel) tmi.next()).getAsString());
}
// locals and loop vars
if(currentMacroContext != null) {
set.addAll(currentMacroContext.getLocalVariableNames());
}
if (localContextStack != null) {
for (int i = localContextStack.size()-1; i>=0; i--) {
LocalContext lc = (LocalContext) localContextStack.get(i);
set.addAll(lc.getLocalVariableNames());
}
}
return set;
}
/**
* Outputs the instruction stack. Useful for debugging.
* {@link TemplateException}s incorporate this information in their stack
* traces.
*/
public void outputInstructionStack(PrintWriter pw) {
pw.println("----------");
ListIterator iter = elementStack.listIterator(elementStack.size());
if(iter.hasPrevious()) {
pw.print("==> ");
TemplateElement prev = (TemplateElement) iter.previous();
pw.print(prev.getDescription());
pw.print(" [");
pw.print(prev.getStartLocation());
pw.println("]");
}
while(iter.hasPrevious()) {
TemplateElement prev = (TemplateElement) iter.previous();
if (prev instanceof UnifiedCall || prev instanceof Include) {
String location = prev.getDescription() + " [" + prev.getStartLocation() + "]";
if(location != null && location.length() > 0) {
pw.print(" in ");
pw.println(location);
}
}
}
pw.println("----------");
pw.flush();
}
private void pushLocalContext(LocalContext localContext) {
if (localContextStack == null) {
localContextStack = new ArrayList();
}
localContextStack.add(localContext);
}
private void popLocalContext() {
localContextStack.remove(localContextStack.size() - 1);
}
ArrayList getLocalContextStack() {
return localContextStack;
}
/**
* Returns the name-space for the name if exists, or null.
* @param name the template path that you have used with the <code>import</code> directive
* or {@link #importLib(String, String)} call, in normalized form. That is, the path must be an absolute
* path, and it must not contain "/../" or "/./". The leading "/" is optional.
*/
public Namespace getNamespace(String name) {
if (name.startsWith("/")) name = name.substring(1);
if (loadedLibs != null) {
return (Namespace) loadedLibs.get(name);
} else {
return null;
}
}
/**
* Returns the main name-space.
* This is correspondent of FTL <code>.main</code> hash.
*/
public Namespace getMainNamespace() {
return mainNamespace;
}
/**
* Returns the main name-space.
* This is correspondent of FTL <code>.namespace</code> hash.
*/
public Namespace getCurrentNamespace() {
return currentNamespace;
}
/**
* Returns a fictitious name-space that contains the globally visible variables
* that were created in the template, but not the variables of the data-model.
* There is no such thing in FTL; this strange method was added because of the
* JSP taglib support, since this imaginary name-space contains the page-scope
* attributes.
*/
public Namespace getGlobalNamespace() {
return globalNamespace;
}
/**
* Returns the data model hash.
* This is correspondent of FTL <code>.datamodel</code> hash.
* That is, it contains both the variables of the root hash passed to the
* <code>Template.process(...)</code>, and the shared variables in the
* <code>Configuration</code>.
*/
public TemplateHashModel getDataModel() {
return new TemplateHashModel() {
public boolean isEmpty() {
return false;
}
public TemplateModel get(String key) throws TemplateModelException {
TemplateModel result = rootDataModel.get(key);
if (result == null) {
result = getConfiguration().getSharedVariable(key);
}
return result;
}
};
}
/**
* Returns the read-only hash of globally visible variables.
* This is the correspondent of FTL <code>.globals</code> hash.
* That is, you see the variables created with
* <code><#global ...></code>, and the variables of the data-model.
* To create new global variables, use {@link #setGlobalVariable setGlobalVariable}.
*/
public TemplateHashModel getGlobalVariables() {
return new TemplateHashModel() {
public boolean isEmpty() {
return false;
}
public TemplateModel get(String key) throws TemplateModelException {
TemplateModel result = globalNamespace.get(key);
if (result == null) {
result = rootDataModel.get(key);
}
if (result == null) {
result = getConfiguration().getSharedVariable(key);
}
return result;
}
};
}
private void pushElement(TemplateElement element) {
elementStack.add(element);
}
private void popElement() {
elementStack.remove(elementStack.size() - 1);
}
public TemplateNodeModel getCurrentVisitorNode() {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -