package org.dataone.jibx.schema.codegen.extend;
import java.util.Iterator;
import org.apache.bcel.generic.Type;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.IfStatement;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.jibx.binding.model.ElementBase;
import org.jibx.schema.codegen.IClassHolder;
import org.jibx.schema.codegen.NameUtils;
import org.jibx.schema.codegen.extend.ClassDecorator;
import org.jibx.schema.codegen.extend.NameMatchDecoratorBase;
import org.jibx.util.NameUtilities;
public class SliceMethodsDecorator extends NameMatchDecoratorBase implements ClassDecorator {
/** Parser instance used by class. */
private final ASTParser m_parser = ASTParser.newParser(AST.JLS3);
/** Serial version UID value (null
if not set). */
private Long m_serialVersion;
/** Text for template class. */
private static final String s_classText = "class Gorph { "
+ "java.util.List $1; "
+ "/** Get the 'count' attribute value. The number of entries in the slice.\n"
+ " * @return size of wrapped list\n */\n"
+ "@Override\n"
+ "public int getCount() { "
+ "if ($1 == null) { $1 = new ArrayList<$3>(); } "
+ "return $1.size(); "
+ "}"
+ "/** Get the number of $0 items.\n * @return count\n */\n "
+ "public int size$5() { "
+ "if ($1 == null) { $1 = new ArrayList<$3>(); } "
+ "return $1.size(); } "
+ "/** Add a $0 item.\n * @param item\n */\n "
+ "public void add$2($3 item) { "
+ "if ($1 == null) { $1 = new ArrayList<$3>(); }\n "
+ "$1.add(item); "
+ "}"
+ "/** Get $0 item by position.\n * @return item\n * @param index\n */\n"
+ "public $3 get$2(int index) { "
+ "if ($1 == null) { $1 = new ArrayList<$3>(); } "
+ "return $4$1.get(index); "
+ "}"
+ "/** Remove all $0 items.\n */\n "
+ "public void clear$5() { "
+ "if ($1 == null) { $1 = new ArrayList<$3>(); } "
+ "$1.clear(); "
+ "} "
+ "}";
// $0 is the description text
// $1 is the field name
// $2 is the value name with initial uppercase character
// $3 is the type
// $4 is a cast if an untyped list is used, or empty if a typed list is used
// $5 is the uppercase field name
/**
* Method called before starting code generation for the target class.
*/
@Override
public void start(IClassHolder holder) {
// empty
}
/**
* Method called after completing code generation for the target class.
*/
@Override
public void finish(ElementBase binding, IClassHolder holder) {
// empty
}
/**
* Method called after adding each data value to class.
*
* @param basename base name used for data value
* @param collect repeated value flag
* @param type value type (item value type, in the case of a repeated value)
* @param field actual field
* @param getmeth read access method (null
if a flag value)
* @param setmeth write access method (null
if a flag value)
* @param descript value description text
* @param holder
*/
@Override
public void valueAdded(String basename, boolean collect, String type, FieldDeclaration field,
MethodDeclaration getmeth, MethodDeclaration setmeth, String descript, IClassHolder holder) {
String fieldtype = field.getType().toString();
if (matchName(holder.getName()))
if (collect && (fieldtype.startsWith("List") || fieldtype.startsWith("java.util.List"))) {
// make substitutions in template text
StringBuffer buff = new StringBuffer(s_classText);
VariableDeclarationFragment vardecl = (VariableDeclarationFragment)field.fragments().get(0);
replace("$0", descript, buff);
replace("$1", vardecl.getName().getIdentifier(), buff);
replace("$2", NameUtilities.depluralize(NameUtils.toNameWord(basename)), buff);
replace("$3", holder.getTypeName(type), buff);
String cast = field.getType().isParameterizedType() ? "" : ("(" + type + ")");
replace("$4", cast, buff);
replace("$5", getmeth.getName().getIdentifier().substring(3), buff);
// parse the resulting text
m_parser.setSource(buff.toString().toCharArray());
CompilationUnit unit = (CompilationUnit)m_parser.createAST(null);
// add all methods from output tree to class under construction
TypeDeclaration typedecl = (TypeDeclaration)unit.types().get(0);
for (Iterator iter = typedecl.bodyDeclarations().iterator(); iter.hasNext();) {
ASTNode node = (ASTNode)iter.next();
if (node instanceof MethodDeclaration) {
holder.addMethod((MethodDeclaration)node);
}
}
}
}
/**
* Replace all occurrences of one string with another in a buffer.
*/
private static void replace(String match, String replace, StringBuffer buff) {
int base = 0;
while ((base = buff.indexOf(match, base)) >= 0) {
buff.replace(base, base+match.length(), replace);
}
}
}