blob: 69d40efee1fffcc79460fbe6425c534249c1304c [file] [log] [blame]
package org.apache.freemarker.core;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
import java.io.IOException;
import java.io.Writer;
import org.apache.freemarker.core.model.ArgumentArrayLayout;
import org.apache.freemarker.core.model.TemplateDirectiveModel;
import org.apache.freemarker.core.model.TemplateModel;
import org.apache.freemarker.core.model.impl.SimpleNumber;
import org.apache.freemarker.core.outputformat.MarkupOutputFormat;
import org.apache.freemarker.core.util.CallableUtils;
import org.apache.freemarker.core.util.CommonSupplier;
import org.apache.freemarker.core.util.StringToIndexMap;
/**
* Example of an AST directive that's bound to some Configuration setting (the htmlOutputFormat in this case).
*/
//TODO [FM3][FREEMARKER-99] Delete this class when we are finished.
class ASTDirAdhocTest1 extends ASTDirective {
private final MarkupOutputFormat<?> htmlOutputFormat;
private ASTExpression p1;
private ASTExpression p2;
private ASTExpression n1;
private ASTExpression n2;
private StringToIndexMap nestedContentParamNames;
private ASTDirAdhocTest1(MarkupOutputFormat<?> htmlOutputFormat) {
this.htmlOutputFormat = htmlOutputFormat;
}
static class Factory implements CommonSupplier<ASTDirective> {
private final MarkupOutputFormat<?> htmlOutputFormat;
Factory(MarkupOutputFormat<?> htmlOutputFormat) {
this.htmlOutputFormat = htmlOutputFormat;
}
@Override
public ASTDirective get() {
return new ASTDirAdhocTest1(htmlOutputFormat);
}
}
static TemplateDirectiveModel VALUE = new TemplateDirectiveModel() {
@Override
public void execute(TemplateModel[] args, CallPlace callPlace, Writer out, Environment env)
throws TemplateException, IOException {
throw new UnsupportedOperationException("execute not implemented");
}
@Override
public boolean isNestedContentSupported() {
return true;
}
@Override
public ArgumentArrayLayout getDirectiveArgumentArrayLayout() {
return ARGS_LAYOUT;
}
};
private static final ArgumentArrayLayout ARGS_LAYOUT = ArgumentArrayLayout.create(2, false,
StringToIndexMap.of("n1", 2, "n2", 3), false);
@Override
public void setPositionalArgument(int position, ASTExpression valueExp) throws StaticLinkingCheckException {
if (position == 0) {
p1 = valueExp;
} else if (position == 1) {
p2 = valueExp;
} else {
// TODO: Standardize error message; see CallableUtils
throw new StaticLinkingCheckException(new _ErrorDescriptionBuilder(
"Too many positional arguments; can only have ",
ARGS_LAYOUT.getPredefinedPositionalArgumentCount(), "."));
}
}
@Override
public void setNamedArgument(String name, ASTExpression valueExp) throws StaticLinkingCheckException {
if (name.equals("n1")) {
n1 = valueExp;
} else if (name.equals("n2")) {
n2 = valueExp;
} else {
// TODO: Standardize error message; see CallableUtils
throw new StaticLinkingCheckException(new _ErrorDescriptionBuilder(
"Unsupported parameter name ", new _DelayedJQuote(name), ". The supported parameters are: ",
new _DelayedJQuotedListing(ARGS_LAYOUT.getPredefinedNamedArgumentsMap().getKeys())));
}
}
@Override
public void checkArgumentsAndSetNestedContentParameters(StringToIndexMap nestedContentParamNames)
throws StaticLinkingCheckException {
// TODO: Standardize error message; see CallableUtils
if (p1 == null) {
throw new StaticLinkingCheckException(new _ErrorDescriptionBuilder(
"Missing mandatory ", new _DelayedOrdinal(1), " positional argument"));
}
// TODO: Standardize error message; see CallableUtils
if (n1 == null) {
throw new StaticLinkingCheckException(new _ErrorDescriptionBuilder(
"Missing mandatory named argument, ", new _DelayedJQuote("n1")));
}
// TODO: Make this check easier?
if (nestedContentParamNames == null || nestedContentParamNames.size() != 1) {
throw new StaticLinkingCheckException(
MessageUtils.newBadNumberOfNestedContentParameterPassedMessage(nestedContentParamNames, 1));
}
this.nestedContentParamNames = nestedContentParamNames;
}
@Override
public StringToIndexMap getNestedContentParamNames() {
return nestedContentParamNames;
}
@Override
ASTElement[] execute(Environment env) throws TemplateException, IOException {
env.pushElement(this);
try {
Writer out = env.getOut();
out.write("#foo(");
// TODO Bind to cfg.getOutputFormat("HTML")
int p1Int = CallableUtils.castArgumentValueToInt(p1.eval(env), 0, false, 0, VALUE, false);
env.interpolate(p1, htmlOutputFormat, AutoEscapingPolicy.ENABLE_IF_DEFAULT, env);
if (p2 != null) {
out.write(", ");
env.interpolate(p2, htmlOutputFormat, AutoEscapingPolicy.ENABLE_IF_DEFAULT, env);
}
out.write(", n1=");
env.interpolate(n1, htmlOutputFormat, AutoEscapingPolicy.ENABLE_IF_DEFAULT, env);
if (n2 != null) {
out.write(", n2=");
env.interpolate(n2, htmlOutputFormat, AutoEscapingPolicy.ENABLE_IF_DEFAULT, env);
}
out.write(") {\n");
for (int i = 0; i < p1Int; i++) {
env.executeNestedContent(this, nestedContentParamNames, new TemplateModel[] { new SimpleNumber(i) });
}
out.write("}-foo\n");
return null;
} finally {
env.popElement();
}
}
@Override
boolean isNestedBlockRepeater() {
// TODO Auto-generated method stub
return false;
}
@Override
String dump(boolean canonical) {
return "<#adhocTest1 ...>";
}
@Override
public String getLabelWithoutParameters() {
return "#adhocTest1";
}
@Override
int getParameterCount() {
// TODO Auto-generated method stub
return 0;
}
@Override
Object getParameterValue(int idx) {
// TODO Auto-generated method stub
return null;
}
@Override
ParameterRole getParameterRole(int idx) {
// TODO Auto-generated method stub
return null;
}
}