/**
* Copyright 2010 Bing Ran<bing_ran@hotmail.com>
*
* 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 cn.bran.japid.classmeta;
import japa.parser.ast.body.Parameter;
import java.util.List;
import cn.bran.japid.compiler.JavaSyntaxTool;
import cn.bran.japid.tags.Each;
/**
* used to wrapped the body of an invocation of a user defined tag based on tag template file
*
* @author bran
*
*/
public class InnerClassMeta {
private static final String EXTRA_LOOP_ATTRS = ", final int _size, final int _index, final boolean _isOdd, final String _parity, final boolean _isFirst, final boolean _isLast";
String tagName;
// the sequence of the same tag called in a single template
int counter;
// like in a function call
String renderParams;
String renderBody;
// private String interfaceName;
public InnerClassMeta(String tagName, int counter, String callbackArgs, String renderBody) {
this.tagName = tagName.replace('/', '.');
this.counter = counter;
this.renderParams = JavaSyntaxTool.boxPrimitiveTypesInParams(callbackArgs);
this.renderBody = renderBody;
}
//
// /**
// * something like this:
// * <pre>
// * class Display1_Body implements DoBodyInterface{
// void render(String title) {
// pln ("The real title is: ", title);
// }
// * }
// </pre>
// * @deprecated this method is the old way of declaring inner class. Now use the getAnonymous() in inline fashion.
// */
// @Override
// public String toString() {
// ExprParser ep = new ExprParser(this.renderArgs);
// List<String> argTokens = ep.split();
// // something String a Date b
// assert(argTokens.size() % 2 == 0);
//
// String[] argTypes = new String[argTokens.size() /2];
//
// String classParams = "";
// for (int i = 0; i < argTypes.length; i++) {
// classParams += ", " + argTokens.get(i * 2);
// }
//
// if (Each.class.getSimpleName().equals(tagName)) {
// // append extra argument to the render method
// renderArgs += EXTRA_LOOP_ATTRS;
// }
//
// // remove the leading ,
//
//
// if (classParams.startsWith(","))
// classParams = "<" + classParams.substring(1) + ">";
//
// StringBuilder sb = new StringBuilder();
// line(sb, "class " + getVarRoot() + counter + "DoBody implements " + tagName + ".DoBody" + classParams + "{");
// line(sb, "\tpublic void render(" + renderArgs + ") {");
// line(sb, "\t\t" + renderBody);
// line(sb, "\t}");
// line(sb, "}");
//
// // bodyclass instance
// String bodyClassName = getVarRoot() + counter + "DoBody";
// String bodyField = "private " + bodyClassName +" _" + bodyClassName +
// " = new " + bodyClassName + "();";
// line(sb, "\t" + bodyField);
//
// return sb.toString();
// }
private void line (StringBuilder sb, String line) {
sb.append(line + "\n");
}
public String getVarRoot() {
return tagName.replace('.', '_').replace('/', '_');
}
/**
* get something like this
* <pre>
* new Display.DoBody<String>() {
* public void render(String title) {
* p(" The real title is: ");
* p(title);
* }
* });
* </pre>
* @return
*/
public String getAnonymous(String lineMarker) {
List<Parameter> params = JavaSyntaxTool.parseParams(this.renderParams);
String[] argTypes = new String[params.size()];
String generics = "";
for (int i = 0; i < argTypes.length; i++) {
generics += ", " + params.get(i).getType();
}
if (generics.startsWith(","))
generics = "<" + generics.substring(1).trim() + ">";
if (Each.class.getSimpleName().equalsIgnoreCase(tagName)) {
// append extra argument to the render method
tagName = Each.class.getSimpleName();
renderParams += EXTRA_LOOP_ATTRS;
}
String paramList = renderParams;
String renderArgsWithFinal = JavaSyntaxTool.addFinalToAllParams(paramList);
StringBuilder sb = new StringBuilder();
line(sb, "new " + tagName + ".DoBody" + generics + "(){ " + lineMarker);
line(sb, "public void render(" + renderArgsWithFinal + ") { " + lineMarker);
line(sb, renderBody);
line(sb, "}");
String bufferString = "\r\n" +
"StringBuilder oriBuffer;\r\n" +
"@Override\r\n" +
"public void setBuffer(StringBuilder sb) {\r\n" +
" oriBuffer = getOut();\r\n" +
" setOut(sb);\r\n" +
"}\r\n" +
"\r\n" +
"@Override\r\n" +
"public void resetBuffer() {\r\n" +
" setOut(oriBuffer);\r\n" +
"}\r\n";
line(sb, bufferString);
line(sb, "}");
return sb.toString();
}
}