package com.github.geequery.codegen.ast;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.util.List;
import jef.tools.IOUtils;
import jef.tools.StringUtils;
import jef.tools.collection.CollectionUtils;
import com.github.javaparser.JavaParser;
import com.github.javaparser.ParseException;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.TypeParameter;
import com.github.javaparser.ast.body.BodyDeclaration;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.ConstructorDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.body.VariableDeclarator;
import com.github.javaparser.ast.expr.AnnotationExpr;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import com.github.javaparser.ast.visitor.DumpVisitor;
public class JefParser implements JavaUnitParser{
private static final char[] LEFT_TRIM=" \t\n\r".toCharArray();
private static final char[] RIGHT_TRIM=" \t\n\r;".toCharArray();
private BufferedReader reader;
private CompilationUnit unit;
private int lineNum=1;
public JavaUnit parse(File file, String charset){
try{
this.reader=IOUtils.getReader(file, charset);
unit= JavaParser.parse(file,charset);
return doParse();
}catch(IOException e){
throw new RuntimeException(e);
} catch (ParseException e) {
throw new RuntimeException(e);
}finally{
IOUtils.closeQuietly(reader);
}
}
private JavaUnit doParse()throws IOException{
String pkgName=(unit.getPackage()==null)?"":unit.getPackage().getName().toString();
ClassOrInterfaceDeclaration type;
if(unit.getTypes().get(0) instanceof ClassOrInterfaceDeclaration){
type=(ClassOrInterfaceDeclaration)unit.getTypes().get(0);
}else{
throw new RuntimeException("The Javaunit can only support One MainClass in a java file.");
}
JavaUnit java=new JavaUnit(pkgName,type.getName());
java.setAddNotModifiedTag(false);
if(type.getTypeParameters()!=null){
for(TypeParameter tp:type.getTypeParameters()){
java.addTypeParameter(tp.toString());
}
}
if(type.getImplements()!=null){
for(ClassOrInterfaceType t:type.getImplements()){
java.addImplementsInterface(t.getName());
}
}
java.setModifiers(type.getModifiers());
java.setInterface(type.isInterface());
if(type.getExtends()!=null && type.getExtends().size()>0){
java.setExtends(type.getExtends().get(0).getName());
}
//jianghy3 2012.08.29 Bug #55696 解决思路:先保留原有的,再根据本次配置信息删除/修改。
List<AnnotationExpr> annos = type.getAnnotations();
if(!CollectionUtils.isEmpty(annos)){
java.addAnnotation(parseAnnoExprToString(annos.toArray(new AnnotationExpr[annos.size()])));
}
/*开始逐行解析和处理*/
//包定义前的部分
processBeforePackage(java,0,unit.getPackage().getBeginLine());
//包定义到类定义前的部分
int start=unit.getPackage().getEndLine()+1;
int end=type.getBeginLine();//不含
processRawBeforeTypeDef(java,start,end);//将所有的前行添加
List<BodyDeclaration> members = type.getMembers();
if(members!=null && members.size()>0){
this.skipLines(members.get(0).getBeginLine());
}
for (BodyDeclaration member : members) {
//类成员1
if (member instanceof MethodDeclaration) {
MethodDeclaration m=(MethodDeclaration)member;
processMethod(java,m,m.getEndLine()+1);
}else if(member instanceof FieldDeclaration){
FieldDeclaration f=( FieldDeclaration)member;
processField(java,f,f.getEndLine()+1);
}else if(member instanceof ConstructorDeclaration){
ConstructorDeclaration c=(ConstructorDeclaration)member;
processConstructor(java,c,c.getEndLine()+1);
}else{
processOtherBodyDec(java,member,member.getEndLine()+1);
}
}
return java;
}
private void processConstructor(JavaUnit java, ConstructorDeclaration c, int i) throws IOException {
DefaultJavaElement element=new DefaultJavaElement();
boolean isStarted=false;
for(;lineNum<i;lineNum++){
String line=reader.readLine();
if(StringUtils.isBlank(line) && !isStarted){
continue;
}
if(isStarted==false){
element.addContent(line.trim());
}else{
element.addContent(line);
}
isStarted=true;
}
JavaConstructor jm=new JavaConstructor();
if(c.getParameters()!=null){
for(Parameter param:c.getParameters()){
jm.addparam(param.getType().toString(), param.getId().getName(),param.getModifiers());
if(param.isVarArgs()){
jm.setVarArg(true);
}
}
}
java.addMethod(jm.getKey(), element);
}
private void processOtherBodyDec(JavaUnit java, BodyDeclaration member, int i) throws IOException {
boolean isStarted=false;
DefaultJavaElement element=new DefaultJavaElement();
for(;lineNum<i;lineNum++){
String line=reader.readLine();
if(StringUtils.isBlank(line) && !isStarted){
continue;
}
isStarted=true;
element.addContent(line);
}
java.addRawBlock(element);
}
private void processField(JavaUnit java, FieldDeclaration field, int i) throws IOException {
DefaultJavaElement element=new DefaultJavaElement();
boolean isStarted=false;
for(;lineNum<i;lineNum++){
String line=reader.readLine();
if(StringUtils.isBlank(line) && !isStarted){
continue;
}
if(isStarted==false){
element.addContent(line.trim());
}else{
element.addContent(line);
}
isStarted=true;
}
VariableDeclarator v=field.getVariables().get(0);
String name=v.getId().toString();
java.addField(name,element);
}
private void processMethod(JavaUnit java, MethodDeclaration method, int i) throws IOException {
DefaultJavaElement element=new DefaultJavaElement();
boolean isStarted=false;
for(;lineNum<i;lineNum++){
String line=reader.readLine();
if(StringUtils.isBlank(line) && !isStarted){
continue;
}
if(isStarted==false){
element.addContent(line.trim());
}else{
element.addContent(line);
}
isStarted=true;
}
JavaMethod jm=new JavaMethod(method.getName());
if(method.getParameters()!=null){
for(Parameter param:method.getParameters()){
jm.addparam(param.getType().toString(), param.getId().getName(),param.getModifiers());
if(param.isVarArgs()){
jm.setVarArg(true);
}
}
}
java.addMethod(jm.getKey(), element);
}
private void processBeforePackage(JavaUnit java, int start, int end) throws IOException {
skipLines(end);
// for(;lineNum<end;lineNum++){
// reader.readLine();
// lineNum++;
// }
}
private void processRawBeforeTypeDef(JavaUnit java, int start, int end) throws IOException {
DefaultJavaElement element=new DefaultJavaElement();
skipLines(start);
boolean isStarted=false;
for(;lineNum<end;lineNum++){
String line=reader.readLine();
if(StringUtils.isBlank(line) && !isStarted){
continue;
}
isStarted=true;
if(line.startsWith("import ")){
String name=StringUtils.substringAfter(line, "import ");
name=StringUtils.lrtrim(name, LEFT_TRIM, RIGHT_TRIM);
java.addImport(name);
}else if(StringUtils.isBlank(line)){
java.addImport("");
}else{
element.addContent(line);
}
}
java.setRawLinesBeforeTypeDef(element);
}
private void skipLines(int start) throws IOException {
while(lineNum<start){
@SuppressWarnings("unused")
String line=reader.readLine();
lineNum++;
}
}
private String[] parseAnnoExprToString(AnnotationExpr[] annos){
if(annos != null){
String[] annoStrArr = new String[annos.length];
for(int i=0; i<annos.length; i++){
//copy from japa.parser.ast.Node.toString().
DumpVisitor visitor = new DumpVisitor();
annos[i].accept(visitor, null);
annoStrArr[i] = visitor.getSource();
}
return annoStrArr;
}
return new String[0];
}
}