/**
* Copyright 2015 the original author or authors.
*
* 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 org.mybatis.scripting.freemarker;
import freemarker.core.Environment;
import freemarker.ext.util.WrapperTemplateModel;
import freemarker.template.*;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* Custom FreeMarker directive for generating "#{paramName}" declarations in convenient way.
* Problem is FreeMarker supports this syntax natively and there are no chance to disable this
* (although it is deprecated). And to get "#{paramName}" we should write ${r"#{paramName}"}.
* With this directive you can write more simple:
*
* <blockquote><pre>
* <@p name="paramName"/>
* </pre></blockquote>
*
* Also directive supports `value` attribute. If it is specified, param will take passed value
* and create the corresponding #{}-parameter. This is useful in loops:
*
* <blockquote><pre>
* <#list ids as id>
* <@p value=id/>
* <#if id_has_next>,</#if>
* </#list>
* </pre></blockquote>
*
* will be translated into
*
* <blockquote><pre>
* #{_p0},#{_p1},#{_p2}
* </pre></blockquote>
*
* And MyBatis engine will convert it to `?`-params finally.
*
* @author elwood
*/
public class MyBatisParamDirective implements TemplateDirectiveModel {
public static String DEFAULT_KEY = "p";
@Override
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException {
SimpleScalar name = (SimpleScalar) params.get("name");
if (params.containsKey("value")) {
Object valueObject = params.get("value");
Object value;
if (valueObject == null) {
value = null;
} else if (valueObject instanceof WrapperTemplateModel) {
value = ((WrapperTemplateModel) valueObject).getWrappedObject();
} else if (valueObject instanceof TemplateScalarModel) {
value = ((TemplateScalarModel) valueObject).getAsString();
} else if (valueObject instanceof TemplateNumberModel) {
value = ((TemplateNumberModel) valueObject).getAsNumber();
} else if (valueObject instanceof TemplateDateModel) {
value = ((TemplateDateModel) valueObject).getAsDate();
} else if (valueObject instanceof TemplateBooleanModel) {
value = ((TemplateBooleanModel) valueObject).getAsBoolean();
} else {
throw new UnsupportedOperationException(
String.format("Type %s is not supported yet in this context.",
valueObject.getClass().getSimpleName()));
}
TemplateModel generatedParamsObject = env.getGlobalVariables().get(FreeMarkerSqlSource.GENERATED_PARAMS_KEY);
List generatedParams;
if (generatedParamsObject instanceof DefaultListAdapter) {
generatedParams = (List) ((DefaultListAdapter) generatedParamsObject).getWrappedObject();
} else {
generatedParams = ((GeneratedParamsTemplateModel) generatedParamsObject)
.getGeneratedParams();
}
String generatedParamName = "_p" + generatedParams.size();
env.getOut().write(String.format("#{%s}", generatedParamName));
generatedParams.add(value);
} else {
env.getOut().write(String.format("#{%s}", name));
}
}
}