use of freemarker.template.TemplateDirectiveBody in project freemarker by apache.
the class GetOptionalTemplateMethod method exec.
public Object exec(List args) throws TemplateModelException {
final int argCnt = args.size();
if (argCnt < 1 || argCnt > 2) {
throw _MessageUtil.newArgCntError(methodName, argCnt, 1, 2);
}
final Environment env = Environment.getCurrentEnvironment();
if (env == null) {
throw new IllegalStateException("No freemarer.core.Environment is associated to the current thread.");
}
final String absTemplateName;
{
TemplateModel arg = (TemplateModel) args.get(0);
if (!(arg instanceof TemplateScalarModel)) {
throw _MessageUtil.newMethodArgMustBeStringException(methodName, 0, arg);
}
String templateName = EvalUtil.modelToString((TemplateScalarModel) arg, null, env);
try {
absTemplateName = env.toFullTemplateName(env.getCurrentTemplate().getName(), templateName);
} catch (MalformedTemplateNameException e) {
throw new _TemplateModelException(e, "Failed to convert template path to full path; see cause exception.");
}
}
final TemplateHashModelEx options;
if (argCnt > 1) {
TemplateModel arg = (TemplateModel) args.get(1);
if (!(arg instanceof TemplateHashModelEx)) {
throw _MessageUtil.newMethodArgMustBeExtendedHashException(methodName, 1, arg);
}
options = (TemplateHashModelEx) arg;
} else {
options = null;
}
String encoding = null;
boolean parse = true;
if (options != null) {
final KeyValuePairIterator kvpi = TemplateModelUtils.getKeyValuePairIterator(options);
while (kvpi.hasNext()) {
final KeyValuePair kvp = kvpi.next();
final String optName;
{
TemplateModel optNameTM = kvp.getKey();
if (!(optNameTM instanceof TemplateScalarModel)) {
throw _MessageUtil.newMethodArgInvalidValueException(methodName, 1, "All keys in the options hash must be strings, but found ", new _DelayedAOrAn(new _DelayedFTLTypeDescription(optNameTM)));
}
optName = ((TemplateScalarModel) optNameTM).getAsString();
}
final TemplateModel optValue = kvp.getValue();
if (OPTION_ENCODING.equals(optName)) {
encoding = getStringOption(OPTION_ENCODING, optValue);
} else if (OPTION_PARSE.equals(optName)) {
parse = getBooleanOption(OPTION_PARSE, optValue);
} else {
throw _MessageUtil.newMethodArgInvalidValueException(methodName, 1, "Unsupported option ", new _DelayedJQuote(optName), "; valid names are: ", new _DelayedJQuote(OPTION_ENCODING), ", ", new _DelayedJQuote(OPTION_PARSE), ".");
}
}
}
final Template template;
try {
template = env.getTemplateForInclusion(absTemplateName, encoding, parse, true);
} catch (IOException e) {
throw new _TemplateModelException(e, "I/O error when trying to load optional template ", new _DelayedJQuote(absTemplateName), "; see cause exception");
}
SimpleHash result = new SimpleHash(env.getObjectWrapper());
result.put(RESULT_EXISTS, template != null);
// conveniently provided like in <@optTemp.include!myDefaultMacro />.
if (template != null) {
result.put(RESULT_INCLUDE, new TemplateDirectiveModel() {
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
if (!params.isEmpty()) {
throw new TemplateException("This directive supports no parameters.", env);
}
if (loopVars.length != 0) {
throw new TemplateException("This directive supports no loop variables.", env);
}
if (body != null) {
throw new TemplateException("This directive supports no nested content.", env);
}
env.include(template);
}
});
result.put(RESULT_IMPORT, new TemplateMethodModelEx() {
public Object exec(List args) throws TemplateModelException {
if (!args.isEmpty()) {
throw new TemplateModelException("This method supports no parameters.");
}
try {
return env.importLib(template, null);
} catch (IOException e) {
throw new _TemplateModelException(e, "Failed to import loaded template; see cause exception");
} catch (TemplateException e) {
throw new _TemplateModelException(e, "Failed to import loaded template; see cause exception");
}
}
});
}
return result;
}
use of freemarker.template.TemplateDirectiveBody in project be5 by DevelopmentOnTheEdge.
the class Environment method visit.
public void visit(final TemplateElement element, TemplateDirectiveModel directiveModel, Map args, final List bodyParameterNames) throws TemplateException, IOException {
TemplateDirectiveBody nested;
if (element == null) {
nested = null;
} else {
nested = new TemplateDirectiveBody() {
public void render(Writer newOut) throws TemplateException, IOException {
Writer prevOut = out;
out = newOut;
try {
Environment.this.visit(element);
} finally {
out = prevOut;
}
}
};
}
final TemplateModel[] outArgs;
if (bodyParameterNames == null || bodyParameterNames.isEmpty()) {
outArgs = NO_OUT_ARGS;
} else {
outArgs = new TemplateModel[bodyParameterNames.size()];
}
if (outArgs.length > 0) {
pushLocalContext(new LocalContext() {
public TemplateModel getLocalVariable(String name) {
int index = bodyParameterNames.indexOf(name);
return index != -1 ? outArgs[index] : null;
}
public Collection getLocalVariableNames() {
return bodyParameterNames;
}
});
}
try {
directiveModel.execute(this, args, outArgs, nested);
} finally {
if (outArgs.length > 0) {
popLocalContext();
}
}
}
use of freemarker.template.TemplateDirectiveBody in project freemarker by apache.
the class NumberFormatTest method testStringBIDoesSnapshot.
/**
* ?string formats lazily (at least in 2.3.x), so it must make a snapshot of the format inputs when it's called.
*/
@Test
public void testStringBIDoesSnapshot() throws Exception {
// TemplateNumberModel-s shouldn't change, but we have to keep BC when that still happens.
final MutableTemplateNumberModel nm = new MutableTemplateNumberModel();
nm.setNumber(123);
addToDataModel("n", nm);
addToDataModel("incN", new TemplateDirectiveModel() {
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
nm.setNumber(nm.getAsNumber().intValue() + 1);
}
});
assertOutput("<#assign s1 = n?string>" + "<#setting numberFormat='@loc'>" + "<#assign s2 = n?string>" + "<#setting numberFormat='@hex'>" + "<#assign s3 = n?string>" + "${s1} ${s2} ${s3}", "123 123_en_US 7b");
assertOutput("<#assign s1 = n?string>" + "<@incN />" + "<#assign s2 = n?string>" + "${s1} ${s2}", "123 124");
}
use of freemarker.template.TemplateDirectiveBody in project freemarker by apache.
the class Environment method visit.
void visit(final TemplateElement[] childBuffer, TemplateDirectiveModel directiveModel, Map args, final List bodyParameterNames) throws TemplateException, IOException {
TemplateDirectiveBody nested;
if (childBuffer == null) {
nested = null;
} else {
nested = new NestedElementTemplateDirectiveBody(childBuffer);
}
final TemplateModel[] outArgs;
if (bodyParameterNames == null || bodyParameterNames.isEmpty()) {
outArgs = NO_OUT_ARGS;
} else {
outArgs = new TemplateModel[bodyParameterNames.size()];
}
if (outArgs.length > 0) {
pushLocalContext(new LocalContext() {
public TemplateModel getLocalVariable(String name) {
int index = bodyParameterNames.indexOf(name);
return index != -1 ? outArgs[index] : null;
}
public Collection getLocalVariableNames() {
return bodyParameterNames;
}
});
}
try {
directiveModel.execute(this, args, outArgs, nested);
} catch (FlowControlException e) {
throw e;
} catch (TemplateException e) {
throw e;
} catch (IOException e) {
// For backward compatibility, we assume that this is because the output Writer has thrown it.
throw e;
} catch (Exception e) {
if (EvalUtil.shouldWrapUncheckedException(e, this)) {
throw new _MiscTemplateException(e, this, "Directive has thrown an unchecked exception; see the cause exception.");
} else if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else {
throw new UndeclaredThrowableException(e);
}
} finally {
if (outArgs.length > 0) {
localContextStack.pop();
}
}
}
Aggregations