Skip to content

Instantly share code, notes, and snippets.

@harawata
Created January 21, 2015 16:43
Show Gist options
  • Save harawata/96c0ac23622afd7e80be to your computer and use it in GitHub Desktop.
Save harawata/96c0ac23622afd7e80be to your computer and use it in GitHub Desktop.
A custom Velocity directive for MyBatis to perform text substitution. Related to https://github.com/mybatis/mybatis-3/pull/331
<sql id="sometable">
@prefix@Table
</sql>
<sql id="someinclude">
@include_target@
</sql>
<select id="select" lang="velocity" resultType="map">
#substitute("include_target:<include refid="org.apache.ibatis.submitted.includes.fragments.select"/>")
<include refid="someinclude" />
#end
field1, field2, field3
from
#substitute("prefix:Some", "include_target:<include refid="sometable"/>")
<include refid="someinclude" />
#end
</select>
/*
* Copyright 2009-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.velocity.use;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.directive.Directive;
import org.apache.velocity.runtime.parser.node.ASTBlock;
import org.apache.velocity.runtime.parser.node.Node;
public class SubstituteDirective extends Directive {
@Override
public String getName() {
return "substitute";
}
@Override
public int getType() {
return BLOCK;
}
@Override
public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException {
String body = null;
Map<String, String> map = new HashMap<String, String>();
for (int i = 0; i < node.jjtGetNumChildren(); i++) {
if (node.jjtGetChild(i) != null) {
if (node.jjtGetChild(i) instanceof ASTBlock) {
StringWriter stringWriter = new StringWriter();
node.jjtGetChild(i).render(context, stringWriter);
body = stringWriter.toString();
break;
} else {
String keyValueStr = String.valueOf(node.jjtGetChild(i).value(context));
int equalPos = keyValueStr.indexOf(':');
if (equalPos > 0) {
String key = keyValueStr.substring(0, equalPos).trim();
if (equalPos == keyValueStr.length() - 1)
map.put(key, "");
else
map.put(key, keyValueStr.substring(equalPos + 1).trim());
}
}
}
}
writer.write(translate(body, map));
return true;
}
private String translate(String body, Map<String, String> map) {
if (body == null || body.length() == 0 || map.isEmpty())
return body;
for (Entry<String, String> entry : map.entrySet()) {
// you may want to rewrite this part for better performance
body = body.replaceAll("@" + entry.getKey() + "@", entry.getValue());
}
return body;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment